mini_kraken 0.1.04 → 0.1.05

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/Gemfile +3 -1
  4. data/README.md +6 -6
  5. data/Rakefile +5 -3
  6. data/lib/mini_kraken/core/any_value.rb +9 -7
  7. data/lib/mini_kraken/core/association.rb +20 -7
  8. data/lib/mini_kraken/core/association_walker.rb +5 -1
  9. data/lib/mini_kraken/core/atomic_term.rb +5 -3
  10. data/lib/mini_kraken/core/binary_relation.rb +8 -6
  11. data/lib/mini_kraken/core/composite_term.rb +5 -20
  12. data/lib/mini_kraken/core/cons_cell.rb +7 -3
  13. data/lib/mini_kraken/core/duck_fiber.rb +3 -1
  14. data/lib/mini_kraken/core/environment.rb +24 -10
  15. data/lib/mini_kraken/core/equals.rb +106 -165
  16. data/lib/mini_kraken/core/fail.rb +3 -1
  17. data/lib/mini_kraken/core/freshness.rb +11 -8
  18. data/lib/mini_kraken/core/goal.rb +4 -2
  19. data/lib/mini_kraken/core/k_integer.rb +4 -3
  20. data/lib/mini_kraken/core/k_symbol.rb +4 -3
  21. data/lib/mini_kraken/core/nullary_relation.rb +3 -1
  22. data/lib/mini_kraken/core/outcome.rb +5 -3
  23. data/lib/mini_kraken/core/relation.rb +4 -18
  24. data/lib/mini_kraken/core/succeed.rb +4 -2
  25. data/lib/mini_kraken/core/term.rb +2 -0
  26. data/lib/mini_kraken/core/variable.rb +13 -3
  27. data/lib/mini_kraken/core/variable_ref.rb +10 -32
  28. data/lib/mini_kraken/core/vocabulary.rb +250 -35
  29. data/lib/mini_kraken/glue/fresh_env.rb +5 -3
  30. data/lib/mini_kraken/glue/run_star_expression.rb +10 -9
  31. data/lib/mini_kraken/version.rb +3 -1
  32. data/lib/mini_kraken.rb +3 -1
  33. data/mini_kraken.gemspec +15 -13
  34. data/spec/core/association_spec.rb +4 -4
  35. data/spec/core/association_walker_spec.rb +25 -24
  36. data/spec/core/cons_cell_spec.rb +4 -3
  37. data/spec/core/duck_fiber_spec.rb +10 -11
  38. data/spec/core/environment_spec.rb +16 -28
  39. data/spec/core/equals_spec.rb +7 -7
  40. data/spec/core/fail_spec.rb +7 -7
  41. data/spec/core/goal_spec.rb +10 -10
  42. data/spec/core/k_symbol_spec.rb +5 -6
  43. data/spec/core/succeed_spec.rb +4 -4
  44. data/spec/core/variable_ref_spec.rb +0 -4
  45. data/spec/core/vocabulary_spec.rb +28 -22
  46. data/spec/glue/fresh_env_spec.rb +1 -1
  47. data/spec/glue/run_star_expression_spec.rb +13 -8
  48. data/spec/mini_kraken_spec.rb +2 -0
  49. data/spec/spec_helper.rb +3 -1
  50. data/spec/support/factory_methods.rb +4 -2
  51. metadata +2 -2
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require_relative 'binary_relation'
3
5
  # require_relative 'any_value'
@@ -24,193 +26,132 @@ module MiniKraken
24
26
  the bindings/constraints can be undone if enclosing fails, otherwise
25
27
  the bindings/constraints are rolled up.
26
28
  =end
27
- =begin
28
- def unify(aGoal, vars)
29
- arg1, arg2 = aGoal.actuals
30
- arg_kinds = [arg1.kind_of?(VariableRef), arg2.kind_of?(VariableRef)]
31
- case arg_kinds
32
- when [false, false]
33
- if arg1.eql?(arg2)
34
- result = Outcome.new(:"#s", [])
29
+ def solver_for(actuals, anEnv)
30
+ arg1, arg2 = *actuals
31
+ DuckFiber.new(:custom) { unification(arg1, arg2, anEnv) }
32
+ end
33
+
34
+ def unification(arg1, arg2, anEnv)
35
+ arg1_nil = arg1.nil?
36
+ arg2_nil = arg2.nil?
37
+ if arg1_nil || arg2_nil
38
+ if arg1_nil && arg2_nil
39
+ result = Outcome.new(:"#s", anEnv)
35
40
  else
