clipsruby 0.0.23 → 0.0.25

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 +98 -0
  3. data/ext/clipsruby/clipsruby.c +837 -0
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 994b076d823d294b992d1621ec327e72cd415602c744d3214b16e15b6624dcbd
4
- data.tar.gz: 864a892fb3405400362b6ceeea13d24f3c22bf4508f4013b14c6f3a6dd102e4f
3
+ metadata.gz: 1856bf108cc073000e859ba1b7552a781471fef0503640a2741d555990b74ae8
4
+ data.tar.gz: 667938c636e983f3ae6f90c3ba20363273f7189c5cdfc9e0d472c34c97656b01
5
5
  SHA512:
6
- metadata.gz: 0a2bbd8b165667a1a2b07b19b8099ec0dfae9ccbf4b669d469421f5db66c53840a00a0855f07479b272e030b0fb06430f28382340af1e3efe60af13858542ca4
7
- data.tar.gz: 918c4ffd67a5623d761805e4f60920c4ac250e321cb33fca2f61ad26ff5ac28b4cc92acaaeaa1478e8110c3697d719a9c8e69da5da96fcda88d5b2a4d078bef0
6
+ metadata.gz: d2c746946cb8d3bcf43c59587d61c95e636d04b233c8065354f1b16319ef5e195cd5004ddf56e2083a9837995ed21685c71d3bc7bad815066f50039e33af18ec
7
+ data.tar.gz: 5ef09dd92b97e409b012c7183673d11871a3bba2e494467bbf84f91d31e1db29d40c67b6fd2c242d22af113f6a9c6c14ebdde771a7486bbf7299f324608ba216
data/README.md CHANGED
@@ -571,6 +571,56 @@ CLIPS::Environment::Deftemplate.assert_hash(deftemplate, foo: :bar)
571
571
  deftemplate.assert_hash(foo: :bar)
572
572
  ```
573
573
 
574
+ ### `CLIPS::Environment::Deftemplate.defmodule_name`
575
+ ### `CLIPS::Environment::Deftemplate#defmodule_name`
576
+
577
+ Returns the name of the defmodule in which the deftemplate is defined
578
+
579
+ ```ruby
580
+ CLIPS::Environment::Deftemplate.defmodule_name(deftemplate)
581
+ deftemplate.defmodule_name
582
+ ```
583
+
584
+ ### `CLIPS::Environment::Deftemplate.slot_names`
585
+ ### `CLIPS::Environment::Deftemplate#slot_names`
586
+
587
+ Returns the slot names of a deftemplate as symbols
588
+
589
+ ```ruby
590
+ CLIPS::Environment::Deftemplate.slot_names(deftemplate)
591
+ deftemplate.slot_names
592
+ ```
593
+
594
+ ### `CLIPS::Environment::Deftemplate.is_deletable`
595
+ ### `CLIPS::Environment::Deftemplate#is_deletable`
596
+
597
+ Returns a boolean whether the Deftemplate is deletable or not
598
+
599
+ ```ruby
600
+ CLIPS::Environment::Deftemplate.is_deletable(deftemplate)
601
+ deftemplate.is_deletable
602
+ ```
603
+
604
+ ### `CLIPS::Environment::Deftemplate.slot_allowed_values`
605
+ ### `CLIPS::Environment::Deftemplate#slot_allowed_values`
606
+
607
+ Returns the allowed values for the slot of a deftemplate as symbols
608
+
609
+ ```ruby
610
+ CLIPS::Environment::Deftemplate.slot_allowed_values(deftemplate, :foo)
611
+ deftemplate.slot_allowed_values('bar')
612
+ ```
613
+
614
+ ### `CLIPS::Environment::Deftemplate.slot_default_value`
615
+ ### `CLIPS::Environment::Deftemplate#slot_default_value`
616
+
617
+ Returns the default value(s) for the slot of a deftemplate as symbols
618
+
619
+ ```ruby
620
+ CLIPS::Environment::Deftemplate.slot_default_value(deftemplate, :foo)
621
+ deftemplate.slot_default_value('bar')
622
+ ```
623
+
574
624
  ### `CLIPS::Environment::Defmodule.get_deftemplate_list`
575
625
  ### `CLIPS::Environment::Defmodule#get_deftemplate_list`
576
626
 
@@ -611,6 +661,54 @@ CLIPS::Environment::Deffacts.pp_form(deffacts)
611
661
  deffacts.pp_form
