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
@@ -1,5 +1,6 @@
1
1
  module Kernel
2
- def theory *args, &block
3
- Rubylog.theory *args, &block
2
+ # Calls the given block within the default Rubylog context (::Rubylog)
3
+ def rubylog &block
4
+ Rubylog::DefaultContext.instance_exec &block
4
5
  end
5
6
  end
@@ -1,3 +1,2 @@
1
1
  class Method
2
- include Rubylog::Predicate
3
2
  end
@@ -2,7 +2,8 @@ class Object
2
2
  include Rubylog::Term
3
3
 
4
4
  def rubylog_matches_as_guard? other
5
- Rubylog.current_theory.print_trace 0, "#{inspect}===#{other.inspect}"
6
5
  self === other
7
6
  end
7
+
8
+ rubylog_traceable :rubylog_matches_as_guard?
8
9
  end
@@ -1,14 +1,14 @@
1
1
  class Proc
2
2
 
3
- # Callable methods
4
- include Rubylog::Callable
3
+ # Clause methods
4
+ include Rubylog::Clause
5
5
 
6
6
  def prove
7
7
  yield if call_with_rubylog_variables
8
8
  end
9
9
 
10
- # CompositeTerm methods
11
- include Rubylog::CompositeTerm
10
+ # CompoundTerm methods
11
+ include Rubylog::CompoundTerm
12
12
  def rubylog_clone
13
13
  yield dup
14
14
  end
@@ -20,18 +20,15 @@ class Proc
20
20
  call_with_rubylog_variables
21
21
  end
22
22
 
23
+ # Calls the proc with the given rubylog variables or with the currently
24
+ # available variables.
23
25
  def call_with_rubylog_variables vars = nil
24
26
  vars ||= @rubylog_variables
25
- raise Rubylog::InvalidStateError, "variables not available" if not vars
27
+ raise Rubylog::InvalidStateError, "Variables not matched" if not vars
26
28
 
27
- Rubylog::Theory.with_vars vars do
29
+ # Call the block with the variables substituted
30
+ Rubylog::DSL::Variables.with_vars vars do
28
31
  return call
29
32
  end
30
- # to pass arguments:
31
- #if arity == -1
32
- # call *@rubylog_variables.map{|v|v.value}
33
- #else
34
- # call *@rubylog_variables[0...arity].map{|v|v.value}
35
- #end
36
33
  end
37
34
  end
@@ -6,11 +6,9 @@ class String
6
6
  RubylogStringVariableGuards = [[]]
7
7
 
8
8
  def self.rubylog_unify_strings a, a_segments, a_vars, b
9
- #p a, a_segments, a_vars, b
10
9
  if a_segments.count == 1
11
10
  segment = a_segments[0]
12
11
  if b.end_with?(segment)
13
- #p b[0...b.length-segment.length]
14
12
  a_vars[0].rubylog_unify b[0...b.length-segment.length] do
15
13
  yield
16
14
  end
@@ -34,7 +32,7 @@ class String
34
32
  other_has_vars = other =~ RUBYLOG_VAR_REGEXP
35
33
 
36
34
  return super{yield} unless self_has_vars or other_has_vars
37
- raise Rubylog::InstantiationError, "Cannot unify two strings with variables inside" if self_has_vars and other_has_vars
35
+ raise ArgumentError, "Cannot unify two strings with variables inside" if self_has_vars and other_has_vars
38
36
 
39
37
  a, b = self_has_vars ? [self, other] : [other, self]
40
38
  a_segments, a_vars = a.rubylog_segments
@@ -48,8 +46,8 @@ class String
48
46
 
49
47
  end
50
48
 
51
- # CompositeTerm methods
52
- include Rubylog::CompositeTerm
49
+ # CompoundTerm methods
50
+ include Rubylog::CompoundTerm
53
51
  def rubylog_clone &block
54
52
  scan RUBYLOG_VAR_REGEXP do
55
53
  guards = RubylogStringVariableGuards[$2.to_i]
