rubylog 2.0pre1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +197 -98
- data/RELEASE_NOTES.rdoc +3 -4
- data/VERSION +1 -1
- data/examples/mice.rb +2 -2
- data/examples/tracing.rb +2 -2
- data/lib/rubylog/builtins/ensure.rb +1 -1
- data/lib/rubylog/builtins/logic.rb +47 -25
- data/lib/rubylog/compound_term.rb +12 -2
- data/lib/rubylog/context_modules/predicates.rb +2 -36
- data/lib/rubylog/dsl/indicators.rb +36 -0
- data/lib/rubylog/dsl/variables.rb +1 -1
- data/lib/rubylog/errors.rb +2 -2
- data/lib/rubylog/{clause.rb → goal.rb} +2 -2
- data/lib/rubylog/mixins/proc.rb +2 -2
- data/lib/rubylog/mixins/symbol.rb +2 -2
- data/lib/rubylog/procedure.rb +5 -1
- data/lib/rubylog/rule.rb +4 -0
- data/lib/rubylog/structure.rb +2 -2
- data/lib/rubylog/variable.rb +29 -9
- data/lib/rubylog.rb +1 -1
- data/rubylog.gemspec +8 -4
- data/spec/inriasuite_spec.rb +1 -3
- data/spec/integration/dsl_spec.rb +2 -2
- data/spec/rubylog/builtins/logic_spec.rb +42 -0
- data/spec/rubylog/builtins/term_spec.rb +0 -4
- data/spec/rubylog/context_modules/predicates_spec.rb +0 -22
- data/spec/rubylog/context_modules/thats_spec.rb +1 -1
- data/spec/rubylog/dsl/indicators_spec.rb +26 -0
- data/spec/rubylog/interfaces/term_spec.rb +9 -9
- data/spec/rubylog/mixins/array_spec.rb +1 -1
- data/spec/rubylog/procedure_spec.rb +11 -0
- data/spec/rubylog/rule_spec.rb +13 -0
- data/spec/rubylog/variable_spec.rb +21 -4
- metadata +21 -17
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rubylog/rule'
|
2
|
+
require 'rubylog/dsl/indicators'
|
2
3
|
|
3
4
|
|
4
5
|
module Rubylog
|
@@ -42,44 +43,9 @@ module Rubylog
|
|
42
43
|
flatten.
|
43
44
|
map{|str|str.split(" ")}.
|
44
45
|
flatten.
|
45
|
-
map{|i| unhumanize_indicator(i)}.
|
46
|
+
map{|i| Rubylog::DSL::Indicators.unhumanize_indicator(i)}.
|
46
47
|
each {|i| yield i }
|
47
48
|
end
|
48
|
-
|
49
|
-
|
50
|
-
# Makes human-friendly output from the indicator
|
51
|
-
# For example, .and()
|
52
|
-
def humanize_indicator indicator
|
53
|
-
return indicator if String === indicator
|
54
|
-
functor, arity = indicator
|
55
|
-
if arity > 1
|
56
|
-
".#{functor}(#{ ','*(arity-2) })"
|
57
|
-
elsif arity == 1
|
58
|
-
".#{functor}"
|
59
|
-
elsif arity == 0
|
60
|
-
":#{functor}"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Makes internal representation from predicate indicator
|
65
|
-
#
|
66
|
-
# For example, <tt>.and()</tt> becomes <tt>[:and,2]</tt>
|
67
|
-
def unhumanize_indicator indicator
|
68
|
-
case indicator
|
69
|
-
when Array
|
70
|
-
indicator
|
71
|
-
when /\A:(\w+)\z/
|
72
|
-
[:"#{$1}",0]
|
73
|
-
when /\A\w*\.(\w+)\z/
|
74
|
-
[:"#{$1}",1]
|
75
|
-
when /\A\w*\.(\w+)\(\w*((,\w*)*)\)\z/
|
76
|
-
[:"#{$1}",$2.count(",")+2]
|
77
|
-
else
|
78
|
-
raise ArgumentError, "invalid indicator: #{indicator.inspect}"
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
49
|
end
|
84
50
|
end
|
85
51
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Rubylog::DSL
|
2
|
+
module Indicators
|
3
|
+
# Makes human-friendly output from the indicator
|
4
|
+
# For example, .and()
|
5
|
+
def self.humanize_indicator indicator
|
6
|
+
return indicator if String === indicator
|
7
|
+
functor, arity = indicator
|
8
|
+
if arity > 1
|
9
|
+
".#{functor}(#{ ','*(arity-2) })"
|
10
|
+
elsif arity == 1
|
11
|
+
".#{functor}"
|
12
|
+
elsif arity == 0
|
13
|
+
":#{functor}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Makes internal representation from predicate indicator
|
18
|
+
#
|
19
|
+
# For example, <tt>.and()</tt> becomes <tt>[:and,2]</tt>
|
20
|
+
def self.unhumanize_indicator indicator
|
21
|
+
case indicator
|
22
|
+
when Array
|
23
|
+
indicator
|
24
|
+
when /\A:(\w+)\z/
|
25
|
+
[:"#{$1}",0]
|
26
|
+
when /\A\w*\.(\w+)\z/
|
27
|
+
[:"#{$1}",1]
|
28
|
+
when /\A\w*\.(\w+)\(\w*((,\w*)*)\)\z/
|
29
|
+
[:"#{$1}",$2.count(",")+2]
|
30
|
+
else
|
31
|
+
raise ArgumentError, "invalid indicator: #{indicator.inspect}"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -15,7 +15,7 @@ module Rubylog::DSL
|
|
15
15
|
# A.is(5).map{A} # => [5]
|
16
16
|
# B.is(5).and(A.is([2,B])).map{A} # => [[2,5]]
|
17
17
|
#
|
18
|
-
# When
|
18
|
+
# When a variable does not have a value, it is not substituted.
|
19
19
|
#
|
20
20
|
# A.is(B).map{A} # => [B]
|
21
21
|
# B.is(C).and(A.is([2,B])).map{A} # => [[2,C]]
|
data/lib/rubylog/errors.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Rubylog::
|
1
|
+
module Rubylog::Goal
|
2
2
|
# Clients should implement this method.
|
3
3
|
# Yields for each possible solution of the predicate
|
4
4
|
def prove
|
@@ -12,7 +12,7 @@ module Rubylog::Clause
|
|
12
12
|
|
13
13
|
def solve &block
|
14
14
|
goal = rubylog_match_variables
|
15
|
-
catch :
|
15
|
+
catch :rubylog_cut do
|
16
16
|
goal.prove { block.call_with_rubylog_variables(goal.rubylog_variables) if block }
|
17
17
|
end
|
18
18
|
end
|
data/lib/rubylog/mixins/proc.rb
CHANGED
data/lib/rubylog/procedure.rb
CHANGED
@@ -7,6 +7,10 @@ module Rubylog
|
|
7
7
|
@rules = rules
|
8
8
|
end
|
9
9
|
|
10
|
+
def inspect
|
11
|
+
"#{Rubylog::DSL::Indicators.humanize_indicator([functor,arity])}: #{@rules.inspect}"
|
12
|
+
end
|
13
|
+
|
10
14
|
def method_missing name, *args, &block
|
11
15
|
@rules.send name, *args, &block
|
12
16
|
end
|
@@ -14,7 +18,7 @@ module Rubylog
|
|
14
18
|
# accepts the *args of the called structure
|
15
19
|
def call *args
|
16
20
|
# catch cuts
|
17
|
-
catch :
|
21
|
+
catch :rubylog_cut do
|
18
22
|
|
19
23
|
# for each rule
|
20
24
|
each do |rule|
|
data/lib/rubylog/rule.rb
CHANGED
data/lib/rubylog/structure.rb
CHANGED
data/lib/rubylog/variable.rb
CHANGED
@@ -16,10 +16,12 @@ module Rubylog
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def inspect
|
19
|
+
return "#{@name}=#{@value.inspect}" if @bound
|
20
|
+
|
19
21
|
if @guards.empty?
|
20
22
|
@name.to_s
|
21
23
|
else
|
22
|
-
"#{@name}#{@guards}"
|
24
|
+
"#{@name}#{@guards.inspect}"
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
@@ -56,6 +58,7 @@ module Rubylog
|
|
56
58
|
# values are variables, unifies them with the other being bound to the
|
57
59
|
# receiver. If one of them is a variable, it gets bound to the other value.
|
58
60
|
# If none of them is a variable, they are checked for equality with eql?.
|
61
|
+
# Succeeds if other is the same object as the receiver.
|
59
62
|
#
|
60
63
|
def rubylog_unify other
|
61
64
|
# check if we are bound
|
@@ -71,11 +74,13 @@ module Rubylog
|
|
71
74
|
|
72
75
|
# if the other is a variable
|
73
76
|
if other.is_a? Rubylog::Variable
|
77
|
+
# succeed if same object
|
78
|
+
(yield; return) if self.equal? other
|
79
|
+
|
74
80
|
# we union our guards with the other's
|
75
81
|
other.append_guards guards do
|
76
|
-
#
|
77
|
-
|
78
|
-
other.bind_to self do
|
82
|
+
# and bind to the other
|
83
|
+
bind_to other do
|
79
84
|
yield
|
80
85
|
end
|
81
86
|
end
|
@@ -109,8 +114,8 @@ module Rubylog
|
|
109
114
|
end
|
110
115
|
end
|
111
116
|
|
112
|
-
#
|
113
|
-
include
|
117
|
+
# Goal methods
|
118
|
+
include Goal
|
114
119
|
|
115
120
|
def prove
|
116
121
|
v = rubylog_dereference
|
@@ -120,10 +125,25 @@ module Rubylog
|
|
120
125
|
unless v.rubylog_variables
|
121
126
|
v = v.rubylog_match_variables
|
122
127
|
end
|
123
|
-
|
124
|
-
|
125
|
-
|
128
|
+
|
129
|
+
caught_cut = false
|
130
|
+
|
131
|
+
catch :rubylog_cut do
|
132
|
+
v.prove do
|
133
|
+
# intercept cuts that come from the yield
|
134
|
+
catch :rubylog_no_cut do
|
135
|
+
catch :rubylog_cut do
|
136
|
+
yield
|
137
|
+
throw :rubylog_no_cut
|
138
|
+
end
|
139
|
+
caught_cut = true
|
140
|
+
end
|
141
|
+
break if caught_cut
|
142
|
+
end
|
126
143
|
end
|
144
|
+
|
145
|
+
# pass through cut if one was caught from yield
|
146
|
+
throw :rubylog_cut if caught_cut
|
127
147
|
end
|
128
148
|
|
129
149
|
|
data/lib/rubylog.rb
CHANGED
data/rubylog.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "rubylog"
|
8
|
-
s.version = "2.
|
8
|
+
s.version = "2.0.0"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Bern\u{e1}t Kall\u{f3}"]
|
12
|
-
s.date = "2013-05-
|
12
|
+
s.date = "2013-05-07"
|
13
13
|
s.description = "Rubylog is a Prolog-like DSL for Ruby."
|
14
14
|
s.email = "kallo.bernat@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -66,7 +66,6 @@ Gem::Specification.new do |s|
|
|
66
66
|
"lib/rubylog/builtins/logic.rb",
|
67
67
|
"lib/rubylog/builtins/reflection.rb",
|
68
68
|
"lib/rubylog/builtins/term.rb",
|
69
|
-
"lib/rubylog/clause.rb",
|
70
69
|
"lib/rubylog/compound_term.rb",
|
71
70
|
"lib/rubylog/context.rb",
|
72
71
|
"lib/rubylog/context_creation.rb",
|
@@ -77,10 +76,12 @@ Gem::Specification.new do |s|
|
|
77
76
|
"lib/rubylog/context_modules/thats.rb",
|
78
77
|
"lib/rubylog/default_context.rb",
|
79
78
|
"lib/rubylog/dsl/array_splat.rb",
|
79
|
+
"lib/rubylog/dsl/indicators.rb",
|
80
80
|
"lib/rubylog/dsl/primitives.rb",
|
81
81
|
"lib/rubylog/dsl/thats.rb",
|
82
82
|
"lib/rubylog/dsl/variables.rb",
|
83
83
|
"lib/rubylog/errors.rb",
|
84
|
+
"lib/rubylog/goal.rb",
|
84
85
|
"lib/rubylog/mixins/array.rb",
|
85
86
|
"lib/rubylog/mixins/hash.rb",
|
86
87
|
"lib/rubylog/mixins/kernel.rb",
|
@@ -185,6 +186,7 @@ Gem::Specification.new do |s|
|
|
185
186
|
"spec/rubylog/context_modules/predicates_spec.rb",
|
186
187
|
"spec/rubylog/context_modules/thats_spec.rb",
|
187
188
|
"spec/rubylog/dsl/array_splat_spec.rb",
|
189
|
+
"spec/rubylog/dsl/indicators_spec.rb",
|
188
190
|
"spec/rubylog/dsl/primitives_spec.rb",
|
189
191
|
"spec/rubylog/errors_spec.rb",
|
190
192
|
"spec/rubylog/interfaces/term_spec.rb",
|
@@ -193,6 +195,8 @@ Gem::Specification.new do |s|
|
|
193
195
|
"spec/rubylog/mixins/proc_spec.rb",
|
194
196
|
"spec/rubylog/mixins/string_spec.rb",
|
195
197
|
"spec/rubylog/mixins/symbol_spec.rb",
|
198
|
+
"spec/rubylog/procedure_spec.rb",
|
199
|
+
"spec/rubylog/rule_spec.rb",
|
196
200
|
"spec/rubylog/structure_spec.rb",
|
197
201
|
"spec/rubylog/term_spec.rb",
|
198
202
|
"spec/rubylog/tracing_spec.input",
|
data/spec/inriasuite_spec.rb
CHANGED
@@ -870,9 +870,7 @@ describe "inriasuite", :rubylog=>true do
|
|
870
870
|
specify %(['='(X,1),[[X <-- 1]]].) do
|
871
871
|
X.is(1).map{X}.should eql [1]
|
872
872
|
end
|
873
|
-
specify %(['='(X,Y),[[Y <-- X]]].)
|
874
|
-
X.is(Y).map{Y}.should eql [X]
|
875
|
-
end
|
873
|
+
specify %(['='(X,Y),[[Y <-- X]]].), pending: "This happens the other way around in Rubylog, X will be bound to Y."
|
876
874
|
specify %([('='(X,Y),'='(X,abc)),[[X <-- abc, Y <-- abc]]].) do
|
877
875
|
X.is(Y).and(X.is(:abc)).map{[X,Y]}.should eql [[:abc,:abc]]
|
878
876
|
end
|
@@ -29,9 +29,9 @@ describe "Rubylog dsl", :rubylog=>true do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
describe "variables" do
|
32
|
-
check A.is(ANY).and{ A == Rubylog::Variable.new(:
|
32
|
+
check A.is(ANY).and{ A == Rubylog::Variable.new(:ANY) }
|
33
33
|
check A.is(4) .and{ A == 4 }
|
34
|
-
check B.is(A) .and{ A == Rubylog::Variable.new(:
|
34
|
+
check B.is(A) .and{ A == Rubylog::Variable.new(:A) and B == Rubylog::Variable.new(:A) }
|
35
35
|
check B.is(ANY).and{ A == Rubylog::Variable.new(:A) }
|
36
36
|
end
|
37
37
|
|
@@ -163,6 +163,29 @@ describe "logic builtins", :rubylog => true do
|
|
163
163
|
:john.happy.if((:true.and :true).or :true)
|
164
164
|
:john.should be_happy
|
165
165
|
end
|
166
|
+
|
167
|
+
it "works after variable calls" do
|
168
|
+
(A.is(:true).and A.and :cut!.and :fail).or(:true).true?.should be_false
|
169
|
+
end
|
170
|
+
|
171
|
+
it "works after variable calls (control)" do
|
172
|
+
(A.is(:true).and A.and :fail).or(:true).true?.should be_true
|
173
|
+
end
|
174
|
+
|
175
|
+
it "works after variable calls (branch or)" do
|
176
|
+
:john.happy.if A.is(:true).and A.and :cut!.and :fail
|
177
|
+
:john.happy.if :true
|
178
|
+
:john.should_not be_happy
|
179
|
+
end
|
180
|
+
|
181
|
+
it "works after variable calls with multiple solutions of the variable" do
|
182
|
+
(A.is(B.is(4).or(B.is(6))).and A.and :cut!).map{B}.should == [4]
|
183
|
+
end
|
184
|
+
|
185
|
+
it "works after variable calls with multiple solutions of the variable (control)" do
|
186
|
+
(A.is(B.is(4).or(B.is(6))).and A).map{B}.should == [4,6]
|
187
|
+
end
|
188
|
+
|
166
189
|
end
|
167
190
|
|
168
191
|
describe "all,any,one,none,every" do
|
@@ -280,6 +303,13 @@ describe "logic builtins", :rubylog => true do
|
|
280
303
|
end
|
281
304
|
|
282
305
|
describe "every" do
|
306
|
+
specify "works as infix" do
|
307
|
+
:john.likes(X).every(:john.likes(X)).true?.should be_true
|
308
|
+
:john.likes(X).every(:jane.likes(X)).true?.should be_true
|
309
|
+
:john.likes(X).every(:jeff.likes(X)).true?.should_not be_true
|
310
|
+
:john.likes(X).every(:todd.likes(X)).true?.should_not be_true
|
311
|
+
end
|
312
|
+
|
283
313
|
specify "works like all" do
|
284
314
|
every(:john.likes(X),:john.likes(X)).true?.should be_true
|
285
315
|
every(:john.likes(X),:jane.likes(X)).true?.should be_true
|
@@ -331,6 +361,18 @@ describe "logic builtins", :rubylog => true do
|
|
331
361
|
every(:john.likes(X), X.good.assumed).and(Y.good).map{Y}.should == [:beer, :water]
|
332
362
|
end
|
333
363
|
|
364
|
+
specify "passes variables" do
|
365
|
+
solve N.is(5).and K.in{1..N}.every {N.should eql 5}
|
366
|
+
end
|
367
|
+
|
368
|
+
specify "passes variables" do
|
369
|
+
solve N.is(5).and K.in{1..N}.every L.in{1..N}
|
370
|
+
end
|
371
|
+
|
372
|
+
specify "passes variables if b contains the variable" do
|
373
|
+
solve N.is(5).and every I.in{2..N}, K.is{N/I}
|
374
|
+
end
|
375
|
+
|
334
376
|
end
|
335
377
|
|
336
378
|
|
@@ -37,10 +37,6 @@ describe "Term builtins", :rubylog => true do
|
|
37
37
|
(2.in [1,3,4]).to_a.should == []
|
38
38
|
end
|
39
39
|
|
40
|
-
it "works with clauses" do
|
41
|
-
(A.likes(B).and B.in{:john.likes(X).map{X}}).map{[A,B]}.should == [[:john, :beer]]
|
42
|
-
end
|
43
|
-
|
44
40
|
it "checks instatiation" do
|
45
41
|
expect { 5.in(B).map{B} }.to raise_error Rubylog::InstantiationError
|
46
42
|
end
|
@@ -32,26 +32,4 @@ describe Rubylog::ContextModules::Predicates, :rubylog=>true do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
describe "#humanize_indicator" do
|
36
|
-
specify { humanize_indicator([:fail,0]).should == ":fail" }
|
37
|
-
specify { humanize_indicator([:false,1]).should == ".false" }
|
38
|
-
specify { humanize_indicator([:and,2]).should == ".and()" }
|
39
|
-
specify { humanize_indicator([:splits,3]).should == ".splits(,)" }
|
40
|
-
specify { humanize_indicator([:is,4]).should == ".is(,,)" }
|
41
|
-
end
|
42
|
-
|
43
|
-
describe "#unhumanize_indicator" do
|
44
|
-
specify { unhumanize_indicator(":fail" ).should == [:fail,0] }
|
45
|
-
specify { unhumanize_indicator(".false" ).should == [:false,1] }
|
46
|
-
specify { unhumanize_indicator(".and()" ).should == [:and,2] }
|
47
|
-
specify { unhumanize_indicator(".splits(,)" ).should == [:splits,3] }
|
48
|
-
specify { unhumanize_indicator(".is(,,)" ).should == [:is,4] }
|
49
|
-
|
50
|
-
describe "with comment variables" do
|
51
|
-
specify { unhumanize_indicator("Predicate.false" ).should == [:false,1] }
|
52
|
-
specify { unhumanize_indicator("a.and(b)" ).should == [:and,2] }
|
53
|
-
specify { unhumanize_indicator("LIST.splits(HEAD,TAIL)" ).should == [:splits,3] }
|
54
|
-
specify { unhumanize_indicator("C.is(A,OP,B)" ).should == [:is,4] }
|
55
|
-
end
|
56
|
-
end
|
57
35
|
end
|
@@ -32,7 +32,7 @@ describe "thats", :rubylog=>true do
|
|
32
32
|
describe "files" do
|
33
33
|
check { "#{S[String, thats.start_with?(".")]}".filename_in(".").map{S}.include? ".gitignore" }
|
34
34
|
check { not "#{S[String, thats.start_with?(".")]}". dirname_in(".").map{S}.include? "lib" }
|
35
|
-
|
35
|
+
specify { "#{S[/\A(.*)\.rb/]}".filename_in("lib").map{S}.should == ["rubylog.rb"] }
|
36
36
|
end
|
37
37
|
|
38
38
|
describe "factorial" do
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubylog::DSL::Indicators do
|
4
|
+
describe "#humanize_indicator" do
|
5
|
+
specify { Rubylog::DSL::Indicators.humanize_indicator([:fail,0]).should == ":fail" }
|
6
|
+
specify { Rubylog::DSL::Indicators.humanize_indicator([:false,1]).should == ".false" }
|
7
|
+
specify { Rubylog::DSL::Indicators.humanize_indicator([:and,2]).should == ".and()" }
|
8
|
+
specify { Rubylog::DSL::Indicators.humanize_indicator([:splits,3]).should == ".splits(,)" }
|
9
|
+
specify { Rubylog::DSL::Indicators.humanize_indicator([:is,4]).should == ".is(,,)" }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#unhumanize_indicator" do
|
13
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator(":fail" ).should == [:fail,0] }
|
14
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator(".false" ).should == [:false,1] }
|
15
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator(".and()" ).should == [:and,2] }
|
16
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator(".splits(,)" ).should == [:splits,3] }
|
17
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator(".is(,,)" ).should == [:is,4] }
|
18
|
+
|
19
|
+
describe "with comment variables" do
|
20
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator("Predicate.false" ).should == [:false,1] }
|
21
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator("a.and(b)" ).should == [:and,2] }
|
22
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator("LIST.splits(HEAD,TAIL)" ).should == [:splits,3] }
|
23
|
+
specify { Rubylog::DSL::Indicators.unhumanize_indicator("C.is(A,OP,B)" ).should == [:is,4] }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -23,50 +23,50 @@ describe "unification", :rubylog=>true do
|
|
23
23
|
:john.rubylog_unify(:mary) { result = true }
|
24
24
|
result.should == false
|
25
25
|
end
|
26
|
-
it "works on
|
26
|
+
it "works on structures" do
|
27
27
|
result = false
|
28
28
|
(:john.likes :beer).rubylog_unify(A.likes B) { result = true }
|
29
29
|
result.should == true
|
30
30
|
end
|
31
|
-
it "works on
|
31
|
+
it "works on structures with equal values" do
|
32
32
|
result = false
|
33
33
|
(:john.likes :beer).rubylog_unify(:john.likes :beer) { result = true }
|
34
34
|
result.should == true
|
35
35
|
end
|
36
|
-
it "works on
|
36
|
+
it "works on structures with different values" do
|
37
37
|
result = false
|
38
38
|
(:john.likes :beer).rubylog_unify(:john.likes :milk) { result = true }
|
39
39
|
result.should == false
|
40
40
|
end
|
41
|
-
it "works on
|
41
|
+
it "works on structures with variables and equal values" do
|
42
42
|
result = false
|
43
43
|
(:john.likes :beer).rubylog_unify(X.likes :beer) { result = true }
|
44
44
|
result.should == true
|
45
45
|
end
|
46
|
-
it "works on
|
46
|
+
it "works on structures with variables and equal values #2" do
|
47
47
|
result = false
|
48
48
|
(:john.likes :beer).rubylog_unify(:john.likes DRINK) { result = true }
|
49
49
|
result.should == true
|
50
50
|
end
|
51
|
-
it "works on
|
51
|
+
it "works on structures with variables and different values" do
|
52
52
|
result = false
|
53
53
|
(:john.likes :beer).rubylog_unify(X.likes :milk) { result = true }
|
54
54
|
result.should == false
|
55
55
|
end
|
56
|
-
it "works on
|
56
|
+
it "works on structures with variables and different values #2" do
|
57
57
|
result = false
|
58
58
|
(:john.likes :beer).rubylog_unify(:jane.likes D) { result = true }
|
59
59
|
result.should == false
|
60
60
|
end
|
61
61
|
|
62
|
-
it "works on
|
62
|
+
it "works on structures with repeated variables #1" do
|
63
63
|
result = false
|
64
64
|
(A.likes A).rubylog_match_variables.rubylog_unify(:john.likes :jane) { result = true }
|
65
65
|
result.should == false
|
66
66
|
(A.likes A).rubylog_match_variables.rubylog_unify(:john.likes :john) { result = true }
|
67
67
|
result.should == true
|
68
68
|
end
|
69
|
-
it "works on
|
69
|
+
it "works on structures with repeated variables #1" do
|
70
70
|
result = false
|
71
71
|
(:john.likes :jane).rubylog_unify(A.likes(A).rubylog_match_variables) { result = true }
|
72
72
|
result.should == false
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "rubylog/procedure"
|
3
|
+
|
4
|
+
describe Rubylog::Procedure, rubylog:true do
|
5
|
+
describe "#inspect" do
|
6
|
+
it "returns a human-readable output" do
|
7
|
+
predicate_for String, ".likes()"
|
8
|
+
A.likes(B).predicate.inspect.should == ".likes(): []"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rubylog/rule'
|
3
|
+
|
4
|
+
describe Rubylog::Rule, rubylog:true do
|
5
|
+
describe "#inspect" do
|
6
|
+
it "returns a human-readable output" do
|
7
|
+
predicate_for String, ".likes()"
|
8
|
+
A.likes(B).if B.is(:water)
|
9
|
+
|
10
|
+
A.likes(B).predicate[0].inspect.should == "A.likes(B).if(B.is(:water))"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -57,13 +57,13 @@ describe Rubylog::Variable, :rubylog=>true do
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
it "unifies with another unbound variable with
|
60
|
+
it "unifies with another unbound variable with getting bound" do
|
61
61
|
a=A
|
62
62
|
b=B
|
63
63
|
a.rubylog_unify(b) do
|
64
|
-
|
65
|
-
|
66
|
-
|
64
|
+
a.should be_bound
|
65
|
+
a.value.should equal b
|
66
|
+
b.should_not be_bound
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -86,6 +86,23 @@ describe Rubylog::Variable, :rubylog=>true do
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
|
+
|
90
|
+
it "unifies with self" do
|
91
|
+
a=A
|
92
|
+
a.rubylog_unify(a) do
|
93
|
+
a.should_not be_bound
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it "unifies with another bound to self" do
|
98
|
+
a=A
|
99
|
+
b=B
|
100
|
+
a.rubylog_unify(b) do
|
101
|
+
b.rubylog_unify(a) do
|
102
|
+
b.should_not be_bound
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
89
106
|
end
|
90
107
|
|
91
108
|
describe "dereferencing" do
|