612
662
  ```
613
663
 
664
+ ### `CLIPS::Environment.watch`
665
+ ### `env.watch`
666
+ ### `CLIPS::Environment.unwatch`
667
+ ### `env.unwatch`
668
+
669
+ "Watch" or "Unwatch" a specific thing that happens in the CLIPS environment.
670
+ There are several things that may be watched (or unwatched) such that CLIPS will
671
+ report debugging information to `STDOUT`. This gem provides two ways to watch
672
+ or unwatch a debug item: either pass the watch item as a symbol to `watch` or
673
+ `unwatch`, or use the corresponding `watch_foo` or `unwatch_foo` methods where
674
+ `foo` is replaced by the watch item (as listed):
675
+
676
+ ```ruby
677
+ :all
678
+ :facts
679
+ :instances
680
+ :slots
681
+ :rules
682
+ :activations
683
+ :messages
684
+ :message_handlers
685
+ :generic_functions
686
+ :methods
687
+ :deffunctions
688
+ :compilations
689
+ :statistics
690
+ :globals
691
+ :focus
692
+ ```
693
+
694
+ ```ruby
695
+ CLIPS::Environment.watch_facts
696
+ env.watch_statistics
697
+ CLIPS::Environment.unwatch(:facts)
698
+ env.unwatch(:statistics)
699
+ ```
700
+
701
+ ### `CLIPS::Environment.get_watch_state`
702
+ ### `env.get_watch_state`
703
+
704
+ Returns a bool representing whether or not the given debug item
705
+ is currently being watched in the environment.
706
+
707
+ ```ruby
708
+ CLIPS::Environment.get_watch_state(env, :facts)
709
+ env.get_watch_state(:methods)
710
+ ```
711
+
614
712
  ## Running the tests
615
713
 
616
714
  Simply do `rake compile` and then `rake test` in order to run the tests.
@@ -96,6 +96,21 @@ static VALUE clips_environment_fact_static_deftemplate_name(VALUE self, VALUE rb
96
96
  return clips_environment_fact_deftemplate_name(rbFact);
97
97
  }
98
98
 
99
+ static VALUE clips_environment_deftemplate_defmodule_name(VALUE self)
100
+ {
101
+ Deftemplate *template;
102
+
103
+ TypedData_Get_Struct(self, Deftemplate, &Deftemplate_type, template);
104
+
105
+ return ID2SYM(rb_intern(DeftemplateModule(template)));
106
+ }
107
+
108
+ static VALUE clips_environment_deftemplate_static_defmodule_name(VALUE self, VALUE rbDeftemplate)
109
+ {
110
+ return clips_environment_deftemplate_defmodule_name(rbDeftemplate);
111
+ }
112
+
113
+
99
114
  void environment_free(void *data)
100
115
  {
101
116
  DestroyEnvironment((Environment*) data);
@@ -736,6 +751,31 @@ static VALUE clips_environment_static_add_udf(int argc, VALUE *argv, VALUE klass
736
751
  return _clips_environment_add_udf(environment, method_name, clips_function_name);
737
752
  }
738
753
 
754
+ static VALUE clips_environment_deftemplate_slot_names(VALUE self)
755
+ {
756
+ Deftemplate *template;
757
+ Environment *env;
758
+ CLIPSValue value;
759
+ VALUE out;
760
+
761
+ VALUE rbEnvironment = rb_iv_get(self, "@environment");
762
+
763
+ TypedData_Get_Struct(self, Deftemplate, &Deftemplate_type, template);
764
+ TypedData_Get_Struct(rbEnvironment, Environment, &Environment_type, env);
765
+
766
+ DeftemplateSlotNames(template, &value);
767
+
768
+ CLIPSValue_to_VALUE(&value, &out, &rbEnvironment);
769
+
770
+ return out;
771
+ }
772
+
773
+ static VALUE clips_environment_deftemplate_static_slot_names(VALUE self, VALUE rbDeftemplate)
774
+ {
775
+ return clips_environment_deftemplate_slot_names(rbDeftemplate);
776
+ }
777
+
778
+
739
779
  static VALUE clips_environment_run(int argc, VALUE *argv, VALUE environment) {
740
780
  VALUE integer;
741
781
  Environment *env;
@@ -1195,6 +1235,71 @@ static VALUE clips_environment_fact_static_get_slot(VALUE self, VALUE rbFact, VA
1195
1235
  return clips_environment_fact_get_slot(rbFact, slot_name);
1196
1236
  }
1197
1237
 
1238
+ static VALUE clips_environment_deftemplate_slot_allowed_values(VALUE self, VALUE slot_name)
1239
+ {
1240
+ Deftemplate *template;
1241
+ CLIPSValue slot_allowed_values;
1242
+ VALUE rbEnvironment = rb_iv_get(self, "@environment");
1243
+
1244
+ TypedData_Get_Struct(self, Deftemplate, &Deftemplate_type, template);
1245
+
1246
+ switch (TYPE(slot_name)) {
1247
+ case T_STRING:
1248
+ DeftemplateSlotAllowedValues(template, StringValueCStr(slot_name), &slot_allowed_values);
1249
+ break;
1250
+ case T_SYMBOL:
1251
+ DeftemplateSlotAllowedValues(template, rb_id2name(SYM2ID(slot_name)), &slot_allowed_values);
1252
+ break;
1253
+ default:
1254
+ rb_warn("slot name must be string or symbol in call to slot_allowed_values!");
1255
+ return Qnil;
1256
+ }
1257
+
1258
+ VALUE out;
1259
+
1260
+ CLIPSValue_to_VALUE(&slot_allowed_values, &out, &rbEnvironment);
1261
+
1262
+ return out;
1263
+ }
1264
+
1265
+ static VALUE clips_environment_deftemplate_static_slot_allowed_values(VALUE self, VALUE rbDeftemplate, VALUE slot_name)
1266
+ {
1267
+ return clips_environment_deftemplate_slot_allowed_values(rbDeftemplate, slot_name);
1268
+ }
1269
+
1270
+ static VALUE clips_environment_deftemplate_slot_default_value(VALUE self, VALUE slot_name)
1271
+ {
1272
+ Deftemplate *template;
1273
+ CLIPSValue slot_default_value;
1274
+ VALUE rbEnvironment = rb_iv_get(self, "@environment");
1275
+
1276
+ TypedData_Get_Struct(self, Deftemplate, &Deftemplate_type, template);
1277
+
1278
+ switch (TYPE(slot_name)) {
1279
+ case T_STRING:
1280
+ DeftemplateSlotDefaultValue(template, StringValueCStr(slot_name), &slot_default_value);
1281
+ break;
1282
+ case T_SYMBOL:
1283
+ DeftemplateSlotDefaultValue(template, rb_id2name(SYM2ID(slot_name)), &slot_default_value);
1284
+ break;
1285
+ default:
1286
+ rb_warn("slot name must be string or symbol in call to slot_default_value!");
1287
+ return Qnil;
1288
+ }
1289
+
1290
+ VALUE out;
1291
+
1292
+ CLIPSValue_to_VALUE(&slot_default_value, &out, &rbEnvironment);
1293
+
1294
+ return out;
1295
+ }
1296
+
1297
+ static VALUE clips_environment_deftemplate_static_slot_default_value(VALUE self, VALUE rbDeftemplate, VALUE slot_name)
1298
+ {
1299
+ return clips_environment_deftemplate_slot_default_value(rbDeftemplate, slot_name);
1300
+ }
1301
+
1302
+
1198
1303
  static VALUE clips_environment_fact_retract(VALUE self)
1199
1304
  {
1200
1305
  Fact *fact;
@@ -1876,6 +1981,24 @@ static VALUE clips_environment_defrule_static_is_deletable(VALUE self, VALUE rbD
1876
1981
  return clips_environment_defrule_is_deletable(rbDefrule);
1877
1982
  }
1878
1983
 
1984
+ static VALUE clips_environment_deftemplate_is_deletable(VALUE self)
1985
+ {
1986
+ Deftemplate *deftemplate;
1987
+
1988
+ TypedData_Get_Struct(self, Deftemplate, &Deftemplate_type, deftemplate);
1989
+
1990
+ if (DeftemplateIsDeletable(deftemplate)) {
1991
+ return Qtrue;
1992
+ } else {
1993
+ return Qfalse;
1994
+ }
1995
+ }
1996
+
1997
+ static VALUE clips_environment_deftemplate_static_is_deletable(VALUE self, VALUE rbDeftemplate)
1998
+ {
1999
+ return clips_environment_deftemplate_is_deletable(rbDeftemplate);
2000
+ }
2001
+
1879
2002
  static VALUE clips_environment_defrule_has_breakpoint(VALUE self)
1880
2003
  {
1881
2004
  Defrule *defrule;
@@ -1928,6 +2051,644 @@ static VALUE clips_environment_defrule_static_remove_break(VALUE self, VALUE rbD
1928
2051
  return clips_environment_defrule_remove_break(rbDefrule);
1929
2052
  }
1930
2053
 
2054
+ static VALUE clips_environment_watch(VALUE self, VALUE item)
2055
+ {
2056
+ Environment *env;
2057
+ WatchItem watchItem;
2058
+
2059
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2060
+
2061
+ if (item == ID2SYM(rb_intern("all"))) {
2062
+ watchItem = ALL;
2063
+ } else if (item == ID2SYM(rb_intern("facts"))) {
2064
+ watchItem = FACTS;
2065
+ } else if (item == ID2SYM(rb_intern("instances"))) {
2066
+ watchItem = INSTANCES;
2067
+ } else if (item == ID2SYM(rb_intern("slots"))) {
2068
+ watchItem = SLOTS;
2069
+ } else if (item == ID2SYM(rb_intern("rules"))) {
2070
+ watchItem = RULES;
2071
+ } else if (item == ID2SYM(rb_intern("activations"))) {
2072
+ watchItem = ACTIVATIONS;
2073
+ } else if (item == ID2SYM(rb_intern("messages"))) {
2074
+ watchItem = MESSAGES;
2075
+ } else if (item == ID2SYM(rb_intern("message_handlers"))) {
2076
+ watchItem = MESSAGE_HANDLERS;
2077
+ } else if (item == ID2SYM(rb_intern("generic_functions"))) {
2078
+ watchItem = GENERIC_FUNCTIONS;
2079
+ } else if (item == ID2SYM(rb_intern("methods"))) {
2080
+ watchItem = METHODS;
2081
+ } else if (item == ID2SYM(rb_intern("deffunctions"))) {
2082
+ watchItem = DEFFUNCTIONS;
2083
+ } else if (item == ID2SYM(rb_intern("compilations"))) {
2084
+ watchItem = COMPILATIONS;
2085
+ } else if (item == ID2SYM(rb_intern("statistics"))) {
2086
+ watchItem = STATISTICS;
2087
+ } else if (item == ID2SYM(rb_intern("globals"))) {
2088
+ watchItem = GLOBALS;
2089
+ } else if (item == ID2SYM(rb_intern("focus"))) {
2090
+ watchItem = FOCUS;
2091
+ } else {
2092
+ rb_warn("unknown watch item");
2093
+ return Qnil;
2094
+ }
2095
+
2096
+ Watch(env, watchItem);
2097
+
2098
+ return Qnil;
2099
+ }
2100
+
2101
+ static VALUE clips_environment_static_watch(VALUE self, VALUE rbEnvironment, VALUE item)
2102
+ {
2103
+ return clips_environment_watch(rbEnvironment, item);
2104
+ }
2105
+
2106
+ static VALUE clips_environment_unwatch(VALUE self, VALUE item)
2107
+ {
2108
+ Environment *env;
2109
+ WatchItem watchItem;
2110
+
2111
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2112
+
2113
+ if (item == ID2SYM(rb_intern("all"))) {
2114
+ watchItem = ALL;
2115
+ } else if (item == ID2SYM(rb_intern("facts"))) {
2116
+ watchItem = FACTS;
2117
+ } else if (item == ID2SYM(rb_intern("instances"))) {
2118
+ watchItem = INSTANCES;
2119
+ } else if (item == ID2SYM(rb_intern("slots"))) {
2120
+ watchItem = SLOTS;
2121
+ } else if (item == ID2SYM(rb_intern("rules"))) {
2122
+ watchItem = RULES;
2123
+ } else if (item == ID2SYM(rb_intern("activations"))) {
2124
+ watchItem = ACTIVATIONS;
2125
+ } else if (item == ID2SYM(rb_intern("messages"))) {
2126
+ watchItem = MESSAGES;
2127
+ } else if (item == ID2SYM(rb_intern("message_handlers"))) {
2128
+ watchItem = MESSAGE_HANDLERS;
2129
+ } else if (item == ID2SYM(rb_intern("generic_functions"))) {
2130
+ watchItem = GENERIC_FUNCTIONS;
2131
+ } else if (item == ID2SYM(rb_intern("methods"))) {
2132
+ watchItem = METHODS;
2133
+ } else if (item == ID2SYM(rb_intern("deffunctions"))) {
2134
+ watchItem = DEFFUNCTIONS;
2135
+ } else if (item == ID2SYM(rb_intern("compilations"))) {
2136
+ watchItem = COMPILATIONS;
2137
+ } else if (item == ID2SYM(rb_intern("statistics"))) {
2138
+ watchItem = STATISTICS;
2139
+ } else if (item == ID2SYM(rb_intern("globals"))) {
2140
+ watchItem = GLOBALS;
2141
+ } else if (item == ID2SYM(rb_intern("focus"))) {
2142
+ watchItem = FOCUS;
2143
+ } else {
2144
+ rb_warn("unknown watch item");
2145
+ return Qnil;
2146
+ }
2147
+
2148
+ Unwatch(env, watchItem);
2149
+
2150
+ return Qnil;
2151
+ }
2152
+
2153
+ static VALUE clips_environment_static_unwatch(VALUE self, VALUE rbEnvironment, VALUE item)
2154
+ {
2155
+ return clips_environment_unwatch(rbEnvironment, item);
2156
+ }
2157
+
2158
+ static VALUE clips_environment_watch_all(VALUE self)
2159
+ {
2160
+ Environment *env;
2161
+
2162
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2163
+
2164
+ Watch(env, ALL);
2165
+
2166
+ return Qnil;
2167
+ }
2168
+
2169
+ static VALUE clips_environment_static_watch_all(VALUE self, VALUE rbEnvironment)
2170
+ {
2171
+ return clips_environment_watch_all(rbEnvironment);
2172
+ }
2173
+
2174
+ static VALUE clips_environment_watch_facts(VALUE self)
2175
+ {
2176
+ Environment *env;
2177
+
2178
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2179
+
2180
+ Watch(env, FACTS);
2181
+
2182
+ return Qnil;
2183
+ }
2184
+
2185
+ static VALUE clips_environment_static_watch_facts(VALUE self, VALUE rbEnvironment)
2186
+ {
2187
+ return clips_environment_watch_facts(rbEnvironment);
2188
+ }
2189
+
2190
+ static VALUE clips_environment_watch_instances(VALUE self)
2191
+ {
2192
+ Environment *env;
2193
+
2194
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2195
+
2196
+ Watch(env, INSTANCES);
2197
+
2198
+ return Qnil;
2199
+ }
2200
+
2201
+ static VALUE clips_environment_static_watch_instances(VALUE self, VALUE rbEnvironment)
2202
+ {
2203
+ return clips_environment_watch_instances(rbEnvironment);
2204
+ }
2205
+
2206
+ static VALUE clips_environment_watch_slots(VALUE self)
2207
+ {
2208
+ Environment *env;
2209
+
2210
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2211
+
2212
+ Watch(env, SLOTS);
2213
+
2214
+ return Qnil;
2215
+ }
2216
+
2217
+ static VALUE clips_environment_static_watch_slots(VALUE self, VALUE rbEnvironment)
2218
+ {
2219
+ return clips_environment_watch_slots(rbEnvironment);
2220
+ }
2221
+
2222
+ static VALUE clips_environment_watch_rules(VALUE self)
2223
+ {
2224
+ Environment *env;
2225
+
2226
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2227
+
2228
+ Watch(env, RULES);
2229
+
2230
+ return Qnil;
2231
+ }
2232
+
2233
+ static VALUE clips_environment_static_watch_rules(VALUE self, VALUE rbEnvironment)
2234
+ {
2235
+ return clips_environment_watch_rules(rbEnvironment);
2236
+ }
2237
+
2238
+ static VALUE clips_environment_watch_activations(VALUE self)
2239
+ {
2240
+ Environment *env;
2241
+
2242
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2243
+
2244
+ Watch(env, ACTIVATIONS);
2245
+
2246
+ return Qnil;
2247
+ }
2248
+
2249
+ static VALUE clips_environment_static_watch_activations(VALUE self, VALUE rbEnvironment)
2250
+ {
2251
+ return clips_environment_watch_activations(rbEnvironment);
2252
+ }
2253
+
2254
+ static VALUE clips_environment_watch_messages(VALUE self)
2255
+ {
2256
+ Environment *env;
2257
+
2258
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2259
+
2260
+ Watch(env, MESSAGES);
2261
+
2262
+ return Qnil;
2263
+ }
2264
+
2265
+ static VALUE clips_environment_static_watch_messages(VALUE self, VALUE rbEnvironment)
2266
+ {
2267
+ return clips_environment_watch_messages(rbEnvironment);
2268
+ }
2269
+
2270
+ static VALUE clips_environment_watch_message_handlers(VALUE self)
2271
+ {
2272
+ Environment *env;
2273
+
2274
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2275
+
2276
+ Watch(env, MESSAGE_HANDLERS);
2277
+
2278
+ return Qnil;
2279
+ }
2280
+
2281
+ static VALUE clips_environment_static_watch_message_handlers(VALUE self, VALUE rbEnvironment)
2282
+ {
2283
+ return clips_environment_watch_message_handlers(rbEnvironment);
2284
+ }
2285
+
2286
+ static VALUE clips_environment_watch_generic_functions(VALUE self)
2287
+ {
2288
+ Environment *env;
2289
+
2290
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2291
+
2292
+ Watch(env, GENERIC_FUNCTIONS);
2293
+
2294
+ return Qnil;
2295
+ }
2296
+
2297
+ static VALUE clips_environment_static_watch_generic_functions(VALUE self, VALUE rbEnvironment)
2298
+ {
2299
+ return clips_environment_watch_generic_functions(rbEnvironment);
2300
+ }
2301
+
2302
+ static VALUE clips_environment_watch_methods(VALUE self)
2303
+ {
2304
+ Environment *env;
2305
+
2306
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2307
+
2308
+ Watch(env, METHODS);
2309
+
2310
+ return Qnil;
2311
+ }
2312
+
2313
+ static VALUE clips_environment_static_watch_methods(VALUE self, VALUE rbEnvironment)
2314
+ {
2315
+ return clips_environment_watch_methods(rbEnvironment);
2316
+ }
2317
+
2318
+ static VALUE clips_environment_watch_deffunctions(VALUE self)
2319
+ {
2320
+ Environment *env;
2321
+
2322
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2323
+
2324
+ Watch(env, DEFFUNCTIONS);
2325
+
2326
+ return Qnil;
2327
+ }
2328
+
2329
+ static VALUE clips_environment_static_watch_deffunctions(VALUE self, VALUE rbEnvironment)
2330
+ {
2331
+ return clips_environment_watch_deffunctions(rbEnvironment);
2332
+ }
2333
+
2334
+ static VALUE clips_environment_watch_compilations(VALUE self)
2335
+ {
2336
+ Environment *env;
2337
+
2338
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2339
+
2340
+ Watch(env, COMPILATIONS);
2341
+
2342
+ return Qnil;
2343
+ }
2344
+
2345
+ static VALUE clips_environment_static_watch_compilations(VALUE self, VALUE rbEnvironment)
2346
+ {
2347
+ return clips_environment_watch_compilations(rbEnvironment);
2348
+ }
2349
+
2350
+ static VALUE clips_environment_watch_statistics(VALUE self)
2351
+ {
2352
+ Environment *env;
2353
+
2354
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2355
+
2356
+ Watch(env, STATISTICS);
2357
+
2358
+ return Qnil;
2359
+ }
2360
+
2361
+ static VALUE clips_environment_static_watch_statistics(VALUE self, VALUE rbEnvironment)
2362
+ {
2363
+ return clips_environment_watch_statistics(rbEnvironment);
2364
+ }
2365
+
2366
+ static VALUE clips_environment_watch_globals(VALUE self)
2367
+ {
2368
+ Environment *env;
2369
+
2370
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2371
+
2372
+ Watch(env, GLOBALS);
2373
+
2374
+ return Qnil;
2375
+ }
2376
+
2377
+ static VALUE clips_environment_static_watch_globals(VALUE self, VALUE rbEnvironment)
2378
+ {
2379
+ return clips_environment_watch_globals(rbEnvironment);
2380
+ }
2381
+
2382
+ static VALUE clips_environment_watch_focus(VALUE self)
2383
+ {
2384
+ Environment *env;
2385
+
2386
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2387
+
2388
+ Watch(env, FOCUS);
2389
+
2390
+ return Qnil;
2391
+ }
2392
+
2393
+ static VALUE clips_environment_static_watch_focus(VALUE self, VALUE rbEnvironment)
2394
+ {
2395
+ return clips_environment_watch_focus(rbEnvironment);
2396
+ }
2397
+
2398
+ static VALUE clips_environment_unwatch_all(VALUE self)
2399
+ {
2400
+ Environment *env;
2401
+
2402
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2403
+
2404
+ Unwatch(env, ALL);
2405
+
2406
+ return Qnil;
2407
+ }
2408
+
2409
+ static VALUE clips_environment_static_unwatch_all(VALUE self, VALUE rbEnvironment)
2410
+ {
2411
+ return clips_environment_unwatch_all(rbEnvironment);
2412
+ }
2413
+
2414
+ static VALUE clips_environment_unwatch_facts(VALUE self)
2415
+ {
2416
+ Environment *env;
2417
+
2418
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2419
+
2420
+ Unwatch(env, FACTS);
2421
+
2422
+ return Qnil;
2423
+ }
2424
+
2425
+ static VALUE clips_environment_static_unwatch_facts(VALUE self, VALUE rbEnvironment)
2426
+ {
2427
+ return clips_environment_unwatch_facts(rbEnvironment);
2428
+ }
2429
+
2430
+ static VALUE clips_environment_unwatch_instances(VALUE self)
2431
+ {
2432
+ Environment *env;
2433
+
2434
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2435
+
2436
+ Unwatch(env, INSTANCES);
2437
+
2438
+ return Qnil;
2439
+ }
2440
+
2441
+ static VALUE clips_environment_static_unwatch_instances(VALUE self, VALUE rbEnvironment)
2442
+ {
2443
+ return clips_environment_unwatch_instances(rbEnvironment);
2444
+ }
2445
+
2446
+ static VALUE clips_environment_unwatch_slots(VALUE self)
2447
+ {
2448
+ Environment *env;
2449
+
2450
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2451
+
2452
+ Unwatch(env, SLOTS);
2453
+
2454
+ return Qnil;
2455
+ }
2456
+
2457
+ static VALUE clips_environment_static_unwatch_slots(VALUE self, VALUE rbEnvironment)
2458
+ {
2459
+ return clips_environment_unwatch_slots(rbEnvironment);
2460
+ }
2461
+
2462
+ static VALUE clips_environment_unwatch_rules(VALUE self)
2463
+ {
2464
+ Environment *env;
2465
+
2466
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2467
+
2468
+ Unwatch(env, RULES);
2469
+
2470
+ return Qnil;
2471
+ }
2472
+
2473
+ static VALUE clips_environment_static_unwatch_rules(VALUE self, VALUE rbEnvironment)
2474
+ {
2475
+ return clips_environment_unwatch_rules(rbEnvironment);
2476
+ }
2477
+
2478
+ static VALUE clips_environment_unwatch_activations(VALUE self)
2479
+ {
2480
+ Environment *env;
2481
+
2482
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2483
+
2484
+ Unwatch(env, ACTIVATIONS);
2485
+
2486
+ return Qnil;
2487
+ }
2488
+
2489
+ static VALUE clips_environment_static_unwatch_activations(VALUE self, VALUE rbEnvironment)
2490
+ {
2491
+ return clips_environment_unwatch_activations(rbEnvironment);
2492
+ }
2493
+
2494
+ static VALUE clips_environment_unwatch_messages(VALUE self)
2495
+ {
2496
+ Environment *env;
2497
+
2498
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2499
+
2500
+ Unwatch(env, MESSAGES);
2501
+
2502
+ return Qnil;
2503
+ }
2504
+
2505
+ static VALUE clips_environment_static_unwatch_messages(VALUE self, VALUE rbEnvironment)
2506
+ {
2507
+ return clips_environment_unwatch_messages(rbEnvironment);
2508
+ }
2509
+
2510
+ static VALUE clips_environment_unwatch_message_handlers(VALUE self)
2511
+ {
2512
+ Environment *env;
2513
+
2514
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2515
+
2516
+ Unwatch(env, MESSAGE_HANDLERS);
2517
+
2518
+ return Qnil;
2519
+ }
2520
+
2521
+ static VALUE clips_environment_static_unwatch_message_handlers(VALUE self, VALUE rbEnvironment)
2522
+ {
2523
+ return clips_environment_unwatch_message_handlers(rbEnvironment);
2524
+ }
2525
+
2526
+ static VALUE clips_environment_unwatch_generic_functions(VALUE self)
2527
+ {
2528
+ Environment *env;
2529
+
2530
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2531
+
2532
+ Unwatch(env, GENERIC_FUNCTIONS);
2533
+
2534
+ return Qnil;
2535
+ }
2536
+
2537
+ static VALUE clips_environment_static_unwatch_generic_functions(VALUE self, VALUE rbEnvironment)
2538
+ {
2539
+ return clips_environment_unwatch_generic_functions(rbEnvironment);
2540
+ }
2541
+
2542
+ static VALUE clips_environment_unwatch_methods(VALUE self)
2543
+ {
2544
+ Environment *env;
2545
+
2546
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2547
+
2548
+ Unwatch(env, METHODS);
2549
+
2550
+ return Qnil;
2551
+ }
2552
+
2553
+ static VALUE clips_environment_static_unwatch_methods(VALUE self, VALUE rbEnvironment)
2554
+ {
2555
+ return clips_environment_unwatch_methods(rbEnvironment);
2556
+ }
2557
+
2558
+ static VALUE clips_environment_unwatch_deffunctions(VALUE self)
2559
+ {
2560
+ Environment *env;
2561
+
2562
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2563
+
2564
+ Unwatch(env, DEFFUNCTIONS);
2565
+
2566
+ return Qnil;
2567
+ }
2568
+
2569
+ static VALUE clips_environment_static_unwatch_deffunctions(VALUE self, VALUE rbEnvironment)
2570
+ {
2571
+ return clips_environment_unwatch_deffunctions(rbEnvironment);
2572
+ }
2573
+
2574
+ static VALUE clips_environment_unwatch_compilations(VALUE self)
2575
+ {
2576
+ Environment *env;
2577
+
2578
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2579
+
2580
+ Unwatch(env, COMPILATIONS);
2581
+
2582
+ return Qnil;
2583
+ }
2584
+
2585
+ static VALUE clips_environment_static_unwatch_compilations(VALUE self, VALUE rbEnvironment)
2586
+ {
2587
+ return clips_environment_unwatch_compilations(rbEnvironment);
2588
+ }
2589
+
2590
+ static VALUE clips_environment_unwatch_statistics(VALUE self)
2591
+ {
2592
+ Environment *env;
2593
+
2594
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2595
+
2596
+ Unwatch(env, STATISTICS);
2597
+
2598
+ return Qnil;
2599
+ }
2600
+
2601
+ static VALUE clips_environment_static_unwatch_statistics(VALUE self, VALUE rbEnvironment)
2602
+ {
2603
+ return clips_environment_unwatch_statistics(rbEnvironment);
2604
+ }
2605
+
2606
+ static VALUE clips_environment_unwatch_globals(VALUE self)
2607
+ {
2608
+ Environment *env;
2609
+
2610
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2611
+
2612
+ Unwatch(env, GLOBALS);
2613
+
2614
+ return Qnil;
2615
+ }
2616
+
2617
+ static VALUE clips_environment_static_unwatch_globals(VALUE self, VALUE rbEnvironment)
2618
+ {
2619
+ return clips_environment_unwatch_globals(rbEnvironment);
2620
+ }
2621
+
2622
+ static VALUE clips_environment_unwatch_focus(VALUE self)
2623
+ {
2624
+ Environment *env;
2625
+
2626
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2627
+
2628
+ Unwatch(env, FOCUS);
2629
+
2630
+ return Qnil;
2631
+ }
2632
+
2633
+ static VALUE clips_environment_static_unwatch_focus(VALUE self, VALUE rbEnvironment)
2634
+ {
2635
+ return clips_environment_unwatch_focus(rbEnvironment);
2636
+ }
2637
+
2638
+ static VALUE clips_environment_get_watch_state(VALUE self, VALUE item)
2639
+ {
2640
+ Environment *env;
2641
+ WatchItem watchItem;
2642
+
2643
+ TypedData_Get_Struct(self, Environment, &Environment_type, env);
2644
+
2645
+ if (item == ID2SYM(rb_intern("all"))) {
2646
+ watchItem = ALL;
2647
+ } else if (item == ID2SYM(rb_intern("facts"))) {
2648
+ watchItem = FACTS;
2649
+ } else if (item == ID2SYM(rb_intern("instances"))) {
2650
+ watchItem = INSTANCES;
2651
+ } else if (item == ID2SYM(rb_intern("slots"))) {
2652
+ watchItem = SLOTS;
2653
+ } else if (item == ID2SYM(rb_intern("rules"))) {
2654
+ watchItem = RULES;
2655
+ } else if (item == ID2SYM(rb_intern("activations"))) {
2656
+ watchItem = ACTIVATIONS;
2657
+ } else if (item == ID2SYM(rb_intern("messages"))) {
2658
+ watchItem = MESSAGES;
2659
+ } else if (item == ID2SYM(rb_intern("message_handlers"))) {
2660
+ watchItem = MESSAGE_HANDLERS;
2661
+ } else if (item == ID2SYM(rb_intern("generic_functions"))) {
2662
+ watchItem = GENERIC_FUNCTIONS;
2663
+ } else if (item == ID2SYM(rb_intern("methods"))) {
2664
+ watchItem = METHODS;
2665
+ } else if (item == ID2SYM(rb_intern("deffunctions"))) {
2666
+ watchItem = DEFFUNCTIONS;
2667
+ } else if (item == ID2SYM(rb_intern("compilations"))) {
2668
+ watchItem = COMPILATIONS;
2669
+ } else if (item == ID2SYM(rb_intern("statistics"))) {
2670
+ watchItem = STATISTICS;
2671
+ } else if (item == ID2SYM(rb_intern("globals"))) {
2672
+ watchItem = GLOBALS;
2673
+ } else if (item == ID2SYM(rb_intern("focus"))) {
2674
+ watchItem = FOCUS;
2675
+ } else {
2676
+ rb_warn("unknown watch item");
2677
+ return Qnil;
2678
+ }
2679
+
2680
+ if (GetWatchState(env, watchItem)) {
2681
+ return Qtrue;
2682
+ } else {
2683
+ return Qfalse;
2684
+ }
2685
+ }
2686
+
2687
+ static VALUE clips_environment_static_get_watch_state(VALUE self, VALUE rbEnvironment, VALUE item)
2688
+ {
2689
+ return clips_environment_get_watch_state(rbEnvironment, item);
2690
+ }
2691
+
1931
2692
  void Init_clipsruby(void)
1932
2693
  {
1933
2694
  VALUE rbCLIPS = rb_define_module("CLIPS");
@@ -1991,6 +2752,72 @@ void Init_clipsruby(void)
1991
2752
  rb_define_method(rbEnvironment, "get_deftemplate_list", clips_environment_get_deftemplate_list, -1);
1992
2753
  rb_define_singleton_method(rbEnvironment, "find_deffacts", clips_environment_static_find_deffacts, 2);
1993
2754
  rb_define_method(rbEnvironment, "find_deffacts", clips_environment_find_deffacts, 1);
2755
+ rb_define_singleton_method(rbEnvironment, "watch", clips_environment_static_watch, 2);
2756
+ rb_define_method(rbEnvironment, "watch", clips_environment_watch, 1);
2757
+ rb_define_singleton_method(rbEnvironment, "watch_all", clips_environment_static_watch_all, 1);
2758
+ rb_define_method(rbEnvironment, "watch_all", clips_environment_watch_all, 0);
2759
+ rb_define_singleton_method(rbEnvironment, "watch_facts", clips_environment_static_watch_facts, 1);
2760
+ rb_define_method(rbEnvironment, "watch_facts", clips_environment_watch_facts, 0);
2761
+ rb_define_singleton_method(rbEnvironment, "watch_instances", clips_environment_static_watch_instances, 1);
2762
+ rb_define_method(rbEnvironment, "watch_instances", clips_environment_watch_instances, 0);
2763
+ rb_define_singleton_method(rbEnvironment, "watch_slots", clips_environment_static_watch_slots, 1);
2764
+ rb_define_method(rbEnvironment, "watch_slots", clips_environment_watch_slots, 0);
2765
+ rb_define_singleton_method(rbEnvironment, "watch_rules", clips_environment_static_watch_rules, 1);
2766
+ rb_define_method(rbEnvironment, "watch_rules", clips_environment_watch_rules, 0);
2767
+ rb_define_singleton_method(rbEnvironment, "watch_activations", clips_environment_static_watch_activations, 1);
2768
+ rb_define_method(rbEnvironment, "watch_activations", clips_environment_watch_activations, 0);
2769
+ rb_define_singleton_method(rbEnvironment, "watch_messages", clips_environment_static_watch_messages, 1);
2770
+ rb_define_method(rbEnvironment, "watch_messages", clips_environment_watch_messages, 0);
2771
+ rb_define_singleton_method(rbEnvironment, "watch_message_handlers", clips_environment_static_watch_message_handlers, 1);
2772
+ rb_define_method(rbEnvironment, "watch_message_handlers", clips_environment_watch_message_handlers, 0);
2773
+ rb_define_singleton_method(rbEnvironment, "watch_generic_functions", clips_environment_static_watch_generic_functions, 1);
2774
+ rb_define_method(rbEnvironment, "watch_generic_functions", clips_environment_watch_generic_functions, 0);
2775
+ rb_define_singleton_method(rbEnvironment, "watch_methods", clips_environment_static_watch_methods, 1);
2776
+ rb_define_method(rbEnvironment, "watch_methods", clips_environment_watch_methods, 0);
2777
+ rb_define_singleton_method(rbEnvironment, "watch_deffunctions", clips_environment_static_watch_deffunctions, 1);
2778
+ rb_define_method(rbEnvironment, "watch_deffunctions", clips_environment_watch_deffunctions, 0);
2779
+ rb_define_singleton_method(rbEnvironment, "watch_compilations", clips_environment_static_watch_compilations, 1);
2780
+ rb_define_method(rbEnvironment, "watch_compilations", clips_environment_watch_compilations, 0);
2781
+ rb_define_singleton_method(rbEnvironment, "watch_statistics", clips_environment_static_watch_statistics, 1);
2782
+ rb_define_method(rbEnvironment, "watch_statistics", clips_environment_watch_statistics, 0);
2783
+ rb_define_singleton_method(rbEnvironment, "watch_globals", clips_environment_static_watch_globals, 1);
2784
+ rb_define_method(rbEnvironment, "watch_globals", clips_environment_watch_globals, 0);
2785
+ rb_define_singleton_method(rbEnvironment, "watch_focus", clips_environment_static_watch_focus, 1);
2786
+ rb_define_method(rbEnvironment, "watch_focus", clips_environment_watch_focus, 0);
2787
+ rb_define_singleton_method(rbEnvironment, "unwatch", clips_environment_static_unwatch, 2);
2788
+ rb_define_method(rbEnvironment, "unwatch", clips_environment_unwatch, 1);
2789
+ rb_define_singleton_method(rbEnvironment, "unwatch_all", clips_environment_static_unwatch_all, 1);
2790
+ rb_define_method(rbEnvironment, "unwatch_all", clips_environment_unwatch_all, 0);
2791
+ rb_define_singleton_method(rbEnvironment, "unwatch_facts", clips_environment_static_unwatch_facts, 1);
2792
+ rb_define_method(rbEnvironment, "unwatch_facts", clips_environment_unwatch_facts, 0);
2793
+ rb_define_singleton_method(rbEnvironment, "unwatch_instances", clips_environment_static_unwatch_instances, 1);
2794
+ rb_define_method(rbEnvironment, "unwatch_instances", clips_environment_unwatch_instances, 0);
2795
+ rb_define_singleton_method(rbEnvironment, "unwatch_slots", clips_environment_static_unwatch_slots, 1);
2796
+ rb_define_method(rbEnvironment, "unwatch_slots", clips_environment_unwatch_slots, 0);
2797
+ rb_define_singleton_method(rbEnvironment, "unwatch_rules", clips_environment_static_unwatch_rules, 1);
2798
+ rb_define_method(rbEnvironment, "unwatch_rules", clips_environment_unwatch_rules, 0);
2799
+ rb_define_singleton_method(rbEnvironment, "unwatch_activations", clips_environment_static_unwatch_activations, 1);
2800
+ rb_define_method(rbEnvironment, "unwatch_activations", clips_environment_unwatch_activations, 0);
2801
+ rb_define_singleton_method(rbEnvironment, "unwatch_messages", clips_environment_static_unwatch_messages, 1);
2802
+ rb_define_method(rbEnvironment, "unwatch_messages", clips_environment_unwatch_messages, 0);
2803
+ rb_define_singleton_method(rbEnvironment, "unwatch_message_handlers", clips_environment_static_unwatch_message_handlers, 1);
2804
+ rb_define_method(rbEnvironment, "unwatch_message_handlers", clips_environment_unwatch_message_handlers, 0);
2805
+ rb_define_singleton_method(rbEnvironment, "unwatch_generic_functions", clips_environment_static_unwatch_generic_functions, 1);
2806
+ rb_define_method(rbEnvironment, "unwatch_generic_functions", clips_environment_unwatch_generic_functions, 0);
2807
+ rb_define_singleton_method(rbEnvironment, "unwatch_methods", clips_environment_static_unwatch_methods, 1);
2808
+ rb_define_method(rbEnvironment, "unwatch_methods", clips_environment_unwatch_methods, 0);
2809
+ rb_define_singleton_method(rbEnvironment, "unwatch_deffunctions", clips_environment_static_unwatch_deffunctions, 1);
2810
+ rb_define_method(rbEnvironment, "unwatch_deffunctions", clips_environment_unwatch_deffunctions, 0);
2811
+ rb_define_singleton_method(rbEnvironment, "unwatch_compilations", clips_environment_static_unwatch_compilations, 1);
2812
+ rb_define_method(rbEnvironment, "unwatch_compilations", clips_environment_unwatch_compilations, 0);
2813
+ rb_define_singleton_method(rbEnvironment, "unwatch_statistics", clips_environment_static_unwatch_statistics, 1);
2814
+ rb_define_method(rbEnvironment, "unwatch_statistics", clips_environment_unwatch_statistics, 0);
2815
+ rb_define_singleton_method(rbEnvironment, "unwatch_globals", clips_environment_static_unwatch_globals, 1);
2816
+ rb_define_method(rbEnvironment, "unwatch_globals", clips_environment_unwatch_globals, 0);
2817
+ rb_define_singleton_method(rbEnvironment, "unwatch_focus", clips_environment_static_unwatch_focus, 1);
2818
+ rb_define_method(rbEnvironment, "unwatch_focus", clips_environment_unwatch_focus, 0);
2819
+ rb_define_singleton_method(rbEnvironment, "get_watch_state", clips_environment_static_get_watch_state, 2);
2820
+ rb_define_method(rbEnvironment, "get_watch_state", clips_environment_get_watch_state, 1);
1994
2821
 
1995
2822
  VALUE rbDeffacts = rb_define_class_under(rbEnvironment, "Deffacts", rb_cObject);
1996
2823
  rb_define_alloc_func(rbDeffacts, deffacts_alloc);
@@ -2007,6 +2834,16 @@ void Init_clipsruby(void)
2007
2834
  rb_define_method(rbDeftemplate, "pp_form", clips_environment_deftemplate_pp_form, 0);
2008
2835
  rb_define_singleton_method(rbDeftemplate, "assert_hash", clips_environment_deftemplate_static_assert_hash, 2);
2009
2836
  rb_define_method(rbDeftemplate, "assert_hash", clips_environment_deftemplate_assert_hash, 1);
2837
+ rb_define_singleton_method(rbDeftemplate, "defmodule_name", clips_environment_deftemplate_static_defmodule_name, 1);
2838
+ rb_define_method(rbDeftemplate, "defmodule_name", clips_environment_deftemplate_defmodule_name, 0);
2839
+ rb_define_singleton_method(rbDeftemplate, "slot_names", clips_environment_deftemplate_static_slot_names, 1);
2840
+ rb_define_method(rbDeftemplate, "slot_names", clips_environment_deftemplate_slot_names, 0);
2841
+ rb_define_singleton_method(rbDeftemplate, "is_deletable", clips_environment_deftemplate_static_is_deletable, 1);
2842
+ rb_define_method(rbDeftemplate, "is_deletable", clips_environment_deftemplate_is_deletable, 0);
2843
+ rb_define_singleton_method(rbDeftemplate, "slot_allowed_values", clips_environment_deftemplate_static_slot_allowed_values, 2);
2844
+ rb_define_method(rbDeftemplate, "slot_allowed_values", clips_environment_deftemplate_slot_allowed_values, 1);
2845
+ rb_define_singleton_method(rbDeftemplate, "slot_default_value", clips_environment_deftemplate_static_slot_default_value, 2);
2846
+ rb_define_method(rbDeftemplate, "slot_default_value", clips_environment_deftemplate_slot_default_value, 1);
2010
2847
 
2011
2848
  VALUE rbDefmodule = rb_define_class_under(rbEnvironment, "Defmodule", rb_cObject);
2012
2849
  rb_define_alloc_func(rbDefmodule, defmodule_alloc);
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clipsruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.23
4
+ version: 0.0.25
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-14 00:00:00.000000000 Z
11
+ date: 2024-09-16 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