@@ -60,45 +58,39 @@ class String
60
58
 
61
59
  def rubylog_deep_dereference
62
60
  gsub RUBYLOG_VAR_REGEXP do
63
- rubylog_get_string_variable($1).rubylog_deep_dereference.to_s
61
+ rubylog_get_string_variable($1,$2).rubylog_deep_dereference.to_s
64
62
  end
65
63
  end
66
64
 
67
- # returns a list of substrings which are before, between and after the rubylog
68
- # string variables
65
+ # returns a list of substrings which are before, between and after the
66
+ # rubylog
67
+ # string variables, and the list of variabes in between
69
68
  def rubylog_segments
70
69
  segments = [[0]]
71
70
  vars = []
72
71
 
73
72
  scan RUBYLOG_VAR_REGEXP do
74
73
  match = Regexp.last_match
75
- #p match
76
- #p match.begin(0)
77
- #p match.end(0)
78
- #p match[0]
79
- #p match[1]
80
74
  segments.last << match.begin(0)
81
75
  segments << [match.end(0)]
82
- vars << rubylog_get_string_variable(match[1])
76
+ vars << rubylog_get_string_variable(match[1], match[2])
83
77
  end
84
78
 
85
79
 
86
80
  segments.last << length
87
- #p segments, vars
88
81
  segments = segments.map{|s|self[s[0]...s[1]]}
89
- #p [self, segments, vars]
90
82
  return segments, vars
91
83
  end
92
84
 
93
85
  protected
94
86
 
95
- def rubylog_get_string_variable s
96
- s = s.to_sym
97
- if @rubylog_variables
98
- @rubylog_variables.find{|v|v.name == s}
99
- else
100
- raise Rubylog::InvalidStateError, "Rubylog variables not available"
101
- end
87
+ #
88
+ def rubylog_get_string_variable name, guards_index
89
+ name = name.to_sym
90
+ raise Rubylog::InvalidStateError, "Variables not matched" unless @rubylog_variables
91
+
92
+ @rubylog_variables.find{|v|v.name == name} ||
93
+ Rubylog::Variable.new[*RubylogStringVariableGuards[guards_index.to_i]]
102
94
  end
103
95
 
104
96
  end
@@ -1,16 +1,7 @@
1
1
  class Symbol
2
2
 
3
- # a proxy for Structure
4
- def functor
5
- self
6
- end
7
-
8
- def arity
9
- 0
10
- end
11
-
12
- def indicator
13
- [self, 0]
3
+ def predicate
4
+ Rubylog::NullaryPredicates[self] or raise Rubylog::ExistenceError.new(self)
14
5
  end
15
6
 
16
7
  def args
@@ -23,22 +14,14 @@ class Symbol
23
14
  # Term methods
24
15
  include Rubylog::Term
25
16
 
26
- # Callable methods
27
- include Rubylog::Callable
17
+ # Clause methods
18
+ include Rubylog::Clause
28
19
 
29
20
  def prove
30
- begin
31
- Rubylog.current_theory.print_trace 1, self, rubylog_variables_hash
32
-
33
- predicate = Rubylog.current_theory[[self,0]]
34
- raise Rubylog::ExistenceError, indicator if not predicate
35
-
36
- predicate.call(*args) { yield }
37
-
38
- ensure
39
- Rubylog.current_theory.print_trace -1
40
- end
21
+ predicate.call { yield }
41
22
  end
42
23
 
24
+ rubylog_traceable :prove
25
+
43
26
 
44
27
  end
