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
@@ -0,0 +1,94 @@
1
+ require "spec_helper"
2
+ require "rubylog/builtins/file_system"
3
+
4
+ describe "thats", :rubylog=>true do
5
+ describe "one level" do
6
+ check 4.is(ANY[Integer,thats < 10])
7
+ check 4.is(ANY[Integer,thats < 5])
8
+ check 4.is(ANY[Integer,thats < 4]).false
9
+ check 4.is(ANY[Integer,thats < 2]).false
10
+ end
11
+
12
+ describe "question mark" do
13
+ check "".is(ANY[thats.empty?])
14
+ check "a".is(ANY[thats.empty?]).false
15
+ end
16
+
17
+ describe "two levels" do
18
+ check "hello".is(ANYTHING[thats.reverse == "olleh"])
19
+ check "hello".is(ANYTHING[thats.reverse == "olle"]).false
20
+ end
21
+
22
+ describe "four levels" do
23
+ check "hello".is(ANY[thats.upcase.partition("E")[0] == "H"])
24
+ check "hello".is(ANY[thats.upcase.partition("E")[1] == "E"])
25
+ check "hello".is(ANY[thats.upcase.partition("E")[2] == "LLO"])
26
+ check "hello".is(ANY[thats.upcase.partition("E")[1] == "H"]).false
27
+ check "hello".is(ANY[thats.upcase.partition("E")[0] == "h"]).false
28
+ check "hello".is(ANY[thats.upcase.partition("L")[0] == "H"]).false
29
+ check "hello".is(ANY[thats.upcase.partition("e")[0] == "H"]).false
30
+ end
31
+
32
+ describe "files" do
33
+ check { "#{S[String, thats.start_with?(".")]}".filename_in(".").map{S}.include? ".gitignore" }
34
+ check { not "#{S[String, thats.start_with?(".")]}". dirname_in(".").map{S}.include? "lib" }
35
+ check { "#{S[/\A(.*)\.rb/]}".filename_in("lib").map{S} == ["rubylog.rb"] }
36
+ end
37
+
38
+ describe "factorial" do
39
+ predicate_for Integer, ".factorial()"
40
+ 0.factorial! 1
41
+ K[thats > 0].factorial(N).if K0.is{K-1}.and K0.factorial(N0).and N.is{N0*K}
42
+ end
43
+
44
+ describe "palindrome" do
45
+ predicate_for String, ".palindrome"
46
+ S[String, thats.length <= 1].palindrome!
47
+ "#{A[thats.length == 1]}#{B}#{A}".palindrome.if B.palindrome
48
+
49
+ check "a".palindrome
50
+ check "aa".palindrome
51
+ check "aga".palindrome
52
+ check "aaa".palindrome
53
+ check "avava".palindrome
54
+ check "ab".palindrome.false
55
+ check "abb".palindrome.false
56
+ check "abab".palindrome.false
57
+ end
58
+
59
+ end
60
+
61
+ describe "thats_not", :rubylog=>true do
62
+ describe "one level" do
63
+ check 4.is(ANY[Integer,thats_not < 10]).false
64
+ check 4.is(ANY[Integer,thats_not < 5]).false
65
+ check 4.is(ANY[Integer,thats_not < 4])
66
+ check 4.is(ANY[Integer,thats_not < 2])
67
+ end
68
+
69
+ describe "question mark" do
70
+ check "".is(ANY[thats_not.empty?]).false
71
+ check "a".is(ANY[thats_not.empty?])
72
+ end
73
+
74
+ describe "two levels" do
75
+ check "hello".is(ANYTHING[thats_not.reverse == "olleh"]).false
76
+ check "hello".is(ANYTHING[thats_not.reverse == "olle"])
77
+ end
78
+
79
+ describe "four levels" do
80
+ check "hello".is(ANY[thats_not.upcase.partition("E")[0] == "H"]).false
81
+ check "hello".is(ANY[thats_not.upcase.partition("E")[1] == "E"]).false
82
+ check "hello".is(ANY[thats_not.upcase.partition("E")[2] == "LLO"]).false
83
+ check "hello".is(ANY[thats_not.upcase.partition("E")[1] == "H"])
84
+ check "hello".is(ANY[thats_not.upcase.partition("E")[0] == "h"])
85
+ check "hello".is(ANY[thats_not.upcase.partition("L")[0] == "H"])
86
+ check "hello".is(ANY[thats_not.upcase.partition("e")[0] == "H"])
87
+ end
88
+
89
+ describe "files" do
90
+ check { not "#{S[String, thats_not.start_with?(".")]}".filename_in(".").map{S}.include? ".gitignore" }
91
+ check { "#{S[String, thats_not.start_with?(".")]}". dirname_in(".").map{S}.include? "lib" }
92
+ end
93
+
94
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ describe Rubylog::DSL::ArraySplat, :rubylog=>true do
4
+ describe "#inspect" do
5
+ [*A].inspect.should == "[*A]"
6
+ end
7
+
8
+ specify "#==" do
9
+ [*A].should == [*A]
10
+ end
11
+
12
+ specify "#eql?" do
13
+ [*A].should eql [*A]
14
+ end
15
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ describe Rubylog::DSL::Primitives, :rubylog=>true do
4
+ describe "#primitives" do
5
+ before do
6
+ String.instance_methods.should_not include :looong
7
+ end
8
+
9
+ it "defines functors on default subject" do
10
+ self.default_subject = String
11
+ class << primitives
12
+ def looong s
13
+ end
14
+ end
15
+ String.instance_methods.should include :looong
16
+ String.instance_methods.should include :looong!
17
+ String.instance_methods.should include :looong?
18
+ end
19
+ end
20
+
21
+ describe "#primitives_for" do
22
+ before do
23
+ Integer.instance_methods.should_not include :large
24
+ end
25
+
26
+ it "defines functors on the given subject" do
27
+ class << primitives_for(Integer)
28
+ def large s
29
+ end
30
+ end
31
+ Integer.instance_methods.should include :large
32
+ Integer.instance_methods.should include :large!
33
+ Integer.instance_methods.should include :large?
34
+ end
35
+ end
36
+
37
+ describe "Primitives#inspect" do
38
+ specify do
39
+ primitives_for(Integer).inspect.should =~ /\Aprimitives_for\(.*\)\z/
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Rubylog errors", :rubylog=>true do
4
+
5
+ describe "syntax error" do
6
+ predicate_for String, ".happy"
7
+
8
+ specify { proc{ "John".happy.if }.should raise_error Rubylog::SyntaxError }
9
+ specify { proc{ "John".happy.if! }.should raise_error Rubylog::SyntaxError }
10
+ specify { proc{ "John".happy.unless }.should raise_error Rubylog::SyntaxError }
11
+ end
12
+
13
+ describe Rubylog::InstantiationError do
14
+ specify { proc { A.true? }.should raise_error(Rubylog::InstantiationError, "Instantiation error in A") }
15
+ specify { proc { A.sum_of(B,1).true? }.should raise_error(Rubylog::InstantiationError, "Instantiation error in A.sum_of(B, 1)") }
16
+ end
17
+
18
+ end
@@ -1,9 +1,8 @@
1
- theory "Uni" do
2
- subject Symbol
3
- functor :likes
4
- end
1
+ require 'spec_helper'
2
+
3
+ describe "unification", :rubylog=>true do
4
+ predicate_for Symbol, ".likes"
5
5
 
