mini_kraken 0.2.04 → 0.3.00
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +16 -16
- data/lib/mini_kraken/atomic/all_atomic.rb +1 -0
- data/lib/mini_kraken/atomic/atomic_term.rb +32 -17
- data/lib/mini_kraken/atomic/k_integer.rb +0 -4
- data/lib/mini_kraken/atomic/k_string.rb +17 -0
- data/lib/mini_kraken/atomic/k_symbol.rb +0 -6
- data/lib/mini_kraken/composite/all_composite.rb +4 -0
- data/lib/mini_kraken/composite/composite_term.rb +2 -18
- data/lib/mini_kraken/composite/cons_cell.rb +178 -11
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +12 -64
- data/lib/mini_kraken/composite/list.rb +32 -0
- data/lib/mini_kraken/core/all_core.rb +8 -0
- data/lib/mini_kraken/core/any_value.rb +31 -7
- data/lib/mini_kraken/core/arity.rb +69 -0
- data/lib/mini_kraken/core/association.rb +29 -4
- data/lib/mini_kraken/core/association_copy.rb +50 -0
- data/lib/mini_kraken/core/base_term.rb +13 -0
- data/lib/mini_kraken/core/blackboard.rb +315 -0
- data/lib/mini_kraken/core/bookmark.rb +46 -0
- data/lib/mini_kraken/core/context.rb +624 -0
- data/lib/mini_kraken/core/duck_fiber.rb +21 -19
- data/lib/mini_kraken/core/entry.rb +40 -0
- data/lib/mini_kraken/core/fail.rb +20 -18
- data/lib/mini_kraken/core/fusion.rb +29 -0
- data/lib/mini_kraken/core/goal.rb +20 -29
- data/lib/mini_kraken/core/log_var.rb +4 -30
- data/lib/mini_kraken/core/log_var_ref.rb +72 -48
- data/lib/mini_kraken/core/nullary_relation.rb +2 -9
- data/lib/mini_kraken/core/parametrized_term.rb +61 -0
- data/lib/mini_kraken/core/relation.rb +14 -28
- data/lib/mini_kraken/core/scope.rb +67 -0
- data/lib/mini_kraken/core/solver_adapter.rb +58 -0
- data/lib/mini_kraken/core/specification.rb +48 -0
- data/lib/mini_kraken/core/succeed.rb +21 -17
- data/lib/mini_kraken/core/symbol_table.rb +137 -0
- data/lib/mini_kraken/core/term.rb +15 -4
- data/lib/mini_kraken/glue/dsl.rb +35 -69
- data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
- data/lib/mini_kraken/rela/all_rela.rb +8 -0
- data/lib/mini_kraken/rela/binary_relation.rb +30 -0
- data/lib/mini_kraken/rela/conde.rb +146 -0
- data/lib/mini_kraken/rela/conj2.rb +65 -0
- data/lib/mini_kraken/rela/def_relation.rb +64 -0
- data/lib/mini_kraken/rela/disj2.rb +70 -0
- data/lib/mini_kraken/rela/fresh.rb +98 -0
- data/lib/mini_kraken/{core → rela}/goal_relation.rb +6 -8
- data/lib/mini_kraken/rela/unify.rb +258 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/atomic/atomic_term_spec.rb +23 -20
- data/spec/atomic/k_symbol_spec.rb +0 -5
- data/spec/composite/cons_cell_spec.rb +116 -0
- data/spec/composite/cons_cell_visitor_spec.rb +16 -3
- data/spec/composite/list_spec.rb +50 -0
- data/spec/core/any_value_spec.rb +52 -0
- data/spec/core/arity_spec.rb +91 -0
- data/spec/core/association_copy_spec.rb +69 -0
- data/spec/core/association_spec.rb +25 -0
- data/spec/core/blackboard_spec.rb +287 -0
- data/spec/core/bookmark_spec.rb +40 -0
- data/spec/core/context_spec.rb +221 -0
- data/spec/core/core_spec.rb +40 -0
- data/spec/core/duck_fiber_spec.rb +22 -46
- data/spec/core/fail_spec.rb +5 -6
- data/spec/core/goal_spec.rb +20 -11
- data/spec/core/log_var_ref_spec.rb +80 -5
- data/spec/core/log_var_spec.rb +35 -6
- data/spec/core/nullary_relation_spec.rb +33 -0
- data/spec/core/parametrized_tem_spec.rb +39 -0
- data/spec/core/relation_spec.rb +33 -0
- data/spec/core/scope_spec.rb +73 -0
- data/spec/core/solver_adapter_spec.rb +70 -0
- data/spec/core/specification_spec.rb +43 -0
- data/spec/core/succeed_spec.rb +5 -5
- data/spec/core/symbol_table_spec.rb +142 -0
- data/spec/glue/dsl_chap1_spec.rb +88 -99
- data/spec/glue/dsl_chap2_spec.rb +59 -41
- data/spec/glue/run_star_expression_spec.rb +69 -896
- data/spec/{core → rela}/conde_spec.rb +50 -46
- data/spec/rela/conj2_spec.rb +123 -0
- data/spec/rela/def_relation_spec.rb +119 -0
- data/spec/rela/disj2_spec.rb +117 -0
- data/spec/rela/fresh_spec.rb +147 -0
- data/spec/rela/unify_spec.rb +369 -0
- data/spec/support/factory_atomic.rb +7 -0
- data/spec/support/factory_composite.rb +21 -0
- metadata +71 -48
- data/lib/mini_kraken/core/association_walker.rb +0 -183
- data/lib/mini_kraken/core/base_arg.rb +0 -10
- data/lib/mini_kraken/core/binary_relation.rb +0 -63
- data/lib/mini_kraken/core/composite_goal.rb +0 -46
- data/lib/mini_kraken/core/conde.rb +0 -143
- data/lib/mini_kraken/core/conj2.rb +0 -79
- data/lib/mini_kraken/core/def_relation.rb +0 -53
- data/lib/mini_kraken/core/designation.rb +0 -55
- data/lib/mini_kraken/core/disj2.rb +0 -72
- data/lib/mini_kraken/core/environment.rb +0 -73
- data/lib/mini_kraken/core/equals.rb +0 -191
- data/lib/mini_kraken/core/formal_arg.rb +0 -22
- data/lib/mini_kraken/core/formal_ref.rb +0 -25
- data/lib/mini_kraken/core/freshness.rb +0 -45
- data/lib/mini_kraken/core/goal_arg.rb +0 -12
- data/lib/mini_kraken/core/goal_template.rb +0 -102
- data/lib/mini_kraken/core/outcome.rb +0 -63
- data/lib/mini_kraken/core/tap.rb +0 -46
- data/lib/mini_kraken/core/vocabulary.rb +0 -446
- data/lib/mini_kraken/glue/fresh_env.rb +0 -108
- data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
- data/spec/core/association_walker_spec.rb +0 -194
- data/spec/core/conj2_spec.rb +0 -116
- data/spec/core/def_relation_spec.rb +0 -99
- data/spec/core/disj2_spec.rb +0 -100
- data/spec/core/environment_spec.rb +0 -144
- data/spec/core/equals_spec.rb +0 -319
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -56
- data/spec/core/vocabulary_spec.rb +0 -220
- data/spec/glue/fresh_env_factory_spec.rb +0 -99
- data/spec/glue/fresh_env_spec.rb +0 -62
@@ -1,45 +1,47 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'context'
|
4
4
|
|
5
5
|
module MiniKraken
|
6
6
|
module Core
|
7
7
|
# A mock class that mimicks the behavior of a Fiber instance.
|
8
|
+
# More specifically, it responds to `resume` message & returns a Context.
|
8
9
|
class DuckFiber
|
9
|
-
# @return [
|
10
|
-
attr_reader :
|
10
|
+
# @return [Proc, #call] The callable object to yield.
|
11
|
+
attr_reader :callable
|
11
12
|
|
12
13
|
# @return [Symbol] one of: :initial, :yielded
|
13
14
|
attr_reader :state
|
14
15
|
|
15
|
-
#
|
16
|
-
|
16
|
+
# Constructor.
|
17
|
+
# @param aCallable [Proc, #call] The receiver of the 'call' message.
|
18
|
+
def initialize(aCallable)
|
19
|
+
@callable = valid_callable(aCallable)
|
17
20
|
@state = :initial
|
18
|
-
if outcomeKind == :custom && block_given?
|
19
|
-
@outcome = customization.call
|
20
|
-
else
|
21
|
-
@outcome = valid_outcome(outcomeKind)
|
22
|
-
end
|
23
21
|
end
|
24
22
|
|
23
|
+
# Quacks like a Fiber object.
|
24
|
+
# The first time, this method will return a Context objet.
|
25
|
+
# Subsequents calls just return nil (= no other solution available)
|
26
|
+
# @return [Core::Context, NilClass]
|
25
27
|
def resume(*_args)
|
26
28
|
if state == :initial
|
27
29
|
@state = :yielded
|
28
|
-
return
|
30
|
+
return callable.call
|
29
31
|
else
|
30
32
|
return nil
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
else
|
41
|
-
raise StandardError, "Unknonw outcome kind #{outcomeKind}"
|
36
|
+
private
|
37
|
+
|
38
|
+
def valid_callable(aCallable)
|
39
|
+
unless aCallable.kind_of?(Proc) || aCallable.respond_to?(:call)
|
40
|
+
err_msg = "Expected a Proc instead of #{aCallable.class}."
|
41
|
+
raise StandardError, err_msg
|
42
42
|
end
|
43
|
+
|
44
|
+
aCallable
|
43
45
|
end
|
44
46
|
end # class
|
45
47
|
end # module
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MiniKraken
|
4
|
+
module Core
|
5
|
+
# Mix-in module that implements the expected common behaviour of entries
|
6
|
+
# placed in the symbol table.
|
7
|
+
module Entry
|
8
|
+
# @return [String] User-defined name of the entry.
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# @return [String] Suffix for building the internal name of the entry.
|
12
|
+
attr_accessor :suffix
|
13
|
+
|
14
|
+
alias label name
|
15
|
+
|
16
|
+
# Initialize the entry with given name
|
17
|
+
# @param aName [String] The name of the entry
|
18
|
+
def init_name(aName)
|
19
|
+
@name = aName.dup
|
20
|
+
@name.freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return the internal name of the entry
|
24
|
+
# Internal names used to disambiguate entry names.
|
25
|
+
# There might be homonyns between variable because:
|
26
|
+
# - A child Scope may have a entry with same name as one of its
|
27
|
+
# ancestor(s).
|
28
|
+
# - Multiple calls to same defrel or procedure may imply multiple creation
|
29
|
+
# of a entry given name...
|
30
|
+
# @return [String] internal name
|
31
|
+
def i_name
|
32
|
+
if suffix =~ /^_/
|
33
|
+
label + suffix
|
34
|
+
else
|
35
|
+
(suffix.nil? || suffix.empty?) ? label : suffix
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end # module
|
39
|
+
end # module
|
40
|
+
end # module
|
@@ -4,24 +4,26 @@ require 'singleton'
|
|
4
4
|
require_relative 'duck_fiber'
|
5
5
|
require_relative 'nullary_relation'
|
6
6
|
|
7
|
-
|
8
|
-
module
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
include Singleton
|
7
|
+
module MiniKraken
|
8
|
+
module Core
|
9
|
+
# A nullary relation that always returns a failure outcome.
|
10
|
+
class Fail < NullaryRelation
|
11
|
+
include Singleton
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
# Constructor. Initialize the relation's name & freeze it...
|
14
|
+
def initialize
|
15
|
+
super('fail')
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
# Returns a Fiber-like object (a DuckFiber).
|
19
|
+
# When that object receives the message resume, it will
|
20
|
+
# signal a failure to the provided context.
|
21
|
+
# @param _actuals [Array] MUST be empty array for nullary relation.
|
22
|
+
# @param ctx [Core::Context] Runtime context
|
23
|
+
# @return [Core::DuckFiber]
|
24
|
+
def solver_for(_actuals, ctx)
|
25
|
+
DuckFiber.new(-> { ctx.failed! })
|
26
|
+
end
|
27
|
+
end # class
|
26
28
|
end # module
|
27
|
-
end #
|
29
|
+
end # module
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
module MiniKraken
|
5
|
+
module Core
|
6
|
+
# A record of the fusion / merge of two or more logical variables.
|
7
|
+
class Fusion
|
8
|
+
# @return [String] i_name of substituting variable.
|
9
|
+
attr_reader :i_name
|
10
|
+
|
11
|
+
# @return [Array<String>] i_names of variables being substituted
|
12
|
+
attr_reader :elements
|
13
|
+
|
14
|
+
# Records the fusion of two or more logical variables.
|
15
|
+
# The fused variables are substituted by a new variable
|
16
|
+
# @param aName [String] Internal name of the substituting variable
|
17
|
+
# @param fused [Array<String>] The i_names of the fused variables
|
18
|
+
def initialize(aName, fused)
|
19
|
+
@i_name = aName
|
20
|
+
@elements = fused
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Set] The empty set
|
24
|
+
def dependencies(_ctx)
|
25
|
+
@dependencies ||= Set.new(elements)
|
26
|
+
end
|
27
|
+
end # class
|
28
|
+
end # module
|
29
|
+
end # module
|
@@ -1,48 +1,39 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative 'parametrized_term'
|
4
|
+
require_relative 'context'
|
4
5
|
|
5
6
|
module MiniKraken
|
6
|
-
require_relative 'goal_arg'
|
7
|
-
|
8
7
|
module Core
|
9
|
-
class Goal <
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# @
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# @param args [Array<Term>] The actual aguments of the goal
|
18
|
-
def initialize(aRelation, args)
|
19
|
-
super()
|
20
|
-
@relation = aRelation
|
21
|
-
@actuals = validated_actuals(args)
|
22
|
-
end
|
23
|
-
|
24
|
-
# Attempt to achieve the goal for a given context (environment)
|
25
|
-
# @param anEnv [Environment] The context in which the goal take place.
|
26
|
-
# @return [Fiber<Outcome>] A Fiber object that will generate the results.
|
27
|
-
def attain(anEnv)
|
28
|
-
relation.solver_for(actuals, anEnv)
|
8
|
+
class Goal < ParametrizedTerm
|
9
|
+
alias relation specification
|
10
|
+
|
11
|
+
# Attempt to obtain one or more solutions for the goal in a given context.
|
12
|
+
# @param ctx [Core::Context] The context in which the goal takes place.
|
13
|
+
# @return [Fiber<Context>] A Fiber object that will generate the results.
|
14
|
+
def achieve(ctx)
|
15
|
+
relation.solver_for(actuals, ctx)
|
29
16
|
end
|
30
17
|
|
31
18
|
private
|
32
19
|
|
33
|
-
def
|
34
|
-
|
35
|
-
|
36
|
-
raise StandardError,
|
20
|
+
def validated_specification(theSpec)
|
21
|
+
spec = super(theSpec)
|
22
|
+
unless spec.kind_of?(Relation)
|
23
|
+
raise StandardError, "Expected a Relation instead of #{theSpec.class}."
|
37
24
|
end
|
38
25
|
|
39
|
-
|
26
|
+
spec
|
27
|
+
end
|
28
|
+
|
29
|
+
def validated_actuals(args)
|
40
30
|
args.each do |actual|
|
41
|
-
if actual.kind_of?(
|
31
|
+
if actual.kind_of?(Term) || actual.respond_to?(:attain)
|
42
32
|
next
|
43
33
|
elsif actual.kind_of?(Array)
|
44
34
|
validated_actuals(actual)
|
45
35
|
else
|
36
|
+
prefix = 'Invalid goal argument'
|
46
37
|
actual_display = actual.nil? ? 'nil' : actual.to_s
|
47
38
|
raise StandardError, "#{prefix} '#{actual_display}'"
|
48
39
|
end
|
@@ -1,47 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require_relative 'any_value'
|
5
|
-
require_relative 'vocabulary'
|
3
|
+
require_relative 'entry'
|
6
4
|
|
7
5
|
module MiniKraken
|
8
6
|
module Core
|
9
7
|
# Representation of a MiniKraken logical variable.
|
10
8
|
# It is a named slot that can be associated with one value at the time.
|
11
9
|
# In relational programming, there is no explicit assignment expression.
|
12
|
-
# A logical variable
|
10
|
+
# A logical variable acquires a value through an algorithm called
|
13
11
|
# 'unification'.
|
14
12
|
class LogVar
|
15
|
-
include
|
16
|
-
|
17
|
-
# @return [String] Internal variable name used by MiniKraken
|
18
|
-
attr_accessor :i_name
|
13
|
+
include Entry # Add expected behaviour for symbol table entries
|
19
14
|
|
20
15
|
# Create a logical variable with given name
|
21
16
|
# @param aName [String] The name of the variable
|
22
17
|
def initialize(aName)
|
23
|
-
|
24
|
-
@i_name = name.dup
|
25
|
-
end
|
26
|
-
|
27
|
-
# Indicate whether this variable is fused with another one.
|
28
|
-
# @return [Boolean]
|
29
|
-
def fused?
|
30
|
-
name != i_name
|
31
|
-
end
|
32
|
-
|
33
|
-
# @param [Core::Vocabulary]
|
34
|
-
def quote(env)
|
35
|
-
raise StandardError, "class #{env}" unless env.kind_of?(Vocabulary)
|
36
|
-
|
37
|
-
val = env.quote_ref(self)
|
38
|
-
unless val
|
39
|
-
result = AnyValue.new(name, env, env.names_fused(name))
|
40
|
-
else
|
41
|
-
result = val
|
42
|
-
end
|
43
|
-
|
44
|
-
result
|
18
|
+
init_name(aName)
|
45
19
|
end
|
46
20
|
end # class
|
47
21
|
end # module
|
@@ -1,83 +1,107 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'set'
|
3
4
|
require_relative 'term'
|
4
|
-
require_relative 'designation'
|
5
|
-
require_relative 'any_value'
|
6
5
|
|
7
6
|
module MiniKraken
|
8
7
|
module Core
|
9
|
-
#
|
10
|
-
# MiniKraken term.
|
8
|
+
# Representation of a reference to a MiniKraken logical variable.
|
11
9
|
class LogVarRef < Term
|
12
|
-
|
13
|
-
|
10
|
+
# @return [String] User-friendly name of the variable.
|
11
|
+
attr_reader :name
|
14
12
|
|
13
|
+
# @return [String] Unique internal name of the variable.
|
14
|
+
attr_accessor :i_name
|
15
|
+
|
16
|
+
# Create a reference to a logical variable with given name
|
15
17
|
# @param aName [String] The name of the variable
|
16
18
|
def initialize(aName)
|
17
19
|
super()
|
18
|
-
|
19
|
-
name.freeze
|
20
|
+
init_name(aName)
|
20
21
|
end
|
21
22
|
|
23
|
+
# Return a text representation of this logical variable reference.
|
24
|
+
# @return [String]
|
22
25
|
def to_s
|
23
26
|
name
|
24
27
|
end
|
25
28
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
# Is the related log variable unbound in the given context?
|
30
|
+
# A log var is unbound when there is no association for the variable.
|
31
|
+
# @param aContext [Core::Context]
|
32
|
+
# @return [Boolean] true if log var is unbound
|
33
|
+
def unbound?(aContext)
|
34
|
+
vr = aContext.lookup(name)
|
35
|
+
raise StandardError, "Unknown variable #{name}" unless vr
|
31
36
|
|
32
|
-
|
33
|
-
|
34
|
-
def values(env)
|
35
|
-
env[var_name].map(&:value)
|
37
|
+
bindings = aContext.associations_for(name)
|
38
|
+
bindings.empty? || (bindings.size == 1 && bindings[0].kind_of?(Fusion))
|
36
39
|
end
|
37
40
|
|
38
|
-
#
|
39
|
-
#
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
# Does the variable have at least one association AND
|
42
|
+
# each of these association refer to at least one unbound variable
|
43
|
+
# or a floating variable?
|
44
|
+
# @param aContext [Core::Context]
|
45
|
+
# @return [Boolean] true if log var is floating
|
46
|
+
def floating?(aContext)
|
47
|
+
vr = aContext.lookup(name)
|
48
|
+
raise StandardError, "Unknown variable #{name}" unless vr
|
44
49
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
assocs = aContext.associations_for(name)
|
51
|
+
unless assocs.empty?
|
52
|
+
assocs.none? { |as| as.pinned?(aContext) }
|
53
|
+
else
|
54
|
+
false
|
55
|
+
end
|
49
56
|
end
|
50
57
|
|
51
|
-
#
|
52
|
-
#
|
53
|
-
# @
|
54
|
-
|
55
|
-
|
56
|
-
return
|
58
|
+
# Is the variable pinned?
|
59
|
+
# In other words, does the referenced variable have a definite value?
|
60
|
+
# @param aContext [Core::Context]
|
61
|
+
# @return [Boolean] true if log var is pinned
|
62
|
+
def pinned?(aContext)
|
63
|
+
return true if @pinned
|
64
|
+
|
65
|
+
vr = aContext.lookup(name)
|
66
|
+
raise StandardError, "Unknown variable #{name}" unless vr
|
57
67
|
|
58
|
-
|
59
|
-
|
68
|
+
assocs = aContext.associations_for(name)
|
69
|
+
unless assocs.empty?
|
70
|
+
@pinned = assocs.all? { |as| as.pinned?(aContext) }
|
71
|
+
else
|
72
|
+
false
|
73
|
+
end
|
60
74
|
end
|
61
75
|
|
62
|
-
|
63
|
-
|
76
|
+
# Return the list of variable (i_names) that this term depends on.
|
77
|
+
# For a variable reference, it will return the i_names of its variable
|
78
|
+
# @param ctx [Core::Context]
|
79
|
+
# @return [Set<String>] a set containing the i_name of the variable
|
80
|
+
def dependencies(ctx)
|
81
|
+
@i_name ||= ctx.lookup(name).i_name
|
82
|
+
s = Set.new
|
83
|
+
s << i_name
|
84
|
+
s
|
64
85
|
end
|
65
86
|
|
66
|
-
#
|
67
|
-
#
|
68
|
-
# @
|
69
|
-
|
70
|
-
|
87
|
+
# Make a copy of self with all the variable reference being
|
88
|
+
# replaced by the corresponding value in the Hash.
|
89
|
+
# @param substitutions [Hash {String => Term}]
|
90
|
+
# @return [Term]
|
91
|
+
def dup_cond(substitutions)
|
92
|
+
key = i_name || name
|
93
|
+
if substitutions.include? key
|
94
|
+
val = substitutions[key]
|
95
|
+
val.kind_of?(Term) ? val.dup_cond(substitutions) : val
|
96
|
+
else
|
97
|
+
dup
|
98
|
+
end
|
71
99
|
end
|
72
100
|
|
73
101
|
private
|
74
102
|
|
75
|
-
def
|
76
|
-
|
77
|
-
raise StandardError, 'Variable name may not be empty.'
|
78
|
-
end
|
79
|
-
|
80
|
-
aName
|
103
|
+
def init_name(aName)
|
104
|
+
@name = aName.dup
|
81
105
|
end
|
82
106
|
end # class
|
83
107
|
end # module
|