@@ -0,0 +1,3 @@
1
+ module Rubylog
2
+ NullaryPredicates = {}
3
+ end
@@ -0,0 +1,53 @@
1
+ module Rubylog
2
+ class Predicate
3
+
4
+ attr_reader :functor, :arity
5
+ def initialize functor, arity
6
+ @functor = functor
7
+ @arity = arity
8
+ end
9
+
10
+ # Yields for each solution of the predicate
11
+ def call *args
12
+ raise "abstract method called on #{self.inspect}"
13
+ end
14
+
15
+ def add_functor_to subjects
16
+ if arity == 0
17
+ # We treat nullary predicates differently. Do not even create functors.
18
+ Rubylog::NullaryPredicates[functor] = self
19
+ return
20
+ end
21
+
22
+ predicate = self
23
+
24
+ [subjects].flatten.each do |subject|
25
+ raise ArgumentError, "#{subject.inspect} is not a class or module" unless subject.is_a? Module
26
+ subject.class_eval do
27
+ f = predicate.functor
28
+ define_method f do |*args, &block|
29
+ args << block if block
30
+ Rubylog::Structure.new predicate, f, self, *args
31
+ end
32
+
33
+ f_bang = :"#{f}!"
34
+ define_method f_bang do |*args, &block|
35
+ args << block if block
36
+ predicate.assert Rubylog::Structure.new(predicate, f, self, *args), :true
37
+ self
38
+ end
39
+
40
+ f_qmark = :"#{f}?"
41
+ define_method f_qmark do |*args, &block|
42
+ args << block if block
43
+ Rubylog::Structure.new(predicate, f, self, *args).true?
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+
51
+
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ module Rubylog
2
+ class Primitive < Predicate
3
+
4
+ def initialize functor, callable
5
+ super functor, callable.arity
6
+ @callable = callable
7
+ end
8
+
9
+ # calls the callable with the argumens
10
+ def call *args
11
+ @callable.call(*args) { yield }
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ module Rubylog
2
+ class Procedure < Predicate
3
+ include Enumerable
4
+
5
+ def initialize functor, arity, rules=Array.new
6
+ super functor, arity
7
+ @rules = rules
8
+ end
9
+
10
+ def method_missing name, *args, &block
11
+ @rules.send name, *args, &block
12
+ end
13
+
14
+ # accepts the *args of the called structure
15
+ def call *args
16
+ # catch cuts
17
+ catch :cut do
18
+
19
+ # for each rule
20
+ each do |rule|
21
+ # compile
22
+ rule = rule.rubylog_match_variables
23
+
24
+ # unify the head with the arguments
25
+ rule.head.args.rubylog_unify(args) do
26
+ # call the body
27
+ rule.body.prove do
28
+ yield
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ rubylog_traceable :call
35
+
36
+ # Asserts a rule with a given head and body.
37
+ def assert head, body=:true
38
+ push Rubylog::Rule.new(head, body)
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,24 @@
1
+ module Rubylog
2
+
3
+ # This is an internally used class that represents a rule of a predicate.
4
+ #
5
+ class Rule
6
+ attr_reader :head, :body
7
+
8
+ def initialize head, body
9
+ @head = head
10
+ @body = body
11
+ end
12
+
13
+ # CompoundTerm methods
14
+ include Rubylog::CompoundTerm
15
+ def rubylog_clone &block
16
+ block.call Rule.new @head.rubylog_clone(&block), @body.rubylog_clone(&block)
17
+ end
18
+ def rubylog_deep_dereference
19
+ # this is not necessary
20
+ #Rule.new @head.rubylog_deep_dereference, @body.rubylog_deep_dereference
21
+ raise "Not implemented."
22
+ end
23
+ end
24
+ end
@@ -3,13 +3,19 @@ module Rubylog
3
3
 
4
4
  # data structure
5
5
  attr_reader :functor, :args
6
- def initialize functor, *args
6
+
7
+ def initialize predicate, functor, *args
7
8
  #raise Rubylog::TypeError, "functor cannot be #{functor}" unless functor.is_a? Symbol
9
+ @predicate = predicate
8
10
  @functor = functor
9
11
  @args = args.freeze
10
12
  @arity = args.count
11
13
  end
12
14
 
15
+ def predicate
16
+ @predicate
17
+ end
18
+
13
19
  def [] i
14
20
  @args[i]
15
21
  end
