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
@@ -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