rubylog 1.0.0 → 2.0pre1

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 (163) hide show
  1. data/Gemfile +3 -12
  2. data/Gemfile.lock +22 -48
  3. data/README.rdoc +38 -38
  4. data/README.rdoc.orig +284 -0
  5. data/RELEASE_NOTES.rdoc +51 -0
  6. data/Rakefile +14 -18
  7. data/TODO.txt +0 -0
  8. data/VERSION +1 -1
  9. data/examples/a_plus_b.rb +6 -0
  10. data/examples/checkmate.rb +88 -0
  11. data/examples/combination.rb +17 -0
  12. data/examples/dcg.rb +3 -2
  13. data/examples/dcg2.rb +2 -2
  14. data/{logic → examples}/directory_structure_logic.rb +3 -5
  15. data/examples/dirlist.rb +4 -0
  16. data/examples/divisors.rb +6 -0
  17. data/examples/enumerators.rb +3 -3
  18. data/examples/factorial.rb +2 -3
  19. data/examples/file_search.rb +14 -0
  20. data/examples/hanoi.rb +4 -5
  21. data/examples/hello.rb +6 -4
  22. data/examples/mice.rb +92 -0
  23. data/examples/mice2.rb +19 -0
  24. data/examples/n_queens.rb +32 -0
  25. data/examples/object_oriented.rb +14 -0
  26. data/examples/palindrome_detection.rb +18 -0
  27. data/examples/parsing.rb +6 -4
  28. data/examples/permutation.rb +12 -0
  29. data/examples/prefix.rb +13 -0
  30. data/examples/primality_by_division.rb +22 -0
  31. data/examples/primitives.rb +10 -8
  32. data/examples/sieve_of_eratosthenes.rb +14 -0
  33. data/examples/string_interpolation.rb +4 -0
  34. data/examples/sudoku.rb +52 -0
  35. data/examples/tracing.rb +19 -0
  36. data/lib/rspec/rubylog.rb +29 -0
  37. data/lib/rubylog/assertable.rb +24 -0
  38. data/lib/rubylog/builtins/arithmetics.rb +63 -0
  39. data/lib/rubylog/builtins/assumption.rb +71 -0
  40. data/lib/rubylog/builtins/ensure.rb +13 -0
  41. data/lib/rubylog/builtins/file_system.rb +30 -8
  42. data/lib/rubylog/builtins/logic.rb +69 -38
  43. data/lib/rubylog/builtins/reflection.rb +35 -50
  44. data/lib/rubylog/builtins/term.rb +15 -17
  45. data/lib/rubylog/builtins.rb +11 -0
  46. data/lib/rubylog/clause.rb +19 -0
  47. data/lib/rubylog/{interfaces/composite_term.rb → compound_term.rb} +3 -3
  48. data/lib/rubylog/context.rb +24 -0
  49. data/lib/rubylog/context_creation.rb +71 -0
  50. data/lib/rubylog/context_modules/checks.rb +35 -0
  51. data/lib/rubylog/context_modules/demonstration.rb +16 -0
  52. data/lib/rubylog/context_modules/predicates.rb +86 -0
  53. data/lib/rubylog/context_modules/primitives.rb +18 -0
  54. data/lib/rubylog/context_modules/thats.rb +13 -0
  55. data/lib/rubylog/default_context.rb +9 -0
  56. data/lib/rubylog/dsl/array_splat.rb +11 -3
  57. data/lib/rubylog/dsl/primitives.rb +24 -12
  58. data/lib/rubylog/dsl/thats.rb +6 -0
  59. data/lib/rubylog/dsl/variables.rb +56 -21
  60. data/lib/rubylog/errors.rb +26 -15
  61. data/lib/rubylog/mixins/array.rb +95 -62
  62. data/lib/rubylog/mixins/kernel.rb +3 -2
  63. data/lib/rubylog/mixins/method.rb +0 -1
  64. data/lib/rubylog/mixins/object.rb +2 -1
  65. data/lib/rubylog/mixins/proc.rb +9 -12
  66. data/lib/rubylog/mixins/string.rb +15 -23
  67. data/lib/rubylog/mixins/symbol.rb +7 -24
  68. data/lib/rubylog/nullary_predicates.rb +3 -0
  69. data/lib/rubylog/predicate.rb +53 -0
  70. data/lib/rubylog/primitive.rb +15 -0
  71. data/lib/rubylog/procedure.rb +42 -0
  72. data/lib/rubylog/rule.rb +24 -0
  73. data/lib/rubylog/structure.rb +19 -38
  74. data/lib/rubylog/{interfaces/term.rb → term.rb} +2 -7
  75. data/lib/rubylog/tracing.rb +75 -0
  76. data/lib/rubylog/variable.rb +31 -12
  77. data/lib/rubylog.rb +36 -32
  78. data/rubylog.gemspec +92 -84
  79. data/spec/inriasuite_spec.rb +906 -9
  80. data/spec/integration/custom_classes_spec.rb +61 -0
  81. data/spec/integration/dsl_spec.rb +38 -0
  82. data/spec/integration/recursion_spec.rb +14 -0
  83. data/spec/integration/theory_as_module_spec.rb +20 -0
  84. data/spec/integration/theory_as_module_with_include_spec.rb +14 -0
  85. data/spec/rspec/rubylog_spec.rb +75 -0
  86. data/spec/rubylog/assertable_spec.rb +111 -0
  87. data/spec/rubylog/builtins/arithmetics_spec.rb +94 -0
  88. data/spec/rubylog/builtins/assumption_spec.rb +70 -0
  89. data/spec/rubylog/builtins/ensure_spec.rb +8 -0
  90. data/spec/rubylog/builtins/file_system_spec.rb +40 -0
  91. data/spec/rubylog/builtins/logic_spec.rb +340 -0
  92. data/spec/rubylog/builtins/reflection_spec.rb +43 -0
  93. data/spec/rubylog/builtins/term_spec.rb +85 -0
  94. data/spec/rubylog/context_modules/demonstration_spec.rb +132 -0
  95. data/spec/rubylog/context_modules/predicates_spec.rb +57 -0
  96. data/spec/rubylog/context_modules/thats_spec.rb +94 -0
  97. data/spec/rubylog/dsl/array_splat_spec.rb +15 -0
  98. data/spec/rubylog/dsl/primitives_spec.rb +43 -0
  99. data/spec/rubylog/errors_spec.rb +18 -0
  100. data/spec/{unification_spec.rb → rubylog/interfaces/term_spec.rb} +8 -9
  101. data/spec/rubylog/mixins/array_spec.rb +80 -0
  102. data/spec/rubylog/mixins/composite_term_spec.rb +66 -0
  103. data/spec/rubylog/mixins/proc_spec.rb +59 -0
  104. data/spec/rubylog/mixins/string_spec.rb +48 -0
  105. data/spec/rubylog/mixins/symbol_spec.rb +9 -0
  106. data/spec/{clause_spec.rb → rubylog/structure_spec.rb} +16 -15
  107. data/spec/rubylog/term_spec.rb +7 -0
  108. data/spec/rubylog/tracing_spec.input +27 -0
  109. data/spec/rubylog/tracing_spec.rb +44 -0
  110. data/spec/rubylog/variable_spec.rb +279 -0
  111. data/spec/spec_helper.rb +1 -0
  112. data/vimrc +11 -0
  113. metadata +103 -123
  114. data/README.hu.rb +0 -58
  115. data/bin/rubylog +0 -18
  116. data/examples/theory.rb +0 -32
  117. data/lib/rubylog/builtins/default.rb +0 -10
  118. data/lib/rubylog/dsl.rb +0 -70
  119. data/lib/rubylog/interfaces/assertable.rb +0 -16
  120. data/lib/rubylog/interfaces/callable.rb +0 -18
  121. data/lib/rubylog/interfaces/predicate.rb +0 -8
  122. data/lib/rubylog/interfaces/procedure.rb +0 -60
  123. data/lib/rubylog/mixins/class.rb +0 -11
  124. data/lib/rubylog/simple_procedure.rb +0 -8
  125. data/lib/rubylog/theory.rb +0 -422
  126. data/logic/builtins/file_system_logic.rb +0 -23
  127. data/logic/builtins/reflection_logic.rb +0 -40
  128. data/logic/dereference_logic.rb +0 -23
  129. data/logic/dsl_logic.rb +0 -29
  130. data/logic/errors_logic.rb +0 -9
  131. data/logic/guard_logic.rb +0 -115
  132. data/logic/list_logic.rb +0 -55
  133. data/logic/map_logic.rb +0 -15
  134. data/logic/multitheory.rb +0 -23
  135. data/logic/recursion_logic.rb +0 -12
  136. data/logic/string_logic.rb +0 -41
  137. data/logic/thats_logic.rb +0 -51
  138. data/logic/variable_logic.rb +0 -24
  139. data/spec/bartak_guide_spec.rb +0 -86
  140. data/spec/builtins/all_spec.rb +0 -99
  141. data/spec/builtins/and_spec.rb +0 -22
  142. data/spec/builtins/array_spec.rb +0 -16
  143. data/spec/builtins/branch_or_spec.rb +0 -27
  144. data/spec/builtins/cut_spec.rb +0 -44
  145. data/spec/builtins/fail_spec.rb +0 -5
  146. data/spec/builtins/false_spec.rb +0 -5
  147. data/spec/builtins/in_spec.rb +0 -38
  148. data/spec/builtins/is_false_spec.rb +0 -12
  149. data/spec/builtins/is_spec.rb +0 -26
  150. data/spec/builtins/matches_spec.rb +0 -23
  151. data/spec/builtins/or_spec.rb +0 -22
  152. data/spec/builtins/splits_to.rb +0 -18
  153. data/spec/builtins/then_spec.rb +0 -27
  154. data/spec/builtins/true_spec.rb +0 -5
  155. data/spec/compilation_spec.rb +0 -61
  156. data/spec/custom_classes_spec.rb +0 -43
  157. data/spec/dereference.rb +0 -10
  158. data/spec/queries_spec.rb +0 -150
  159. data/spec/recursion_spec.rb +0 -18
  160. data/spec/ruby_code_spec.rb +0 -52
  161. data/spec/rules_spec.rb +0 -97
  162. data/spec/theory_spec.rb +0 -29
  163. data/spec/variable_spec.rb +0 -26