@@ -45,21 +51,15 @@ module Rubylog
45
51
  # Assertable methods
46
52
  include Rubylog::Assertable
47
53
 
48
- # Callable methods
49
- include Rubylog::Callable
54
+ # Clause methods
55
+ include Rubylog::Clause
50
56
 
51
57
  def prove
52
- begin
53
- Rubylog.current_theory.print_trace 1, self, rubylog_variables_hash
54
- predicate = Rubylog.current_theory[indicator]
55
- raise Rubylog::ExistenceError, indicator.inspect if not predicate
56
- count = 0
57
- predicate.call(*@args) { yield; count+=1 }
58
- count
59
- ensure
60
- Rubylog.current_theory.print_trace -1
61
- end
58
+ count = 0
59
+ predicate.call(*@args) { yield; count+=1 }
60
+ count
62
61
  end
62
+ rubylog_traceable :prove
63
63
 
64
64
 
65
65
  # enumerable methods
@@ -77,38 +77,19 @@ module Rubylog
77
77
 
78
78
  attr_reader :rubylog_variables
79
79
 
80
- # CompositeTerm methods
81
- include Rubylog::CompositeTerm
80
+ # CompoundTerm methods
81
+ include Rubylog::CompoundTerm
82
+
82
83
  def rubylog_clone &block
83
- block.call Structure.new @functor,
84
+ block.call Structure.new @predicate, @functor.rubylog_clone(&block),
84
85
  *@args.map{|a| a.rubylog_clone &block}
85
86
  end
87
+
86
88
  def rubylog_deep_dereference
87
- Structure.new @functor.rubylog_deep_dereference,
89
+ Structure.new @predicate, @functor.rubylog_deep_dereference,
88
90
  *@args.rubylog_deep_dereference
89
91
  end
90
92
 
91
-
92
- # convenience methods
93
- #def each_solution
94
- #goal = rubylog_compile_variables
95
- #goal.variable_hashes_without_compile.each do |hash|
96
- #yield goal.rubylog_clone {|i| hash[i] || i }
97
- #end
98
- #end
99
-
100
- def variable_hashes
101
- rubylog_compile_variables.variable_hashes_without_compile
102
- end
103
-
104
- protected
105
-
106
- def variable_hashes_without_compile
107
- variables = rubylog_variables
108
- map do |*values|
109
- Hash[variables.zip values]
110
- end
111
- end
112
93
  end
113
94
  end
114
95
 
@@ -11,16 +11,11 @@ module Rubylog::Term
11
11
  self
12
12
  end
13
13
 
14
- def rubylog_variables_hash
15
- vars = rubylog_variables
16
- Hash[vars.zip(vars.map{|v|v.value})]
17
- end
18
-
19
14
  def rubylog_unify other
20
15
  if other.kind_of? Rubylog::Variable
21
16
  other.rubylog_unify(self) do yield end
22
17
  else
23
- yield if self == other
18
+ yield if self.eql? other
24
19
  end
25
20
  end
26
21
 
@@ -32,7 +27,7 @@ module Rubylog::Term
32
27
  self
33
28
  end
34
29
 
35
- def rubylog_compile_variables
30
+ def rubylog_match_variables
36
31
  self
37
32
  end
38
33
  end
