clipsruby 0.0.5 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +124 -0
  3. data/ext/clipsruby/clipsruby.c +84 -10
  4. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b86283884e46ed71a0e4db078683c2443b9f1baf9220ab0a5e9f90eef02b0ba
4
- data.tar.gz: 0632d1971aedb15f695e0d43400113f45693fba7db6547d6497887df81c019a4
3
+ metadata.gz: 75e4ce843f3549eb6b8508d4d97ab8193dc8434acab30659af50871953759991
4
+ data.tar.gz: 5372088f0743df5a5e3e94833bb7334608bfe85c0ede4879476e3a014eeb034d
5
5
  SHA512:
6
- metadata.gz: e72f8a5f5eae7b0befcfcfe5fd850a62cdef2c984f5a6cbbfcfab52190adcfa90a5c5af5a7ef028ee573105f4aacfd5ead750bbae7c496bde05e0eedb07df3b9
7
- data.tar.gz: c08ddb4e2559ee1bf6113e6866ff7c75880801201a740292fe6ba3109fe9a7806f1074bdd6b2a6093bacb27c83bd24dff8979e45cb2d137f82e7a3de3ce6c9d6
6
+ metadata.gz: e3700fb8eb942640cd698985ecf00190ad447b89dfeed35df3125924e577de0be0f6b56695a1f0e2adfc078b2cdc7655bbdf08c22f40624eb305d4d539da2fd5
7
+ data.tar.gz: 7626b936453007c332c1cc1f191e449ce3c68f9447281a595fceef524a0cc9bc5a5c603d2afd5553887049d380c6297d0a8e27e9256f9fc54330722cdaaf8ba5
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # clipsruby
2
+
3
+ ## Description
4
+
5
+ Use the CLIPS programming language from within Ruby
6
+
7
+ ## API
8
+
9
+ ### `CLIPS.create_environment`
10
+ ### `CLIPS::Environment.new`
11
+
12
+ Create a new CLIPS environment in which you may define Rules,
13
+ assert Facts, and instantiate Objects.
14
+
15
+ ```ruby
16
+ env = CLIPS.create_environment
17
+ env2 = CLIPS::Environment.new
18
+ ```
19
+
20
+ ### `CLIPS::Environment.assert_string`
21
+ ### `CLIPS::Environment#assert_string`
22
+
23
+ Assert a string as a Fact in the CLIPS environment.
24
+
25
+ ```ruby
26
+ fact = CLIPS::Environment.assert_string(env, "(foo bar)")
27
+ fact2 = env.assert_string("(bat baz)")
28
+ ```
29
+
30
+ ### `CLIPS::Environment.assert_hash`
31
+ ### `CLIPS::Environment#assert_hash`
32
+
33
+ Asserts a Deftemplate fact into the CLIPS environment
34
+
35
+ ```ruby
36
+ fact = CLIPS::Environment.assert_hash(env, :my_deftemplate, a: 1, b: "asdf", c: :C)
37
+ fact2 = env.assert_hash(:my_deftemplate, d: 4.5, e: :asdf)
38
+ ```
39
+
40
+ ### `CLIPS::Environment.find_all_facts`
41
+ ### `CLIPS::Environment#find_all_facts`
42
+
43
+ A light wrapper around the CLIPS find-all-facts function. Accepts a fact set template and query,
44
+ returns Facts in the environment that match as Ruby objects.
45
+
46
+ ```ruby
47
+ CLIPS::Environment.find_all_facts(env, "(?f my_deftemplate)")
48
+ env.find_all_facts("(?f my_deftemplate)")
49
+ CLIPS::Environment.find_all_facts(env, "(?f my_deftemplate)", "(eq ?f:b \"asdf\")")
50
+ env.find_all_facts("(?f my_deftemplate)", "(= ?f:a 1)")
51
+ ```
52
+
53
+ ### `CLIPS::Environment._eval`
54
+ ### `CLIPS::Environment#_eval`
55
+
56
+ Evaluates a passed string in the CLIPS environment and returns the results.
57
+
58
+ ```ruby
59
+ CLIPS::Environment._eval(env, "(find-all-facts ((?f my_deftemplate)) TRUE)")
60
+ env._eval("(find-all-facts ((?f my_deftemplate)) TRUE)")
61
+ ```
62
+
63
+ ### `CLIPS::Environment.build`
64
+ ### `CLIPS::Environment#build`
65
+
66
+ Build the constructs in the env as defined in a string
67
+
68
+ ```ruby
69
+ CLIPS::Environment.build(env, "(deftemplate my_template (slot a) (slot b) (slot c))")
70
+ env.build("(defrule do-a-thing (my_template (a ?a)) => (println \"a: \" ?a))")
71
+ ```
72
+
73
+ ### `CLIPS::Environment.add_udf`
74
+ ### `CLIPS::Environment#add_udf`
75
+
76
+ Adds a ruby method as a User Defined Function (udf) to the CLIPS environment
77
+
78
+ ```ruby
79
+ class CLIPS::Environment
80
+ def foo(a, b=2)
81
+ a + b
82
+ end
83
+
84
+ def bar(word)
85
+ "You said #{word}!"
86
+ end
87
+ end
88
+
89
+ env.add_udf(:foo)
90
+ CLIPS::Environment.add_udf(env, :bar)
91
+ ```
92
+
93
+ ### `CLIPS::Environment.run`
94
+ ### `CLIPS::Environment#run`
95
+
96
+ Runs the rules engine, executing items on the agenda.
97
+ Optionally may take the number of items to run from the agenda as an argument.
98
+
99
+ ```ruby
100
+ CLIPS::Environment.run(env, 1)
101
+ CLIPS::Environment.run(env)
102
+ env.run(1)
103
+ env.run
104
+ ```
105
+
106
+ ### `CLIPS::Environment.facts`
107
+ ### `CLIPS::Environment#facts`
108
+
109
+ Print all Facts defined in the CLIPS environment
110
+
111
+ ```ruby
112
+ CLIPS::Environment.facts(env)
113
+ env.facts
114
+ ```
115
+
116
+ ### `CLIPS::Environment::Fact.deftemplate_name`
117
+ ### `CLIPS::Environment::Fact#deftemplate_name`
118
+
119
+ Returns the name of the Deftemplate for a fact as a symbol
120
+
121
+ ```ruby
122
+ CLIPS::Environment::Fact.deftemplate_name(fact)
123
+ fact.deftemplate_name
124
+ ```
@@ -323,8 +323,10 @@ static VALUE clips_environment_static_assert_hash(VALUE self, VALUE environment,
323
323
  return clips_environment_assert_hash(environment, deftemplate_name, hash);
324
324
  }