6
- describe "unification" do
7
6
  it "works for variables" do
8
7
  result = false
9
8
  A.rubylog_unify(12) { result = true }
@@ -62,16 +61,16 @@ describe "unification" do
62
61
 
63
62
  it "works on clauses with repeated variables #1" do
64
63
  result = false
65
- (A.likes A).rubylog_compile_variables.rubylog_unify(:john.likes :jane) { result = true }
64
+ (A.likes A).rubylog_match_variables.rubylog_unify(:john.likes :jane) { result = true }
66
65
  result.should == false
67
- (A.likes A).rubylog_compile_variables.rubylog_unify(:john.likes :john) { result = true }
66
+ (A.likes A).rubylog_match_variables.rubylog_unify(:john.likes :john) { result = true }
68
67
  result.should == true
69
68
  end
70
69
  it "works on clauses with repeated variables #1" do
71
70
  result = false
72
- (:john.likes :jane).rubylog_unify(A.likes(A).rubylog_compile_variables) { result = true }
71
+ (:john.likes :jane).rubylog_unify(A.likes(A).rubylog_match_variables) { result = true }
73
72
  result.should == false
74
- (:john.likes :john).rubylog_unify(A.likes(A).rubylog_compile_variables) { result = true }
73
+ (:john.likes :john).rubylog_unify(A.likes(A).rubylog_match_variables) { result = true }
75
74
  result.should == true
