rubylog 2.0pre1 → 2.0.0

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.
@@ -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 variables do not have a value, it is not substituted.
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]]
@@ -19,8 +19,8 @@ module Rubylog
19
19
  end
20
20
 
21
21
  class ExistenceError < RubylogError
22
- def initialize clause
23
- super "Predicate #{clause.inspect} does not exist"
22
+ def initialize goal
23
+ super "Predicate #{goal.inspect} does not exist"
24
24
  end
25
25
  end
26
26
 
@@ -1,4 +1,4 @@
1
- module Rubylog::Clause
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 :cut do
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
@@ -1,7 +1,7 @@
1
1
  class Proc
2
2
 
3
- # Clause methods
4
- include Rubylog::Clause
3
+ # Goal methods
4
+ include Rubylog::Goal
5
5
 
6
6
  def prove
7
7
  yield if call_with_rubylog_variables
@@ -14,8 +14,8 @@ class Symbol
14
14
  # Term methods
15
15
  include Rubylog::Term
16
16
 
17
- # Clause methods
18
- include Rubylog::Clause
17
+ # Goal methods
18
+ include Rubylog::Goal
19
19
 
20
20
  def prove
21
21
  predicate.call { yield }
@@ -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 :cut do
21
+ catch :rubylog_cut do
18
22
 
19
23
  # for each rule
20
24
  each do |rule|
data/lib/rubylog/rule.rb CHANGED
@@ -10,6 +10,10 @@ module Rubylog
10
10
  @body = body
11
11
  end
12
12
 
13
+ def inspect
14
+ "#{head.inspect}.if(#{body.inspect})"
15
+ end
16
+
13
17
  # CompoundTerm methods
14
18
  include Rubylog::CompoundTerm
15
19
  def rubylog_clone &block
@@ -51,8 +51,8 @@ module Rubylog
51
51
  # Assertable methods
52
52
  include Rubylog::Assertable
53
53
 
54
- # Clause methods
55
- include Rubylog::Clause
54
+ # Goal methods
55
+ include Rubylog::Goal
56
56
 
57
57
  def prove
58
58
  count = 0
@@ -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
- # we bind the other to self (this order comes from
77
- # inriasuite_spec#unify)
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
- # Clause methods
113
- include Clause
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
- catch :cut do
125
- v.prove{yield}
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
@@ -10,7 +10,7 @@ require 'rubylog/tracing'
10
10
 
11
11
  # interfaces
12
12
  require 'rubylog/term'
13
- require 'rubylog/clause'
13
+ require 'rubylog/goal'
14
14
  require 'rubylog/assertable'
15
15
  require 'rubylog/compound_term'
16
16
 
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.0pre1"
8
+ s.version = "2.0.0"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
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-02"
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",
@@ -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]]].) do
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(:A) }
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(:B) and B == Rubylog::Variable.new(:B) }
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
- check { "#{S[/\A(.*)\.rb/]}".filename_in("lib").map{S} == ["rubylog.rb"] }
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 clauses" do
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 clauses with equal values" do
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 clauses with different values" do
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 clauses with variables and equal values" do
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 clauses with variables and equal values #2" do
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 clauses with variables and different values" do
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 clauses with variables and different values #2" do
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 clauses with repeated variables #1" do
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 clauses with repeated variables #1" do
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
@@ -34,7 +34,7 @@ describe Array, :rubylog=>true do
34
34
  a = A
35
35
  b = B
36
36
  can_unify [*a], [*b] do
37
- b.value.should equal a
37
+ a.value.should equal b
38
38
  end
39
39
  end
40
40
 
@@ -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 the other gettin bound" do
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
- b.should be_bound
65
- b.value.should equal a
66
- a.should_not be_bound
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