data/Gemfile CHANGED
@@ -1,18 +1,9 @@
1
1
  source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
5
2
 
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
3
  group :development do
9
- gem "rspec", "~> 2.8.0"
4
+ gem "rspec", ">= 2.8.0", " < 3"
10
5
  gem "yard", "~> 0.7"
11
- gem "rdoc", "~> 3.12"
12
- gem "cucumber", ">= 0"
13
- gem "bundler", "~> 1.0.0"
14
- gem "jeweler", "~> 1.8.3"
6
+ gem "bundler", ">= 1.0.0"
7
+ gem "jeweler", ">= 1.8.3"
15
8
  gem "simplecov", :require => false
16
- gem "reek", "~> 1.2.8"
17
- gem "roodi", "~> 2.1.0"
18
9
  end
data/Gemfile.lock CHANGED
@@ -1,64 +1,38 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- builder (3.0.0)
5
- cucumber (1.1.4)
6
- builder (>= 2.1.2)
7
- diff-lcs (>= 1.1.2)
8
- gherkin (~> 2.7.1)
9
- json (>= 1.4.6)
10
- term-ansicolor (>= 1.0.6)
11
- diff-lcs (1.1.3)
12
- gherkin (2.7.6)
13
- json (>= 1.4.6)
4
+ diff-lcs (1.2.4)
14
5
  git (1.2.5)