76
75
  end
77
76
 
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe Array, :rubylog=>true do
4
+
5
+ describe "unification" do
6
+ def can_unify a, b
7
+ result = false
8
+ a.rubylog_unify(b) { result = true; yield if block_given? }
9
+ result.should == true
10
+ end
11
+
12
+ def cannot_unify a, b
13
+ result = false
14
+ a.rubylog_unify(b) { result = true }
15
+ result.should == false
16
+ end
17
+
18
+ it "does not unify with non-array" do
19
+ cannot_unify [A,B], 12
20
+ end
21
+
22
+ it "unifies empty arrays" do
23
+ can_unify [], []
24
+ end
25
+
26
+ it "unifies empty array with splat" do
27
+ a = A
28
+ can_unify [], [*a] do
29
+ a.value.should == []
30
+ end
31
+ end
32
+
33
+ it "unifies two splats" do
34
+ a = A
35
+ b = B
36
+ can_unify [*a], [*b] do
37
+ b.value.should equal a
38
+ end
39
+ end
40
+
41
+ it "unifies two arrays with splats at the first element" do
42
+ a = A
43
+ b = B
44
+ can_unify [*a], [*b,5] do
45
+ a.value.should eql [*b,5]
46
+ end
47
+ end
48
+
49
+ it "unifies a splat with empty array" do
50
+ a = A
51
+ can_unify [*a], [] do
52
+ a.value.should eql []
53
+ end
54
+ end
55
+
56
+ it "unififes splats at first elements" do
57
+ A.is([1,2,3]).and([*A,4].is([*B,*ANY])).map{B}.should ==
58
+ [[],[1],[1,2],[1,2,3],[1,2,3,4]]
59
+ end
60
+
61
+ it "unififes first splat with first non-splat" do
62
+ A.is([1,2,3]).and([*A,4].is([X,*C])).map{[X,C]}.should ==
63
+ [[1,[2,3,4]]]
64
+ end
65
+
66
+ it "unififes first empty splat with first non-splat" do
67
+ A.is([]).and([*A,4].is([X,*C])).map{[X,C]}.should ==
68
+ [[4,[]]]
69
+ end
70
+
71
+
72
+ end
73
+
74
+ describe "#rubylog_deep_dereference" do
75
+ it "does keeps unbound splats" do
76
+ [*A].rubylog_deep_dereference.should eql [*A]
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,66 @@
1
+ require "spec_helper"
2
+
3
+ describe Rubylog::CompoundTerm, :rubylog=>true do
4
+ predicate_for Symbol, ".likes()"
5
+
6
+ describe "compilation" do
7
+
8
+ it "makes eql variables be equal" do
9
+ a = A; b = A
10
+ c = (a.likes b)
11
+ c[0].should be_equal a; c[1].should be_equal b
12
+ c[0].should_not be_equal c[1]
13
+ c = c.rubylog_match_variables
14
+ c[0].should be_equal c[1]
15
+ end
16
+
17
+ it "makes non-eql variables be non-equal" do
18
+ a = A; b = B
19
+ c = (a.likes b)
20
+ c[0].should be_equal a; c[1].should be_equal b
21
+ c[0].should_not be_equal c[1]
22
+ c = c.rubylog_match_variables
23
+ c[0].should_not be_equal c[1]
24
+ end
25
+
26
+ it "makes dont-care variables be non-equal" do
27
+ a = ANY; b = ANY
28
+ c = (a.likes b)
29
+ c[0].should be_equal a; c[1].should be_equal b
30
+ c[0].should_not be_equal c[1]
31
+ c = c.rubylog_match_variables
32
+ c[0].should_not be_equal c[1]
33
+ end
34
+
35
+ it "creates new variables" do
36
+ a = A; b = B
37
+ c = (a.likes b)
38
+ c[0].should be_equal a; c[1].should be_equal b
39
+ c = c.rubylog_match_variables
40
+ c[0].should_not be_equal a
41
+ c[1].should_not be_equal a
42
+ c[0].should_not be_equal b
43
+ c[1].should_not be_equal b
44
+ end
45
+
46
+ it "makes variables available" do
47
+ a = A; a1 = A; a2 = A; b = B; b1 = B; c = C;
48
+ (a.likes b).rubylog_match_variables.rubylog_variables.should == [a, b]
49
+ (a.likes a1).rubylog_match_variables.rubylog_variables.should == [a]
50
+ (a.likes a1.in b).rubylog_match_variables.rubylog_variables.should == [a, b]
51
+ (a.likes a1,b,b1,a2,c).rubylog_match_variables.rubylog_variables.should == [a, b, c]
52
+ end
53
+
54
+ it "does not make dont-care variables available" do
55
+ a = ANY; a1 = ANYTHING; a2 = ANYTHING; b = B; b1 = B; c = C;
56
+ (a.likes b).rubylog_match_variables.rubylog_variables.should == [b]
57
+ (a.likes a1).rubylog_match_variables.rubylog_variables.should == []
58
+ (a.likes a1.in b).rubylog_match_variables.
59
+ rubylog_variables.should == [b]
60
+ (a.likes a1,b,b1,a2,c).rubylog_match_variables.
61
+ rubylog_variables.should == [b, c]
62
+ end
63
+
64
+
65
+ end
66
+ end
@@ -0,0 +1,59 @@
1
+ require "spec_helper"
2
+
3
+ describe Proc, :rubylog=>true do
4
+ before do
5
+ predicate_for Symbol, ".is_happy .likes()"
6
+ end
7
+
8
+ describe "using ruby code in clauses" do
9
+ it "works" do
10
+ (:true.and? {false}).should be_false
11
+ (:true.and? {true}).should be_true
12
+ (:fail.and? {false}).should be_false
13
+ (:fail.and? {true}).should be_false
14
+ (:true.or? {false}).should be_true
15
+ (:true.or? {true}).should be_true
16
+ (:fail.or? {false}).should be_false
17
+ (:fail.or? {true}).should be_true
18
+
19
+ (:fail.or? {false}).should be_false
20
+ (:fail.or? {true}).should be_true
21
+ end
22
+ it "runs the query once at every evaluation" do
23
+ count = 0
24
+ :john.is_happy.if :true.and { count += 1 }
25
+ count.should == 0
26
+ :john.is_happy?
27
+ count.should == 1
28
+ :john.is_happy?
29
+ count.should == 2
30
+ (:fail.or? {count+=1}).should be_true
31
+ count.should == 3
32
+ end
33
+
34
+ describe "bindings" do
35
+ it "works for rule bodies" do
36
+ result = nil;
37
+ (A.likes(B).if {result = [A,B]})
38
+ (:john.likes(:beer)).solve{}
39
+ result.should == [:john,:beer]
40
+ end
41
+
42
+ it "works for rules" do
43
+ result = nil
44
+ (A.likes(B).if B.is(4).and A.is(2).and C.is(5).and {result = [A,B,C]})
45
+ (A.likes(B)).solve{}
46
+ result.should == [2,4,5]
47
+ end
48
+
49
+ it "works for inline terms" do
50
+ result = nil
51
+ (A.is(1).and B.is(2).and {result = [A,B]}).solve{}
52
+ result.should == [1,2]
53
+ end
54
+
55
+
56
+
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe String, :rubylog=>true do
4
+ describe "unification" do
5
+ check "asdf".is "asdf"
6
+ check { "abc#{S}def" =~ /abc.S\[\].def/ }
7
+ check { "abc#{S[length: 1]}def" =~ /abc.S\[\d+\].def/ }
8
+ check { "h#{S}o".is("hello").map{S} == ["ell"] }
9
+ check { "#{Base}.#{Ext}".is("hello.rb").map{Base} == ["hello"] }
10
+ check { "#{Base}.#{Ext}".is("hello.rb").map{Ext} == ["rb"] }
11
+ check { "h#{S}o".is("auto").map{S} == [] }
12
+ end
13
+
14
+ describe "backtracked matches" do
15
+ check { "abc".is("#{A}#{B}").map{"#{A}:#{B}"} == [":abc","a:bc","ab:c","abc:"] }
16
+ check { "www.google.com".is("#{A}.#{B}").map{[A,B]} == [["www", "google.com"],["www.google", "com"]] }
17
+ check { "a".is("#{A}#{B}#{C}").map{"#{A}:#{B}:#{C}"} == ["::a",":a:","a::"] }
18
+ check { "ab".is("#{A}#{B}#{C}").map{"#{A}:#{B}:#{C}"} == %w(::ab :a:b :ab: a::b a:b: ab::) }
19
+ end
20
+
21
+ describe "guards" do
22
+ check { "abc".is("#{A[/\A.\z/]}#{B}").map{"#{A}:#{B}"} == ["a:bc"] }
23
+ check { "abc".is("#{A[length: 1]}#{B}").map{"#{A}:#{B}"} == ["a:bc"] }
24
+ end
25
+
26
+
27
+ describe "palindromes" do
28
+ predicate_for String, ".palindrome"
29
+
30
+ S[empty?: true].palindrome!
31
+ S[length: 1].palindrome!
32
+ S[lambda{|s|s.length > 1}].palindrome.if S.is("#{A[length: 1]}#{B}#{A}").and B.palindrome
33
+
34
+ check "".palindrome
35
+ check "dd".palindrome
36
+ check "aba".palindrome
37
+ check "faaf".palindrome
38
+ check "ffaaff".palindrome
39
+ check "rererer".palindrome
40
+ check "lol".palindrome
41
+ check "ji".palindrome.false
42
+ check "doo".palindrome.false
43
+ check "taaaz".palindrome.false
44
+ check "faad".palindrome.false
45
+ check "rerere".palindrome.false
46
+ end
47
+
48
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Symbol, :rubylog=>true do
4
+ it "can be asserted" do
5
+ predicate ":good"
6
+ :good.if { true }
7
+ true?(:good).should be_true
8
+ end
9
+ end
@@ -1,9 +1,9 @@
1
- require 'rubylog'
1
+ require 'spec_helper'
2
2
 
