mini_kraken 0.2.02 → 0.3.02
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 +52 -0
- data/README.md +19 -19
- data/lib/mini_kraken.rb +0 -1
- 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 +299 -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 +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 +45 -81
- 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 +258 -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/composite/cons_cell_visitor_spec.rb +158 -0
- 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 +24 -14
- 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 +96 -144
- data/spec/glue/dsl_chap2_spec.rb +350 -0
- data/spec/glue/run_star_expression_spec.rb +82 -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 +100 -64
- 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/def_relation.rb +0 -50
- 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 -156
- 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 -62
- data/lib/mini_kraken/core/k_boolean.rb +0 -35
- data/lib/mini_kraken/core/outcome.rb +0 -53
- data/lib/mini_kraken/core/variable.rb +0 -41
- data/lib/mini_kraken/core/variable_ref.rb +0 -78
- data/lib/mini_kraken/core/vocabulary.rb +0 -442
- data/lib/mini_kraken/glue/fresh_env.rb +0 -75
- 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 -96
- data/spec/core/disj2_spec.rb +0 -99
- data/spec/core/environment_spec.rb +0 -142
- data/spec/core/equals_spec.rb +0 -304
- data/spec/core/goal_template_spec.rb +0 -74
- data/spec/core/outcome_spec.rb +0 -48
- data/spec/core/variable_ref_spec.rb +0 -27
- data/spec/core/variable_spec.rb +0 -35
- data/spec/core/vocabulary_spec.rb +0 -219
- data/spec/glue/fresh_env_spec.rb +0 -62
data/spec/core/cons_cell_spec.rb
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/k_symbol'
|
5
|
-
|
6
|
-
# Load the class under test
|
7
|
-
require_relative '../../lib/mini_kraken/core/cons_cell'
|
8
|
-
|
9
|
-
module MiniKraken
|
10
|
-
module Core
|
11
|
-
describe ConsCell do
|
12
|
-
let(:pea) { KSymbol.new(:pea) }
|
13
|
-
let(:pod) { KSymbol.new(:pod) }
|
14
|
-
let(:corn) { KSymbol.new(:corn) }
|
15
|
-
subject { ConsCell.new(pea, pod) }
|
16
|
-
|
17
|
-
context 'Initialization:' do
|
18
|
-
it 'could be initialized with one argument' do
|
19
|
-
expect { ConsCell.new(pea) }.not_to raise_error
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'could be initialized with a second optional argument' do
|
23
|
-
expect { ConsCell.new(pea, pod) }.not_to raise_error
|
24
|
-
end
|
25
|
-
|
26
|
-
it 'should know its car child' do
|
27
|
-
expect(subject.car).to eq(pea)
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'should know its cdr child' do
|
31
|
-
expect(subject.cdr).to eq(pod)
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'should know its children' do
|
35
|
-
expect(subject.children).to eq([pea, pod])
|
36
|
-
end
|
37
|
-
|
38
|
-
it 'should know if it is empty (null)' do
|
39
|
-
expect(subject).not_to be_null
|
40
|
-
expect(ConsCell.new(nil, nil)).to be_null
|
41
|
-
expect(NullList).to be_null
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'simplifies cdr if its referencing a null list' do
|
45
|
-
instance = ConsCell.new(pea, NullList)
|
46
|
-
expect(instance.car).to eq(pea)
|
47
|
-
expect(instance.cdr).to be_nil
|
48
|
-
end
|
49
|
-
end # context
|
50
|
-
|
51
|
-
context 'Provided services:' do
|
52
|
-
it 'should compare to itself' do
|
53
|
-
expect(subject.eql?(subject)).to be_truthy
|
54
|
-
synonym = subject
|
55
|
-
expect(subject == synonym).to be_truthy
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'should compare to another instance' do
|
59
|
-
same = ConsCell.new(pea, pod)
|
60
|
-
expect(subject.eql?(same)).to be_truthy
|
61
|
-
|
62
|
-
different = ConsCell.new(pod, pea)
|
63
|
-
expect(subject.eql?(different)).to be_falsey
|
64
|
-
|
65
|
-
different = ConsCell.new(pea)
|
66
|
-
expect(subject.eql?(different)).to be_falsey
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'should append another cons cell' do
|
70
|
-
instance = ConsCell.new(pea)
|
71
|
-
trail = ConsCell.new(pod)
|
72
|
-
instance.append(trail)
|
73
|
-
expect(instance.car).to eq(pea)
|
74
|
-
expect(instance.cdr).to eq(trail)
|
75
|
-
end
|
76
|
-
|
77
|
-
it 'should provide a list representation of itself' do
|
78
|
-
# Case of null list
|
79
|
-
expect(NullList.to_s).to eq '()'
|
80
|
-
|
81
|
-
# Case of one element proper list
|
82
|
-
cell = ConsCell.new(pea)
|
83
|
-
expect(cell.to_s).to eq '(:pea)'
|
84
|
-
|
85
|
-
# Case of two elements proper list
|
86
|
-
cell = ConsCell.new(pea, ConsCell.new(pod))
|
87
|
-
expect(cell.to_s).to eq '(:pea :pod)'
|
88
|
-
|
89
|
-
# Case of two elements improper list
|
90
|
-
expect(subject.to_s).to eq '(:pea . :pod)'
|
91
|
-
|
92
|
-
# Case of three elements proper list
|
93
|
-
cell = ConsCell.new(pea, ConsCell.new(pod, ConsCell.new(corn)))
|
94
|
-
expect(cell.to_s).to eq '(:pea :pod :corn)'
|
95
|
-
|
96
|
-
# Case of three elements improper list
|
97
|
-
cell = ConsCell.new(pea, ConsCell.new(pod, corn))
|
98
|
-
expect(cell.to_s).to eq '(:pea :pod . :corn)'
|
99
|
-
|
100
|
-
# Case of a nested list
|
101
|
-
cell = ConsCell.new(ConsCell.new(pea), ConsCell.new(pod))
|
102
|
-
expect(cell.to_s).to eq '((:pea) :pod)'
|
103
|
-
end
|
104
|
-
end # context
|
105
|
-
end # describe
|
106
|
-
end # module
|
107
|
-
end # module
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/disj2'
|
5
|
-
require_relative '../../lib/mini_kraken/core/equals'
|
6
|
-
require_relative '../../lib/mini_kraken/core/formal_arg'
|
7
|
-
require_relative '../../lib/mini_kraken/core/formal_ref'
|
8
|
-
require_relative '../../lib/mini_kraken/core/goal'
|
9
|
-
require_relative '../../lib/mini_kraken/core/goal_template'
|
10
|
-
require_relative '../../lib/mini_kraken/core/k_symbol'
|
11
|
-
require_relative '../../lib/mini_kraken/core/variable_ref'
|
12
|
-
require_relative '../../lib/mini_kraken/core/environment'
|
13
|
-
|
14
|
-
# Load the class under test
|
15
|
-
require_relative '../../lib/mini_kraken/core/def_relation'
|
16
|
-
|
17
|
-
module MiniKraken
|
18
|
-
module Core
|
19
|
-
describe DefRelation do
|
20
|
-
let(:tea) { KSymbol.new(:tea) }
|
21
|
-
let(:formal_t) { FormalArg.new('t') }
|
22
|
-
let(:t_ref) { FormalRef.new('t') }
|
23
|
-
let(:equals_tea) { GoalTemplate.new(Equals.instance, [tea, t_ref]) }
|
24
|
-
subject { DefRelation.new('teao', equals_tea, [formal_t]) }
|
25
|
-
|
26
|
-
context 'Initialization:' do
|
27
|
-
it 'should be initialized with a name, a goal template, formal args' do
|
28
|
-
expect { DefRelation.new('teao', equals_tea, [formal_t]) }.not_to raise_error
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'should know its name' do
|
32
|
-
expect(subject.name).to eq('teao')
|
33
|
-
end
|
34
|
-
|
35
|
-
it 'should know its goal template' do
|
36
|
-
expect(subject.goal_template).to eq(equals_tea)
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'should know its formals' do
|
40
|
-
expect(subject.formals).to eq([formal_t])
|
41
|
-
end
|
42
|
-
end # context
|
43
|
-
|
44
|
-
context 'Provided services:' do
|
45
|
-
let(:cup) { KSymbol.new(:cup) }
|
46
|
-
let(:ref_x) { VariableRef.new('x') }
|
47
|
-
let(:equals_cup) { GoalTemplate.new(Equals.instance, [cup, t_ref]) }
|
48
|
-
let(:g_template) { GoalTemplate.new(Disj2.instance, [equals_tea, equals_cup]) }
|
49
|
-
subject { DefRelation.new('teacup', g_template, [formal_t]) }
|
50
|
-
let(:env) { Environment.new }
|
51
|
-
|
52
|
-
it 'should provide solver for a single-node goal without var ref' do
|
53
|
-
defrel = DefRelation.new('teao', equals_tea, [formal_t])
|
54
|
-
solver = defrel.solver_for([tea], env)
|
55
|
-
outcome = solver.resume
|
56
|
-
expect(outcome).to be_successful
|
57
|
-
outcome = solver.resume
|
58
|
-
expect(outcome).to be_nil
|
59
|
-
|
60
|
-
solver = defrel.solver_for([cup], env)
|
61
|
-
outcome = solver.resume
|
62
|
-
expect(outcome).not_to be_successful
|
63
|
-
outcome = solver.resume
|
64
|
-
expect(outcome).to be_nil
|
65
|
-
end
|
66
|
-
|
67
|
-
it 'should provide solver for a single-node goal' do
|
68
|
-
defrel = DefRelation.new('teao', equals_tea, [formal_t])
|
69
|
-
env.add_var(Variable.new('x'))
|
70
|
-
solver = defrel.solver_for([ref_x], env)
|
71
|
-
outcome = solver.resume
|
72
|
-
expect(outcome).to be_successful
|
73
|
-
expect(ref_x.value(outcome)).to eq(tea)
|
74
|
-
|
75
|
-
outcome = solver.resume
|
76
|
-
expect(outcome).to be_nil
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'should provide solver for a single-node goal' do
|
80
|
-
env.add_var(Variable.new('x'))
|
81
|
-
solver = subject.solver_for([ref_x], env)
|
82
|
-
outcome = solver.resume
|
83
|
-
expect(outcome).to be_successful
|
84
|
-
expect(ref_x.value(outcome)).to eq(tea)
|
85
|
-
|
86
|
-
outcome = solver.resume
|
87
|
-
expect(outcome).to be_successful
|
88
|
-
expect(ref_x.value(outcome)).to eq(cup)
|
89
|
-
|
90
|
-
outcome = solver.resume
|
91
|
-
expect(outcome).to be_nil
|
92
|
-
end
|
93
|
-
end # context
|
94
|
-
end # describe
|
95
|
-
end # module
|
96
|
-
end # module
|
data/spec/core/disj2_spec.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/k_symbol'
|
5
|
-
require_relative '../../lib/mini_kraken/core/fail'
|
6
|
-
require_relative '../../lib/mini_kraken/core/succeed'
|
7
|
-
require_relative '../../lib/mini_kraken/core/equals'
|
8
|
-
require_relative '../../lib/mini_kraken/core/environment'
|
9
|
-
require_relative '../../lib/mini_kraken/core/variable'
|
10
|
-
require_relative '../../lib/mini_kraken/core/variable_ref'
|
11
|
-
|
12
|
-
# Load the class under test
|
13
|
-
require_relative '../../lib/mini_kraken/core/disj2'
|
14
|
-
|
15
|
-
module MiniKraken
|
16
|
-
module Core
|
17
|
-
describe Disj2 do
|
18
|
-
subject { Disj2.instance }
|
19
|
-
|
20
|
-
context 'Initialization:' do
|
21
|
-
it 'should be initialized without argument' do
|
22
|
-
expect { Disj2.instance }.not_to raise_error
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'should know its name' do
|
26
|
-
expect(subject.name).to eq('disj2')
|
27
|
-
end
|
28
|
-
end # context
|
29
|
-
|
30
|
-
context 'Provided services:' do
|
31
|
-
let(:corn) { KSymbol.new(:corn) }
|
32
|
-
let(:meal) { KSymbol.new(:meal) }
|
33
|
-
let(:oil) { KSymbol.new(:oil) }
|
34
|
-
let(:olive) { KSymbol.new(:olive) }
|
35
|
-
let(:pea) { KSymbol.new(:pea) }
|
36
|
-
let(:fails) { Goal.new(Fail.instance, []) }
|
37
|
-
let(:succeeds) { Goal.new(Succeed.instance, []) }
|
38
|
-
let(:var_q) { Variable.new('q') }
|
39
|
-
let(:ref_q) { VariableRef.new('q') }
|
40
|
-
let(:env) do
|
41
|
-
e = Environment.new
|
42
|
-
e.add_var(var_q)
|
43
|
-
e
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'should complain when one of its argument is not a goal' do
|
47
|
-
err = StandardError
|
48
|
-
expect { subject.solver_for([succeeds, pea], env) }.to raise_error(err)
|
49
|
-
expect { subject.solver_for([pea, succeeds], env) }.to raise_error(err)
|
50
|
-
end
|
51
|
-
|
52
|
-
it 'should fails if both arguments fail' do
|
53
|
-
# Covers frame 1:55
|
54
|
-
solver = subject.solver_for([fails, fails], env)
|
55
|
-
expect(solver.resume).not_to be_successful
|
56
|
-
expect(solver.resume).to be_nil
|
57
|
-
end
|
58
|
-
|
59
|
-
it 'yield success if first argument succeeds' do
|
60
|
-
# Covers frame 1:56
|
61
|
-
subgoal = Goal.new(Equals.instance, [olive, ref_q])
|
62
|
-
solver = subject.solver_for([subgoal, fails], env)
|
63
|
-
outcome = solver.resume
|
64
|
-
expect(outcome).to be_successful
|
65
|
-
expect(outcome.associations['q'].first.value).to eq(olive)
|
66
|
-
expect(solver.resume).to be_nil
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'yield success if second argument succeeds' do
|
70
|
-
# Covers frame 1:57
|
71
|
-
subgoal = Goal.new(Equals.instance, [oil, ref_q])
|
72
|
-
solver = subject.solver_for([fails, subgoal], env)
|
73
|
-
outcome = solver.resume
|
74
|
-
expect(outcome).to be_successful
|
75
|
-
expect(outcome.associations['q'].first.value).to eq(oil)
|
76
|
-
expect(solver.resume).to be_nil
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'yield two solutions if both arguments succeed' do
|
80
|
-
# Covers frame 1:58
|
81
|
-
subgoal1 = Goal.new(Equals.instance, [olive, ref_q])
|
82
|
-
subgoal2 = Goal.new(Equals.instance, [oil, ref_q])
|
83
|
-
solver = subject.solver_for([subgoal1, subgoal2], env)
|
84
|
-
|
85
|
-
# First solution
|
86
|
-
outcome1 = solver.resume
|
87
|
-
expect(outcome1).to be_successful
|
88
|
-
expect(outcome1.associations['q'].first.value).to eq(olive)
|
89
|
-
|
90
|
-
# Second solution
|
91
|
-
outcome2 = solver.resume
|
92
|
-
expect(outcome2).to be_successful
|
93
|
-
expect(outcome2.associations['q'].first.value).to eq(oil)
|
94
|
-
expect(solver.resume).to be_nil
|
95
|
-
end
|
96
|
-
end # context
|
97
|
-
end # describe
|
98
|
-
end # module
|
99
|
-
end # module
|
@@ -1,142 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/k_symbol'
|
5
|
-
require_relative '../../lib/mini_kraken/core/variable'
|
6
|
-
require_relative '../../lib/mini_kraken/core/variable_ref'
|
7
|
-
require_relative '../../lib/mini_kraken/core/outcome'
|
8
|
-
|
9
|
-
# Load the class under test
|
10
|
-
require_relative '../../lib/mini_kraken/core/environment'
|
11
|
-
|
12
|
-
module MiniKraken
|
13
|
-
module Core
|
14
|
-
describe Environment do
|
15
|
-
subject { Environment.new }
|
16
|
-
|
17
|
-
context 'Initialization:' do
|
18
|
-
it 'should be initialized with an optional parent' do
|
19
|
-
expect { Environment.new }.not_to raise_error
|
20
|
-
parent = Environment.new
|
21
|
-
expect { Environment.new(parent) }.not_to raise_error
|
22
|
-
end
|
23
|
-
|
24
|
-
it "shouldn't have variable by default" do
|
25
|
-
expect(subject.vars).to be_empty
|
26
|
-
end
|
27
|
-
|
28
|
-
it "shouldn't have associations by default" do
|
29
|
-
expect(subject.associations).to be_empty
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'shold know its parent (if any)' do
|
33
|
-
# Case: no parent
|
34
|
-
expect(subject.parent).to be_nil
|
35
|
-
|
36
|
-
# Case: there is a parent
|
37
|
-
child = Environment.new(subject)
|
38
|
-
expect(child.parent).to eq(subject)
|
39
|
-
end
|
40
|
-
end # context
|
41
|
-
|
42
|
-
context 'Provided services:' do
|
43
|
-
let(:var_a) { Variable.new('a') }
|
44
|
-
let(:var_b) { Variable.new('b') }
|
45
|
-
let(:var_c) { Variable.new('c') }
|
46
|
-
let(:var_c_bis) { Variable.new('c') }
|
47
|
-
let(:pea) { KSymbol.new(:pea) }
|
48
|
-
let(:pod) { KSymbol.new(:pod) }
|
49
|
-
let(:pad) { KSymbol.new(:pad) }
|
50
|
-
|
51
|
-
it 'should accept the addition of a variable' do
|
52
|
-
subject.add_var(var_a)
|
53
|
-
expect(subject.vars).not_to be_empty
|
54
|
-
expect(subject.vars['a']).to eq(var_a)
|
55
|
-
end
|
56
|
-
|
57
|
-
it 'should accept the addition of multiple variables' do
|
58
|
-
subject.add_var(var_a)
|
59
|
-
expect(subject.vars).not_to be_empty
|
60
|
-
subject.add_var(var_b)
|
61
|
-
expect(subject.vars['a']).to eq(var_a)
|
62
|
-
expect(subject.vars['b']).to eq(var_b)
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'should accept the addition of an association' do
|
66
|
-
subject.add_var(var_a)
|
67
|
-
assoc = subject.add_assoc('a', pea)
|
68
|
-
expect(subject.associations.size).to eq(1)
|
69
|
-
expect(subject.associations['a']).to eq([assoc])
|
70
|
-
end
|
71
|
-
|
72
|
-
it 'should tell that a newborn variable is fresh' do
|
73
|
-
subject.add_var(var_a)
|
74
|
-
|
75
|
-
# By default, a variable is fresh...
|
76
|
-
expect(subject.fresh?(var_a)).to be_truthy
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should tell variable associated with a literal value isn't fresh" do
|
80
|
-
subject.add_var(var_a)
|
81
|
-
|
82
|
-
# Let's associate an atomic term...
|
83
|
-
subject.add_assoc('a', pea)
|
84
|
-
|
85
|
-
expect(subject.fresh?(var_a)).to be_falsey
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'should cope with a variable associated with another variable' do
|
89
|
-
subject.add_var(var_a)
|
90
|
-
subject.add_var(var_b)
|
91
|
-
|
92
|
-
# Let's associate a with (fresh) b
|
93
|
-
subject.add_assoc(var_a, var_b)
|
94
|
-
expect(subject.fresh?(var_a)).to be_truthy
|
95
|
-
|
96
|
-
# Now associate b with something ground...
|
97
|
-
subject.add_assoc(var_b, pea)
|
98
|
-
|
99
|
-
# b is no more fresh, so is ... a
|
100
|
-
expect(subject.fresh?(var_b)).to be_falsey
|
101
|
-
expect(subject.fresh?(var_a)).to be_falsey
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'should remove all associations' do
|
105
|
-
subject.add_var(var_a)
|
106
|
-
subject.add_assoc(var_a, pea)
|
107
|
-
|
108
|
-
subject.add_var(var_b)
|
109
|
-
subject.add_assoc(var_b, pod)
|
110
|
-
|
111
|
-
subject.clear
|
112
|
-
expect(subject.fresh?(var_a)).to be_truthy
|
113
|
-
expect(subject.fresh?(var_a)).to be_truthy
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should propagate associations up in the environment hierarchy' do
|
117
|
-
parent = Environment.new
|
118
|
-
parent.add_var(var_a)
|
119
|
-
instance = Environment.new(parent)
|
120
|
-
instance.add_var(var_b)
|
121
|
-
|
122
|
-
outcome = Outcome.new(:"#s", instance)
|
123
|
-
outcome.add_assoc(var_a, pea)
|
124
|
-
outcome.add_assoc(var_b, pod)
|
125
|
-
expect(outcome.associations.size).to eq(2)
|
126
|
-
|
127
|
-
# Propagate: outcome -> .. -> instance
|
128
|
-
instance.propagate(outcome)
|
129
|
-
expect(outcome.associations.size).to eq(1)
|
130
|
-
expect(instance.associations[var_b.name]).not_to be_nil
|
131
|
-
expect(parent.associations[var_a.name]).to be_nil
|
132
|
-
|
133
|
-
# Propagate: outcome -> .. -> parent
|
134
|
-
parent.propagate(outcome)
|
135
|
-
expect(outcome.associations).to be_empty
|
136
|
-
expect(parent.associations[var_b.name]).to be_nil
|
137
|
-
expect(parent.associations[var_a.name]).not_to be_nil
|
138
|
-
end
|
139
|
-
end # context
|
140
|
-
end # describe
|
141
|
-
end # module
|
142
|
-
end # module
|
data/spec/core/equals_spec.rb
DELETED
@@ -1,304 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
-
require_relative '../../lib/mini_kraken/core/environment'
|
5
|
-
|
6
|
-
require_relative '../support/factory_methods'
|
7
|
-
# Load the class under test
|
8
|
-
require_relative '../../lib/mini_kraken/core/equals'
|
9
|
-
|
10
|
-
module MiniKraken
|
11
|
-
module Core
|
12
|
-
describe Equals do
|
13
|
-
include FactoryMethods
|
14
|
-
|
15
|
-
subject { Equals.instance }
|
16
|
-
|
17
|
-
context 'Initialization:' do
|
18
|
-
it 'should be created without argument' do
|
19
|
-
expect { Equals.instance }.not_to raise_error
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'should know its name' do
|
23
|
-
expect(subject.name).to eq('equals')
|
24
|
-
end
|
25
|
-
end # context
|
26
|
-
|
27
|
-
context 'Provided services:' do
|
28
|
-
def build_var(aName)
|
29
|
-
new_var = Variable.new(aName)
|
30
|
-
env.add_var(new_var)
|
31
|
-
new_var
|
32
|
-
end
|
33
|
-
|
34
|
-
def build_var_ref(aName)
|
35
|
-
VariableRef.new(aName)
|
36
|
-
end
|
37
|
-
|
38
|
-
def solve_for(arg1, arg2)
|
39
|
-
solver = subject.solver_for([arg1, arg2], env)
|
40
|
-
outcome = solver.resume
|
41
|
-
env.propagate(outcome)
|
42
|
-
outcome
|
43
|
-
end
|
44
|
-
|
45
|
-
let(:pea) { KSymbol.new(:pea) }
|
46
|
-
let(:pod) { KSymbol.new(:pod) }
|
47
|
-
let(:sample_cons) { ConsCell.new(pea) }
|
48
|
-
let(:a_composite) { ConsCell.new(pod) }
|
49
|
-
let(:env) { Environment.new }
|
50
|
-
let(:var_q) { build_var('q') }
|
51
|
-
let(:ref_q) do
|
52
|
-
var_q # Force dependency
|
53
|
-
build_var_ref('q')
|
54
|
-
end
|
55
|
-
let(:ref_q_bis) do
|
56
|
-
var_q # Force dependency
|
57
|
-
build_var_ref('q')
|
58
|
-
end
|
59
|
-
let(:var_x) { build_var('x') }
|
60
|
-
let(:ref_x) do
|
61
|
-
var_x # Force dependency
|
62
|
-
build_var_ref('x')
|
63
|
-
end
|
64
|
-
let(:var_y) { build_var('y') }
|
65
|
-
let(:ref_y) do
|
66
|
-
var_y # Force dependency
|
67
|
-
build_var_ref('y')
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
it 'should succeed for equal literal arguments' do
|
72
|
-
result = solve_for(pea, pea)
|
73
|
-
|
74
|
-
expect(result).to be_kind_of(Outcome)
|
75
|
-
expect(result.resultant).to eq(:"#s")
|
76
|
-
expect(result.associations).to be_empty
|
77
|
-
expect(var_q.fresh?(env)).to be_truthy
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'should fail for inequal literal arguments' do
|
81
|
-
result = solve_for(pea, pod)
|
82
|
-
|
83
|
-
expect(result.resultant).to eq(:"#u")
|
84
|
-
expect(result.associations).to be_empty
|
85
|
-
expect(var_q.fresh?(env)).to be_truthy
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'should fail for one left literal and one composite arguments' do
|
89
|
-
result = solve_for(pea, sample_cons)
|
90
|
-
|
91
|
-
expect(result.resultant).to eq(:"#u")
|
92
|
-
expect(result.associations).to be_empty
|
93
|
-
expect(var_q.fresh?(env)).to be_truthy
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'should fail for one right literal and one composite arguments' do
|
97
|
-
# Reasoned S2, frame 1:44
|
98
|
-
# (== '(pea) 'pea) ;; => #u
|
99
|
-
result = solve_for(sample_cons, pea)
|
100
|
-
|
101
|
-
expect(result.resultant).to eq(:"#u")
|
102
|
-
expect(result.associations).to be_empty
|
103
|
-
expect(var_q.fresh?(env)).to be_truthy
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'should succeed for a right-handed fresh argument' do
|
107
|
-
result = solve_for(pea, ref_q)
|
108
|
-
|
109
|
-
expect(result).to be_successful
|
110
|
-
expect(env.associations.size).to eq(1)
|
111
|
-
expect(env.associations['q'].first.value).to eq(pea)
|
112
|
-
expect(var_q.fresh?(result)).to be_falsey
|
113
|
-
expect(ref_q.values(result).first).to eq(pea)
|
114
|
-
end
|
115
|
-
|
116
|
-
it 'should succeed for a left-handed fresh argument' do
|
117
|
-
result = solve_for(ref_q, pea)
|
118
|
-
|
119
|
-
expect(result).to be_successful
|
120
|
-
expect(env.associations.size).to eq(1)
|
121
|
-
expect(env.associations['q'].first.value).to eq(pea)
|
122
|
-
expect(var_q.fresh?(result)).to be_falsey
|
123
|
-
expect(ref_q.values(result).first).to eq(pea)
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'should succeed for a right-handed bound argument equal constant' do
|
127
|
-
ref_q.associate(pod, env)
|
128
|
-
|
129
|
-
result = solve_for(pod, ref_q)
|
130
|
-
expect(result).to be_successful
|
131
|
-
expect(env.associations.size).to eq(1) # No new association
|
132
|
-
expect(ref_q.fresh?(result)).not_to be_truthy
|
133
|
-
expect(ref_q.values(result).first).to eq(pod)
|
134
|
-
end
|
135
|
-
|
136
|
-
it 'should succeed for a left-handed bound argument equal constant' do
|
137
|
-
ref_q.associate(pod, env)
|
138
|
-
|
139
|
-
result = solve_for(ref_q, pod)
|
140
|
-
expect(result).to be_successful
|
141
|
-
expect(result.associations).to be_empty
|
142
|
-
expect(ref_q.fresh?(result)).to be_falsey
|
143
|
-
expect(ref_q.values(result).first).to eq(pod)
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'should fail for a right-handed bound argument to a distinct literal' do
|
147
|
-
ref_q.associate(pod, env)
|
148
|
-
|
149
|
-
result = solve_for(pea, ref_q)
|
150
|
-
expect(result).not_to be_successful
|
151
|
-
expect(result.associations).to be_empty
|
152
|
-
expect(ref_q.fresh?(result)).to be_falsey
|
153
|
-
expect(ref_q.values(result).first).to eq(pod)
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'should fail for a left-handed bound argument to a distinct literal' do
|
157
|
-
ref_q.associate(pod, env)
|
158
|
-
|
159
|
-
result = solve_for(ref_q, pea)
|
160
|
-
expect(result).not_to be_successful
|
161
|
-
expect(result.associations).to be_empty
|
162
|
-
expect(ref_q.fresh?(result)).to be_falsey
|
163
|
-
expect(ref_q.values(result).first).to eq(pod)
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'should succeed for a composite and right-handed fresh argument' do
|
167
|
-
result = solve_for(sample_cons, ref_q)
|
168
|
-
|
169
|
-
expect(result).to be_successful
|
170
|
-
expect(env.associations.size).to eq(1)
|
171
|
-
expect(ref_q.fresh?(result)).to be_falsey
|
172
|
-
expect(ref_q.values(result).first).to eq(sample_cons)
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'should succeed for composite and left-handed fresh argument' do
|
176
|
-
result = solve_for(ref_q, sample_cons)
|
177
|
-
|
178
|
-
expect(result).to be_successful
|
179
|
-
expect(env.associations.size).to eq(1)
|
180
|
-
expect(ref_q.fresh?(result)).to be_falsey
|
181
|
-
expect(ref_q.values(result).first).to eq(sample_cons)
|
182
|
-
end
|
183
|
-
|
184
|
-
it 'should succeed for a right-handed bound equal argument' do
|
185
|
-
ref_q.associate(sample_cons, env)
|
186
|
-
composite = ConsCell.new(pea)
|
187
|
-
result = solve_for(composite, ref_q)
|
188
|
-
|
189
|
-
expect(result).to be_successful
|
190
|
-
expect(result.associations).to be_empty
|
191
|
-
expect(ref_q.fresh?(result)).not_to be_truthy
|
192
|
-
expect(ref_q.values(result).first).to eq(sample_cons)
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'should succeed for a left-handed bound equal argument' do
|
196
|
-
ref_q.associate(sample_cons, env)
|
197
|
-
composite = ConsCell.new(pea)
|
198
|
-
result = solve_for(ref_q, composite)
|
199
|
-
|
200
|
-
expect(result).to be_successful
|
201
|
-
expect(result.associations).to be_empty
|
202
|
-
expect(ref_q.fresh?(result)).not_to be_truthy
|
203
|
-
expect(ref_q.values(result).first).to eq(sample_cons)
|
204
|
-
end
|
205
|
-
|
206
|
-
it 'should succeed for a right-handed bound unequal argument' do
|
207
|
-
ref_q.associate(sample_cons, env)
|
208
|
-
composite = ConsCell.new(pod)
|
209
|
-
result = solve_for(composite, ref_q)
|
210
|
-
|
211
|
-
expect(result).not_to be_successful
|
212
|
-
expect(result.associations).to be_empty
|
213
|
-
expect(ref_q.fresh?(result)).not_to be_truthy
|
214
|
-
expect(ref_q.values(result).first).to eq(sample_cons)
|
215
|
-
end
|
216
|
-
|
217
|
-
it 'should succeed for a left-handed bound unequal argument' do
|
218
|
-
ref_q.associate(sample_cons, env)
|
219
|
-
composite = ConsCell.new(pod)
|
220
|
-
result = solve_for(ref_q, composite)
|
221
|
-
|
222
|
-
expect(result).not_to be_successful
|
223
|
-
expect(result.associations).to be_empty
|
224
|
-
expect(ref_q.fresh?(result)).not_to be_truthy
|
225
|
-
expect(ref_q.values(result).first).to eq(sample_cons)
|
226
|
-
end
|
227
|
-
|
228
|
-
it 'should succeed for both identical fresh arguments' do
|
229
|
-
result = solve_for(ref_q, ref_q)
|
230
|
-
|
231
|
-
expect(result).to be_successful
|
232
|
-
expect(result.associations).to be_empty
|
233
|
-
expect(ref_q.fresh?(result)).to be_truthy
|
234
|
-
end
|
235
|
-
|
236
|
-
it 'should succeed for both same fresh arguments' do
|
237
|
-
result = solve_for(ref_q, ref_q_bis)
|
238
|
-
|
239
|
-
expect(result).to be_successful
|
240
|
-
expect(result.associations).to be_empty
|
241
|
-
expect(ref_q.fresh?(result)).to be_truthy
|
242
|
-
expect(ref_q_bis.fresh?(result)).to be_truthy
|
243
|
-
end
|
244
|
-
|
245
|
-
it 'should succeed for both distinct fresh arguments' do
|
246
|
-
result = solve_for(ref_x, ref_y)
|
247
|
-
|
248
|
-
expect(result).to be_successful
|
249
|
-
expect(env.associations).to be_empty # Symmetric association
|
250
|
-
expect(ref_x.fresh?(result)).to be_truthy
|
251
|
-
expect(ref_y.fresh?(result)).to be_truthy
|
252
|
-
end
|
253
|
-
|
254
|
-
it 'should succeed for arguments bound to equal values' do
|
255
|
-
ref_x.associate(pea, env)
|
256
|
-
ref_y.associate(pea, env)
|
257
|
-
expect(ref_x.fresh?(env)).to be_falsey
|
258
|
-
expect(ref_y.fresh?(env)).to be_falsey
|
259
|
-
|
260
|
-
result = solve_for(ref_x, ref_y)
|
261
|
-
expect(result).to be_successful
|
262
|
-
expect(result.associations).to be_empty
|
263
|
-
end
|
264
|
-
|
265
|
-
it 'should fail for arguments bound unequal values' do
|
266
|
-
ref_x.associate(pea, env)
|
267
|
-
ref_y.associate(pod, env)
|
268
|
-
expect(ref_x.fresh?(env)).to be_falsey
|
269
|
-
expect(ref_y.fresh?(env)).to be_falsey
|
270
|
-
|
271
|
-
result = solve_for(ref_x, ref_y)
|
272
|
-
expect(result).not_to be_successful
|
273
|
-
expect(result.associations).to be_empty
|
274
|
-
end
|
275
|
-
|
276
|
-
it 'should unify composite terms with variables' do
|
277
|
-
# Reasoned S2, frame 1:36
|
278
|
-
# (run* q (fresh (x) (== '(((,q)) ,x) `(((,x)) pod)))) ;; => ('pod)
|
279
|
-
expr1 = cons(cons(cons(ref_q)), ref_x)
|
280
|
-
expr2 = cons(cons(cons(ref_x)), pod)
|
281
|
-
|
282
|
-
result = solve_for(expr1, expr2)
|
283
|
-
# require 'debug'
|
284
|
-
expect(result).to be_successful
|
285
|
-
expect(ref_x.fresh?(env)).to be_falsey
|
286
|
-
expect(ref_q.fresh?(env)).to be_falsey
|
287
|
-
end
|
288
|
-
|
289
|
-
it 'should fail for one right literal and one composite arguments' do
|
290
|
-
# Reasoned S2, frame 1:46
|
291
|
-
# x associated to ('pea 'pod)
|
292
|
-
# (== '(,x) x) ;; => #u
|
293
|
-
expr1 = cons(pea, cons(pod))
|
294
|
-
ref_x.associate(expr1, env)
|
295
|
-
expr2 = cons(ref_x)
|
296
|
-
result = solve_for(expr2, ref_x)
|
297
|
-
|
298
|
-
expect(result.resultant).to eq(:"#u")
|
299
|
-
expect(result.associations).to be_empty
|
300
|
-
end
|
301
|
-
end # context
|
302
|
-
end # describe
|
303
|
-
end # module
|
304
|
-
end # module
|