325
325
 
326
- static void CLIPSValue_to_VALUE(CLIPSValue *from, VALUE *value, Environment *env)
326
+ static void CLIPSValue_to_VALUE(CLIPSValue *from, VALUE *value, VALUE *rbEnvironment)
327
327
  {
328
+ Environment *env;
329
+ TypedData_Get_Struct(*rbEnvironment, Environment, &Environment_type, env);
328
330
  switch (from->header->type)
329
331
  {
330
332
  case VOID_TYPE:
@@ -338,7 +340,7 @@ static void CLIPSValue_to_VALUE(CLIPSValue *from, VALUE *value, Environment *env
338
340
  for (size_t i = 0; i < from->multifieldValue->length; i++)
339
341
  {
340
342
  VALUE innerValue;
341
- CLIPSValue_to_VALUE(&from->multifieldValue->contents[i], &innerValue, env);
343
+ CLIPSValue_to_VALUE(&from->multifieldValue->contents[i], &innerValue, rbEnvironment);
342
344
  rb_ary_push(*value, innerValue);
343
345
  }
344
346
  break;
@@ -358,8 +360,13 @@ static void CLIPSValue_to_VALUE(CLIPSValue *from, VALUE *value, Environment *env
358
360
  case INSTANCE_NAME_TYPE:
359
361
  *value = rb_str_new2(from->lexemeValue->contents);
360
362
  break;
361
- case EXTERNAL_ADDRESS_TYPE:
362
363
  case FACT_ADDRESS_TYPE:
364
+ *value =
365
+ TypedData_Wrap_Struct(rb_const_get(CLASS_OF(*rbEnvironment), rb_intern("Fact")), &Fact_type, from->factValue);
366
+
367
+ rb_iv_set(*value, "@environment", *rbEnvironment);
368
+ break;
369
+ case EXTERNAL_ADDRESS_TYPE:
363
370
  case INSTANCE_ADDRESS_TYPE:
364
371
  default:
365
372
  WriteString(env,STDERR,"Unsupported data type returned from function\n");
@@ -368,8 +375,10 @@ static void CLIPSValue_to_VALUE(CLIPSValue *from, VALUE *value, Environment *env
368
375
  }
369
376
  }
370
377
 
371
- static void UDFValue_to_VALUE(UDFValue *from, VALUE *value, Environment *env)
378
+ static void UDFValue_to_VALUE(UDFValue *from, VALUE *value, VALUE *rbEnvironment)
372
379
  {
380
+ Environment *env;
381
+ TypedData_Get_Struct(*rbEnvironment, Environment, &Environment_type, env);
373
382
  switch (from->header->type)
374
383
  {
375
384
  case VOID_TYPE:
@@ -383,7 +392,7 @@ static void UDFValue_to_VALUE(UDFValue *from, VALUE *value, Environment *env)
383
392
  VALUE innerValue;
384
393
  for (size_t i = 0; i < from->multifieldValue->length; i++)
385
394
  {
386
- CLIPSValue_to_VALUE(&from->multifieldValue->contents[i], &innerValue, env);
395
+ CLIPSValue_to_VALUE(&from->multifieldValue->contents[i], &innerValue, rbEnvironment);
387
396
  rb_ary_push(*value, innerValue);
388
397
  }
389
398
  break;
@@ -403,8 +412,13 @@ static void UDFValue_to_VALUE(UDFValue *from, VALUE *value, Environment *env)
403
412
  case INSTANCE_NAME_TYPE:
404
413
  *value = rb_str_new2(from->lexemeValue->contents);
405
414
  break;
406
- case EXTERNAL_ADDRESS_TYPE:
407
415
  case FACT_ADDRESS_TYPE:
416
+ *value =
417
+ TypedData_Wrap_Struct(rb_const_get(CLASS_OF(*rbEnvironment), rb_intern("Fact")), &Fact_type, from->factValue);
418
+
419
+ rb_iv_set(*value, "@environment", *rbEnvironment);
420
+ break;
421
+ case EXTERNAL_ADDRESS_TYPE:
408
422
  case INSTANCE_ADDRESS_TYPE:
409
423
  default:
410
424
  WriteString(env,STDERR,"Unsupported data type returned from function\n");
@@ -423,11 +437,11 @@ void UDFGenericFunction(
423
437
  VALUE *current_argv = argv;
424
438
  UDFValue theArg;
425
439
  VALUE method = (VALUE)(context->context);
426
- VALUE theValue;
440
+ VALUE rbEnvironment = rb_funcall(method, rb_intern("receiver"), 0);
427
441
  while (UDFHasNextArgument(context))
428
442
  {
429
443
  UDFNextArgument(context, ANY_TYPE_BITS, &theArg);
430
- UDFValue_to_VALUE(&theArg, current_argv, theEnv);
444
+ UDFValue_to_VALUE(&theArg, current_argv, &rbEnvironment);
431
445
  current_argv++;
432
446
  }
433
447
  // Call the method on the object with the provided arguments
@@ -570,7 +584,7 @@ static VALUE clips_environment_run(int argc, VALUE *argv, VALUE environment) {
570
584
 
571
585
  TypedData_Get_Struct(environment, Environment, &Environment_type, env);
572
586
 
573
- return NUM2INT(Run(env, NUM2INT(integer)));
587
+ return INT2NUM(Run(env, NUM2INT(integer)));
574
588
  }
575
589
 
576
590
  static VALUE clips_environment_static_run(int argc, VALUE *argv, VALUE klass) {
@@ -584,7 +598,63 @@ static VALUE clips_environment_static_run(int argc, VALUE *argv, VALUE klass) {
584
598
 
585
599
  TypedData_Get_Struct(environment, Environment, &Environment_type, env);
586
600
 
587
- return NUM2INT(Run(env, NUM2INT(integer)));
601
+ return INT2NUM(Run(env, NUM2INT(integer)));
602
+ }
603
+
604
+ static VALUE clips_environment_eval(VALUE self, VALUE string)
605
+ {
606
+ Environment *env;
607
+ CLIPSValue output;
608
+ VALUE toReturn;
609
+
610
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
611
+
612
+ switch(Eval(env, StringValueCStr(string), &output))
613
+ {
614
+ case EE_NO_ERROR:
615
+ break;
616
+ case EE_PROCESSING_ERROR:
617
+ rb_warn("`eval` failed!");
618
+ break;
619
+ case EE_PARSING_ERROR:
620
+ rb_warn("`eval` failed! Could not parse string correctly.");
621
+ break;
622
+ }
623
+
624
+ CLIPSValue_to_VALUE(&output, &toReturn, &self);
625
+
626
+ return toReturn;
627
+ }
628
+
629
+ static VALUE clips_environment_static_eval(VALUE self, VALUE rbEnvironment, VALUE string)
630
+ {
631
+ return clips_environment_eval(rbEnvironment, string);
632
+ }
633
+
634
+ static VALUE clips_environment_find_all_facts(int argc, VALUE *argv, VALUE environment) {
635
+ VALUE fact_set_template, query;
636
+
637
+ rb_scan_args(argc, argv, "11", &fact_set_template, &query);
638
+ if (NIL_P(query)) {
639
+ query = rb_str_new_cstr("TRUE");
640
+ }
641
+
642
+ return clips_environment_eval(
643
+ environment,
644
+ rb_sprintf("(find-all-facts (%s) %s)", StringValueCStr(fact_set_template), StringValueCStr(query)));
645
+ }
646
+
647
+ static VALUE clips_environment_static_find_all_facts(int argc, VALUE *argv, VALUE klass) {
648
+ VALUE rbEnvironment, fact_set_template, query;
649
+
650
+ rb_scan_args(argc, argv, "21", &rbEnvironment, &fact_set_template, &query);
651
+ if (NIL_P(query)) {
652
+ query = rb_str_new_cstr("TRUE");
653
+ }
654
+
655
+ return clips_environment_eval(
656
+ rbEnvironment,
657
+ rb_sprintf("(find-all-facts (%s) %s)", StringValueCStr(fact_set_template), StringValueCStr(query)));
588
658
  }
589
659
 
590
660
  void Init_clipsruby(void)
@@ -606,6 +676,10 @@ void Init_clipsruby(void)
606
676
  rb_define_method(rbEnvironment, "add_udf", clips_environment_add_udf, -1);
607
677
  rb_define_singleton_method(rbEnvironment, "run", clips_environment_static_run, -1);
608
678
  rb_define_method(rbEnvironment, "run", clips_environment_run, -1);
679
+ rb_define_singleton_method(rbEnvironment, "_eval", clips_environment_static_eval, 2);
680
+ rb_define_method(rbEnvironment, "_eval", clips_environment_eval, 1);
681
+ rb_define_singleton_method(rbEnvironment, "find_all_facts", clips_environment_static_find_all_facts, -1);
682
+ rb_define_method(rbEnvironment, "find_all_facts", clips_environment_find_all_facts, -1);
609
683
 
610
684
  VALUE rbFact = rb_define_class_under(rbEnvironment, "Fact", rb_cObject);
611
685
  rb_define_singleton_method(rbFact, "deftemplate_name", clips_environment_fact_static_deftemplate_name, 1);
metadata CHANGED
@@ -1,22 +1,24 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clipsruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Johnston
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-03 00:00:00.000000000 Z
11
+ date: 2024-09-05 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Calling the CLIPS programming language from within Ruby
14
14
  email: mrryanjohnston@gmail.com
15
15
  executables: []
16
16
  extensions:
17
17
  - ext/clipsruby/extconf.rb
18
- extra_rdoc_files: []
18
+ extra_rdoc_files:
19
+ - README.md
19
20
  files:
21
+ - README.md
20
22
  - ext/clipsruby/agenda.c
21
23
  - ext/clipsruby/agenda.h
22
24
  - ext/clipsruby/analysis.c