3
- theory "Vars" do
4
- end
3
+ describe Rubylog::Structure, :rubylog=>true do
4
+
5
+ predicate_for Symbol, ".is_happy .likes()"
5
6
 
6
- describe "clauses" do
7
7
  it "can be created" do
8
8
  (:john.is_happy).should be_kind_of Rubylog::Term
9
9
  (:john.likes :beer).should be_kind_of Rubylog::Term
@@ -11,19 +11,16 @@ describe "clauses" do
11
11
  (:john.likes Drink).should be_kind_of Rubylog::Term
12
12
  (:john.likes :drinking.in :bar).should be_kind_of Rubylog::Term
13
13
  end
14
+
14
15
  it "forbids non-declared names" do
15
16
  lambda { :john.something_else }.should raise_error(NoMethodError)
16
17
  end
17
- it "also work with operators" do
18
- (:is_happy%1).should be_kind_of Rubylog::Term
19
- (A%B).should be_kind_of Rubylog::Term
20
- end
18
+
21
19
  it "can be asked for their functor" do
22
20
  (:john.is_happy).functor.should == :is_happy
23
- (:is_happy%1).functor.should == :%
24
- (A%1).functor.should == :%
25
21
  (:john.likes :drinking.in :bar).functor.should == :likes
26
22
  end
