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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +378 -333
  3. data/CHANGELOG.md +52 -0
  4. data/README.md +19 -19
  5. data/lib/mini_kraken.rb +0 -1
  6. data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
  7. data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
  8. data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
  9. data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
  10. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  11. data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
  12. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  13. data/lib/mini_kraken/composite/composite_term.rb +27 -0
  14. data/lib/mini_kraken/composite/cons_cell.rb +299 -0
  15. data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
  16. data/lib/mini_kraken/composite/list.rb +32 -0
  17. data/lib/mini_kraken/core/all_core.rb +8 -0
  18. data/lib/mini_kraken/core/any_value.rb +31 -7
  19. data/lib/mini_kraken/core/arity.rb +69 -0
  20. data/lib/mini_kraken/core/association.rb +29 -4
  21. data/lib/mini_kraken/core/association_copy.rb +50 -0
  22. data/lib/mini_kraken/core/base_term.rb +13 -0
  23. data/lib/mini_kraken/core/blackboard.rb +315 -0
  24. data/lib/mini_kraken/core/bookmark.rb +46 -0
  25. data/lib/mini_kraken/core/context.rb +492 -0
  26. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  27. data/lib/mini_kraken/core/entry.rb +40 -0
  28. data/lib/mini_kraken/core/fail.rb +20 -18
  29. data/lib/mini_kraken/core/fusion.rb +29 -0
  30. data/lib/mini_kraken/core/goal.rb +20 -29
  31. data/lib/mini_kraken/core/log_var.rb +22 -0
  32. data/lib/mini_kraken/core/log_var_ref.rb +108 -0
  33. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  34. data/lib/mini_kraken/core/parametrized_term.rb +61 -0
  35. data/lib/mini_kraken/core/relation.rb +14 -28
  36. data/lib/mini_kraken/core/scope.rb +67 -0
  37. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  38. data/lib/mini_kraken/core/specification.rb +48 -0
  39. data/lib/mini_kraken/core/succeed.rb +21 -17
  40. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  41. data/lib/mini_kraken/core/term.rb +15 -4
  42. data/lib/mini_kraken/glue/dsl.rb +45 -81
  43. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  44. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  45. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  46. data/lib/mini_kraken/rela/conde.rb +143 -0
  47. data/lib/mini_kraken/rela/conj2.rb +65 -0
  48. data/lib/mini_kraken/rela/def_relation.rb +93 -0
  49. data/lib/mini_kraken/rela/disj2.rb +70 -0
  50. data/lib/mini_kraken/rela/fresh.rb +98 -0
  51. data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
  52. data/lib/mini_kraken/rela/unify.rb +258 -0
  53. data/lib/mini_kraken/version.rb +1 -1
  54. data/mini_kraken.gemspec +2 -2
  55. data/spec/.rubocop.yml +1 -1
  56. data/spec/atomic/atomic_term_spec.rb +98 -0
  57. data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
  58. data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
  59. data/spec/composite/cons_cell_spec.rb +225 -0
  60. data/spec/composite/cons_cell_visitor_spec.rb +158 -0
  61. data/spec/composite/list_spec.rb +50 -0
  62. data/spec/core/any_value_spec.rb +52 -0
  63. data/spec/core/arity_spec.rb +92 -0
  64. data/spec/core/association_copy_spec.rb +69 -0
  65. data/spec/core/association_spec.rb +31 -4
  66. data/spec/core/blackboard_spec.rb +287 -0
  67. data/spec/core/bookmark_spec.rb +40 -0
  68. data/spec/core/context_spec.rb +245 -0
  69. data/spec/core/core_spec.rb +40 -0
  70. data/spec/core/duck_fiber_spec.rb +16 -46
  71. data/spec/core/fail_spec.rb +5 -6
  72. data/spec/core/goal_spec.rb +24 -14
  73. data/spec/core/log_var_ref_spec.rb +105 -0
  74. data/spec/core/log_var_spec.rb +64 -0
  75. data/spec/core/nullary_relation_spec.rb +33 -0
  76. data/spec/core/parametrized_tem_spec.rb +39 -0
  77. data/spec/core/relation_spec.rb +33 -0
  78. data/spec/core/scope_spec.rb +73 -0
  79. data/spec/core/solver_adapter_spec.rb +70 -0
  80. data/spec/core/specification_spec.rb +43 -0
  81. data/spec/core/succeed_spec.rb +5 -5
  82. data/spec/core/symbol_table_spec.rb +142 -0
  83. data/spec/glue/dsl_chap1_spec.rb +96 -144
  84. data/spec/glue/dsl_chap2_spec.rb +350 -0
  85. data/spec/glue/run_star_expression_spec.rb +82 -906
  86. data/spec/rela/conde_spec.rb +153 -0
  87. data/spec/rela/conj2_spec.rb +123 -0
  88. data/spec/rela/def_relation_spec.rb +119 -0
  89. data/spec/rela/disj2_spec.rb +117 -0
  90. data/spec/rela/fresh_spec.rb +147 -0
  91. data/spec/rela/unify_spec.rb +369 -0
  92. data/spec/support/factory_atomic.rb +29 -0
  93. data/spec/support/factory_composite.rb +21 -0
  94. data/spec/support/factory_methods.rb +11 -26
  95. metadata +100 -64
  96. data/lib/mini_kraken/core/association_walker.rb +0 -183
  97. data/lib/mini_kraken/core/atomic_term.rb +0 -67
  98. data/lib/mini_kraken/core/base_arg.rb +0 -10
  99. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  100. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  101. data/lib/mini_kraken/core/composite_term.rb +0 -41
  102. data/lib/mini_kraken/core/conde.rb +0 -143
  103. data/lib/mini_kraken/core/conj2.rb +0 -79
  104. data/lib/mini_kraken/core/cons_cell.rb +0 -82
  105. data/lib/mini_kraken/core/def_relation.rb +0 -50
  106. data/lib/mini_kraken/core/designation.rb +0 -55
  107. data/lib/mini_kraken/core/disj2.rb +0 -72
  108. data/lib/mini_kraken/core/environment.rb +0 -73
  109. data/lib/mini_kraken/core/equals.rb +0 -156
  110. data/lib/mini_kraken/core/formal_arg.rb +0 -22
  111. data/lib/mini_kraken/core/formal_ref.rb +0 -25
  112. data/lib/mini_kraken/core/freshness.rb +0 -45
  113. data/lib/mini_kraken/core/goal_arg.rb +0 -12
  114. data/lib/mini_kraken/core/goal_template.rb +0 -62
  115. data/lib/mini_kraken/core/k_boolean.rb +0 -35
  116. data/lib/mini_kraken/core/outcome.rb +0 -53
  117. data/lib/mini_kraken/core/variable.rb +0 -41
  118. data/lib/mini_kraken/core/variable_ref.rb +0 -78
  119. data/lib/mini_kraken/core/vocabulary.rb +0 -442
  120. data/lib/mini_kraken/glue/fresh_env.rb +0 -75
  121. data/spec/core/association_walker_spec.rb +0 -192
  122. data/spec/core/conde_spec.rb +0 -147
  123. data/spec/core/conj2_spec.rb +0 -114
  124. data/spec/core/cons_cell_spec.rb +0 -107
  125. data/spec/core/def_relation_spec.rb +0 -96
  126. data/spec/core/disj2_spec.rb +0 -99
  127. data/spec/core/environment_spec.rb +0 -142
  128. data/spec/core/equals_spec.rb +0 -304
  129. data/spec/core/goal_template_spec.rb +0 -74
  130. data/spec/core/outcome_spec.rb +0 -48
  131. data/spec/core/variable_ref_spec.rb +0 -27
  132. data/spec/core/variable_spec.rb +0 -35
  133. data/spec/core/vocabulary_spec.rb +0 -219
  134. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -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
@@ -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
@@ -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