rubylog 1.0.0 → 2.0pre1

Sign up to get free protection for your applications and to get access to all the features.
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