15
- jeweler (1.8.3)
6
+ jeweler (1.8.4)
16
7
  bundler (~> 1.0)
17
8
  git (>= 1.2.5)
18
9
  rake
19
10
  rdoc
20
- json (1.6.5)
21
- multi_json (1.0.4)
22
- rake (0.9.2.2)
23
- rdoc (3.12)
11
+ json (1.7.7)
12
+ multi_json (1.7.2)
13
+ rake (10.0.4)
14
+ rdoc (4.0.1)
24
15
  json (~> 1.4)
25
- reek (1.2.8)
26
- ruby2ruby (~> 1.2)
27
- ruby_parser (~> 2.0)
28
- sexp_processor (~> 3.0)
29
- roodi (2.1.0)
30
- ruby_parser
31
- rspec (2.8.0)
32
- rspec-core (~> 2.8.0)
33
- rspec-expectations (~> 2.8.0)
34
- rspec-mocks (~> 2.8.0)
35
- rspec-core (2.8.0)
36
- rspec-expectations (2.8.0)
37
- diff-lcs (~> 1.1.2)
38
- rspec-mocks (2.8.0)
39
- ruby2ruby (1.3.1)
40
- ruby_parser (~> 2.0)
41
- sexp_processor (~> 3.0)
42
- ruby_parser (2.3.1)
43
- sexp_processor (~> 3.0)
44
- sexp_processor (3.0.10)
45
- simplecov (0.5.4)
46
- multi_json (~> 1.0.3)
47
- simplecov-html (~> 0.5.3)
48
- simplecov-html (0.5.3)
49
- term-ansicolor (1.0.7)
50
- yard (0.7.5)
16
+ rspec (2.13.0)
17
+ rspec-core (~> 2.13.0)
18
+ rspec-expectations (~> 2.13.0)
19
+ rspec-mocks (~> 2.13.0)
20
+ rspec-core (2.13.1)
21
+ rspec-expectations (2.13.0)
22
+ diff-lcs (>= 1.1.3, < 2.0)
23
+ rspec-mocks (2.13.1)
24
+ simplecov (0.7.1)
25
+ multi_json (~> 1.0)
26
+ simplecov-html (~> 0.7.1)
27
+ simplecov-html (0.7.1)
28
+ yard (0.8.6.1)
51
29
 
52
30
  PLATFORMS
53
31
  ruby
54
32
 
55
33
  DEPENDENCIES
56
- bundler (~> 1.0.0)
57
- cucumber
58
- jeweler (~> 1.8.3)
59
- rdoc (~> 3.12)
60
- reek (~> 1.2.8)
61
- roodi (~> 2.1.0)
62
- rspec (~> 2.8.0)
34
+ bundler (>= 1.0.0)
35
+ jeweler (>= 1.8.3)
36
+ rspec (>= 2.8.0, < 3)
63
37
  simplecov