36
41
  result = Failure
37
42
  end
38
- when [false, true]
39
- if arg2.fresh?
40
- arg2.bind_to(arg1)
41
- result = Outcome.new(:"#s", [arg1])
42
- else
43
- if arg2.value.eql?(arg1)
44
- result = Outcome.new(:"#s", [arg1])
45
- else
46
- result = Failure
47
- end
43
+ return result
44
+ end
45
+ new_arg1, new_arg2 = commute_cond(arg1, arg2, anEnv)
46
+ result = do_unification(new_arg1, new_arg2, anEnv)
47
+ # anEnv.merge(result) if result.successful? && !result.association.empty?
48
+
49
+ result
50
+ end
51
+
52
+ private
53
+
54
+ # table: Unification
55
+ # | arg1 | arg2 | Criterion || Unification |
56
+ # | isa? Atomic | isa? Atomic | arg1.eq? arg2 is true || { "s", [] } |
57
+ # | isa? Atomic | isa? Atomic | arg1.eq? arg2 is false || { "u", [] } |
58
+ # | isa? CompositeTerm | isa? Atomic | dont_care || { "u", [] } |
59
+ # | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.car, arg2.car) => "s" || { "s", [bindings*] } |
60
+ # | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.cdr, arg2.cdr) => "u" || { "u", [] ) | |
61
+ # | isa? VariableRef | isa? Atomic | arg1.fresh? is true || { "s", [arg2] } |
62
+ # | isa? VariableRef | isa? Atomic | arg1.fresh? is false || |
63
+ # | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
64
+ # | | unification(arg1.value, arg2) => "u" || { "u", [] } |
65
+ # | isa? VariableRef | isa? CompositeTerm | arg1.fresh? is true || { "s", [arg2] } | # What if arg1 occurs in arg2?
66
+ # | isa? VariableRef | isa? CompositeTerm | arg1.fresh? is false || |
67
+ # | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
68
+ # | | unification(arg1.value, arg2) => "u" || { "u", [] } |
69
+ # | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [true, true] || { "s", [arg1 <=> arg2] } |
70
+ # | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [true, false] || |
71
+ # | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
72
+ # | | unification(arg1, arg2.value) => "u" || { "u", [] } |
73
+ # | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [false, false]|| |
74
+ # | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
75
+ # | | unification(arg1, arg2.value) => "u" || { "u", [] }
76
+ def do_unification(arg1, arg2, anEnv)
77
+ # require 'debug'
78
+ return Outcome.new(:"#s", anEnv) if arg1.equal?(arg2)
79
+
80
+ result = Outcome.new(:"#u", anEnv) # default case
81
+
82
+ if arg1.kind_of?(AtomicTerm)
83
+ result = BasicSuccess if arg1.eql?(arg2)
84
+ elsif arg1.kind_of?(CompositeTerm)
85
+ if arg2.kind_of?(CompositeTerm) # AtomicTerm is default case => fail
86
+ result = unify_composite_terms(arg1, arg2, anEnv)
48
87
  end
49
- when [true, false]
50
- if arg1.fresh?
51
- arg1.bind_to(arg2)
52
- result = Outcome.new(:"#s", [arg2])
53
- else
54
- if arg1.value.eql?(arg2)
55
- result = Outcome.new(:"#s", [arg2])
88
+ elsif arg1.kind_of?(VariableRef)
89
+ arg1_freshness = arg1.freshness(anEnv)
90
+ if arg2.kind_of?(AtomicTerm)
91
+ if arg1_freshness.degree == :fresh
92
+ result = Outcome.new(:"#s", anEnv)
93
+ arg1.associate(arg2, result)
56
94
  else
57
- result = Failure
95
+ result = Outcome.new(:"#s", anEnv) if arg1.value(anEnv).eql?(arg2)
58
96
  end
59
- end
60
- when [true, true]
61
- case [arg1.fresh?, arg2.fresh?]
62
- when [false, false]
63
- if arg1.value == arg2.value
64
- result = Outcome.new(:"#s", [arg1.value])
97
+ elsif arg2.kind_of?(CompositeTerm)
98
+ if arg1_freshness.degree == :fresh
99
+ result = Outcome.new(:"#s", anEnv)
100
+ arg1.associate(arg2, result)
65
101
  else
66
- result = Failure
102
+ # Ground case...
103
+ result = unify_composite_terms(arg1_freshness.associated, arg2, anEnv)
67
104
  end
