mini_kraken 0.2.03 → 0.3.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 +378 -333
- data/CHANGELOG.md +48 -0
- data/README.md +29 -21
- data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
- data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
- data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
- data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
- data/lib/mini_kraken/atomic/k_string.rb +17 -0
- data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
- data/lib/mini_kraken/composite/all_composite.rb +4 -0
- data/lib/mini_kraken/composite/composite_term.rb +27 -0
- data/lib/mini_kraken/composite/cons_cell.rb +301 -0
- data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
- 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 +492 -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 +22 -0
- data/lib/mini_kraken/core/log_var_ref.rb +108 -0
- data/lib/mini_kraken/core/nullary_relation.rb +2 -9
- data/lib/mini_kraken/core/parametrized_term.rb +68 -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 +44 -88
- 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 +143 -0
- data/lib/mini_kraken/rela/conj2.rb +65 -0
- data/lib/mini_kraken/rela/def_relation.rb +93 -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 +7 -9
- data/lib/mini_kraken/rela/unify.rb +265 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/mini_kraken.gemspec +2 -2
- data/spec/.rubocop.yml +1 -1
- data/spec/atomic/atomic_term_spec.rb +98 -0
- data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
- data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
- data/spec/composite/cons_cell_spec.rb +225 -0
- data/spec/{core → composite}/cons_cell_visitor_spec.rb +36 -20
- data/spec/composite/list_spec.rb +50 -0
- data/spec/core/any_value_spec.rb +52 -0
- data/spec/core/arity_spec.rb +92 -0
- data/spec/core/association_copy_spec.rb +69 -0
- data/spec/core/association_spec.rb +31 -4
- data/spec/core/blackboard_spec.rb +287 -0
- data/spec/core/bookmark_spec.rb +40 -0
- data/spec/core/context_spec.rb +245 -0
- data/spec/core/core_spec.rb +40 -0
- data/spec/core/duck_fiber_spec.rb +16 -46
- data/spec/core/fail_spec.rb +5 -6
- data/spec/core/goal_spec.rb +22 -12
- data/spec/core/log_var_ref_spec.rb +105 -0
- data/spec/core/log_var_spec.rb +64 -0
- 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 -144
- data/spec/glue/dsl_chap2_spec.rb +454 -19
- data/spec/glue/run_star_expression_spec.rb +81 -906
- data/spec/rela/conde_spec.rb +153 -0
- 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 +29 -0
- data/spec/support/factory_composite.rb +21 -0
- data/spec/support/factory_methods.rb +11 -26
- metadata +98 -70
- data/lib/mini_kraken/core/association_walker.rb +0 -183
- data/lib/mini_kraken/core/atomic_term.rb +0 -67
- 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/composite_term.rb +0 -41
- data/lib/mini_kraken/core/conde.rb +0 -143
- data/lib/mini_kraken/core/conj2.rb +0 -79
- data/lib/mini_kraken/core/cons_cell.rb +0 -82
- data/lib/mini_kraken/core/cons_cell_visitor.rb +0 -102
- 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 -193
- 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/k_boolean.rb +0 -35
- data/lib/mini_kraken/core/outcome.rb +0 -63
- data/lib/mini_kraken/core/variable.rb +0 -41
- data/lib/mini_kraken/core/variable_ref.rb +0 -84
- data/lib/mini_kraken/core/vocabulary.rb +0 -446
- data/lib/mini_kraken/glue/fresh_env.rb +0 -103
- data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
- data/spec/core/association_walker_spec.rb +0 -192
- data/spec/core/conde_spec.rb +0 -147
- data/spec/core/conj2_spec.rb +0 -114
- data/spec/core/cons_cell_spec.rb +0 -107
- data/spec/core/def_relation_spec.rb +0 -97
- data/spec/core/disj2_spec.rb +0 -99
- data/spec/core/environment_spec.rb +0 -142
- data/spec/core/equals_spec.rb +0 -317
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -56
- data/spec/core/variable_ref_spec.rb +0 -30
- data/spec/core/variable_spec.rb +0 -35
- data/spec/core/vocabulary_spec.rb +0 -219
- data/spec/glue/fresh_env_factory_spec.rb +0 -97
- data/spec/glue/fresh_env_spec.rb +0 -62
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'term'
|
4
|
-
require_relative 'freshness'
|
5
|
-
|
6
|
-
module MiniKraken
|
7
|
-
module Core
|
8
|
-
# An atomic term is an elementary Minikraken term that cannot be
|
9
|
-
# decomposed into simpler MiniKraken data value(s).
|
10
|
-
class AtomicTerm < Term
|
11
|
-
# @return [Object] Internal representation of a MiniKraken data value
|
12
|
-
attr_reader :value
|
13
|
-
|
14
|
-
# @param aValue [Object] Ruby representation of MiniKraken data value
|
15
|
-
def initialize(aValue)
|
16
|
-
super()
|
17
|
-
@value = aValue
|
18
|
-
@value.freeze
|
19
|
-
end
|
20
|
-
|
21
|
-
# An atomic term is by definition a ground term: since it doesn't contain
|
22
|
-
# any bound variable (in Prolog sense).
|
23
|
-
# @param _env [Vocabulary]
|
24
|
-
# @return [Freshness]
|
25
|
-
def freshness(_env)
|
26
|
-
Freshness.new(:ground, self)
|
27
|
-
end
|
28
|
-
|
29
|
-
# An atomic term is a ground term: by definition it doesn't contain
|
30
|
-
# any fresh variable.
|
31
|
-
# @param _env [Vocabulary]
|
32
|
-
# @return [FalseClass]
|
33
|
-
def fresh?(_env)
|
34
|
-
false
|
35
|
-
end
|
36
|
-
|
37
|
-
# An atomic term is a ground term: by definition it doesn't contain
|
38
|
-
# any fresh variable.
|
39
|
-
# @param _env [Vocabulary]
|
40
|
-
# @return [TrueClass]
|
41
|
-
def ground?(_env)
|
42
|
-
true
|
43
|
-
end
|
44
|
-
|
45
|
-
# @return [AtomicTerm]
|
46
|
-
def quote(_env)
|
47
|
-
self
|
48
|
-
end
|
49
|
-
|
50
|
-
# Data equality testing
|
51
|
-
# @return [Boolean]
|
52
|
-
def ==(other)
|
53
|
-
if other.respond_to?(:value)
|
54
|
-
value == other.value
|
55
|
-
else
|
56
|
-
value == other
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Type and data equality testing
|
61
|
-
# @return [Boolean]
|
62
|
-
def eql?(other)
|
63
|
-
(self.class == other.class) && value.eql?(other.value)
|
64
|
-
end
|
65
|
-
end # class
|
66
|
-
end # module
|
67
|
-
end # module
|
@@ -1,63 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'relation'
|
4
|
-
require_relative 'composite_term'
|
5
|
-
|
6
|
-
module MiniKraken
|
7
|
-
module Core
|
8
|
-
class BinaryRelation < Relation
|
9
|
-
# @param aName [String] Name of the relation.
|
10
|
-
# @param alternateName [String, NilClass] Alternative name (optional).
|
11
|
-
def initialize(aName, alternateName = nil)
|
12
|
-
super(aName, alternateName)
|
13
|
-
freeze
|
14
|
-
end
|
15
|
-
|
16
|
-
# Number of arguments for the relation.
|
17
|
-
# @return [Integer]
|
18
|
-
def arity
|
19
|
-
2
|
20
|
-
end
|
21
|
-
|
22
|
-
protected
|
23
|
-
|
24
|
-
# table: Commute
|
25
|
-
# |arg1 | arg2 | arg2.ground? || Commute |
|
26
|
-
# | isa? Atomic | isa? Atomic | dont_care || Yes |
|
27
|
-
# | isa? Atomic | isa? CompositeTerm | dont_care || Yes |
|
28
|
-
# | isa? Atomic | isa? VariableRef | dont_care || Yes |
|
29
|
-
# | isa? CompositeTerm | isa? Atomic | true || No |
|
30
|
-
# | isa? CompositeTerm | isa? CompositeTerm | false || Yes |
|
31
|
-
# | isa? CompositeTerm | isa? CompositeTerm | true || No |
|
32
|
-
# | isa? CompositeTerm | isa? VariableRef | dont_care || Yes |
|
33
|
-
# | isa? VariableRef | isa? Atomic | dont_care || No |
|
34
|
-
# | isa? VariableRef | isa? CompositeTerm | dont_care || No |
|
35
|
-
# | isa? VariableRef | isa? VariableRef | false || Yes |
|
36
|
-
# | isa? VariableRef | isa? VariableRef | true || No |
|
37
|
-
def commute_cond(arg1, arg2, env)
|
38
|
-
commuting = true
|
39
|
-
arg2_is_var_ref = arg2.kind_of?(VariableRef)
|
40
|
-
|
41
|
-
if arg1.kind_of?(CompositeTerm)
|
42
|
-
if arg2_is_var_ref
|
43
|
-
commuting = true
|
44
|
-
else
|
45
|
-
commuting = !arg2.ground?(env)
|
46
|
-
end
|
47
|
-
elsif arg1.kind_of?(VariableRef)
|
48
|
-
if arg2_is_var_ref
|
49
|
-
commuting = !arg2.ground?(env)
|
50
|
-
else
|
51
|
-
commuting = false
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
if commuting
|
56
|
-
[arg2, arg1]
|
57
|
-
else
|
58
|
-
[arg1, arg2]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end # class
|
62
|
-
end # module
|
63
|
-
end # module
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'environment'
|
4
|
-
|
5
|
-
module MiniKraken
|
6
|
-
module Core
|
7
|
-
class CompositeGoal
|
8
|
-
# @return [Operator] The operator corresponding to this goal
|
9
|
-
attr_reader :operator
|
10
|
-
|
11
|
-
# @return [Array<Goal>] The child goals (sub-goals)
|
12
|
-
attr_reader :children
|
13
|
-
|
14
|
-
# @param anOperator [Operator] The operator corresponding to this goal
|
15
|
-
# @param theChildren [Array<Goal>] The child goals (sub-goals)
|
16
|
-
def initialize(anOperator, theChildren)
|
17
|
-
@operator = anOperator
|
18
|
-
@children = validated_children(theChildren)
|
19
|
-
end
|
20
|
-
|
21
|
-
# Attempt to achieve the goal for a given context (environment)
|
22
|
-
# @param anEnv [Environment] The context in which the goal take place.
|
23
|
-
# @return [Fiber<Outcome>] A Fiber object that will generate the results.
|
24
|
-
def attain(anEnv)
|
25
|
-
operator.solver_for(children, anEnv)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def validated_children(theChildren)
|
31
|
-
my_arity = operator.arity
|
32
|
-
if args.size != my_arity
|
33
|
-
err_msg = "Goal has #{theChildren.size} arguments, expected #{my_arity}"
|
34
|
-
raise StandardError, err_msg
|
35
|
-
end
|
36
|
-
|
37
|
-
prefix = 'Invalid goal argument '
|
38
|
-
theChildren.each do |subg|
|
39
|
-
raise StandardError, prefix + subg.to_s unless subg.kind_of?(Goal)
|
40
|
-
end
|
41
|
-
|
42
|
-
theChildren.dup
|
43
|
-
end
|
44
|
-
end # class
|
45
|
-
end # module
|
46
|
-
end # module
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'term'
|
4
|
-
require_relative 'freshness'
|
5
|
-
|
6
|
-
module MiniKraken
|
7
|
-
module Core
|
8
|
-
# An composite term is an Minikraken term that can be
|
9
|
-
# decomposed into simpler MiniKraken data value(s).
|
10
|
-
class CompositeTerm < Term
|
11
|
-
# Abstract method (to override). Return the child terms.
|
12
|
-
# @return [Array<Term>]
|
13
|
-
def children
|
14
|
-
raise NotImplementedError, 'This method must re-defined in subclass(es).'
|
15
|
-
end
|
16
|
-
|
17
|
-
# A composite term is fresh when all its members are nil or all non-nil members
|
18
|
-
# are all fresh
|
19
|
-
# A composite term is bound when it is not fresh and not ground
|
20
|
-
# A composite term is a ground term when all its non-nil members are ground.
|
21
|
-
# @param _env [Vocabulary]
|
22
|
-
# @return [Freshness]
|
23
|
-
def freshness(_env)
|
24
|
-
env.freshness_composite(self)
|
25
|
-
end
|
26
|
-
|
27
|
-
# @param env [Environment]
|
28
|
-
# @return [Boolean]
|
29
|
-
def fresh?(env)
|
30
|
-
env.fresh_value?(self)
|
31
|
-
end
|
32
|
-
|
33
|
-
# A composite is ground if all its children are ground
|
34
|
-
def ground?(anEnv)
|
35
|
-
children.all? do |child|
|
36
|
-
child.nil? || child.ground?(anEnv)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end # class
|
40
|
-
end # module
|
41
|
-
end # module
|
@@ -1,143 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'singleton'
|
4
|
-
require_relative 'conj2'
|
5
|
-
require_relative 'duck_fiber'
|
6
|
-
require_relative 'fail'
|
7
|
-
require_relative 'goal'
|
8
|
-
require_relative 'goal_relation'
|
9
|
-
require_relative 'outcome'
|
10
|
-
|
11
|
-
unless MiniKraken::Core.constants(false).include? :Conde
|
12
|
-
module MiniKraken
|
13
|
-
module Core
|
14
|
-
# A polyadic relation (i.e. it can takes an arbitrary number of argumentt)
|
15
|
-
# that behaves as the disjunction of its arguments.
|
16
|
-
# It succeeds if at least one of its goal arguments succeeds.
|
17
|
-
class Conde < GoalRelation
|
18
|
-
include Singleton
|
19
|
-
|
20
|
-
def initialize
|
21
|
-
super('conde', nil)
|
22
|
-
end
|
23
|
-
|
24
|
-
# A relation is polyadic when it accepts an arbitrary number of arguments.
|
25
|
-
# @return [TrueClass]
|
26
|
-
def polyadic?
|
27
|
-
true
|
28
|
-
end
|
29
|
-
|
30
|
-
# @param actuals [Array<Term>] A two-elements array
|
31
|
-
# @param anEnv [Vocabulary] A vocabulary object
|
32
|
-
# @return [Fiber<Outcome>] A Fiber that yields Outcomes objects
|
33
|
-
def solver_for(actuals, anEnv)
|
34
|
-
args = *validated_args(actuals)
|
35
|
-
Fiber.new { cond(args, anEnv) }
|
36
|
-
end
|
37
|
-
|
38
|
-
# Yields [Outcome, NilClass] result of the disjunction
|
39
|
-
# @param goals [Array<Goal>] Array of goals
|
40
|
-
# @param voc [Vocabulary] A vocabulary object
|
41
|
-
def cond(goals, voc)
|
42
|
-
# require 'debug'
|
43
|
-
success = false
|
44
|
-
|
45
|
-
goals.each do |g|
|
46
|
-
fiber = nil
|
47
|
-
|
48
|
-
case g
|
49
|
-
when Core::Goal
|
50
|
-
fiber = g.attain(voc)
|
51
|
-
when Core::Environment
|
52
|
-
fiber = g.attain(voc)
|
53
|
-
when Array
|
54
|
-
conjunct = conjunction(g)
|
55
|
-
fiber = conjunct.attain(voc)
|
56
|
-
when Core::ConsCell
|
57
|
-
goal_array = to_goal_array(g)
|
58
|
-
conjunct = conjunction(goal_array)
|
59
|
-
fiber = conjunct.attain(voc)
|
60
|
-
end
|
61
|
-
loop do
|
62
|
-
outcome = fiber.resume
|
63
|
-
break unless outcome
|
64
|
-
|
65
|
-
outcome.parent = voc unless outcome.parent
|
66
|
-
if outcome.success?
|
67
|
-
success = true
|
68
|
-
Fiber.yield outcome
|
69
|
-
outcome.clear
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
Fiber.yield Outcome.new(:"#u", voc) unless success
|
75
|
-
Fiber.yield nil
|
76
|
-
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def validated_args(actuals)
|
81
|
-
result = []
|
82
|
-
|
83
|
-
actuals.each do |arg|
|
84
|
-
case arg
|
85
|
-
when Core::Goal
|
86
|
-
result << arg
|
87
|
-
|
88
|
-
when Core::Environment
|
89
|
-
result << arg
|
90
|
-
|
91
|
-
when Array
|
92
|
-
result << validated_args(arg)
|
93
|
-
|
94
|
-
else
|
95
|
-
prefix = "#{name} expects goal as argument, found a "
|
96
|
-
raise StandardError, prefix + "'#{arg.class}'"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
result
|
101
|
-
end
|
102
|
-
|
103
|
-
def conjunction(goal_array)
|
104
|
-
result = nil
|
105
|
-
|
106
|
-
loop do
|
107
|
-
conjunctions = []
|
108
|
-
goal_array.each_slice(2) do |uno_duo|
|
109
|
-
if uno_duo.size == 2
|
110
|
-
conjunctions << Core::Goal.new(Core::Conj2.instance, uno_duo)
|
111
|
-
else
|
112
|
-
conjunctions << uno_duo[0]
|
113
|
-
end
|
114
|
-
end
|
115
|
-
if conjunctions.size == 1
|
116
|
-
result = conjunctions[0]
|
117
|
-
break
|
118
|
-
end
|
119
|
-
goal_array = conjunctions
|
120
|
-
end
|
121
|
-
|
122
|
-
result
|
123
|
-
end
|
124
|
-
|
125
|
-
def to_goal_array(aCons)
|
126
|
-
array = []
|
127
|
-
curr_node = aCons
|
128
|
-
loop do
|
129
|
-
array << curr_node.car if curr_node.car.kind_of?(Core::Goal)
|
130
|
-
break unless curr_node.cdr
|
131
|
-
break unless curr_node.car.kind_of?(Core::Goal)
|
132
|
-
|
133
|
-
curr_node = curr_node.cdr
|
134
|
-
end
|
135
|
-
|
136
|
-
array
|
137
|
-
end
|
138
|
-
end # class
|
139
|
-
|
140
|
-
Conde.instance.freeze
|
141
|
-
end # module
|
142
|
-
end # module
|
143
|
-
end # unless
|
@@ -1,79 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'singleton'
|
4
|
-
require_relative 'duck_fiber'
|
5
|
-
require_relative 'goal'
|
6
|
-
require_relative 'goal_relation'
|
7
|
-
require_relative 'outcome'
|
8
|
-
|
9
|
-
unless MiniKraken::Core.constants(false).include? :Conj2
|
10
|
-
module MiniKraken
|
11
|
-
module Core
|
12
|
-
# The conjunction is a relation that accepts only goal(s) as its two
|
13
|
-
# arguments. It succeeds if and only both its goal arguments succeeds.
|
14
|
-
class Conj2 < GoalRelation
|
15
|
-
include Singleton
|
16
|
-
|
17
|
-
def initialize
|
18
|
-
super('conj2', nil)
|
19
|
-
end
|
20
|
-
|
21
|
-
# @param actuals [Array<Term>] A two-elements array
|
22
|
-
# @param anEnv [Vocabulary] A vocabulary object
|
23
|
-
# @return [Fiber<Outcome>] A Fiber that yields Outcomes objects
|
24
|
-
def solver_for(actuals, anEnv)
|
25
|
-
g1, g2 = *validated_args(actuals)
|
26
|
-
Fiber.new { conjunction(g1, g2, anEnv) }
|
27
|
-
end
|
28
|
-
|
29
|
-
# Yields [Outcome, NilClass] result of the conjunction
|
30
|
-
# @param g1 [Goal] First goal argument
|
31
|
-
# @param g2 [Goal] Second goal argument
|
32
|
-
# @param voc [Vocabulary] A vocabulary object
|
33
|
-
def conjunction(g1, g2, voc)
|
34
|
-
# require 'debug'
|
35
|
-
if g1.relation.kind_of?(Fail) || g2.relation.kind_of?(Fail)
|
36
|
-
Fiber.yield Outcome.new(:"#u", voc)
|
37
|
-
else
|
38
|
-
outcome1 = nil
|
39
|
-
outcome2 = nil
|
40
|
-
f1 = g1.attain(voc)
|
41
|
-
loop do
|
42
|
-
outcome1 = f1.resume
|
43
|
-
break unless outcome1
|
44
|
-
|
45
|
-
outcome1.parent = voc unless outcome1.parent
|
46
|
-
if outcome1.success?
|
47
|
-
f2 = g2.attain(outcome1)
|
48
|
-
loop do
|
49
|
-
outcome2 = f2.resume
|
50
|
-
break unless outcome2
|
51
|
-
|
52
|
-
outcome2.parent = voc unless outcome2.parent
|
53
|
-
if outcome2.success?
|
54
|
-
res = Outcome.new(:"#s", voc)
|
55
|
-
res.merge(outcome1)
|
56
|
-
res.merge(outcome2)
|
57
|
-
Fiber.yield res
|
58
|
-
else
|
59
|
-
Fiber.yield outcome2
|
60
|
-
end
|
61
|
-
outcome2.clear
|
62
|
-
end
|
63
|
-
else
|
64
|
-
Fiber.yield outcome1
|
65
|
-
end
|
66
|
-
if outcome1.success? && (outcome2&.success? || outcome2.nil?)
|
67
|
-
voc.clear
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
Fiber.yield nil
|
73
|
-
end
|
74
|
-
end # class
|
75
|
-
|
76
|
-
Conj2.instance.freeze
|
77
|
-
end # module
|
78
|
-
end # module
|
79
|
-
end # unless
|