64
38
  yard (~> 0.7)
data/README.rdoc CHANGED
@@ -5,6 +5,8 @@ Buck}[http://weblog.jamisbuck.org/2006/10/28/prolog-in-ruby], and the
5
5
  implementation is based on {Yield Prolog}[http://yieldprolog.sourceforge.net/],
6
6
  with lots of sintactic and semantic additions.
7
7
 
8
+ See the {wiki}[https://github.com/cie/rubylog/wiki] for online documentation.
9
+
8
10
  == Getting started
9
11
 
10
12
  First, install the gem
@@ -13,19 +15,14 @@ First, install the gem
13
15
 
14
16
  or, if you use +bundler+, add this line to your +Gemfile+:
15
17
 
16
- gem 'rubylog', '~>1.0.0'
18
+ gem 'rubylog', '~>2.0pre1'
17
19
 
18
20
 
19
21
 
20
- First, you have to create a theory and write your code in the block given to it:
22
+ First, you need a Rubylog context. The simplest you can do is to extend Rubylog::Context into the main object.
21
23
 
22
24
  require 'rubylog'
23
-
24
- MyTheory = theory do
25
- # your code here
26
- end
27
-
28
- All further examples in this file should be written within the +theory+ block.
25
+ extend Rubylog::Context
29
26
 
30
27
 
31
28
  === Data types
@@ -40,13 +37,6 @@ Rubylog variables are (undefined) constant names:
40
37
  A variables whose name starts with +ANY...+ (case-insensitive) is a don't-care
41
38
  variable (like +_+ in Prolog).
42
39
 
43
- Structures are in a different order than they are in prolog:
44
-
45
- functor_for String, :likes
46
- 'John'.likes('beer')
47
-
48
- which would be +likes('John','beer')+ in prolog.
49
-
50
40
  Lists are just Ruby arrays:
51
41
 
52
42
  [1, 2, 3]
@@ -55,28 +45,36 @@ They can have splats:
55
45
 
56
46
  [1, 2, *T]
57
47
 
58
- Which would be +[1,2|T]+ in Prolog, however, in Rubylog, splats are not limited
48
+ Which would be <tt>[1,2|T]</tt> in Prolog, however, in Rubylog, splats are not limited
59
49
  to the end.
60
50
 
61
51
  === Predicates
52
+ As in prolog, predicates are the buinding blocks of your program. However, the arguments are in a different order than they are in prolog:
53
+
54
+ predicate_for String, ".likes()"
55
+ 'John'.likes!('beer')
56
+
57
+ which would be <tt>likes('John','beer').</tt> in prolog. In Rubylog, predicates must be declared. The string indicating the predicate syntax is <tt>".likes()"</tt>. The format is <tt>:asdf .asdf .asdf() .asdf(,) .asdf(,,)</tt> for predicates with 0,1,2,3,4 arguments.
62
58
 
63
59
  You can assert a rule with the +if+ method:
64
60
 
61
+ predicate_for String, ".drinks() .has()"
65
62
  X.drinks(Y).if X.has(Y).and X.likes(Y)
66
63
 
67
64
  This would be +drinks(X,Y) :- has(X,Y), likes(X,Y)+ in Prolog.
68
65
 
69
- You can assert facts with +if(:true)+, or, as a shorthand you can use the bang
66
+ You can assert facts with <tt>if(:true)</tt>, or, as a shorthand you can use the bang
70
67
  syntax:
71
68
 
72
69
  'John'.likes! 'milk'
73
70
 
74
- Bang assertions return their first argument (which is +'John'+ in this case), so they can be chained:
71
+ Bang assertions return their first argument (which is <tt>'John'</tt> in this case), so they can be chained:
75
72
 
76
73
  'John'.likes!('beer').has!('beer')
77
74
 
78
75
  You can also use +unless+:
79
76
 
77
+ predicate_for String, ".good .bad"
80
78
  A.good.unless A.bad
81
79
 
82
80
  Nullary predicates are symbols, similar to Prolog:
@@ -93,17 +91,22 @@ Some built-in predicates and their Prolog equivalents:
93
91
  ------- ------
94
92
  :true true
95
93
  :fail fail
96
- .and ,
97
- .or ;
94
+ .and() ,
95
+ .or() ;
98
96
  :false \+
99
- .is =
100
- .is_not =/=
101
- .in member
97
+ .is() =
98
+ .is_not() =/=
99
+ .in() member
102
100
  :cut! !
103
101
 
104
102
  There are some new ones:
105
103
 
106
- is_not, not_in, all, any, one, none, iff
104
+ not_in, all, any, one, none, iff
105
+
106
+ You can see reference of these in <tt>lib/rubylog/builtins/logic.rb</tt> and <tt>lib/rubylog/builtins/term.rb</tt>
107
+
108
+
109
+ See the documentation in <tt>lib/rubylog/builtins/</tt>
107
110
 
108
111
  === Unification
109
112
 
@@ -180,23 +183,24 @@ variables are substituted with their respecitve value (or +nil+ if they are not
180
183
  bound).
181
184
 
182
185
  All built-in rubylog predicates are clean logical programming predicates witout
183
- a side-effect. If you want some side-effect, you always go into native mode.
186
+ a side-effect. If you want some side-effects, you always go into native mode.
184
187
 
185
188
  === Rubylog as a test suite
186
189
 
187
190
  You can write simple tests using the +check+ method:
188
191
 
189
192
  theory do
190
- check :true
193
+ check :true.or :false
194
+ check A.is(3).and A.in [1,2,3]
191
195
  check { 5+5 == 10 }
192
196
  end
193
197
 
194
- You sould put this file in +"./logic/something\_logic.rb"+. Then you can run it
198
+ You sould put this file in <tt>"./logic/something\_logic.rb"</tt>. Then you can run it
195
199
  with
196
200
 
197
201
  rubylog logic/something_logic.rb
198
202
 
199
- Or you can run all files in +logic/**/*_logic.rb+ with
203
+ Or you can run all files in <tt>logic/**/*\_logic.rb</tt> with
200
204
 
201
205
  rubylog
202
206
 
@@ -240,18 +244,14 @@ You can make some metaprogramming with Rubylog
240
244
  == Contributing
241
245
 
242
246
  === To the language
243
- * Create an issue on the {issue tracker}[https://github.com/cie/rubylog/issues].
244
- * We will discuss it.
245
- * Maybe I'll introduce it.
246
247
 
247
- === To the implementation
248
+ * Post your own examples to the {wiki}[https://github.com/cie/rubylog/wiki/Examples].
249
+ * Improve others' examples.
250
+ * If you have a suggestion for the language, submit an issue.
251
+
252
+ === Reporting bugs or requesting features
253
+
248
254
  * Create an issue on the {issue tracker}[https://github.com/cie/rubylog/issues].
249
- * We will discuss it.
250
- * Maybe I'll implement it.
251
- * If not, fork the project.
252
- * Implement it.
253
- * Have fun.
254
- * Post a pull request.
255
255
 
256
256
  == Copyright
257
257
 
data/README.rdoc.orig ADDED
@@ -0,0 +1,284 @@
1
+ = Rubylog - Prolog interpreter for ruby
2
+
3
+ Rubylog is a Prolog-like DSL for Ruby. The language is inspired by {Jamis
4
+ Buck}[http://weblog.jamisbuck.org/2006/10/28/prolog-in-ruby], and the
5
+ implementation is based on {Yield Prolog}[http://yieldprolog.sourceforge.net/],
6
+ with lots of sintactic and semantic additions.
7
+
8
+ See the {wiki}[https://github.com/cie/rubylog/wiki] for online documentation.
9
+
10
+ == Getting started
11
+
12
+ First, install the gem
13
+
14
+ $ gem install rubylog
15
+
16
+ or, if you use +bundler+, add this line to your +Gemfile+:
17
+
18
+ gem 'rubylog', '~>2.0pre1'
19
+
20
+
21
+
22
+ First, you need a Rubylog context. The simplest you can do is to extend Rubylog::Context into the main object.
23
+
24
+ require 'rubylog'
25
+ extend Rubylog::Context
26
+
27
+
28
+ === Data types
29
+
30
+ Rubylog is similar to Prolog, but there are quite a few differences. In Rubylog,
31
+ you can use any Ruby object as data.
32
+
33
+ Rubylog variables are (undefined) constant names:
34
+
35
+ A, B, ANYTHING
36
+
37
+ A variables whose name starts with +ANY...+ (case-insensitive) is a don't-care
38
+ variable (like +_+ in Prolog).
39
+
40
+ <<<<<<< HEAD
41
+ Structures are in a different order than they are in prolog:
42
+
43
+ functor_for String, :likes
44
+ 'John'.likes('beer')
45
+
46
+ which would be <tt>likes('John','beer')</tt> in prolog.
47
+
48
+ =======
49
+ >>>>>>> develop
50
+ Lists are just Ruby arrays:
51
+
52
+ [1, 2, 3]
53
+
54
+ They can have splats:
55
+
56
+ [1, 2, *T]
57
+
58
+ Which would be <tt>[1,2|T]</tt> in Prolog, however, in Rubylog, splats are not limited
59
+ to the end.
60
+
61
+ === Predicates
62
+ As in prolog, predicates are the buinding blocks of your program. However, the arguments are in a different order than they are in prolog:
63
+
64
+ predicate_for String, ".likes()"
65
+ 'John'.likes!('beer')
66
+
67
+ which would be <tt>likes('John','beer').</tt> in prolog. In Rubylog, predicates must be declared. The string indicating the predicate syntax is <tt>".likes()"</tt>. The format is <tt>:asdf .asdf .asdf() .asdf(,) .asdf(,,)</tt> for predicates with 0,1,2,3,4 arguments.
68
+
69
+ You can assert a rule with the +if+ method:
70
+
71
+ predicate_for String, ".drinks() .has()"
72
+ X.drinks(Y).if X.has(Y).and X.likes(Y)
73
+
74
+ This would be +drinks(X,Y) :- has(X,Y), likes(X,Y)+ in Prolog.
75
+
76
+ You can assert facts with <tt>if(:true)</tt>, or, as a shorthand you can use the bang
77
+ syntax:
78
+
79
+ 'John'.likes! 'milk'
80
+
81
+ Bang assertions return their first argument (which is <tt>'John'</tt> in this case), so they can be chained:
82
+
83
+ 'John'.likes!('beer').has!('beer')
84
+
85
+ You can also use +unless+:
86
+
87
+ predicate_for String, ".good .bad"
88
+ A.good.unless A.bad
89
+
90
+ Nullary predicates are symbols, similar to Prolog:
91
+
92
+ 'John'.drinks('beer').if :false.and(:cut!).or(:true)
93
+
94
+
95
+
96
+ === Built-in predicates
97
+
98
+ Some built-in predicates and their Prolog equivalents:
99
+
100
+ <<<<<<< HEAD
101
+ Prolog Rubylog
102
+ ------ -------
103
+ true/0 :true
104
+ fail/0 :fail
105
+ ','/2 .and()
106
+ ';'/2 .or()
107
+ '\+'/1 .false
108
+ '='/2 .is()
109
+ '=/='/2 .is_not()
110
+ member/2 .in()
111
+ '!'/0 :cut!
112
+ =======
113
+ Rubylog Prolog
114
+ ------- ------
115
+ :true true
116
+ :fail fail
117
+ .and() ,
118
+ .or() ;
119
+ :false \+
120
+ .is() =
121
+ .is_not() =/=
122
+ .in() member
123
+ :cut! !
124
+ >>>>>>> develop
125
+
126
+ There are some new ones:
127
+
128
+ not_in, all, any, one, none, iff
129
+
130
+ You can see reference of these in <tt>lib/rubylog/builtins/logic.rb</tt> and <tt>lib/rubylog/builtins/term.rb</tt>
131
+
132
+
133
+ See the documentation in <tt>lib/rubylog/builtins/</tt>
134
+
135
+ === Unification
136
+
137
+ In Rubylog, unification works quite the same in Prolog, with the +is+ functor.
138
+
139
+ A.is(B)
140
+
141
+ Using arrays, you can benefit the splats:
142
+
143
+ [1,2,3,4].is([A,B,*T]) # [1,2,3,4] = [A,B|T] in prolog
144
+ [1,2,3,4].is([*H,*T]) # append(H, T, [1,2,3,4]) in prolog
145
+
146
+ The +in+ predicate unifies the first argument with any member of the collection:
147
+
148
+ 4.in([1,2,3,4])
149
+
150
+ You can use guards:
151
+
152
+ A[String].in(["asdf",5,nil]).each { p A } # outputs "asdf"
153
+ A[/x/].in(["asdf","xyz"]).each { p A } # outputs "xyz"
154
+ A[thats < 5].in([4,5,6]).each { p A } # outputs 4
155
+
156
+ === Moving between Ruby and Rubylog
157
+ ==== Running a query
158
+
159
+ If you want to run a query, you have many different syntaxes:
160
+
161
+ prove ('John'.drinks 'beer') # => true
162
+ true? ('John'.drinks 'beer') # => true
163
+ ('John'.drinks 'beer').true? # => true
164
+ 'John'.drinks? 'beer' # => true
165
+
166
+ ==== Enumerations
167
+
168
+ +Structure+ implements +Enumerable+, and yields the solutions. Within the
169
+ enumeration block, you can access the values of your variables.
170
+
171
+ 'John'.drinks! 'beer'
172
+ ('John'.drinks X).each {p X} # outputs 'beer'
173
+ ('John'.drinks X).map{X} # => ['beer']
174
+ ('John'.drinks X).count # => 1
175
+
176
+ ==== Procs as predicates
177
+
178
+ You can invoke Ruby codes in Rubylog rules with a proc:
179
+
180
+ 'John'.likes(Y).if proc{ Y =~ /ale/ }
181
+
182
+ or in most cases you can use just a block:
183
+
184
+ 'John'.likes(Y).if { Y =~ /ale/ }
185
+
186
+ The predicate succeeds if the block returns a true value.
187
+
188
+ ==== Procs as functions
189
+
190
+ +is+ and +in+ can take a proc or block argument, which they execute and take its return value:
191
+
192
+ X.good.if X.is { 'BEER'.downcase }
193
+ X.good.if X.in { get_good_drinks() }
194
+
195
+ ==== The two modes of Rubylog
196
+
197
+ Rubylog has two modes, DSL and native. DSL code is executed only once
198
+ at compile time, and is used for describing the Rubylog program. Native code is
199
+ executed runtime. Any block passed to Rubylog structures native code.
200
+
201
+ ('John'.drinks X).and { X != 'beer'}.each { p X }
202
+ ^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^ dsl mode
203
+ ^^^^^^^^^^^^ ^^^^^ native mode
204
+
205
+ In dsl mode, variables are +Rubylog::Variable+ objects. In native mode,
206
+ variables are substituted with their respecitve value (or +nil+ if they are not
207
+ bound).
208
+
209
+ All built-in rubylog predicates are clean logical programming predicates witout
210
+ a side-effect. If you want some side-effects, you always go into native mode.
211
+
212
+ === Rubylog as a test suite
213
+
214
+ You can write simple tests using the +check+ method:
215
+
216
+ theory do
217
+ check :true.or :false
218
+ check A.is(3).and A.in [1,2,3]
219
+ check { 5+5 == 10 }
220
+ end
221
+
222
+ You sould put this file in <tt>"./logic/something\_logic.rb"</tt>. Then you can run it
223
+ with
224
+
225
+ rubylog logic/something_logic.rb
226
+
227
+ Or you can run all files in <tt>logic/**/*\_logic.rb</tt> with
228
+
229
+ rubylog
230
+
231
+ === Other built-in libraries
232
+
233
+ ==== File system
234
+
235
+ You can make some queries on the file system:
236
+
237
+ require "rubylog/builtins/file_system"
238
+
239
+ theory do
240
+ check "README".filename_in "."
241
+
242
+ X.dirname_in(".").each { puts X }
243
+ end
244
+
245
+
246
+ ==== Reflection
247
+
248
+ You can make some metaprogramming with Rubylog
249
+
250
+
251
+ require "rubylog/builtins/reflection"
252
+
253
+ theory do
254
+ functor_for String, :likes
255
+
256
+ check "John".likes("Jane").structure(:likes, ["John", "Jane"])
257
+
258
+ "John".likes(X).if X.likes("John")
259
+ "Jane".likes!("John")
260
+ check "John".likes("Jane").follows_from "Jane".likes("John")
261
+
262
+ "John".likes!("milk")
263
+ check "John".likes("milk").fact
264
+ check "John".likes("beer").fact.false
265
+
266
+ end
267
+
268
+ == Contributing
269
+
270
+ === To the language
271
+
272
+ * Post your own examples to the {wiki}[https://github.com/cie/rubylog/wiki/Examples].
273
+ * Improve others' examples.
274
+ * If you have a suggestion for the language, submit an issue.
275
+
276
+ === Reporting bugs or requesting features
277
+
278
+ * Create an issue on the {issue tracker}[https://github.com/cie/rubylog/issues].
279
+
280
+ == Copyright
281
+
282
+ Copyright (c) 2013 Bernát Kalló. See LICENSE.txt for
283
+ further details.
284
+
@@ -0,0 +1,51 @@
1
+ == Version 2.1 (planned)
2
+ * New features
3
+ * solve without a block returns an enumerator
4
+ * warning for singleton variables
5
+ * predicate for checking bound/unbound variables
6
+
7
+ == Version 2.0.0 (to be released)
8
+ * Backwards incompatibilities
9
+ * <tt>Rubylog.theory</tt> is removed. Use <tt>Kernel#Rubylog</tt>.
10
+ * <tt>file\_in</tt> includes directories and yields relative paths.
11
+ <tt>dir\_in</tt> also yields relative paths.
12
+ * <tt>trace</tt> has became <tt>Rubylog.trace</tt>. If you use
13
+ <tt>Kernel#Rubylog</tt>, it does not matter.
14
+ * <tt>Theory</tt> has changed to <tt>Context</tt> and it became a module.
15
+ * No more inclusion of theories (contexts).
16
+ * Predicates do not have reference in the theory (context), they are only referenced from the
17
+ subject class in closures of the functor methods.
18
+ * Unification uses <tt>eql?</tt> instead of <tt>==</tt>. This means
19
+ <tt>5.0.is\_not(5)</tt>
20
+ * <tt>Theory#eval</tt> removed. Use <tt>Context#instance\_eval</tt>.
21
+ * Removed <tt>functor</tt>, use <tt>predicate</tt> and <tt>predicate\_for</tt>
22
+ instead. The latter ones have a different syntax for indicating predicates, eg.
23
+ <tt>".and() .false :true"</tt> or <tt>"L.splits\_to(H,T)"</tt>
24
+ * <tt>Structure</tt> is bound to the predicate it represents. The first argument of <tt>Structure.new</tt> is the predicate. <tt>S.structure(Predicate,Functor,Args)</tt> now has 4 arguments.
25
+ * <tt>current\_theory</tt> is removed.
26
+ * No more real prefix functors, n-ary prefix functors are n\+1-ary functors with the context object as the first argument. Use <tt>predicate\_for Rubylog::Context, "..."</tt>.
27
+ * <tt>Rubylog::DefaultBuiltins</tt> is replaced by <tt>Rubylog</tt>
28
+ * <tt>Theory#prove</tt> was removed. Use <tt>Context#true?</tt>
29
+ * <tt>Rubylog::Callable<tt> renamed to <tt>Rubylog::Clause</tt>
30
+ * <tt>discontiguous</tt> is removed. No more discontiguity checks.
31
+ * <tt>implicit</tt> is removed. No implicit mode anymore.
32
+ * <tt>Theory#clear</tt> is replaced by <tt>Context#initialize\_context</tt>.
33
+ However, currently it only clears <tt>default\_subject</tt>.
34
+ * <tt>CompositeTerm</tt> is renamed to <tt>CompoundTerm</tt>.
35
+ * <tt>rublog\_compile\_variables</tt> is renamed to
36
+ <tt>rubylog\_match\_variables</tt>, <tt>variable\_hashes</tt> is removed.
37
+ * <tt>rubylog\_variables\_hash</tt> removed
38
+ * Features
39
+ * Rspec integration
40
+ * +include+ or +extend+ <tt>Rubylog::Context</tt> into any class or object
41
+ * thats\_not
42
+ * Comments in indicators
43
+ * New tracer
44
+ * added <tt>every</tt>
45
+ * all builtins are available by default
46
+ * Bug fixes
47
+
48
+
49
+ == Version 1.0.0
50
+ == Version 0.0.1
51
+ == Version 0.0.0
data/Rakefile CHANGED
@@ -11,14 +11,16 @@ rescue Bundler::BundlerError => e
11
11
  end
12
12
  require 'rake'
13
13
 
14
+ # Jeweler - gem manager
14
15
  require 'jeweler'
15
16
  Jeweler::Tasks.new do |gem|
16
17
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
18
  gem.name = "rubylog"
19
+ gem.version = File.open("VERSION"){|f|f.readline.strip}
18
20
  gem.homepage = "https://github.com/cie/rubylog"
19
21
  gem.license = "MIT"
20
- gem.summary = %Q{An embedded Prolog interpreter}
21
- gem.description = %Q{Rubylog is an embedded Prolog language and interpreter for Ruby.}
22
+ gem.summary = %Q{A Prolog-like DSL}
23
+ gem.description = %Q{Rubylog is a Prolog-like DSL for Ruby.}
22
24
  gem.email = "kallo.bernat@gmail.com"
23
25
  gem.authors = ["Bernát Kalló"]
24
26
  gem.executables = Dir["bin/*"].map{|x|File.basename x}
@@ -26,33 +28,27 @@ Jeweler::Tasks.new do |gem|
26
28
  end
27
29
  Jeweler::RubygemsDotOrgTasks.new
28
30
 
31
+ # RSpec - for tests
29
32
  require 'rspec/core'
30
33
  require 'rspec/core/rake_task'
31
34
  RSpec::Core::RakeTask.new(:spec) do |spec|
32
35
  spec.pattern = FileList['spec/**/*_spec.rb']
33
36
  end
34
37
 
35
- require 'cucumber/rake/task'
36
- Cucumber::Rake::Task.new(:features)
38
+ require 'yard'
39
+ YARD::Rake::YardocTask.new
37
40
 
38
- require 'reek/rake/task'
39
- Reek::Rake::Task.new do |t|
40
- t.fail_on_error = true
41
- t.verbose = false
42
- t.source_files = 'lib/**/*.rb'
41
+ file "doc/models.dot" do |f|
42
+ sh "yard graph > #{f.name}"
43
43
  end
44
44
 
45
- require 'roodi'
46
- require 'roodi_task'
47
- RoodiTask.new do |t|
48
- t.verbose = false
45
+ rule ".svg" => ".dot" do |f|
46
+ sh "fdp #{f.source} -Tsvg > #{f.name}"
49
47
  end
50
48
 
51
- task :logic do
52
- run "ruby"
49
+ task :yardserver do
50
+ sh "yard server --reload"
53
51
  end
54
52
 
55
- task :default => :logic
56
53
 
57
- require 'yard'
58
- YARD::Rake::YardocTask.new
54
+
data/TODO.txt ADDED
File without changes
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 2.0pre1
@@ -0,0 +1,6 @@
1
+ require "rubylog"
2
+ extend Rubylog::Context
3
+
4
+ "#{A} #{B}".in{$stdin.readlines}.each do
5
+ puts A.to_i + B.to_i
6
+ end