68
- when [false, true]
69
- arg2.bind_to(arg1)
70
- result = Outcome.new(:"#s", arg1.value)
71
- when [true, false]
72
- arg1.bind_to(arg2)
73
- result = Outcome.new(:"#s", arg2.value)
74
- when [true, true]
75
- if arg1.variable.name == arg2.variable.name
76
- result = Outcome.new(:"#s", [])
105
+ elsif arg2.kind_of?(VariableRef)
106
+ freshness = [arg1.fresh?(anEnv), arg2.fresh?(anEnv)]
107
+ case freshness
108
+ when [false, false] # TODO: confirm this...
109
+ result = unification(arg1.value(anEnv), arg2.value(anEnv), anEnv)
110
+ when [true, true]
111
+ result = Outcome.new(:"#s", anEnv)
112
+ if arg1.var_name != arg2.var_name
113
+ arg1.associate(arg2, result)
114
+ arg2.associate(arg1, result)
115
+ end
77
116
  else
78
- # TODO: add constraints
79
- result = Outcome.new(:"#s", [])
117
+ raise StandardError, "Unsupported freshness combination #{freshness}"
80
118
  end
119
+ else
120
+ arg_kinds = [arg1.class, arg2.class]
121
+ raise StandardError, "Unsupported combination #{arg_kinds}"
81
122
  end
82
123
  end
83
124
 
84
125
  result
85
126
  end
86
- =end
87
-
88
- def solver_for(actuals, anEnv)
89
- arg1, arg2 = *actuals
90
- DuckFiber.new(:custom) { unification(arg1, arg2, anEnv) }
91
- end
92
-
93
- def unification(arg1, arg2, anEnv)
94
- arg1_nil = arg1.nil?
95
- arg2_nil = arg2.nil?
96
- if arg1_nil || arg2_nil
97
- if arg1_nil && arg2_nil
98
- result = Outcome.new(:"#s", anEnv)
99
- else
100
- result = Failure
101
- end
102
- return result
103
- end
104
- new_arg1, new_arg2 = commute_cond(arg1, arg2, anEnv)
105
- result = do_unification(new_arg1, new_arg2, anEnv)
106
- # anEnv.merge(result) if result.successful? && !result.association.empty?
107
127
 
108
- result
109
- end
128
+ # @return [Freshness]
129
+ def unify_composite_terms(arg1, arg2, anEnv)
130
+ # require 'debug'
131
+ result = Outcome.new(:"#u", anEnv)
132
+ children1 = arg1.children
133
+ children2 = arg2.children
110
134
 
111
- private
112
-
113
- # table: Unification
114
- # | arg1 | arg2 | Criterion || Unification |
115
- # | isa? Atomic | isa? Atomic | arg1.eq? arg2 is true || { "s", [] } |
116
- # | isa? Atomic | isa? Atomic | arg1.eq? arg2 is false || { "u", [] } |
117
- # | isa? CompositeTerm | isa? Atomic | dont_care || { "u", [] } |
118
- # | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.car, arg2.car) => "s" || { "s", [bindings*] } |
119
- # | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.cdr, arg2.cdr) => "u" || { "u", [] ) | |
120
- # | isa? VariableRef | isa? Atomic | arg1.fresh? is true || { "s", [arg2] } |
121
- # | isa? VariableRef | isa? Atomic | arg1.fresh? is false || |
122
- # | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
123
- # | | unification(arg1.value, arg2) => "u" || { "u", [] } |
124
- # | isa? VariableRef | isa? CompositeTerm | arg1.fresh? is true || { "s", [arg2] } | # What if arg1 occurs in arg2?
125
- # | isa? VariableRef | isa? CompositeTerm | arg1.fresh? is false || |
126
- # | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
127
- # | | unification(arg1.value, arg2) => "u" || { "u", [] } |
128
- # | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [true, true] || { "s", [arg1 <=> arg2] } |
129
- # | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [true, false] || |
130
- # | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
131
- # | | unification(arg1, arg2.value) => "u" || { "u", [] } |
132
- # | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [false, false]|| |
133
- # | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
134
- # | | unification(arg1, arg2.value) => "u" || { "u", [] }
135
- def do_unification(arg1, arg2, anEnv)
136
- # require 'debug'
137
- return Outcome.new(:"#s", anEnv) if arg1.equal?(arg2)
138
- result = Outcome.new(:"#u", anEnv) # default case
139
-
140
- if arg1.kind_of?(AtomicTerm)
141
- result = BasicSuccess if arg1.eql?(arg2)
142
- elsif arg1.kind_of?(CompositeTerm)
143
- if arg2.kind_of?(CompositeTerm) # AtomicTerm is default case => fail
144
- result = unify_composite_terms(arg1, arg2, anEnv)
145
- end
146
- elsif arg1.kind_of?(VariableRef)
147
- arg1_freshness = arg1.freshness(anEnv)
148
- if arg2.kind_of?(AtomicTerm)
149
- if arg1_freshness.degree == :fresh
150
- result = Outcome.new(:"#s", anEnv)
151
- arg1.associate(arg2, result)
152
- else
153
- result = Outcome.new(:"#s", anEnv) if arg1.value(anEnv).eql?(arg2)
154
- end
155
- elsif arg2.kind_of?(CompositeTerm)
156
- if arg1_freshness.degree == :fresh
157
- result = Outcome.new(:"#s", anEnv)
158
- arg1.associate(arg2, result)
159
- else
160
- # Ground case...
161
- result = unify_composite_terms(arg1_freshness.associated, arg2, anEnv)
135
+ if children1.size == children2.size
136
+ i = 0
137
+ subresults = children1.map do |child1|
138
+ child2 = children2[i]
139
+ i += 1
140
+ unification(child1, child2, anEnv)
162
141
  end
