rubylog 2.0.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +10 -0
- data/README.rdoc +1 -1
- data/RELEASE_NOTES.rdoc +7 -4
- data/VERSION +1 -1
- data/{examples → benchmark}/benchmark.rb +1 -0
- data/{examples → benchmark}/benchmark/compiled_not_indexed.rb +0 -0
- data/{examples → benchmark}/benchmark/compiled_sequence_indexed.rb +0 -0
- data/{examples → benchmark}/benchmark/indexed_procedure.rb +0 -0
- data/{examples → benchmark}/benchmark/prolog.rb +0 -0
- data/benchmark/benchmark/pure.rb +28 -0
- data/bin/rubylog +14 -0
- data/examples/a_plus_b.rb +2 -2
- data/examples/dcg.rb +22 -26
- data/examples/dcg2.rb +25 -30
- data/examples/divisors.rb +1 -3
- data/examples/factorial.rb +8 -15
- data/examples/file_search.rb +14 -13
- data/examples/hanoi.rb +1 -3
- data/examples/hu/csaladfa.rb +0 -4
- data/examples/n_queens.rb +17 -22
- data/examples/palindrome_detection.rb +1 -2
- data/examples/parsing.rb +19 -23
- data/examples/permutation.rb +1 -3
- data/examples/primality_by_division.rb +2 -2
- data/examples/sieve_of_eratosthenes.rb +2 -2
- data/examples/string_interpolation.rb +0 -3
- data/examples/tracing.rb +0 -4
- data/lib/rubylog/builtins/assumption.rb +2 -1
- data/lib/rubylog/builtins/file_system.rb +1 -1
- data/lib/rubylog/default_context.rb +3 -5
- data/lib/rubylog/mixins/kernel.rb +9 -1
- data/lib/rubylog/rubylog_files.rb +7 -0
- data/rubylog.gemspec +17 -22
- data/spec/inriasuite_spec.rb +851 -847
- data/spec/integration/dsl_spec.rb +32 -29
- data/spec/rspec/rubylog_spec.rb +46 -52
- data/spec/rubylog/assertable_spec.rb +92 -90
- data/spec/rubylog/builtins/arithmetics_spec.rb +92 -90
- data/spec/rubylog/builtins/assumption_spec.rb +59 -57
- data/spec/rubylog/builtins/ensure_spec.rb +6 -4
- data/spec/rubylog/builtins/file_system_spec.rb +41 -39
- data/spec/rubylog/builtins/logic_spec.rb +308 -306
- data/spec/rubylog/builtins/reflection_spec.rb +31 -29
- data/spec/rubylog/builtins/term_spec.rb +62 -60
- data/spec/rubylog/context_modules/demonstration_spec.rb +108 -106
- data/spec/rubylog/context_modules/predicates_spec.rb +29 -27
- data/spec/rubylog/context_modules/thats_spec.rb +77 -75
- data/spec/rubylog/dsl/array_splat_spec.rb +11 -9
- data/spec/rubylog/dsl/indicators_spec.rb +23 -21
- data/spec/rubylog/dsl/primitives_spec.rb +30 -28
- data/spec/rubylog/errors_spec.rb +13 -11
- data/spec/rubylog/interfaces/term_spec.rb +78 -76
- data/spec/rubylog/mixins/array_spec.rb +60 -58
- data/spec/rubylog/mixins/composite_term_spec.rb +55 -53
- data/spec/rubylog/mixins/proc_spec.rb +48 -46
- data/spec/rubylog/mixins/string_spec.rb +45 -43
- data/spec/rubylog/mixins/symbol_spec.rb +7 -5
- data/spec/rubylog/procedure_spec.rb +8 -6
- data/spec/rubylog/rule_spec.rb +10 -8
- data/spec/rubylog/structure_spec.rb +73 -71
- data/spec/rubylog/term_spec.rb +5 -3
- data/spec/rubylog/tracing_spec.rb +35 -33
- data/spec/rubylog/variable_spec.rb +249 -247
- data/spec/spec_helper.rb +4 -0
- metadata +54 -43
- data/examples/benchmark/pure.rb +0 -26
- data/examples/checkmate.rb +0 -88
- data/examples/combination.rb +0 -17
- data/examples/directory_structure_logic.rb +0 -17
- data/examples/dirlist.rb +0 -4
- data/examples/enumerators.rb +0 -30
- data/examples/hello.rb +0 -17
- data/examples/mice.rb +0 -92
- data/examples/mice2.rb +0 -37
- data/examples/object_oriented.rb +0 -14
- data/examples/prefix.rb +0 -13
- data/examples/primitives.rb +0 -26
- data/examples/sudoku.rb +0 -17
- data/spec/integration/theory_as_module_spec.rb +0 -20
- data/spec/integration/theory_as_module_with_include_spec.rb +0 -14
@@ -1,80 +1,82 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
module RubylogSpec
|
4
|
+
describe Array, :rubylog=>true do
|
5
|
+
|
6
|
+
describe "unification" do
|
7
|
+
def can_unify a, b
|
8
|
+
result = false
|
9
|
+
a.rubylog_unify(b) { result = true; yield if block_given? }
|
10
|
+
result.should == true
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
def cannot_unify a, b
|
14
|
+
result = false
|
15
|
+
a.rubylog_unify(b) { result = true }
|
16
|
+
result.should == false
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
it "does not unify with non-array" do
|
20
|
+
cannot_unify [A,B], 12
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
it "unifies empty arrays" do
|
24
|
+
can_unify [], []
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
it "unifies empty array with splat" do
|
28
|
+
a = A
|
29
|
+
can_unify [], [*a] do
|
30
|
+
a.value.should == []
|
31
|
+
end
|
30
32
|
end
|
31
|
-
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
it "unifies two splats" do
|
35
|
+
a = A
|
36
|
+
b = B
|
37
|
+
can_unify [*a], [*b] do
|
38
|
+
a.value.should equal b
|
39
|
+
end
|
38
40
|
end
|
39
|
-
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
it "unifies two arrays with splats at the first element" do
|
43
|
+
a = A
|
44
|
+
b = B
|
45
|
+
can_unify [*a], [*b,5] do
|
46
|
+
a.value.should eql [*b,5]
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
it "unifies a splat with empty array" do
|
51
|
+
a = A
|
52
|
+
can_unify [*a], [] do
|
53
|
+
a.value.should eql []
|
54
|
+
end
|
53
55
|
end
|
54
|
-
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
57
|
+
it "unififes splats at first elements" do
|
58
|
+
A.is([1,2,3]).and([*A,4].is([*B,*ANY])).map{B}.should ==
|
59
|
+
[[],[1],[1,2],[1,2,3],[1,2,3,4]]
|
60
|
+
end
|
60
61
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
it "unififes first splat with first non-splat" do
|
63
|
+
A.is([1,2,3]).and([*A,4].is([X,*C])).map{[X,C]}.should ==
|
64
|
+
[[1,[2,3,4]]]
|
65
|
+
end
|
65
66
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
67
|
+
it "unififes first empty splat with first non-splat" do
|
68
|
+
A.is([]).and([*A,4].is([X,*C])).map{[X,C]}.should ==
|
69
|
+
[[4,[]]]
|
70
|
+
end
|
70
71
|
|
71
72
|
|
72
|
-
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
describe "#rubylog_deep_dereference" do
|
76
|
+
it "does keeps unbound splats" do
|
77
|
+
[*A].rubylog_deep_dereference.should eql [*A]
|
78
|
+
end
|
77
79
|
end
|
78
|
-
end
|
79
80
|
|
81
|
+
end
|
80
82
|
end
|
@@ -1,66 +1,68 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
module RubylogSpec
|
4
|
+
describe Rubylog::CompoundTerm, :rubylog=>true do
|
5
|
+
predicate_for Symbol, ".likes()"
|
5
6
|
|
6
|
-
|
7
|
+
describe "compilation" do
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
it "makes eql variables be equal" do
|
10
|
+
a = A; b = A
|
11
|
+
c = (a.likes b)
|
12
|
+
c[0].should be_equal a; c[1].should be_equal b
|
13
|
+
c[0].should_not be_equal c[1]
|
14
|
+
c = c.rubylog_match_variables
|
15
|
+
c[0].should be_equal c[1]
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
it "makes non-eql variables be non-equal" do
|
19
|
+
a = A; b = B
|
20
|
+
c = (a.likes b)
|
21
|
+
c[0].should be_equal a; c[1].should be_equal b
|
22
|
+
c[0].should_not be_equal c[1]
|
23
|
+
c = c.rubylog_match_variables
|
24
|
+
c[0].should_not be_equal c[1]
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
27
|
+
it "makes dont-care variables be non-equal" do
|
28
|
+
a = ANY; b = ANY
|
29
|
+
c = (a.likes b)
|
30
|
+
c[0].should be_equal a; c[1].should be_equal b
|
31
|
+
c[0].should_not be_equal c[1]
|
32
|
+
c = c.rubylog_match_variables
|
33
|
+
c[0].should_not be_equal c[1]
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
36
|
+
it "creates new variables" do
|
37
|
+
a = A; b = B
|
38
|
+
c = (a.likes b)
|
39
|
+
c[0].should be_equal a; c[1].should be_equal b
|
40
|
+
c = c.rubylog_match_variables
|
41
|
+
c[0].should_not be_equal a
|
42
|
+
c[1].should_not be_equal a
|
43
|
+
c[0].should_not be_equal b
|
44
|
+
c[1].should_not be_equal b
|
45
|
+
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
47
|
+
it "makes variables available" do
|
48
|
+
a = A; a1 = A; a2 = A; b = B; b1 = B; c = C;
|
49
|
+
(a.likes b).rubylog_match_variables.rubylog_variables.should == [a, b]
|
50
|
+
(a.likes a1).rubylog_match_variables.rubylog_variables.should == [a]
|
51
|
+
(a.likes a1.in b).rubylog_match_variables.rubylog_variables.should == [a, b]
|
52
|
+
(a.likes a1,b,b1,a2,c).rubylog_match_variables.rubylog_variables.should == [a, b, c]
|
53
|
+
end
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
55
|
+
it "does not make dont-care variables available" do
|
56
|
+
a = ANY; a1 = ANYTHING; a2 = ANYTHING; b = B; b1 = B; c = C;
|
57
|
+
(a.likes b).rubylog_match_variables.rubylog_variables.should == [b]
|
58
|
+
(a.likes a1).rubylog_match_variables.rubylog_variables.should == []
|
59
|
+
(a.likes a1.in b).rubylog_match_variables.
|
60
|
+
rubylog_variables.should == [b]
|
61
|
+
(a.likes a1,b,b1,a2,c).rubylog_match_variables.
|
62
|
+
rubylog_variables.should == [b, c]
|
63
|
+
end
|
63
64
|
|
64
65
|
|
66
|
+
end
|
65
67
|
end
|
66
68
|
end
|
@@ -1,59 +1,61 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
3
|
+
module RubylogSpec
|
4
|
+
describe Proc, :rubylog=>true do
|
5
|
+
before do
|
6
|
+
predicate_for Symbol, ".is_happy .likes()"
|
32
7
|
end
|
33
8
|
|
34
|
-
describe "
|
35
|
-
it "works
|
36
|
-
|
37
|
-
(
|
38
|
-
(:
|
39
|
-
|
9
|
+
describe "using ruby code in clauses" do
|
10
|
+
it "works" do
|
11
|
+
(:true.and? {false}).should be_false
|
12
|
+
(:true.and? {true}).should be_true
|
13
|
+
(:fail.and? {false}).should be_false
|
14
|
+
(:fail.and? {true}).should be_false
|
15
|
+
(:true.or? {false}).should be_true
|
16
|
+
(:true.or? {true}).should be_true
|
17
|
+
(:fail.or? {false}).should be_false
|
18
|
+
(:fail.or? {true}).should be_true
|
19
|
+
|
20
|
+
(:fail.or? {false}).should be_false
|
21
|
+
(:fail.or? {true}).should be_true
|
40
22
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
23
|
+
it "runs the query once at every evaluation" do
|
24
|
+
count = 0
|
25
|
+
:john.is_happy.if :true.and { count += 1 }
|
26
|
+
count.should == 0
|
27
|
+
:john.is_happy?
|
28
|
+
count.should == 1
|
29
|
+
:john.is_happy?
|
30
|
+
count.should == 2
|
31
|
+
(:fail.or? {count+=1}).should be_true
|
32
|
+
count.should == 3
|
47
33
|
end
|
48
34
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
35
|
+
describe "bindings" do
|
36
|
+
it "works for rule bodies" do
|
37
|
+
result = nil;
|
38
|
+
(A.likes(B).if {result = [A,B]})
|
39
|
+
(:john.likes(:beer)).solve{}
|
40
|
+
result.should == [:john,:beer]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "works for rules" do
|
44
|
+
result = nil
|
45
|
+
(A.likes(B).if B.is(4).and A.is(2).and C.is(5).and {result = [A,B,C]})
|
46
|
+
(A.likes(B)).solve{}
|
47
|
+
result.should == [2,4,5]
|
48
|
+
end
|
54
49
|
|
50
|
+
it "works for inline terms" do
|
51
|
+
result = nil
|
52
|
+
(A.is(1).and B.is(2).and {result = [A,B]}).solve{}
|
53
|
+
result.should == [1,2]
|
54
|
+
end
|
55
55
|
|
56
56
|
|
57
|
+
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
@@ -1,48 +1,50 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
3
|
+
module RubylogSpec
|
4
|
+
describe String, :rubylog=>true do
|
5
|
+
describe "unification" do
|
6
|
+
check "asdf".is "asdf"
|
7
|
+
check { "abc#{S}def" =~ /abc.S\[\].def/ }
|
8
|
+
check { "abc#{S[length: 1]}def" =~ /abc.S\[\d+\].def/ }
|
9
|
+
check { "h#{S}o".is("hello").map{S} == ["ell"] }
|
10
|
+
check { "#{Base}.#{Ext}".is("hello.rb").map{Base} == ["hello"] }
|
11
|
+
check { "#{Base}.#{Ext}".is("hello.rb").map{Ext} == ["rb"] }
|
12
|
+
check { "h#{S}o".is("auto").map{S} == [] }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "backtracked matches" do
|
16
|
+
check { "abc".is("#{A}#{B}").map{"#{A}:#{B}"} == [":abc","a:bc","ab:c","abc:"] }
|
17
|
+
check { "www.google.com".is("#{A}.#{B}").map{[A,B]} == [["www", "google.com"],["www.google", "com"]] }
|
18
|
+
check { "a".is("#{A}#{B}#{C}").map{"#{A}:#{B}:#{C}"} == ["::a",":a:","a::"] }
|
19
|
+
check { "ab".is("#{A}#{B}#{C}").map{"#{A}:#{B}:#{C}"} == %w(::ab :a:b :ab: a::b a:b: ab::) }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "guards" do
|
23
|
+
check { "abc".is("#{A[/\A.\z/]}#{B}").map{"#{A}:#{B}"} == ["a:bc"] }
|
24
|
+
check { "abc".is("#{A[length: 1]}#{B}").map{"#{A}:#{B}"} == ["a:bc"] }
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
describe "palindromes" do
|
29
|
+
predicate_for String, ".palindrome"
|
30
|
+
|
31
|
+
S[empty?: true].palindrome!
|
32
|
+
S[length: 1].palindrome!
|
33
|
+
S[lambda{|s|s.length > 1}].palindrome.if S.is("#{A[length: 1]}#{B}#{A}").and B.palindrome
|
34
|
+
|
35
|
+
check "".palindrome
|
36
|
+
check "dd".palindrome
|
37
|
+
check "aba".palindrome
|
38
|
+
check "faaf".palindrome
|
39
|
+
check "ffaaff".palindrome
|
40
|
+
check "rererer".palindrome
|
41
|
+
check "lol".palindrome
|
42
|
+
check "ji".palindrome.false
|
43
|
+
check "doo".palindrome.false
|
44
|
+
check "taaaz".palindrome.false
|
45
|
+
check "faad".palindrome.false
|
46
|
+
check "rerere".palindrome.false
|
47
|
+
end
|
20
48
|
|
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
49
|
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
50
|
end
|