23
+
27
24
  it "can be indexed" do
28
25
  (:john.is_happy)[0].should == :john
29
26
  (:john.likes :beer)[0].should == :john
@@ -32,6 +29,7 @@ describe "clauses" do
32
29
  (:john.likes(:cold, :beer))[1..2].should == [:cold,:beer]
33
30
  (:john.likes :drinking.in :bar)[1].should == (:drinking.in :bar)
34
31
  end
32
+
35
33
  it "can be asked for their args" do
36
34
  (:john.is_happy).args.should == [:john]
37
35
  (:john.likes :beer).args.should == [:john, :beer]
@@ -72,11 +70,14 @@ describe "clauses" do
72
70
  (:john.likes :drinking,:beer).arity.should == 3
73
71
  (:john.likes :drinking.in :bar).arity.should == 2
74
72
  end
75
- it "can tell their descriptor" do
76
- (:john.is_happy).desc.should == [:is_happy,1]
77
- (:john.likes :beer).desc.should == [:likes,2]
78
- (:john.likes :drinking,:beer).desc.should == [:likes,3]
79
- (:john.likes :drinking.in :bar).desc.should == [:likes,2]
73
+
74
+ it "can tell their indicator" do
75
+ (:john.is_happy).indicator.should == [:is_happy,1]
76
+ (:john.likes :beer).indicator.should == [:likes,2]
77
+ (:john.likes :drinking,:beer).indicator.should == [:likes,3]
78
+ (:john.likes :drinking.in :bar).indicator.should == [:likes,2]
80
79
  end