163
- elsif arg2.kind_of?(VariableRef)
164
- freshness = [arg1.fresh?(anEnv), arg2.fresh?(anEnv)]
165
- case freshness
166
- when [false, false] # TODO: confirm this...
167
- result = unification(arg1.value(anEnv), arg2.value(anEnv), anEnv)
168
- when [true, true]
169
- result = Outcome.new(:"#s", anEnv)
170
- if arg1.var_name != arg2.var_name
171
- arg1.associate(arg2, result)
172
- arg2.associate(arg1, result)
142
+ total_success = subresults.all?(&:successful?)
143
+ if total_success
144
+ memo = Outcome.new(:"#s", anEnv)
145
+ associations = subresults.reduce(memo) do |sub_total, outcome|
146
+ sub_total.merge(outcome)
147
+ sub_total
173
148
  end
174
- else
175
- raise StandardError, "Unsupported freshness combination #{freshness}"
149
+ result = memo
176
150
  end
177
- else
178
- arg_kinds = [arg1.class, arg2.class]
179
- raise StandardError, "Unsupported combination #{arg_kinds}"
180
151
  end
181
- end
182
-
183
- result
184
- end
185
152
 
186
- # @return [Freshness]
187
- def unify_composite_terms(arg1, arg2, anEnv)
188
- # require 'debug'
189
- result = Outcome.new(:"#u", anEnv)
190
- children1 = arg1.children
191
- children2 = arg2.children
192
-
193
- if children1.size == children2.size
194
- i = 0
195
- subresults = children1.map do |child1|
196
- child2 = children2[i]
197
- i += 1
198
- unification(child1, child2, anEnv)
199
- end
200
- total_success = subresults.all?(&:successful?)
201
- if total_success
202
- memo = Outcome.new(:"#s", anEnv)
203
- associations = subresults.reduce(memo) do |sub_total, outcome|
204
- sub_total.merge(outcome)
205
- sub_total
206
- end
207
- result = memo
208
- end
153
+ result
209
154
  end
210
-
211
- result
212
- end
213
-
214
155
  end # class
215
156
  end # module
216
- end # module
157
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require_relative 'duck_fiber'
3
5
  require_relative 'nullary_relation'
@@ -18,4 +20,4 @@ module MiniKraken
18
20
  end
19
21
  end # class
20
22
  end # module
21
- end # module
23
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MiniKraken
2
4
  module Core
3
5
  # Freshness: fresh, bound, ground
@@ -12,31 +14,32 @@ module MiniKraken
12
14
  def initialize(aDegree, anAssociated)
13
15
  super(aDegree, valid_associated(anAssociated))
14
16
  end
15
-
17
+
16
18
  def fresh?
17
- self.degree == :fresh
19
+ degree == :fresh
18
20
  end
19
21
 
20
22
  def bound?
21
- self.degree == :bound
23
+ degree == :bound
22
24
  end
23
25
 
24
26
  def ground?
25
- self.degree == :ground
27
+ degree == :ground
26
28
  end
27
29
 
28
30
  # Does this instance represent something fresh according to
29
31
  # "Reasoned Schemer" book ?
30
32
  def rs_fresh?
31
- self.degree != ground
33
+ degree != ground
32
34
  end
33
-
35
+
34
36
  private
