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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +3 -1
- data/README.md +6 -6
- data/Rakefile +5 -3
- data/lib/mini_kraken/core/any_value.rb +9 -7
- data/lib/mini_kraken/core/association.rb +20 -7
- data/lib/mini_kraken/core/association_walker.rb +5 -1
- data/lib/mini_kraken/core/atomic_term.rb +5 -3
- data/lib/mini_kraken/core/binary_relation.rb +8 -6
- data/lib/mini_kraken/core/composite_term.rb +5 -20
- data/lib/mini_kraken/core/cons_cell.rb +7 -3
- data/lib/mini_kraken/core/duck_fiber.rb +3 -1
- data/lib/mini_kraken/core/environment.rb +24 -10
- data/lib/mini_kraken/core/equals.rb +106 -165
- data/lib/mini_kraken/core/fail.rb +3 -1
- data/lib/mini_kraken/core/freshness.rb +11 -8
- data/lib/mini_kraken/core/goal.rb +4 -2
- data/lib/mini_kraken/core/k_integer.rb +4 -3
- data/lib/mini_kraken/core/k_symbol.rb +4 -3
- data/lib/mini_kraken/core/nullary_relation.rb +3 -1
- data/lib/mini_kraken/core/outcome.rb +5 -3
- data/lib/mini_kraken/core/relation.rb +4 -18
- data/lib/mini_kraken/core/succeed.rb +4 -2
- data/lib/mini_kraken/core/term.rb +2 -0
- data/lib/mini_kraken/core/variable.rb +13 -3
- data/lib/mini_kraken/core/variable_ref.rb +10 -32
- data/lib/mini_kraken/core/vocabulary.rb +250 -35
- data/lib/mini_kraken/glue/fresh_env.rb +5 -3
- data/lib/mini_kraken/glue/run_star_expression.rb +10 -9
- data/lib/mini_kraken/version.rb +3 -1
- data/lib/mini_kraken.rb +3 -1
- data/mini_kraken.gemspec +15 -13
- data/spec/core/association_spec.rb +4 -4
- data/spec/core/association_walker_spec.rb +25 -24
- data/spec/core/cons_cell_spec.rb +4 -3
- data/spec/core/duck_fiber_spec.rb +10 -11
- data/spec/core/environment_spec.rb +16 -28
- data/spec/core/equals_spec.rb +7 -7
- data/spec/core/fail_spec.rb +7 -7
- data/spec/core/goal_spec.rb +10 -10
- data/spec/core/k_symbol_spec.rb +5 -6
- data/spec/core/succeed_spec.rb +4 -4
- data/spec/core/variable_ref_spec.rb +0 -4
- data/spec/core/vocabulary_spec.rb +28 -22
- data/spec/glue/fresh_env_spec.rb +1 -1
- data/spec/glue/run_star_expression_spec.rb +13 -8
- data/spec/mini_kraken_spec.rb +2 -0
- data/spec/spec_helper.rb +3 -1
- data/spec/support/factory_methods.rb +4 -2
- 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
|
-
|
28
|
-
|
29
|
-
arg1, arg2
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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 =
|
95
|
+
result = Outcome.new(:"#s", anEnv) if arg1.value(anEnv).eql?(arg2)
|
58
96
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
102
|
+
# Ground case...
|
103
|
+
result = unify_composite_terms(arg1_freshness.associated, arg2, anEnv)
|
67
104
|
end
|
68
|
-
|
69
|
-
arg2.
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
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
|
-
|
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
|
-
|
109
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
19
|
+
degree == :fresh
|
18
20
|
end
|
19
21
|
|
20
22
|
def bound?
|
21
|
-
|
23
|
+
degree == :bound
|
22
24
|
end
|
23
25
|
|
24
26
|
def ground?
|
25
|
-
|
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
|
-
|
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 =
|
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 'vocabulary'
|
2
4
|
|
3
5
|
module MiniKraken
|
@@ -14,14 +16,14 @@ module MiniKraken
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def successful?
|
17
|
-
|
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
|
-
|
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
|
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
|
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]
|
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
|
-
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
75
|
-
|
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
|
-
|
82
|
-
|
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
|
-
|
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,
|
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
|