80
+
81
+
81
82
  end
82
83
 
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe "unification", :rubylog=>true do
4
+ it "uses eql?" do
5
+ check 5.is_not 5.0
6
+ end
7
+ end
@@ -0,0 +1,44 @@
1
+ require "spec_helper"
2
+
3
+ describe Rubylog::Tracing, :rubylog=>true do
4
+ before do
5
+ @old_argv = ARGV.dup
6
+ ARGV.replace ["spec/rubylog/tracing_spec.input"]
7
+ @old_stdout = $stdout
8
+ $stdout = @output = StringIO.new
9
+ end
10
+
11
+ after do
12
+ Rubylog.trace?.should == false
13
+ $stdout = @old_stdout
14
+ ARGV.replace @old_argv
15
+ end
16
+
17
+ it "can be called with true/false" do
18
+ Rubylog.trace true
19
+ 1.is(A).solve
20
+ Rubylog.trace false
21
+ @output.string.should include "1.is(A).prove()"
22
+ end
23
+
24
+ it "can be called without true" do
25
+ Rubylog.trace
26
+ 1.is(A).solve
27
+ Rubylog.trace false
28
+ @output.string.should include "1.is(A).prove()"
29
+ end
30
+
31
+ it "can be called with a block" do
32
+ Rubylog.trace do
33
+ 1.is(A).solve
34
+ end
35
+ @output.string.should include "1.is(A).prove()"
36
+ end
37
+
38
+ it "traces unifications" do
39
+ Rubylog.trace do
40
+ 1.is(A).solve
41
+ end
42
+ @output.string.should include "A.bind_to(1)"
43
+ end
44
+ end