@@ -0,0 +1,75 @@
1
+ class Class
2
+ def rubylog_traceable name
3
+ Rubylog.traceable instance_method(name)
4
+ end
5
+ end
6
+
7
+ module Rubylog
8
+ module Tracing
9
+ attr_reader :traceable_methods
10
+ attr_accessor :trace_levels
11
+
12
+ # Turns trace on. If value is given and is false, turns trace off. If a
13
+ # block is given, calls the block with trace on.
14
+ #
15
+ def trace value=true
16
+ if not block_given?
17
+ @trace = value
18
+ @trace_levels = 0
19
+ update_trace
20
+ else
21
+ begin
22
+ trace
23
+ return yield
24
+ ensure
25
+ trace false
26
+ end
27
+ end
28
+ end
29
+
30
+ # returns true if tracing is active
31
+ def trace?
32
+ @trace
33
+ end
34
+
35
+
36
+ def traceable method
37
+ @traceable_methods ||= []
38
+ @traceable_methods << method
39
+ end
40
+
41
+ private
42
+
43
+ def update_trace
44
+ if trace?
45
+ traceable_methods.each do |m|
46
+ m.owner.send :define_method, m.name do |*args,&block|
47
+ begin
48
+ print " "*Rubylog.trace_levels
49
+ Rubylog.trace_levels += 1
50
+ print "#{inspect}.#{m.name}(#{args.map{|k|k.inspect}.join(", ")})?"
51
+ gets
52
+
53
+ return m.bind(self).call *args, &block
54
+ ensure
55
+ Rubylog.trace_levels -= 1
56
+ print " "*Rubylog.trace_levels
57
+ print "*"
58
+ puts
59
+ end
60
+ end
61
+ end
62
+ else
63
+ traceable_methods.each do |m|
64
+ m.owner.send :define_method, m.name do |*args, &block|
65
+ m.bind(self).call(*args, &block)
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ extend Tracing
73
+ end
74
+
75
+
@@ -35,8 +35,7 @@ module Rubylog
35
35
 
36
36
 
37
37
  def value
38
- return nil if (val = rubylog_dereference).kind_of? Variable
39
- val
38
+ @value if @bound
40
39
  end
41
40
 
42
41
  def dont_care?
@@ -51,7 +50,13 @@ module Rubylog
51
50
  [self]
52
51
  end
53
52
 
54
- # unify two variables
53
+ # Unifies the receiver with another value.
54
+ #
55
+ # First dereferences both the receiver and the other. If both dereferenced
56
+ # values are variables, unifies them with the other being bound to the
57
+ # receiver. If one of them is a variable, it gets bound to the other value.
58
+ # If none of them is a variable, they are checked for equality with eql?.
59
+ #
55
60
  def rubylog_unify other
56
61
  # check if we are bound
57
62
  if @bound
@@ -68,7 +73,9 @@ module Rubylog
68
73
  if other.is_a? Rubylog::Variable
69
74
  # we union our guards with the other's
70
75
  other.append_guards guards do
71
- bind_to other do
76
+ # we bind the other to self (this order comes from
77
+ # inriasuite_spec#unify)
78
+ other.bind_to self do
72
79
  yield
73
80
  end
74
81
  end
@@ -102,13 +109,21 @@ module Rubylog
102
109
  end
103
110
  end
104
111
 
105
- # Callable methods
106
- include Callable
112
+ # Clause methods
113
+ include Clause
107
114
 
108
115
  def prove
109
- v = value
110
- raise InstantiationError, self if v.nil?
111
- v.prove{yield}
116
+ v = rubylog_dereference
117
+ raise Rubylog::InstantiationError.new(self) if v.is_a? Rubylog::Variable
118
+
119
+ # match variables if not matched
120
+ unless v.rubylog_variables
121
+ v = v.rubylog_match_variables
122
+ end
123
+
124
+ catch :cut do
125
+ v.prove{yield}
126
+ end
112
127
  end
113
128
 
114
129
 
@@ -145,15 +160,19 @@ module Rubylog
145
160
  def bind_to other
146
161
  begin
147
162
  @bound = true; @value = other
148
- Rubylog.current_theory.print_trace 1, "#{inspect}=#{@value.inspect}"
149
163
 
150
164
  yield
151
-
152
165
  ensure
153
166
  @bound = false
154
- Rubylog.current_theory.print_trace -1
155
167
  end
156
168
  end
169
+ rubylog_traceable :bind_to
170
+
171
+ def bind_to! other
172
+ @bound = true; @value = other
173
+ self
174
+ end
175
+ private :bind_to!
157
176
 
158
177
  # yields with self.guards = self.guards + other_guards, then restores guards
159
178
  def append_guards other_guards