mini_kraken 0.2.03 → 0.2.04
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/mini_kraken/atomic/all_atomic.rb +4 -0
- data/lib/mini_kraken/{core → atomic}/atomic_term.rb +23 -9
- data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
- data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -1
- data/lib/mini_kraken/{core → atomic}/k_symbol.rb +5 -3
- data/lib/mini_kraken/{core → composite}/composite_term.rb +6 -4
- data/lib/mini_kraken/composite/cons_cell.rb +132 -0
- data/lib/mini_kraken/{core → composite}/cons_cell_visitor.rb +1 -1
- data/lib/mini_kraken/core/association_walker.rb +14 -14
- data/lib/mini_kraken/core/binary_relation.rb +10 -10
- data/lib/mini_kraken/core/equals.rb +159 -161
- data/lib/mini_kraken/core/goal_relation.rb +2 -2
- data/lib/mini_kraken/core/goal_template.rb +7 -7
- data/lib/mini_kraken/core/{variable.rb → log_var.rb} +10 -3
- data/lib/mini_kraken/core/{variable_ref.rb → log_var_ref.rb} +3 -3
- data/lib/mini_kraken/core/tap.rb +46 -0
- data/lib/mini_kraken/core/vocabulary.rb +8 -8
- data/lib/mini_kraken/glue/dsl.rb +21 -17
- data/lib/mini_kraken/glue/fresh_env.rb +7 -2
- data/lib/mini_kraken/glue/fresh_env_factory.rb +1 -1
- data/lib/mini_kraken/glue/run_star_expression.rb +2 -2
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/.rubocop.yml +1 -1
- data/spec/atomic/atomic_term_spec.rb +94 -0
- data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
- data/spec/{core → atomic}/k_symbol_spec.rb +3 -11
- data/spec/{core → composite}/cons_cell_spec.rb +10 -8
- data/spec/{core → composite}/cons_cell_visitor_spec.rb +11 -10
- data/spec/core/association_spec.rb +6 -4
- data/spec/core/association_walker_spec.rb +8 -6
- data/spec/core/conde_spec.rb +19 -17
- data/spec/core/conj2_spec.rb +10 -8
- data/spec/core/def_relation_spec.rb +9 -7
- data/spec/core/disj2_spec.rb +11 -10
- data/spec/core/environment_spec.rb +12 -10
- data/spec/core/equals_spec.rb +12 -10
- data/spec/core/goal_spec.rb +6 -5
- data/spec/core/goal_template_spec.rb +5 -5
- data/spec/core/{variable_ref_spec.rb → log_var_ref_spec.rb} +4 -4
- data/spec/core/{variable_spec.rb → log_var_spec.rb} +4 -4
- data/spec/core/vocabulary_spec.rb +12 -11
- data/spec/glue/dsl_chap1_spec.rb +0 -45
- data/spec/glue/dsl_chap2_spec.rb +115 -7
- data/spec/glue/fresh_env_factory_spec.rb +11 -9
- data/spec/glue/fresh_env_spec.rb +3 -3
- data/spec/glue/run_star_expression_spec.rb +13 -11
- data/spec/support/factory_atomic.rb +22 -0
- data/spec/support/factory_methods.rb +11 -26
- metadata +28 -23
- data/lib/mini_kraken/core/cons_cell.rb +0 -82
- data/lib/mini_kraken/core/k_boolean.rb +0 -35
@@ -2,192 +2,190 @@
|
|
2
2
|
|
3
3
|
require 'singleton'
|
4
4
|
require_relative 'binary_relation'
|
5
|
-
require_relative 'cons_cell_visitor'
|
5
|
+
require_relative '../composite/cons_cell_visitor'
|
6
6
|
require_relative 'duck_fiber'
|
7
|
-
require_relative '
|
8
|
-
require_relative '
|
9
|
-
|
10
|
-
|
11
|
-
module
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
7
|
+
require_relative 'log_var'
|
8
|
+
require_relative 'log_var_ref'
|
9
|
+
|
10
|
+
module MiniKraken
|
11
|
+
module Core
|
12
|
+
# equals tries to unify two terms
|
13
|
+
class Equals < BinaryRelation
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super('equals', '==')
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param actuals [Array<Term>] A two-elements array
|
21
|
+
# @param anEnv [Vocabulary] A vocabulary object
|
22
|
+
# @return [Fiber<Outcome>] A Fiber(-like) instance that yields Outcomes
|
23
|
+
def solver_for(actuals, anEnv)
|
24
|
+
arg1, arg2 = *actuals
|
25
|
+
DuckFiber.new(:custom) do
|
26
|
+
outcome = unification(arg1, arg2, anEnv)
|
27
|
+
outcome.prune!
|
19
28
|
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
end
|
30
|
+
|
31
|
+
def unification(arg1, arg2, anEnv)
|
32
|
+
arg1_nil = arg1.nil?
|
33
|
+
arg2_nil = arg2.nil?
|
34
|
+
if arg1_nil || arg2_nil
|
35
|
+
if arg1_nil && arg2_nil
|
36
|
+
result = Outcome.success(anEnv)
|
37
|
+
else
|
38
|
+
result = Outcome.failure(anEnv)
|
29
39
|
end
|
40
|
+
return result
|
30
41
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
42
|
+
new_arg1, new_arg2 = commute_cond(arg1, arg2, anEnv)
|
43
|
+
do_unification(new_arg1, new_arg2, anEnv)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
|
49
|
+
# table: Unification
|
50
|
+
# | arg1 | arg2 | Criterion || Unification |
|
51
|
+
# | isa? Atomic | isa? Atomic | arg1.eq? arg2 is true || { "s", [] } |
|
52
|
+
# | isa? Atomic | isa? Atomic | arg1.eq? arg2 is false || { "u", [] } |
|
53
|
+
# | isa? CompositeTerm | isa? Atomic | dont_care || { "u", [] } |
|
54
|
+
# | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.car, arg2.car) => "s" || { "s", [bindings*] } |
|
55
|
+
# | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.cdr, arg2.cdr) => "u" || { "u", [] ) | |
|
56
|
+
# | isa? LogVarRef | isa? Atomic | arg1.fresh? is true || { "s", [arg2] } |
|
57
|
+
# | isa? LogVarRef | isa? Atomic | arg1.fresh? is false || |
|
58
|
+
# | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
|
59
|
+
# | | unification(arg1.value, arg2) => "u" || { "u", [] } |
|
60
|
+
# | isa? LogVarRef | isa? CompositeTerm | arg1.fresh? is true || { "s", [arg2] } | # What if arg1 occurs in arg2?
|
61
|
+
# | isa? LogVarRef | isa? CompositeTerm | arg1.fresh? is false || |
|
62
|
+
# | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
|
63
|
+
# | | unification(arg1.value, arg2) => "u" || { "u", [] } |
|
64
|
+
# | isa? LogVarRef | isa? LogVarRef | arg1.fresh?, arg2.fresh? => [true, true] || { "s", [arg1 <=> arg2] } |
|
65
|
+
# | isa? LogVarRef | isa? LogVarRef | arg1.fresh?, arg2.fresh? => [true, false] || |
|
66
|
+
# | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
|
67
|
+
# | | unification(arg1, arg2.value) => "u" || { "u", [] } |
|
68
|
+
# | isa? LogVarRef | isa? LogVarRef | arg1.fresh?, arg2.fresh? => [false, false]|| |
|
69
|
+
# | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
|
70
|
+
# | | unification(arg1, arg2.value) => "u" || { "u", [] }
|
71
|
+
def do_unification(arg1, arg2, anEnv)
|
72
|
+
# require 'debug'
|
73
|
+
return Outcome.success(anEnv) if arg1.equal?(arg2)
|
74
|
+
|
75
|
+
result = Outcome.failure(anEnv) # default case
|
76
|
+
|
77
|
+
if arg1.kind_of?(Atomic::AtomicTerm)
|
78
|
+
result = Outcome.success(anEnv) if arg1.eql?(arg2)
|
79
|
+
elsif arg1.kind_of?(Composite::CompositeTerm)
|
80
|
+
if arg2.kind_of?(Composite::CompositeTerm) # Atomic::AtomicTerm is default case => fail
|
81
|
+
result = unify_composite_terms(arg1, arg2, anEnv)
|
82
|
+
end
|
83
|
+
elsif arg1.kind_of?(LogVarRef)
|
84
|
+
arg1_freshness = arg1.freshness(anEnv)
|
85
|
+
if arg2.kind_of?(Atomic::AtomicTerm)
|
86
|
+
if arg1_freshness.degree == :fresh
|
37
87
|
result = Outcome.success(anEnv)
|
88
|
+
arg1.associate(arg2, result)
|
38
89
|
else
|
39
|
-
result = Outcome.
|
40
|
-
end
|
41
|
-
return result
|
42
|
-
end
|
43
|
-
new_arg1, new_arg2 = commute_cond(arg1, arg2, anEnv)
|
44
|
-
do_unification(new_arg1, new_arg2, anEnv)
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
|
49
|
-
|
50
|
-
# table: Unification
|
51
|
-
# | arg1 | arg2 | Criterion || Unification |
|
52
|
-
# | isa? Atomic | isa? Atomic | arg1.eq? arg2 is true || { "s", [] } |
|
53
|
-
# | isa? Atomic | isa? Atomic | arg1.eq? arg2 is false || { "u", [] } |
|
54
|
-
# | isa? CompositeTerm | isa? Atomic | dont_care || { "u", [] } |
|
55
|
-
# | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.car, arg2.car) => "s" || { "s", [bindings*] } |
|
56
|
-
# | isa? CompositeTerm | isa? CompositeTerm | unification(arg1.cdr, arg2.cdr) => "u" || { "u", [] ) | |
|
57
|
-
# | isa? VariableRef | isa? Atomic | arg1.fresh? is true || { "s", [arg2] } |
|
58
|
-
# | isa? VariableRef | isa? Atomic | arg1.fresh? is false || |
|
59
|
-
# | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
|
60
|
-
# | | unification(arg1.value, arg2) => "u" || { "u", [] } |
|
61
|
-
# | isa? VariableRef | isa? CompositeTerm | arg1.fresh? is true || { "s", [arg2] } | # What if arg1 occurs in arg2?
|
62
|
-
# | isa? VariableRef | isa? CompositeTerm | arg1.fresh? is false || |
|
63
|
-
# | | unification(arg1.value, arg2) => "s" || { "s", [bindings*] } |
|
64
|
-
# | | unification(arg1.value, arg2) => "u" || { "u", [] } |
|
65
|
-
# | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [true, true] || { "s", [arg1 <=> arg2] } |
|
66
|
-
# | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [true, false] || |
|
67
|
-
# | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
|
68
|
-
# | | unification(arg1, arg2.value) => "u" || { "u", [] } |
|
69
|
-
# | isa? VariableRef | isa? VariableRef | arg1.fresh?, arg2.fresh? => [false, false]|| |
|
70
|
-
# | | unification(arg1, arg2.value) => "s" || { "s", [bindings*] } |
|
71
|
-
# | | unification(arg1, arg2.value) => "u" || { "u", [] }
|
72
|
-
def do_unification(arg1, arg2, anEnv)
|
73
|
-
# require 'debug'
|
74
|
-
return Outcome.success(anEnv) if arg1.equal?(arg2)
|
75
|
-
|
76
|
-
result = Outcome.failure(anEnv) # default case
|
77
|
-
|
78
|
-
if arg1.kind_of?(AtomicTerm)
|
79
|
-
result = Outcome.success(anEnv) if arg1.eql?(arg2)
|
80
|
-
elsif arg1.kind_of?(CompositeTerm)
|
81
|
-
if arg2.kind_of?(CompositeTerm) # AtomicTerm is default case => fail
|
82
|
-
result = unify_composite_terms(arg1, arg2, anEnv)
|
90
|
+
result = Outcome.success(anEnv) if arg1.value(anEnv).eql?(arg2)
|
83
91
|
end
|
84
|
-
elsif
|
85
|
-
arg1_freshness
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
elsif arg2.kind_of?(CompositeTerm)
|
94
|
-
if arg1_freshness.degree == :fresh
|
95
|
-
result = Outcome.success(anEnv)
|
96
|
-
arg1.associate(arg2, result)
|
97
|
-
else
|
98
|
-
# Ground case...
|
99
|
-
arg1_associated = arg1_freshness.associated
|
100
|
-
unless arg1_associated.kind_of?(AtomicTerm)
|
101
|
-
result = unify_composite_terms(arg1_associated, arg2, anEnv)
|
102
|
-
end
|
92
|
+
elsif arg2.kind_of?(Composite::CompositeTerm)
|
93
|
+
if arg1_freshness.degree == :fresh
|
94
|
+
result = Outcome.success(anEnv)
|
95
|
+
arg1.associate(arg2, result)
|
96
|
+
else
|
97
|
+
# Ground case...
|
98
|
+
arg1_associated = arg1_freshness.associated
|
99
|
+
unless arg1_associated.kind_of?(Atomic::AtomicTerm)
|
100
|
+
result = unify_composite_terms(arg1_associated, arg2, anEnv)
|
103
101
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
arg2.associate(arg1, result)
|
114
|
-
end
|
115
|
-
when [true, false]
|
116
|
-
result = Outcome.success(anEnv)
|
102
|
+
end
|
103
|
+
elsif arg2.kind_of?(LogVarRef)
|
104
|
+
freshness = [arg1.fresh?(anEnv), arg2.fresh?(anEnv)]
|
105
|
+
case freshness
|
106
|
+
when [false, false] # TODO: confirm this...
|
107
|
+
result = unification(arg1.value(anEnv), arg2.value(anEnv), anEnv)
|
108
|
+
when [true, true]
|
109
|
+
result = Outcome.success(anEnv)
|
110
|
+
if arg1.var_name != arg2.var_name
|
117
111
|
arg1.associate(arg2, result)
|
118
|
-
|
119
|
-
raise StandardError, "Unsupported freshness combination #{freshness}"
|
112
|
+
arg2.associate(arg1, result)
|
120
113
|
end
|
114
|
+
when [true, false]
|
115
|
+
result = Outcome.success(anEnv)
|
116
|
+
arg1.associate(arg2, result)
|
121
117
|
else
|
122
|
-
|
123
|
-
raise StandardError, "Unsupported combination #{arg_kinds}"
|
118
|
+
raise StandardError, "Unsupported freshness combination #{freshness}"
|
124
119
|
end
|
120
|
+
else
|
121
|
+
arg_kinds = [arg1.class, arg2.class]
|
122
|
+
raise StandardError, "Unsupported combination #{arg_kinds}"
|
125
123
|
end
|
126
|
-
|
127
|
-
result
|
128
124
|
end
|
129
125
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
skip_children1 = true
|
156
|
-
skip_children2 = false
|
157
|
-
sub_result = unification(cell1, cell2, anEnv)
|
158
|
-
result = merge_results(result, sub_result)
|
159
|
-
when [VariableRef, ConsCell]
|
160
|
-
skip_children1 = false
|
161
|
-
skip_children2 = true
|
162
|
-
sub_result = do_unification(cell1, cell2, anEnv)
|
163
|
-
result = merge_results(result, sub_result)
|
164
|
-
else
|
126
|
+
result
|
127
|
+
end
|
128
|
+
|
129
|
+
# @param arg1 [Composite::ConsCell]
|
130
|
+
# @param arg2 [Composite::ConsCell]
|
131
|
+
# @return [Outcome]
|
132
|
+
def unify_composite_terms(arg1, arg2, anEnv)
|
133
|
+
# require 'debug'
|
134
|
+
result = Outcome.success(anEnv)
|
135
|
+
# We'll do parallel iteration
|
136
|
+
visitor1 = Composite::ConsCellVisitor.df_visitor(arg1)
|
137
|
+
visitor2 = Composite::ConsCellVisitor.df_visitor(arg2)
|
138
|
+
skip_children1 = false
|
139
|
+
skip_children2 = false
|
140
|
+
|
141
|
+
loop do
|
142
|
+
side1, cell1 = visitor1.resume(skip_children1)
|
143
|
+
side2, cell2 = visitor2.resume(skip_children2)
|
144
|
+
if side1 != side2
|
145
|
+
result = Outcome.failure(anEnv)
|
146
|
+
elsif side1 == :stop
|
147
|
+
break
|
148
|
+
else
|
149
|
+
case [cell1.class, cell2.class] # nil, Atomic::AtomicTerm, Composite::ConsCell, LogVarRef
|
150
|
+
when [Composite::ConsCell, Composite::ConsCell]
|
165
151
|
skip_children1 = false
|
166
152
|
skip_children2 = false
|
153
|
+
when [Composite::ConsCell, LogVarRef]
|
154
|
+
skip_children1 = true
|
155
|
+
skip_children2 = false
|
167
156
|
sub_result = unification(cell1, cell2, anEnv)
|
168
157
|
result = merge_results(result, sub_result)
|
169
|
-
|
158
|
+
when [LogVarRef, Composite::ConsCell]
|
159
|
+
skip_children1 = false
|
160
|
+
skip_children2 = true
|
161
|
+
sub_result = do_unification(cell1, cell2, anEnv)
|
162
|
+
result = merge_results(result, sub_result)
|
163
|
+
else
|
164
|
+
skip_children1 = false
|
165
|
+
skip_children2 = false
|
166
|
+
sub_result = unification(cell1, cell2, anEnv)
|
167
|
+
result = merge_results(result, sub_result)
|
170
168
|
end
|
171
|
-
|
172
|
-
break if result.failure?
|
173
169
|
end
|
174
170
|
|
175
|
-
result
|
171
|
+
break if result.failure?
|
176
172
|
end
|
177
173
|
|
178
|
-
|
179
|
-
|
174
|
+
result
|
175
|
+
end
|
180
176
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
177
|
+
def merge_results(result1, result2)
|
178
|
+
raise StandardError if result2.kind_of?(Hash)
|
179
|
+
|
180
|
+
if result2.success?
|
181
|
+
result1.merge(result2)
|
182
|
+
result1
|
183
|
+
else
|
184
|
+
result2
|
187
185
|
end
|
188
|
-
end
|
186
|
+
end
|
187
|
+
end # class
|
189
188
|
|
190
|
-
|
191
|
-
end # module
|
189
|
+
Equals.instance.freeze
|
192
190
|
end # module
|
193
|
-
end #
|
191
|
+
end # module
|
@@ -15,9 +15,9 @@ module MiniKraken
|
|
15
15
|
|
16
16
|
def validated_args(actuals)
|
17
17
|
actuals.each do |arg|
|
18
|
-
unless arg.kind_of?(Goal)
|
18
|
+
unless arg.kind_of?(Goal) || arg.kind_of?(Glue::FreshEnv)
|
19
19
|
prefix = "#{name} expects goal as argument, found a "
|
20
|
-
raise StandardError, prefix + "'#{arg.class}'"
|
20
|
+
raise StandardError, prefix + "'#{arg.class}': #{arg}"
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'base_arg'
|
4
|
-
require_relative 'cons_cell_visitor'
|
4
|
+
require_relative '../composite/cons_cell_visitor'
|
5
5
|
|
6
6
|
module MiniKraken
|
7
7
|
module Core
|
@@ -54,7 +54,7 @@ module MiniKraken
|
|
54
54
|
goal_args << formals2actuals[arg.name]
|
55
55
|
elsif arg.kind_of?(GoalTemplate)
|
56
56
|
goal_args << arg.send(:do_instantiate, formals2actuals)
|
57
|
-
elsif arg.kind_of?(ConsCell)
|
57
|
+
elsif arg.kind_of?(Composite::ConsCell)
|
58
58
|
# if list contains a formal_ref it must be replaced by the actual
|
59
59
|
goal_args << transform(arg, formals2actuals)
|
60
60
|
else
|
@@ -71,9 +71,9 @@ module MiniKraken
|
|
71
71
|
return aConsCell if aConsCell.null?
|
72
72
|
|
73
73
|
member = { car: :@car, cdr: :@cdr }
|
74
|
-
visitor = ConsCellVisitor.df_visitor(aConsCell)
|
74
|
+
visitor = Composite::ConsCellVisitor.df_visitor(aConsCell)
|
75
75
|
side, cell = visitor.resume
|
76
|
-
result = ConsCell.new(nil, nil)
|
76
|
+
result = Composite::ConsCell.new(nil, nil)
|
77
77
|
node = result
|
78
78
|
|
79
79
|
loop do
|
@@ -84,15 +84,15 @@ module MiniKraken
|
|
84
84
|
case cell
|
85
85
|
when FormalRef
|
86
86
|
converted = formals2actuals[cell.name]
|
87
|
-
when ConsCell
|
88
|
-
converted = ConsCell.new(nil, nil)
|
87
|
+
when Composite::ConsCell
|
88
|
+
converted = Composite::ConsCell.new(nil, nil)
|
89
89
|
when GoalTemplate
|
90
90
|
converted = cell.send(:do_instantiate, formals2actuals)
|
91
91
|
else
|
92
92
|
converted = cell
|
93
93
|
end
|
94
94
|
node.instance_variable_set(member[side], converted)
|
95
|
-
node = converted if converted.kind_of?(ConsCell)
|
95
|
+
node = converted if converted.kind_of?(Composite::ConsCell)
|
96
96
|
end
|
97
97
|
|
98
98
|
result
|
@@ -6,24 +6,31 @@ require_relative 'vocabulary'
|
|
6
6
|
|
7
7
|
module MiniKraken
|
8
8
|
module Core
|
9
|
-
# Representation of a MiniKraken variable.
|
10
|
-
# It is a named slot that can be associated with one value.
|
11
|
-
|
9
|
+
# Representation of a MiniKraken logical variable.
|
10
|
+
# It is a named slot that can be associated with one value at the time.
|
11
|
+
# In relational programming, there is no explicit assignment expression.
|
12
|
+
# A logical variable acquire a value through an algorithm called
|
13
|
+
# 'unification'.
|
14
|
+
class LogVar
|
12
15
|
include Designation # Mixin: Acquire name attribute
|
13
16
|
|
14
17
|
# @return [String] Internal variable name used by MiniKraken
|
15
18
|
attr_accessor :i_name
|
16
19
|
|
20
|
+
# Create a logical variable with given name
|
17
21
|
# @param aName [String] The name of the variable
|
18
22
|
def initialize(aName)
|
19
23
|
init_designation(aName)
|
20
24
|
@i_name = name.dup
|
21
25
|
end
|
22
26
|
|
27
|
+
# Indicate whether this variable is fused with another one.
|
28
|
+
# @return [Boolean]
|
23
29
|
def fused?
|
24
30
|
name != i_name
|
25
31
|
end
|
26
32
|
|
33
|
+
# @param [Core::Vocabulary]
|
27
34
|
def quote(env)
|
28
35
|
raise StandardError, "class #{env}" unless env.kind_of?(Vocabulary)
|
29
36
|
|
@@ -8,7 +8,7 @@ module MiniKraken
|
|
8
8
|
module Core
|
9
9
|
# A variable reference represents the occurrence of a variable (name) in a
|
10
10
|
# MiniKraken term.
|
11
|
-
class
|
11
|
+
class LogVarRef < Term
|
12
12
|
include Designation # Mixin: Acquire name attribute
|
13
13
|
alias var_name name
|
14
14
|
|
@@ -48,7 +48,7 @@ module MiniKraken
|
|
48
48
|
val.nil? ? AnyValue.new(var_name, env, names_fused(env)) : val
|
49
49
|
end
|
50
50
|
|
51
|
-
# param another [
|
51
|
+
# param another [LogVarRef]
|
52
52
|
# @param env [Environment]
|
53
53
|
# @return [Boolean]
|
54
54
|
def fused_with?(another, env)
|
@@ -63,7 +63,7 @@ module MiniKraken
|
|
63
63
|
env.names_fused(var_name)
|
64
64
|
end
|
65
65
|
|
66
|
-
# param another [
|
66
|
+
# param another [LogVarRef]
|
67
67
|
# @param env [Environment]
|
68
68
|
# @return [Boolean]
|
69
69
|
def different_from?(another, env)
|