35
-
37
+
36
38
  def valid_associated(anAssociated)
37
39
  raise StandardError, 'Wrong argument' if anAssociated.kind_of?(self.class)
40
+
38
41
  anAssociated
39
42
  end
40
43
  end # struct
41
44
  end # module
42
- end # module
45
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'environment'
2
4
 
3
5
  module MiniKraken
@@ -31,7 +33,7 @@ module MiniKraken
31
33
  raise StandardError, err_msg
32
34
  end
33
35
 
34
- prefix = "Invalid goal argument "
36
+ prefix = 'Invalid goal argument '
35
37
  args.each do |actl|
36
38
  raise StandardError, prefix + actl.to_s unless actl.kind_of?(Term)
37
39
  end
@@ -40,4 +42,4 @@ module MiniKraken
40
42
  end
41
43
  end # class
42
44
  end # module
43
- end # module
45
+ end # module
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'atomic_term'
2
4
 
3
5
  module MiniKraken
4
6
  module Core
5
7
  # A specialized atomic term that represents an integer value.
6
- # in MiniKraken
8
+ # in MiniKraken
7
9
  class KInteger < AtomicTerm
8
-
9
10
  # @param aValue [Integer] Ruby representation of integer value
10
11
  def initialize(aValue)
11
12
  super(aValue)
12
13
  end
13
14
  end # class
14
15
  end # module
15
- end # module
16
+ end # module
@@ -1,15 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'atomic_term'
2
4
 
3
5
  module MiniKraken
4
6
  module Core
5
7
  # A specialized atomic term that represents a symbolic value.
6
- # in MiniKraken
8
+ # in MiniKraken
7
9
  class KSymbol < AtomicTerm
8
-
9
10
  # @param aValue [Symbol] Ruby representation of symbol value
10
11
  def initialize(aValue)
11
12
  super(aValue)
12
13
  end
13
14
  end # class
14
15
  end # module
15
- end # module
16
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'relation'
2
4
 
3
5
  module MiniKraken
@@ -17,4 +19,4 @@ module MiniKraken
17
19
  end
18
20
  end # class
19
21
  end # module
20
- end # module
22
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'vocabulary'
2
4
 
3
5
  module MiniKraken
@@ -14,14 +16,14 @@ module MiniKraken
14
16
  end
15
17
 
16
18
  def successful?
17
- self.resultant == :"#s"
19
+ resultant == :"#s"
18
20
  end
19
21
 
20
22
  def ==(other)
21
23
  are_equal = false
22
24
 
23
25
  if resultant == other.resultant && parent == other.parent &&
24
- associations == other.associations
26
+ associations == other.associations
25
27
  are_equal = true
26
28
  end
27
29
 
@@ -32,4 +34,4 @@ module MiniKraken
32
34
  Failure = Outcome.new(:"#u")
33
35
  BasicSuccess = Outcome.new(:"#s")
34
36
  end # module
35
- end # module
37
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MiniKraken
2
4
  module Core
3
5
  class Relation
@@ -20,25 +22,9 @@ module MiniKraken
20
22
  raise NotImplementedError
21
23
  end
22
24
 
23
- # Attempt to achieve the goal for a given context (environment)
24
- # @param anEnv [Environment] The context in which the goal take place.
25
- # @return [Fiber<Outcome>] A Fiber object that will generate the results.
26
- # def solve(args, anEnv)
27
- # Fiber instance responds to resume(*args) message
28
- # If too much resume calls => FiberError: dead fiber called message.
29
-
30
- # Fiber.new do |first_yield_arg| do
31
- # begin
32
- # result = relation.solve(actuals, anEnv)
33
- # Fiber.yield result
34
- # while result.success?
35
-
36
- nil
37
- # end
38
-
39
25
  def inspect
40
- alt_name ? alt_name : name
26
+ alt_name || name
41
27
  end
42
28
  end # class
43
29
  end # module
44
- end # module
30
+ end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'singleton'
2
4
  require_relative 'duck_fiber'
3
5
  require_relative 'nullary_relation'
@@ -11,10 +13,10 @@ module MiniKraken
11
13
  def initialize
12
14
  super('succeed', '#s')
13
15
  end
14
-
16
+
15
17
  def solver_for(_actuals, _env)
16
18
  DuckFiber.new(:success)
17
- end
19
+ end
18
20
  end # class
19
21
  end # module
20
22
  end # module
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MiniKraken
2
4
  module Core
3
5
  # The generalization of data value in MiniKraken
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'any_value'
2
4
  require_relative 'vocabulary'
