mini_kraken 0.1.12 → 0.2.03
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/.rubocop.yml +334 -0
- data/CHANGELOG.md +54 -0
- data/README.md +95 -13
- data/lib/mini_kraken.rb +7 -1
- data/lib/mini_kraken/core/any_value.rb +5 -1
- data/lib/mini_kraken/core/atomic_term.rb +1 -0
- data/lib/mini_kraken/core/conde.rb +1 -1
- data/lib/mini_kraken/core/conj2.rb +3 -3
- data/lib/mini_kraken/core/cons_cell.rb +29 -1
- data/lib/mini_kraken/core/cons_cell_visitor.rb +102 -0
- data/lib/mini_kraken/core/def_relation.rb +4 -0
- data/lib/mini_kraken/core/disj2.rb +2 -2
- data/lib/mini_kraken/core/environment.rb +2 -2
- data/lib/mini_kraken/core/equals.rb +60 -26
- data/lib/mini_kraken/core/formal_ref.rb +2 -1
- data/lib/mini_kraken/core/goal.rb +4 -2
- data/lib/mini_kraken/core/goal_template.rb +44 -2
- data/lib/mini_kraken/core/k_boolean.rb +4 -0
- data/lib/mini_kraken/core/k_symbol.rb +11 -0
- data/lib/mini_kraken/core/outcome.rb +11 -1
- data/lib/mini_kraken/core/variable.rb +10 -4
- data/lib/mini_kraken/core/variable_ref.rb +7 -0
- data/lib/mini_kraken/core/vocabulary.rb +8 -3
- data/lib/mini_kraken/glue/dsl.rb +236 -0
- data/lib/mini_kraken/glue/fresh_env.rb +31 -3
- data/lib/mini_kraken/glue/fresh_env_factory.rb +83 -0
- data/lib/mini_kraken/glue/run_star_expression.rb +3 -5
- data/lib/mini_kraken/version.rb +1 -1
- data/mini_kraken.gemspec +6 -3
- data/spec/.rubocop.yml +13 -0
- data/spec/core/conde_spec.rb +10 -10
- data/spec/core/conj2_spec.rb +7 -7
- data/spec/core/cons_cell_spec.rb +35 -0
- data/spec/core/cons_cell_visitor_spec.rb +144 -0
- data/spec/core/def_relation_spec.rb +6 -5
- data/spec/core/disj2_spec.rb +5 -5
- data/spec/core/duck_fiber_spec.rb +2 -2
- data/spec/core/equals_spec.rb +34 -21
- data/spec/core/goal_spec.rb +2 -2
- data/spec/core/k_boolean_spec.rb +6 -0
- data/spec/core/k_symbol_spec.rb +4 -0
- data/spec/core/outcome_spec.rb +8 -0
- data/spec/core/variable_ref_spec.rb +3 -0
- data/spec/glue/dsl_chap1_spec.rb +679 -0
- data/spec/glue/dsl_chap2_spec.rb +100 -0
- data/spec/glue/fresh_env_factory_spec.rb +97 -0
- data/spec/glue/run_star_expression_spec.rb +11 -11
- metadata +17 -4
data/lib/mini_kraken.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
# This file acts as a jumping-off point for loading dependencies expected
|
4
|
+
# for a MiniKraken client.
|
5
|
+
|
6
|
+
require_relative './mini_kraken/version'
|
7
|
+
require_relative './mini_kraken/glue/dsl'
|
4
8
|
|
5
9
|
module MiniKraken
|
6
10
|
class Error < StandardError; end
|
7
11
|
# Your code goes here...
|
8
12
|
end
|
13
|
+
|
14
|
+
# End of file
|
@@ -12,7 +12,11 @@ module MiniKraken
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def ==(other)
|
15
|
-
|
15
|
+
if other.is_a?(AnyValue)
|
16
|
+
rank == other.rank
|
17
|
+
elsif other.id2name =~ /_\d+/
|
18
|
+
rank == other.id2name.sub(/_/, '').to_i
|
19
|
+
end
|
16
20
|
end
|
17
21
|
|
18
22
|
# Use same text representation as in Reasoned Schemer.
|
@@ -43,14 +43,14 @@ unless MiniKraken::Core.constants(false).include? :Conj2
|
|
43
43
|
break unless outcome1
|
44
44
|
|
45
45
|
outcome1.parent = voc unless outcome1.parent
|
46
|
-
if outcome1.
|
46
|
+
if outcome1.success?
|
47
47
|
f2 = g2.attain(outcome1)
|
48
48
|
loop do
|
49
49
|
outcome2 = f2.resume
|
50
50
|
break unless outcome2
|
51
51
|
|
52
52
|
outcome2.parent = voc unless outcome2.parent
|
53
|
-
if outcome2.
|
53
|
+
if outcome2.success?
|
54
54
|
res = Outcome.new(:"#s", voc)
|
55
55
|
res.merge(outcome1)
|
56
56
|
res.merge(outcome2)
|
@@ -63,7 +63,7 @@ unless MiniKraken::Core.constants(false).include? :Conj2
|
|
63
63
|
else
|
64
64
|
Fiber.yield outcome1
|
65
65
|
end
|
66
|
-
if outcome1.
|
66
|
+
if outcome1.success? && (outcome2&.success? || outcome2.nil?)
|
67
67
|
voc.clear
|
68
68
|
end
|
69
69
|
end
|
@@ -10,8 +10,13 @@ unless MiniKraken::Core.constants(false).include? :ConsCell
|
|
10
10
|
attr_reader :cdr
|
11
11
|
|
12
12
|
def initialize(obj1, obj2 = nil)
|
13
|
+
super()
|
13
14
|
@car = obj1
|
14
|
-
|
15
|
+
if obj2.kind_of?(ConsCell) && obj2.null?
|
16
|
+
@cdr = nil
|
17
|
+
else
|
18
|
+
@cdr = obj2
|
19
|
+
end
|
15
20
|
end
|
16
21
|
|
17
22
|
def children
|
@@ -42,9 +47,32 @@ unless MiniKraken::Core.constants(false).include? :ConsCell
|
|
42
47
|
ConsCell.new(new_car, new_cdr)
|
43
48
|
end
|
44
49
|
|
50
|
+
# Use the list notation from Lisp as a text representation.
|
51
|
+
def to_s
|
52
|
+
return '()' if null?
|
53
|
+
|
54
|
+
"(#{pair_to_s})"
|
55
|
+
end
|
56
|
+
|
45
57
|
def append(another)
|
46
58
|
@cdr = another
|
47
59
|
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
def pair_to_s
|
64
|
+
result = +car.to_s
|
65
|
+
if cdr
|
66
|
+
result << ' '
|
67
|
+
if cdr.kind_of?(ConsCell)
|
68
|
+
result << cdr.pair_to_s
|
69
|
+
else
|
70
|
+
result << ". #{cdr}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
result
|
75
|
+
end
|
48
76
|
end # class
|
49
77
|
|
50
78
|
# Constant representing the null (empty) list.
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
require_relative 'cons_cell'
|
5
|
+
|
6
|
+
module MiniKraken
|
7
|
+
module Core
|
8
|
+
# Factory class.
|
9
|
+
# Purpose: to create an enumerator specialized in the visit of cons cells.
|
10
|
+
class ConsCellVisitor
|
11
|
+
# Build a depth-first in-order expression tree visitor.
|
12
|
+
# The visitor is implemented as an Enumerator.
|
13
|
+
# The enumerator returns couples of the form: [:car or :cdr or :nil, visitee]
|
14
|
+
# [anExpr] the term to visit.
|
15
|
+
# @param aCell [ConsCell]
|
16
|
+
# @return [Fiber]
|
17
|
+
def self.df_visitor(aCell)
|
18
|
+
first = aCell # The visit will start from the provided cons cell
|
19
|
+
visitor = Fiber.new do |skipping|
|
20
|
+
# Initialization part: will run once
|
21
|
+
visitees = Set.new # Keep track of the conscell already visited
|
22
|
+
visit_stack = first.nil? ? [] : [[:car, first]] # The LIFO queue of cells to visit
|
23
|
+
|
24
|
+
until visit_stack.empty? # Traversal part (as a loop)
|
25
|
+
to_swap = false
|
26
|
+
side, cell = visit_stack.pop
|
27
|
+
next if visitees.include?(cell)
|
28
|
+
|
29
|
+
visitees << cell
|
30
|
+
|
31
|
+
skip_children = Fiber.yield [side, cell]
|
32
|
+
# require 'debug' if skip_children
|
33
|
+
next if skip_children || skipping
|
34
|
+
|
35
|
+
skipping = false
|
36
|
+
case cell.car
|
37
|
+
when ConsCell
|
38
|
+
visit_stack.push([:car, cell.car])
|
39
|
+
to_swap = true
|
40
|
+
else
|
41
|
+
Fiber.yield [:car, cell.car]
|
42
|
+
end
|
43
|
+
|
44
|
+
case cell.cdr
|
45
|
+
when ConsCell
|
46
|
+
if to_swap
|
47
|
+
visit_stack.insert(-2, [:cdr, cell.cdr])
|
48
|
+
else
|
49
|
+
visit_stack.push([:cdr, cell.cdr])
|
50
|
+
end
|
51
|
+
else
|
52
|
+
Fiber.yield [:cdr, cell.cdr]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Send stop mark
|
57
|
+
Fiber.yield [:stop, nil]
|
58
|
+
end
|
59
|
+
|
60
|
+
=begin
|
61
|
+
visitor = Enumerator.new do |requester| # requester argument is a Yielder
|
62
|
+
# Initialization part: will run once
|
63
|
+
visitees = Set.new # Keep track of the conscell already visited
|
64
|
+
visit_stack = first.nil? ? [] : [[ :car, first ]] # The LIFO queue of cells to visit
|
65
|
+
|
66
|
+
until visit_stack.empty? # Traversal part (as a loop)
|
67
|
+
to_swap = false
|
68
|
+
side, cell = visit_stack.pop()
|
69
|
+
next if visitees.include?(cell)
|
70
|
+
|
71
|
+
requester << [side, cell]
|
72
|
+
case cell.car
|
73
|
+
when ConsCell
|
74
|
+
visit_stack.push([:car, cell.car])
|
75
|
+
to_swap = true
|
76
|
+
else
|
77
|
+
requester << [:car, cell.car]
|
78
|
+
end
|
79
|
+
|
80
|
+
case cell.cdr
|
81
|
+
when ConsCell
|
82
|
+
if to_swap
|
83
|
+
visit_stack.insert(-2, [:cdr, cell.cdr])
|
84
|
+
else
|
85
|
+
visit_stack.push([:cdr, cell.cdr])
|
86
|
+
end
|
87
|
+
else
|
88
|
+
requester << [:cdr, cell.cdr]
|
89
|
+
end
|
90
|
+
|
91
|
+
visitees << cell
|
92
|
+
end
|
93
|
+
|
94
|
+
# Send stop mark
|
95
|
+
requester << [:stop, nil]
|
96
|
+
end
|
97
|
+
=end
|
98
|
+
return visitor
|
99
|
+
end
|
100
|
+
end # class
|
101
|
+
end # module
|
102
|
+
end # module
|
@@ -15,10 +15,12 @@ module MiniKraken
|
|
15
15
|
|
16
16
|
# @param aName [String] name of def relation
|
17
17
|
# @param aGoalTemplate [GoalTemplate]
|
18
|
+
# @param theFormals [Array<FormalArg>]
|
18
19
|
def initialize(aName, aGoalTemplate, theFormals, alternateName = nil)
|
19
20
|
super(aName, alternateName)
|
20
21
|
@formals = validated_formals(theFormals)
|
21
22
|
@goal_template = validated_goal_template(aGoalTemplate)
|
23
|
+
freeze
|
22
24
|
end
|
23
25
|
|
24
26
|
# Number of arguments for the relation.
|
@@ -42,6 +44,8 @@ module MiniKraken
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def validated_goal_template(aGoalTemplate)
|
47
|
+
raise StandardError unless aGoalTemplate
|
48
|
+
|
45
49
|
aGoalTemplate
|
46
50
|
end
|
47
51
|
end # class
|
@@ -44,7 +44,7 @@ unless MiniKraken::Core.constants(false).include? :Disj2
|
|
44
44
|
break unless outcome1
|
45
45
|
|
46
46
|
outcome1.parent = voc unless outcome1.parent
|
47
|
-
if outcome1.
|
47
|
+
if outcome1.success?
|
48
48
|
Fiber.yield outcome1
|
49
49
|
outcome1.clear
|
50
50
|
end
|
@@ -55,7 +55,7 @@ unless MiniKraken::Core.constants(false).include? :Disj2
|
|
55
55
|
break unless outcome2
|
56
56
|
|
57
57
|
outcome2.parent = voc unless outcome2.parent
|
58
|
-
if outcome2.
|
58
|
+
if outcome2.success?
|
59
59
|
Fiber.yield outcome2
|
60
60
|
outcome2.clear
|
61
61
|
end
|
@@ -57,10 +57,10 @@ module MiniKraken
|
|
57
57
|
# Roll up associations from descendent outcome object
|
58
58
|
# @param descendent [Outcome]
|
59
59
|
def do_propagate(descendent)
|
60
|
-
return unless descendent.
|
60
|
+
return unless descendent.success?
|
61
61
|
|
62
62
|
vars.each_key do |var_name|
|
63
|
-
assocs = descendent[var_name]
|
63
|
+
# assocs = descendent[var_name]
|
64
64
|
move_assocs(var_name, descendent)
|
65
65
|
end
|
66
66
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'singleton'
|
4
4
|
require_relative 'binary_relation'
|
5
|
-
|
5
|
+
require_relative 'cons_cell_visitor'
|
6
6
|
require_relative 'duck_fiber'
|
7
7
|
require_relative 'variable'
|
8
8
|
require_relative 'variable_ref'
|
@@ -23,7 +23,10 @@ unless MiniKraken::Core.constants(false).include? :Equals
|
|
23
23
|
# @return [Fiber<Outcome>] A Fiber(-like) instance that yields Outcomes
|
24
24
|
def solver_for(actuals, anEnv)
|
25
25
|
arg1, arg2 = *actuals
|
26
|
-
DuckFiber.new(:custom)
|
26
|
+
DuckFiber.new(:custom) do
|
27
|
+
outcome = unification(arg1, arg2, anEnv)
|
28
|
+
outcome.prune!
|
29
|
+
end
|
27
30
|
end
|
28
31
|
|
29
32
|
def unification(arg1, arg2, anEnv)
|
@@ -38,10 +41,7 @@ unless MiniKraken::Core.constants(false).include? :Equals
|
|
38
41
|
return result
|
39
42
|
end
|
40
43
|
new_arg1, new_arg2 = commute_cond(arg1, arg2, anEnv)
|
41
|
-
|
42
|
-
# anEnv.merge(result) if result.successful? && !result.association.empty?
|
43
|
-
|
44
|
-
result
|
44
|
+
do_unification(new_arg1, new_arg2, anEnv)
|
45
45
|
end
|
46
46
|
|
47
47
|
private
|
@@ -96,7 +96,10 @@ unless MiniKraken::Core.constants(false).include? :Equals
|
|
96
96
|
arg1.associate(arg2, result)
|
97
97
|
else
|
98
98
|
# Ground case...
|
99
|
-
|
99
|
+
arg1_associated = arg1_freshness.associated
|
100
|
+
unless arg1_associated.kind_of?(AtomicTerm)
|
101
|
+
result = unify_composite_terms(arg1_associated, arg2, anEnv)
|
102
|
+
end
|
100
103
|
end
|
101
104
|
elsif arg2.kind_of?(VariableRef)
|
102
105
|
freshness = [arg1.fresh?(anEnv), arg2.fresh?(anEnv)]
|
@@ -124,33 +127,64 @@ unless MiniKraken::Core.constants(false).include? :Equals
|
|
124
127
|
result
|
125
128
|
end
|
126
129
|
|
127
|
-
# @
|
130
|
+
# @param arg1 [ConsCell]
|
131
|
+
# @param arg2 [ConsCell]
|
132
|
+
# @return [Outcome]
|
128
133
|
def unify_composite_terms(arg1, arg2, anEnv)
|
129
134
|
# require 'debug'
|
130
|
-
result = Outcome.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
135
|
+
result = Outcome.success(anEnv)
|
136
|
+
# We'll do parallel iteration
|
137
|
+
visitor1 = ConsCellVisitor.df_visitor(arg1)
|
138
|
+
visitor2 = ConsCellVisitor.df_visitor(arg2)
|
139
|
+
skip_children1 = false
|
140
|
+
skip_children2 = false
|
141
|
+
|
142
|
+
loop do
|
143
|
+
side1, cell1 = visitor1.resume(skip_children1)
|
144
|
+
side2, cell2 = visitor2.resume(skip_children2)
|
145
|
+
if side1 != side2
|
146
|
+
result = Outcome.failure(anEnv)
|
147
|
+
elsif side1 == :stop
|
148
|
+
break
|
149
|
+
else
|
150
|
+
case [cell1.class, cell2.class] # nil, AtomicTerm, ConsCell, VariableRef
|
151
|
+
when [ConsCell, ConsCell]
|
152
|
+
skip_children1 = false
|
153
|
+
skip_children2 = false
|
154
|
+
when [ConsCell, VariableRef]
|
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
|
165
|
+
skip_children1 = false
|
166
|
+
skip_children2 = false
|
167
|
+
sub_result = unification(cell1, cell2, anEnv)
|
168
|
+
result = merge_results(result, sub_result)
|
147
169
|
end
|
148
|
-
result = memo
|
149
170
|
end
|
171
|
+
|
172
|
+
break if result.failure?
|
150
173
|
end
|
151
174
|
|
152
175
|
result
|
153
176
|
end
|
177
|
+
|
178
|
+
def merge_results(result1, result2)
|
179
|
+
raise StandardError if result2.kind_of?(Hash)
|
180
|
+
|
181
|
+
if result2.success?
|
182
|
+
result1.merge(result2)
|
183
|
+
result1
|
184
|
+
else
|
185
|
+
result2
|
186
|
+
end
|
187
|
+
end
|
154
188
|
end # class
|
155
189
|
|
156
190
|
Equals.instance.freeze
|
@@ -7,10 +7,11 @@ module MiniKraken
|
|
7
7
|
# A formal reference represents the occurrence of a formal argument name in a
|
8
8
|
# goal template argument list.
|
9
9
|
class FormalRef < BaseArg
|
10
|
-
# @return [String]
|
10
|
+
# @return [String] The name of a formal argument.
|
11
11
|
attr_reader :name
|
12
12
|
|
13
13
|
def initialize(aName)
|
14
|
+
super()
|
14
15
|
@name = validated_name(aName)
|
15
16
|
end
|
16
17
|
|
@@ -16,6 +16,7 @@ module MiniKraken
|
|
16
16
|
# @param aRelation [Relation] The relation corresponding to this goal
|
17
17
|
# @param args [Array<Term>] The actual aguments of the goal
|
18
18
|
def initialize(aRelation, args)
|
19
|
+
super()
|
19
20
|
@relation = aRelation
|
20
21
|
@actuals = validated_actuals(args)
|
21
22
|
end
|
@@ -35,14 +36,15 @@ module MiniKraken
|
|
35
36
|
raise StandardError, err_msg
|
36
37
|
end
|
37
38
|
|
38
|
-
prefix = 'Invalid goal argument
|
39
|
+
prefix = 'Invalid goal argument'
|
39
40
|
args.each do |actual|
|
40
41
|
if actual.kind_of?(GoalArg) || actual.kind_of?(Environment)
|
41
42
|
next
|
42
43
|
elsif actual.kind_of?(Array)
|
43
44
|
validated_actuals(actual)
|
44
45
|
else
|
45
|
-
|
46
|
+
actual_display = actual.nil? ? 'nil' : actual.to_s
|
47
|
+
raise StandardError, "#{prefix} '#{actual_display}'"
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
@@ -1,24 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'base_arg'
|
4
|
+
require_relative 'cons_cell_visitor'
|
4
5
|
|
5
6
|
module MiniKraken
|
6
7
|
module Core
|
7
8
|
# A meta-goal that is parametrized with generic formal arguments.
|
8
9
|
# The individual goals are instantiated when the formal arguments
|
9
|
-
# are bound to goal arguments
|
10
|
+
# are bound to goal arguments.
|
10
11
|
class GoalTemplate < BaseArg
|
11
|
-
# @return [Array<BaseArg>
|
12
|
+
# @return [Array<BaseArg>] Arguments of goal template.
|
12
13
|
attr_reader :args
|
13
14
|
|
14
15
|
# @return [Relation] Main relation for the goal template
|
15
16
|
attr_reader :relation
|
16
17
|
|
18
|
+
# @param aRelation [Core::Rzlation] the relation
|
19
|
+
# @param theArgs [Array<Core::BaseArg>] Arguments of goal template.
|
17
20
|
def initialize(aRelation, theArgs)
|
21
|
+
super()
|
18
22
|
@relation = validated_relation(aRelation)
|
19
23
|
@args = validated_args(theArgs)
|
24
|
+
args.freeze
|
20
25
|
end
|
21
26
|
|
27
|
+
# Factory method: Create a goal object.
|
22
28
|
# @param formals [Array<FormalArg>] Array of formal arguments
|
23
29
|
# @param actuals [Array<GoalArg>] Array of actual arguments
|
24
30
|
# @return [Goal] instantiate a goal object given the actuals and environment
|
@@ -48,6 +54,9 @@ module MiniKraken
|
|
48
54
|
goal_args << formals2actuals[arg.name]
|
49
55
|
elsif arg.kind_of?(GoalTemplate)
|
50
56
|
goal_args << arg.send(:do_instantiate, formals2actuals)
|
57
|
+
elsif arg.kind_of?(ConsCell)
|
58
|
+
# if list contains a formal_ref it must be replaced by the actual
|
59
|
+
goal_args << transform(arg, formals2actuals)
|
51
60
|
else
|
52
61
|
goal_args << arg
|
53
62
|
end
|
@@ -55,6 +64,39 @@ module MiniKraken
|
|
55
64
|
|
56
65
|
Goal.new(relation, goal_args)
|
57
66
|
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def transform(aConsCell, formals2actuals)
|
71
|
+
return aConsCell if aConsCell.null?
|
72
|
+
|
73
|
+
member = { car: :@car, cdr: :@cdr }
|
74
|
+
visitor = ConsCellVisitor.df_visitor(aConsCell)
|
75
|
+
side, cell = visitor.resume
|
76
|
+
result = ConsCell.new(nil, nil)
|
77
|
+
node = result
|
78
|
+
|
79
|
+
loop do
|
80
|
+
side, cell = visitor.resume
|
81
|
+
break if side == :stop
|
82
|
+
|
83
|
+
converted = nil
|
84
|
+
case cell
|
85
|
+
when FormalRef
|
86
|
+
converted = formals2actuals[cell.name]
|
87
|
+
when ConsCell
|
88
|
+
converted = ConsCell.new(nil, nil)
|
89
|
+
when GoalTemplate
|
90
|
+
converted = cell.send(:do_instantiate, formals2actuals)
|
91
|
+
else
|
92
|
+
converted = cell
|
93
|
+
end
|
94
|
+
node.instance_variable_set(member[side], converted)
|
95
|
+
node = converted if converted.kind_of?(ConsCell)
|
96
|
+
end
|
97
|
+
|
98
|
+
result
|
99
|
+
end
|
58
100
|
end # class
|
59
101
|
end # module
|
60
102
|
end # module
|