3
5
 
@@ -6,12 +8,16 @@ module MiniKraken
6
8
  # Representation of a MiniKraken variable.
7
9
  # It is a named slot that can be associated with one value.
8
10
  class Variable
9
- # @return [String] Name of the variable
11
+ # @return [String] User-defined name of the variable
10
12
  attr_reader :name
11
13
 
14
+ # @return [String] Internal variable name used by MiniKraken
15
+ attr_accessor :i_name
16
+
12
17
  # @param aName [String] The name of the variable
13
18
  def initialize(aName)
14
19
  @name = valid_name(aName)
20
+ @i_name = name.dup
15
21
  end
16
22
 
17
23
  def fresh?(anEnvironment)
@@ -21,13 +27,17 @@ module MiniKraken
21
27
  # @param env [Environment]
22
28
  # @return [Freshness]
23
29
  def freshness(env)
24
- freshness = env.freshness_ref(self)
30
+ env.freshness_ref(self)
25
31
  end
26
32
 
27
33
  def ground?(anEnvironment)
28
34
  !fresh?(anEnvironment)
29
35
  end
30
36
 
37
+ def fused?
38
+ name != i_name
39
+ end
40
+
31
41
  def quote(anEnvironment)
32
42
  raise StandardError, "class #{anEnvironment}" unless anEnvironment.kind_of?(Vocabulary)
33
43
 
@@ -39,7 +49,7 @@ module MiniKraken
39
49
 
40
50
  def valid_name(aName)
41
51
  if aName.empty?
42
- raise StandardError, "Variable name may not be empty."
52
+ raise StandardError, 'Variable name may not be empty.'
43
53
  end
44
54
 
45
55
  aName
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'term'
2
4
  require_relative 'any_value'
3
- require_relative 'association'
4
5
 
5
6
  module MiniKraken
6
7
  module Core
@@ -37,8 +38,7 @@ module MiniKraken
37
38
  # @param aValue [Term]
38
39
  # @param env [Environment]
39
40
  def associate(aValue, env)
40
- assoc = Association.new(var_name, aValue)
41
- env.add_assoc(assoc)
41
+ env.add_assoc(var_name, aValue)
42
42
  end
43
43
 
44
44
  # @param env [Environment]
@@ -57,10 +57,9 @@ module MiniKraken
57
57
  # @param env [Environment]
58
58
  # @return [Freshness]
59
59
  def freshness(env)
60
- freshness = env.freshness_ref(self)
60
+ env.freshness_ref(self)
61
61
  end
62
62
 
63
-
64
63
  # @param env [Environment]
65
64
  def quote(env)
66
65
  val = env.quote_ref(self)
@@ -71,34 +70,15 @@ module MiniKraken
71
70
  # @param env [Environment]
72
71
  # @return [Boolean]
73
72
  def fused_with?(another, env)
74
- # I should point to 'another'...
75
- other_name = another.var_name
76
- to_another = values(env).find do |val|
77
- val.kind_of?(VariableRef) && val.var_name == other_name
78
- end
79
- return false unless to_another
73
+ my_var = env.name2var(var_name)
74
+ return false unless my_var.fused?
80
75
 
81
- # 'another' should point to me
82
- to_me = another.values(env).find do |val|
83
- val.kind_of?(VariableRef) && val.var_name == var_name
84
- end
85
- !to_me.nil?
76
+ other_var = env.name2var(another.var_name)
77
+ return my_var.i_name == other_var.i_name
86
78
  end
87
79
 
88
80
  def names_fused(env)
89
- to_others = values(env).select do |val|
90
- val.kind_of?(VariableRef)
91
- end
92
- return [] if to_others.empty?
93
-
94
- # 'others' should point to me
95
- to_me = to_others.select do |other|
96
- other.values(env).find do |val|
97
- val.kind_of?(VariableRef) && val.var_name == var_name
98
- end
99
- end
100
-
101
- to_me.map { |other| other.var_name }
81
+ env.names_fused(var_name)
102
82
  end
103
83
 
104
84
  # param another [VariableRef]
@@ -112,13 +92,11 @@ module MiniKraken
112
92
 
113
93
  def valid_name(aName)
114
94
  if aName.empty?
115
- raise StandardError, "Variable name may not be empty."
95
+ raise StandardError, 'Variable name may not be empty.'
116
96
  end
117
97
 
118
98
  aName
119
99
  end
120
-
121
-
122
100
  end # class
123
101
  end # module
124
102
  end # module