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
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
|
5
|
+
# Load the class under test
|
6
|
+
require_relative '../../lib/mini_kraken/core/relation'
|
7
|
+
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe Relation do
|
12
|
+
subject { Relation.new('caro', 2) }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'should be initialized with a name and an arity' do
|
16
|
+
expect { Relation.new('caro', Arity.new(2, 2)) }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be initialized with a name and an integer' do
|
20
|
+
expect { Relation.new('caro', 2) }.not_to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should know its name' do
|
24
|
+
expect(subject.name).to eq('caro')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should know its arity' do
|
28
|
+
expect(subject.arity).to eq(Arity.new(2, 2))
|
29
|
+
end
|
30
|
+
end # context
|
31
|
+
end # describe
|
32
|
+
end # module
|
33
|
+
end # module
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../support/factory_atomic'
|
5
|
+
|
6
|
+
# Load the class under test
|
7
|
+
require_relative '../../lib/mini_kraken/core/scope'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe Scope do
|
12
|
+
include MiniKraken::FactoryAtomic # Use mix-in module
|
13
|
+
let(:mother) { Scope.new }
|
14
|
+
subject { Scope.new(mother) }
|
15
|
+
|
16
|
+
def var(aName)
|
17
|
+
LogVar.new(aName)
|
18
|
+
end
|
19
|
+
|
20
|
+
context 'Initialization:' do
|
21
|
+
it 'could be initialized without argument' do
|
22
|
+
expect { Scope.new }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'could be initialized with a parent scope' do
|
26
|
+
expect { Scope.new(mother) }.not_to raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it "shouldn't have definitions by default" do
|
30
|
+
expect(subject.defns).to be_empty
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should know its parent (if any)' do
|
34
|
+
expect(subject.parent).to eq(mother)
|
35
|
+
end
|
36
|
+
end # context
|
37
|
+
|
38
|
+
context 'Provided services:' do
|
39
|
+
it 'should accept the addition of a variable' do
|
40
|
+
subject.insert(var('a'))
|
41
|
+
expect(subject.defns).not_to be_empty
|
42
|
+
var_a = subject.defns['a']
|
43
|
+
expect(var_a).to be_kind_of(Core::LogVar)
|
44
|
+
expect(var_a.label).to eq('a')
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should accept the addition of multiple variables' do
|
48
|
+
subject.insert(var('a'))
|
49
|
+
expect(subject.defns).not_to be_empty
|
50
|
+
|
51
|
+
subject.insert(var('b'))
|
52
|
+
var_b = subject.defns['b']
|
53
|
+
expect(var_b).to be_kind_of(Core::LogVar)
|
54
|
+
expect(var_b.label).to eq('b')
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should set the suffix of just created variable' do
|
58
|
+
subject.insert(var('a'))
|
59
|
+
var_a = subject.defns['a']
|
60
|
+
expect(var_a.suffix).to eq("_#{subject.object_id.to_s(16)}")
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should complain when variable names collide' do
|
64
|
+
subject.insert(var('c'))
|
65
|
+
expect(subject.defns['c']).to be_kind_of(Core::LogVar)
|
66
|
+
err = StandardError
|
67
|
+
err_msg = "Variable with name 'c' already exists."
|
68
|
+
expect { subject.insert(var('c')) }.to raise_error(err, err_msg)
|
69
|
+
end
|
70
|
+
end # context
|
71
|
+
end # describe
|
72
|
+
end # module
|
73
|
+
end # module
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
require_relative '../../lib/mini_kraken/core/context'
|
7
|
+
|
8
|
+
# Load the class under test
|
9
|
+
require_relative '../../lib/mini_kraken/core/solver_adapter'
|
10
|
+
|
11
|
+
|
12
|
+
module MiniKraken
|
13
|
+
module Core
|
14
|
+
describe SolverAdapter do
|
15
|
+
let(:ctx) { Context.new }
|
16
|
+
let(:fib) { make_fiber(ctx, true, true, false, nil) }
|
17
|
+
let(:blk) do
|
18
|
+
lambda do |adapter, _context|
|
19
|
+
adapter.adaptee.resume
|
20
|
+
end
|
21
|
+
end
|
22
|
+
subject { SolverAdapter.new(fib, &blk) }
|
23
|
+
|
24
|
+
# Factory method.
|
25
|
+
def make_fiber(ctx, *args)
|
26
|
+
Fiber.new do
|
27
|
+
signature = *args
|
28
|
+
signature.each do |outcome|
|
29
|
+
if outcome
|
30
|
+
Fiber.yield ctx.succeeded!
|
31
|
+
next
|
32
|
+
elsif outcome.nil?
|
33
|
+
Fiber.yield nil
|
34
|
+
break
|
35
|
+
else
|
36
|
+
Fiber.yield ctx.failed!
|
37
|
+
next
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'Initialization:' do
|
44
|
+
it 'should be initialized with a Fiber-like object' do
|
45
|
+
expect { SolverAdapter.new(fib, &blk) }.not_to raise_error
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should know its adaptee' do
|
49
|
+
expect(subject.adaptee).to eq(fib)
|
50
|
+
end
|
51
|
+
end # context
|
52
|
+
|
53
|
+
context 'Provided services:' do
|
54
|
+
it 'should respond to the resume message' do
|
55
|
+
result = subject.resume(ctx)
|
56
|
+
expect(result).to be_success
|
57
|
+
|
58
|
+
result = subject.resume(ctx)
|
59
|
+
expect(result).to be_success
|
60
|
+
|
61
|
+
result = subject.resume(ctx)
|
62
|
+
expect(result).to be_failure
|
63
|
+
|
64
|
+
result = subject.resume(ctx)
|
65
|
+
expect(result).to be_nil
|
66
|
+
end
|
67
|
+
end # context
|
68
|
+
end # describe
|
69
|
+
end # module
|
70
|
+
end # module
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
|
5
|
+
# Load the class under test
|
6
|
+
require_relative '../../lib/mini_kraken/core/specification'
|
7
|
+
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe Specification do
|
12
|
+
subject { Specification.new('cons', 2) }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'should be initialized with a name and an arity' do
|
16
|
+
expect { Specification.new('cons', Arity.new(2, 2)) }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be initialized with a name and an integer' do
|
20
|
+
expect { Specification.new('cons', 2) }.not_to raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should know its name' do
|
24
|
+
expect(subject.name).to eq('cons')
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should know its arity' do
|
28
|
+
expect(subject.arity).to be_binary
|
29
|
+
end
|
30
|
+
end # context
|
31
|
+
|
32
|
+
context 'Provided services:' do
|
33
|
+
it "should complain when number of arguments does't fit arity" do
|
34
|
+
dummy_arg = double('dummy-stuff')
|
35
|
+
|
36
|
+
err = StandardError
|
37
|
+
err_msg = 'Count of arguments (1) is out of allowed range (2, 2).'
|
38
|
+
expect { subject.check_arity([dummy_arg]) }.to raise_error(err, err_msg)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end # describe
|
42
|
+
end # module
|
43
|
+
end # module
|
data/spec/core/succeed_spec.rb
CHANGED
@@ -21,17 +21,17 @@ module MiniKraken
|
|
21
21
|
end # context
|
22
22
|
|
23
23
|
context 'Provided services:' do
|
24
|
-
|
25
|
-
args = double('fake-args')
|
26
|
-
env = double('fake-env')
|
24
|
+
let(:ctx) { Context.new }
|
27
25
|
|
26
|
+
it 'should unconditionally return a success result' do
|
28
27
|
solver = nil
|
29
|
-
expect { solver = subject.solver_for(
|
28
|
+
expect { solver = subject.solver_for([], ctx) }.not_to raise_error
|
30
29
|
|
31
30
|
# Solver should quack like a Fiber
|
32
31
|
dummy_arg = double('dummy-stuff')
|
33
32
|
result = solver.resume(dummy_arg)
|
34
|
-
expect(result).to eq(
|
33
|
+
expect(result).to eq(ctx)
|
34
|
+
expect(result).to be_success
|
35
35
|
|
36
36
|
# Only one "solution", next 'resume' call should return nil
|
37
37
|
result = solver.resume(dummy_arg)
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require_relative '../../lib/mini_kraken/core/log_var'
|
5
|
+
|
6
|
+
# Load the class under test
|
7
|
+
require_relative '../../lib/mini_kraken/core/symbol_table'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe SymbolTable do
|
12
|
+
subject { SymbolTable.new }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'should be initialized without argument' do
|
16
|
+
expect { SymbolTable.new }.not_to raise_error
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should have a root scope' do
|
20
|
+
expect(subject.root).not_to be_nil
|
21
|
+
expect(subject.current_scope).to eq(subject.root)
|
22
|
+
expect(subject.root).to be_kind_of(Core::Scope)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "shouldn't have names at initialization" do
|
26
|
+
expect(subject.name2scopes).to be_empty
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should be empty at initialization' do
|
30
|
+
expect(subject).to be_empty
|
31
|
+
end
|
32
|
+
end # context
|
33
|
+
|
34
|
+
context 'Provided services:' do
|
35
|
+
def var(aName)
|
36
|
+
LogVar.new(aName)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should allow the addition of a variable' do
|
40
|
+
expect { subject.insert(var('q')) }.not_to raise_error
|
41
|
+
expect(subject).not_to be_empty
|
42
|
+
expect(subject.name2scopes['q']).to be_kind_of(Array)
|
43
|
+
expect(subject.name2scopes['q'].size).to eq(1)
|
44
|
+
expect(subject.name2scopes['q'].first).to eq(subject.current_scope)
|
45
|
+
expect(subject.current_scope.defns['q']).to be_kind_of(Core::LogVar)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should allow the addition of several labels for same env' do
|
49
|
+
i_name = subject.insert(var('q'))
|
50
|
+
expect(i_name).to match(/^q_[0-9a-z]+$/)
|
51
|
+
|
52
|
+
expect { subject.insert(var('x')) }.not_to raise_error
|
53
|
+
expect(subject.name2scopes['x']).to be_kind_of(Array)
|
54
|
+
expect(subject.name2scopes['x'].first).to eq(subject.current_scope)
|
55
|
+
expect(subject.current_scope.defns['x']).to be_kind_of(Core::LogVar)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should allow the entry into a new scope' do
|
59
|
+
subject.insert(var('q'))
|
60
|
+
new_scope = Core::Scope.new
|
61
|
+
expect { subject.enter_scope(new_scope) }.not_to raise_error
|
62
|
+
expect(subject.current_scope).to eq(new_scope)
|
63
|
+
expect(subject.current_scope.parent).to eq(subject.root)
|
64
|
+
expect(subject.name2scopes['q']).to eq([subject.root])
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should allow the addition of same name in different scopes' do
|
68
|
+
subject.insert(var('q'))
|
69
|
+
subject.enter_scope(Core::Scope.new)
|
70
|
+
subject.insert(var('q'))
|
71
|
+
expect(subject.name2scopes['q']).to be_kind_of(Array)
|
72
|
+
expect(subject.name2scopes['q'].size).to eq(2)
|
73
|
+
expect(subject.name2scopes['q'].first).to eq(subject.root)
|
74
|
+
expect(subject.name2scopes['q'].last).to eq(subject.current_scope)
|
75
|
+
expect(subject.current_scope.defns['q']).to be_kind_of(Core::LogVar)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should allow the removal of a scope' do
|
79
|
+
subject.insert(var('q'))
|
80
|
+
new_scope = Core::Scope.new
|
81
|
+
subject.enter_scope(new_scope)
|
82
|
+
subject.insert(var('q'))
|
83
|
+
expect(subject.name2scopes['q'].size).to eq(2)
|
84
|
+
|
85
|
+
expect { subject.leave_scope }.not_to raise_error
|
86
|
+
expect(subject.current_scope).to eq(subject.root)
|
87
|
+
expect(subject.name2scopes['q'].size).to eq(1)
|
88
|
+
expect(subject.name2scopes['q']).to eq([subject.root])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should allow the search of an entry based on its name' do
|
92
|
+
subject.insert(var('q'))
|
93
|
+
subject.insert(var('x'))
|
94
|
+
subject.enter_scope(Core::Scope.new)
|
95
|
+
subject.insert(var('q'))
|
96
|
+
subject.insert(var('y'))
|
97
|
+
|
98
|
+
# Search for unknown name
|
99
|
+
expect(subject.lookup('z')).to be_nil
|
100
|
+
|
101
|
+
# Search for existing unique names
|
102
|
+
expect(subject.lookup('y')).to eq(subject.current_scope.defns['y'])
|
103
|
+
expect(subject.lookup('x')).to eq(subject.root.defns['x'])
|
104
|
+
|
105
|
+
# Search for redefined name
|
106
|
+
expect(subject.lookup('q')).to eq(subject.current_scope.defns['q'])
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should allow the search of an entry based on its i_name' do
|
110
|
+
subject.insert(var('q'))
|
111
|
+
i_name_x = subject.insert(var('x'))
|
112
|
+
subject.enter_scope(Core::Scope.new)
|
113
|
+
i_name_q2 = subject.insert(var('q'))
|
114
|
+
i_name_y = subject.insert(var('y'))
|
115
|
+
|
116
|
+
# Search for unknown i_name
|
117
|
+
expect(subject.lookup_i_name('dummy')).to be_nil
|
118
|
+
|
119
|
+
curr_scope = subject.current_scope
|
120
|
+
# # Search for existing unique names
|
121
|
+
expect(subject.lookup_i_name(i_name_y)).to eq(curr_scope.defns['y'])
|
122
|
+
expect(subject.lookup_i_name(i_name_x)).to eq(subject.root.defns['x'])
|
123
|
+
|
124
|
+
# Search for redefined name
|
125
|
+
expect(subject.lookup_i_name(i_name_q2)).to eq(curr_scope.defns['q'])
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should list all the variables defined in all the szcope chain' do
|
129
|
+
subject.insert(var('q'))
|
130
|
+
subject.enter_scope(Core::Scope.new)
|
131
|
+
subject.insert(var('x'))
|
132
|
+
subject.enter_scope(Core::Scope.new)
|
133
|
+
subject.insert(var('y'))
|
134
|
+
subject.insert(var('x'))
|
135
|
+
|
136
|
+
vars = subject.all_variables
|
137
|
+
expect(vars.map(&:name)).to eq(%w[q x y x])
|
138
|
+
end
|
139
|
+
end # context
|
140
|
+
end # describe
|
141
|
+
end # module
|
142
|
+
end # module
|
data/spec/glue/dsl_chap1_spec.rb
CHANGED
@@ -22,14 +22,14 @@ module MiniKraken
|
|
22
22
|
it 'passes frame 1:10' do
|
23
23
|
# (run* q (== 'pea 'pod) ;; => ()
|
24
24
|
|
25
|
-
result = run_star('q',
|
25
|
+
result = run_star('q', unify(:pea, :pod))
|
26
26
|
expect(result).to be_null
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'passes frame 1:11' do
|
30
30
|
# (run* q (== q 'pea) ;; => (pea)
|
31
31
|
|
32
|
-
result = run_star('q',
|
32
|
+
result = run_star('q', unify(q, :pea))
|
33
33
|
expect(result.car).to eq(:pea)
|
34
34
|
end
|
35
35
|
|
@@ -37,7 +37,7 @@ module MiniKraken
|
|
37
37
|
# Reasoned S2, frame 1:12
|
38
38
|
# (run* q (== 'pea q) ;; => (pea)
|
39
39
|
|
40
|
-
result = run_star('q',
|
40
|
+
result = run_star('q', unify(:pea, q))
|
41
41
|
expect(result.car).to eq(:pea)
|
42
42
|
end
|
43
43
|
|
@@ -52,14 +52,14 @@ module MiniKraken
|
|
52
52
|
# Reasoned S2, frame 1:19
|
53
53
|
# (run* q (== 'pea 'pea)) ;; => (_0)
|
54
54
|
|
55
|
-
result = run_star('q',
|
55
|
+
result = run_star('q', unify(:pea, :pea))
|
56
56
|
expect(result.car).to eq(:_0)
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'passes frame 1:20' do
|
60
60
|
# (run* q (== q q)) ;; => (_0)
|
61
61
|
|
62
|
-
result = run_star('q',
|
62
|
+
result = run_star('q', unify(q, q))
|
63
63
|
expect(result.car).to eq(:_0)
|
64
64
|
end
|
65
65
|
|
@@ -67,28 +67,30 @@ module MiniKraken
|
|
67
67
|
# Reasoned S2, frame 1:21
|
68
68
|
# (run* q (fresh (x) (== 'pea q))) ;; => (pea)
|
69
69
|
|
70
|
-
result = run_star('q', fresh('x',
|
70
|
+
result = run_star('q', fresh('x', unify(:pea, q)))
|
71
71
|
expect(result.car).to eq(:pea)
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'passes frame 1:25' do
|
75
|
-
# (run* q
|
76
|
-
#
|
77
|
-
|
78
|
-
|
75
|
+
# (run* q
|
76
|
+
# (fresh (x)
|
77
|
+
# (== (cons x '()) q))) ;; => ((_0))
|
78
|
+
|
79
|
+
result = run_star('q', fresh('x', unify(cons(x, null_list), q)))
|
80
|
+
expect(result.car.to_s).to eq('(_0)')
|
79
81
|
end
|
80
82
|
|
81
83
|
it 'passes frame 1:31' do
|
82
84
|
# (run* q (fresh (x) (== x q))) ;; => (_0)
|
83
85
|
|
84
|
-
result = run_star('q', fresh('x',
|
86
|
+
result = run_star('q', fresh('x', unify(x, q)))
|
85
87
|
expect(result.car).to eq(:_0)
|
86
88
|
end
|
87
89
|
|
88
90
|
it 'passes frame 1:32' do
|
89
91
|
# (run* q (== '(((pea)) pod) '(((pea)) pod))) ;; => (_0)
|
90
92
|
|
91
|
-
result = run_star('q',
|
93
|
+
result = run_star('q', unify(cons(cons(:pea), :pod), cons(cons(:pea), :pod)))
|
92
94
|
expect(result.car).to eq(:_0)
|
93
95
|
end
|
94
96
|
|
@@ -96,7 +98,7 @@ module MiniKraken
|
|
96
98
|
# Beware: quasiquoting
|
97
99
|
# (run* q (== '(((pea)) pod) '(((pea)) ,q))) ;; => ('pod)
|
98
100
|
|
99
|
-
result = run_star('q',
|
101
|
+
result = run_star('q', unify(cons(cons(:pea), :pod), cons(cons(:pea), q)))
|
100
102
|
expect(result.car).to eq(:pod)
|
101
103
|
end
|
102
104
|
|
@@ -107,14 +109,14 @@ module MiniKraken
|
|
107
109
|
expect(expr1.to_s).to eq('(((q)) :pod)')
|
108
110
|
expr2 = cons(cons(cons(:pea)), cons(:pod))
|
109
111
|
expect(expr2.to_s).to eq('(((:pea)) :pod)')
|
110
|
-
result = run_star('q',
|
112
|
+
result = run_star('q', unify(expr1, expr2))
|
111
113
|
expect(result.car).to eq(:pea)
|
112
114
|
end
|
113
115
|
|
114
116
|
it 'passes frame 1:35' do
|
115
117
|
# (run* q (fresh (x) (== '(((,q)) pod) `(((,x)) pod)))) ;; => (_0)
|
116
118
|
|
117
|
-
result = run_star('q', fresh('x',
|
119
|
+
result = run_star('q', fresh('x', unify(cons(cons(q), :pod), cons(cons(x), :pod))))
|
118
120
|
expect(result.car).to eq(:_0)
|
119
121
|
end
|
120
122
|
|
@@ -125,21 +127,21 @@ module MiniKraken
|
|
125
127
|
expect(expr1.to_s).to eq('(((q)) x)')
|
126
128
|
expr2 = cons(cons(cons(x)), cons(:pod))
|
127
129
|
expect(expr2.to_s).to eq('(((x)) :pod)')
|
128
|
-
result = run_star('q', fresh('x',
|
130
|
+
result = run_star('q', fresh('x', unify(expr1, expr2)))
|
129
131
|
expect(result.car).to eq(:pod)
|
130
132
|
end
|
131
133
|
|
132
134
|
it 'passes frame 1:37' do
|
133
135
|
# (run* q (fresh (x) (== '( ,x ,x) q))) ;; => (_0 _0)
|
134
136
|
|
135
|
-
result = run_star('q', fresh('x',
|
137
|
+
result = run_star('q', fresh('x', unify(cons(x, cons(x)), q)))
|
136
138
|
expect(result.car).to eq(cons(:_0, cons(:_0)))
|
137
139
|
end
|
138
140
|
|
139
141
|
it 'passes frame 1:38' do
|
140
142
|
# (run* q (fresh (x) (fresh (y) (== '( ,q ,y) '((,x ,y) ,x))))) ;; => (_0 _0)
|
141
143
|
|
142
|
-
result = run_star('q', fresh('x', fresh('y',
|
144
|
+
result = run_star('q', fresh('x', fresh('y', unify(cons(q, cons(y)), cons(cons(x, cons(y)), cons(x))))))
|
143
145
|
expect(result.car).to eq(cons(:_0, cons(:_0)))
|
144
146
|
end
|
145
147
|
|
@@ -147,7 +149,7 @@ module MiniKraken
|
|
147
149
|
# Reasoned S2, frame 1:41
|
148
150
|
# (run* q (fresh (x) (fresh (y) (== '( ,x ,y) q)))) ;; => (_0 _1)
|
149
151
|
|
150
|
-
result = run_star('q', fresh('x', fresh('y',
|
152
|
+
result = run_star('q', fresh('x', fresh('y', unify(cons(x, cons(y)), q))))
|
151
153
|
# q should be bound to '(,x ,y)
|
152
154
|
expect(result.car).to eq(cons(:_0, cons(:_1)))
|
153
155
|
end
|
@@ -155,7 +157,7 @@ module MiniKraken
|
|
155
157
|
it 'passes frame 1:42' do
|
156
158
|
# (run* s (fresh (t) (fresh (u) (== '( ,t ,u) s)))) ;; => (_0 _1)
|
157
159
|
|
158
|
-
result = run_star('s', fresh('t', fresh('u',
|
160
|
+
result = run_star('s', fresh('t', fresh('u', unify(cons(t, cons(u)), s))))
|
159
161
|
# s should be bound to '(,t ,u)
|
160
162
|
expect(result.car).to eq(cons(:_0, cons(:_1)))
|
161
163
|
end
|
@@ -163,7 +165,7 @@ module MiniKraken
|
|
163
165
|
it 'passes frame 1:43' do
|
164
166
|
# (run* q (fresh (x) (fresh (y) (== '( ,x ,y ,x) q)))) ;; => (_0 _1 _0)
|
165
167
|
|
166
|
-
result = run_star('q', fresh('x', fresh('y',
|
168
|
+
result = run_star('q', fresh('x', fresh('y', unify(cons(x, cons(y, cons(x))), q))))
|
167
169
|
# q should be bound to '(,x ,y, ,x)
|
168
170
|
expect(result.car).to eq(cons(:_0, cons(:_1, cons(:_0))))
|
169
171
|
end
|
@@ -179,14 +181,14 @@ module MiniKraken
|
|
179
181
|
it 'passes frame 1:51' do
|
180
182
|
# (run* q (conj2 succeed (== 'corn q)) ;; => ('corn)
|
181
183
|
|
182
|
-
result = run_star('q', conj2(succeed,
|
184
|
+
result = run_star('q', conj2(succeed, unify(:corn, q)))
|
183
185
|
expect(result.car).to eq(:corn)
|
184
186
|
end
|
185
187
|
|
186
188
|
it 'passes frame 1:52' do
|
187
189
|
# (run* q (conj2 fail (== 'corn q)) ;; => ()
|
188
190
|
|
189
|
-
result = run_star('q', conj2(_fail,
|
191
|
+
result = run_star('q', conj2(_fail, unify(:corn, q)))
|
190
192
|
expect(result).to be_null
|
191
193
|
end
|
192
194
|
|
@@ -194,14 +196,14 @@ module MiniKraken
|
|
194
196
|
# Reasoned S2, frame 1:53
|
195
197
|
# (run* q (conj2 (== 'corn q)(== 'meal q)) ;; => ()
|
196
198
|
|
197
|
-
result = run_star('q', conj2(
|
199
|
+
result = run_star('q', conj2(unify(:corn, q), unify(:meal, q)))
|
198
200
|
expect(result).to be_null
|
199
201
|
end
|
200
202
|
|
201
203
|
it 'passes frame 1:54' do
|
202
204
|
# (run* q (conj2 (== 'corn q)(== 'corn q)) ;; => ('corn)
|
203
205
|
|
204
|
-
result = run_star('q', conj2(
|
206
|
+
result = run_star('q', conj2(unify(:corn, q), unify(:corn, q)))
|
205
207
|
expect(result.car).to eq(:corn)
|
206
208
|
end
|
207
209
|
|
@@ -215,21 +217,21 @@ module MiniKraken
|
|
215
217
|
it 'passes frame 1:56' do
|
216
218
|
# (run* q (disj2 (== 'olive q) fail)) ;; => ('olive)
|
217
219
|
|
218
|
-
result = run_star('q', disj2(
|
220
|
+
result = run_star('q', disj2(unify(:olive, q), _fail))
|
219
221
|
expect(result.car).to eq(:olive)
|
220
222
|
end
|
221
223
|
|
222
224
|
it 'passes frame 1:57' do
|
223
225
|
# (run* q (disj2 fail (== 'oil q))) ;; => (oil)
|
224
226
|
|
225
|
-
result = run_star('q', disj2(_fail,
|
227
|
+
result = run_star('q', disj2(_fail, unify(:oil, q)))
|
226
228
|
expect(result.car).to eq(:oil)
|
227
229
|
end
|
228
230
|
|
229
231
|
it 'passes frame 1:58' do
|
230
232
|
# (run* q (disj2 (== 'olive q) (== 'oil q))) ;; => (olive oil)
|
231
233
|
|
232
|
-
result = run_star('q', disj2(
|
234
|
+
result = run_star('q', disj2(unify(:olive, q), unify(:oil, q)))
|
233
235
|
expect(result.car).to eq(:olive)
|
234
236
|
expect(result.cdr.car).to eq(:oil)
|
235
237
|
end
|
@@ -238,7 +240,7 @@ module MiniKraken
|
|
238
240
|
# (run* q (fresh (x) (fresh (y) (disj2 (== '( ,x ,y ) q) (== '( ,x ,y ) q)))))
|
239
241
|
# ;; => ((_0 _1) (_0 _1))
|
240
242
|
|
241
|
-
result = run_star('q', fresh('x', (fresh 'y', disj2(
|
243
|
+
result = run_star('q', fresh('x', (fresh 'y', disj2(unify(cons(x, cons(y)), q), unify(cons(x, cons(y)), q)))))
|
242
244
|
# q should be bound to '(,x ,y), then to '(,y ,x)
|
243
245
|
expect(result.car).to eq(cons(:_0, cons(:_1)))
|
244
246
|
expect(result.cdr.car).to eq(cons(:_0, cons(:_1)))
|
@@ -249,7 +251,7 @@ module MiniKraken
|
|
249
251
|
# (conj2 (== 'olive x) fail)
|
250
252
|
# (== 'oil x))) ;; => (oil)
|
251
253
|
|
252
|
-
result = run_star('x', disj2(conj2(
|
254
|
+
result = run_star('x', disj2(conj2(unify(:olive, x), _fail), unify(:oil, x)))
|
253
255
|
expect(result.car).to eq(:oil)
|
254
256
|
end
|
255
257
|
|
@@ -258,7 +260,7 @@ module MiniKraken
|
|
258
260
|
# (conj2 (== 'olive x) succeed)
|
259
261
|
# ('oil x))) ;; => (olive oil)
|
260
262
|
|
261
|
-
result = run_star('x', disj2(conj2(
|
263
|
+
result = run_star('x', disj2(conj2(unify(:olive, x), succeed), unify(:oil, x)))
|
262
264
|
expect(result).to eq(cons(:olive, cons(:oil)))
|
263
265
|
end
|
264
266
|
|
@@ -267,7 +269,7 @@ module MiniKraken
|
|
267
269
|
# (== 'oil x)
|
268
270
|
# (conj2 (== 'olive x) succeed))) ;; => (oil olive)
|
269
271
|
|
270
|
-
result = run_star('x', disj2(
|
272
|
+
result = run_star('x', disj2(unify(:oil, x), conj2(unify(:olive, x), succeed)))
|
271
273
|
expect(result).to eq(cons(:oil, cons(:olive)))
|
272
274
|
end
|
273
275
|
|
@@ -280,9 +282,10 @@ module MiniKraken
|
|
280
282
|
# succeed
|
281
283
|
# (== 'oil x))))) ;; => (olive _0 oil)
|
282
284
|
|
283
|
-
result = run_star('x', disj2(conj2(
|
284
|
-
disj2(
|
285
|
+
result = run_star('x', disj2(conj2(unify(:virgin, x), _fail),
|
286
|
+
disj2(unify(:olive, x), disj2(succeed, unify(:oil, x)))))
|
285
287
|
expect(result).to eq(cons(:olive, cons(:_0, cons(:oil))))
|
288
|
+
expect(result.to_s).to eq('(:olive _0 :oil)')
|
286
289
|
end
|
287
290
|
|
288
291
|
it 'passes frame 1:67' do
|
@@ -296,9 +299,9 @@ module MiniKraken
|
|
296
299
|
# (== '(,x ,y) r)))))) ;; => ((split pea))
|
297
300
|
|
298
301
|
result = run_star('r', fresh('x', fresh('y',
|
299
|
-
conj2(
|
300
|
-
conj2(
|
301
|
-
expect(result).to eq(
|
302
|
+
conj2(unify(:split, x),
|
303
|
+
conj2(unify(:pea, y), unify(cons(x, cons(y)), r))))))
|
304
|
+
expect(result.to_s).to eq('((:split :pea))')
|
302
305
|
end
|
303
306
|
|
304
307
|
it 'passes frame 1:68' do
|
@@ -312,9 +315,9 @@ module MiniKraken
|
|
312
315
|
# (== '(,x ,y) r)))))) ;; => ((split pea))
|
313
316
|
|
314
317
|
result = run_star('r', fresh('x', fresh('y',
|
315
|
-
conj2(conj2(
|
316
|
-
|
317
|
-
expect(result).to eq(
|
318
|
+
conj2(conj2(unify(:split, x), unify(:pea, y)),
|
319
|
+
unify(cons(x, cons(y)), r)))))
|
320
|
+
expect(result.to_s).to eq('((:split :pea))')
|
318
321
|
end
|
319
322
|
|
320
323
|
it 'passes frame 1:70' do
|
@@ -327,9 +330,9 @@ module MiniKraken
|
|
327
330
|
# (== '(,x ,y) r))))) ;; => ((split pea))
|
328
331
|
|
329
332
|
result = run_star('r', fresh(%w[x y], conj2(
|
330
|
-
conj2(
|
331
|
-
|
332
|
-
expect(result).to eq(
|
333
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
334
|
+
unify(cons(x, cons(y)), r))))
|
335
|
+
expect(result.to_s).to eq('((:split :pea))')
|
333
336
|
end
|
334
337
|
|
335
338
|
it 'passes frame 1:72' do
|
@@ -354,14 +357,15 @@ module MiniKraken
|
|
354
357
|
# pea nil pea nil
|
355
358
|
|
356
359
|
result = run_star(%w[r x y], conj2(
|
357
|
-
conj2(
|
358
|
-
|
360
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
361
|
+
unify(cons(x, cons(y)), r)))
|
359
362
|
expect(result.car.car.car).to eq(:split)
|
360
363
|
expect(result.car.car.cdr.car).to eq(:pea)
|
361
364
|
expect(result.car.car.cdr.cdr).to be_nil
|
362
365
|
expect(result.car.cdr.car).to eq(:split)
|
363
366
|
expect(result.car.cdr.cdr.car).to eq(:pea)
|
364
367
|
expect(result.car.cdr.cdr.cdr).to be_nil
|
368
|
+
expect(result.to_s).to eq('(((:split :pea) :split :pea))')
|
365
369
|
end
|
366
370
|
|
367
371
|
it 'passes frame 1:75' do
|
@@ -370,8 +374,8 @@ module MiniKraken
|
|
370
374
|
# (== 'split x)
|
371
375
|
# (== 'pea y))) ;; => ((split pea))
|
372
376
|
|
373
|
-
result = run_star(%w[x y], conj2(
|
374
|
-
expect(result.
|
377
|
+
result = run_star(%w[x y], conj2(unify(:split, x), unify(:pea, y)))
|
378
|
+
expect(result.to_s).to eq('((:split :pea))')
|
375
379
|
end
|
376
380
|
|
377
381
|
it 'passes frame 1:76' do
|
@@ -381,8 +385,9 @@ module MiniKraken
|
|
381
385
|
# (conj2 (== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
|
382
386
|
|
383
387
|
result = run_star(%w[x y], disj2(
|
384
|
-
conj2(
|
385
|
-
conj2(
|
388
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
389
|
+
conj2(unify(:red, x), unify(:bean, y))))
|
390
|
+
expect(result.to_s).to eq('((:split :pea) (:red :bean))')
|
386
391
|
expect(result.car).to eq(list(:split, :pea))
|
387
392
|
expect(result.cdr.car).to eq(list(:red, :bean))
|
388
393
|
end
|
@@ -399,9 +404,10 @@ module MiniKraken
|
|
399
404
|
result = run_star('r',
|
400
405
|
fresh(%w[x y], conj2(
|
401
406
|
disj2(
|
402
|
-
conj2(
|
403
|
-
conj2(
|
404
|
-
|
407
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
408
|
+
conj2(unify(:red, x), unify(:bean, y))),
|
409
|
+
unify(cons(x, cons(y, cons(:soup))), r))))
|
410
|
+
expect(result.to_s).to eq('((:split :pea :soup) (:red :bean :soup))')
|
405
411
|
expect(result.car).to eq(list(:split, :pea, :soup))
|
406
412
|
expect(result.cdr.car).to eq(list(:red, :bean, :soup))
|
407
413
|
end
|
@@ -416,11 +422,10 @@ module MiniKraken
|
|
416
422
|
|
417
423
|
result = run_star('r',
|
418
424
|
fresh(%w[x y], [disj2(
|
419
|
-
conj2(
|
420
|
-
conj2(
|
421
|
-
|
422
|
-
expect(result.
|
423
|
-
expect(result.cdr.car).to eq(list(:red, :bean, :soup))
|
425
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
426
|
+
conj2(unify(:red, x), unify(:bean, y))),
|
427
|
+
unify(cons(x, cons(y, cons(:soup))), r)]))
|
428
|
+
expect(result.to_s).to eq('((:split :pea :soup) (:red :bean :soup))')
|
424
429
|
end
|
425
430
|
|
426
431
|
it 'passes frame 1:80' do
|
@@ -431,9 +436,9 @@ module MiniKraken
|
|
431
436
|
# (== 'soup z)) ;; => ((split pea soup) (red bean soup))
|
432
437
|
|
433
438
|
result = run_star(%w[x y z], [disj2(
|
434
|
-
conj2(
|
435
|
-
conj2(
|
436
|
-
|
439
|
+
conj2(unify(:split, x), unify(:pea, y)),
|
440
|
+
conj2(unify(:red, x), unify(:bean, y))),
|
441
|
+
unify(:soup, z)])
|
437
442
|
expect(result.car).to eq(list(:split, :pea, :soup))
|
438
443
|
expect(result.cdr.car).to eq(list(:red, :bean, :soup))
|
439
444
|
end
|
@@ -443,42 +448,26 @@ module MiniKraken
|
|
443
448
|
# (== 'split x)
|
444
449
|
# (== 'pea y)) ;; => ((split pea))
|
445
450
|
|
446
|
-
result = run_star(%w[x y], [
|
451
|
+
result = run_star(%w[x y], [unify(:split, x), unify(:pea, y)])
|
447
452
|
expect(result.car).to eq(list(:split, :pea))
|
448
453
|
end
|
449
454
|
|
450
455
|
it "supports 'defrel' and passes frame 1:82" do
|
451
456
|
# (defrel (teacupo t)
|
452
457
|
# (disj2 (== 'tea t) (== 'cup t)))
|
453
|
-
|
454
|
-
result = defrel('teacupo', 't')
|
455
|
-
|
456
|
-
end
|
457
|
-
|
458
|
-
expect(result).to be_kind_of(Core::DefRelation)
|
458
|
+
expr = disj2(unify(:tea, t), unify(:cup, t))
|
459
|
+
result = defrel('teacupo', ['t'], expr)
|
460
|
+
expect(result).to be_kind_of(Rela::DefRelation)
|
459
461
|
expect(result.name).to eq('teacupo')
|
460
462
|
expect(result.formals.size).to eq(1)
|
461
|
-
expect(result.formals[0]
|
462
|
-
|
463
|
-
expect(
|
464
|
-
expect(
|
465
|
-
|
466
|
-
first_arg = g_template.args[0]
|
467
|
-
expect(first_arg).to be_kind_of(Core::GoalTemplate)
|
468
|
-
expect(first_arg.relation).to eq(Core::Equals.instance)
|
469
|
-
expect(first_arg.args[0]).to eq(:tea)
|
470
|
-
expect(first_arg.args[1]).to be_kind_of(Core::FormalRef)
|
471
|
-
expect(first_arg.args[1].name).to eq('t')
|
472
|
-
second_arg = g_template.args[1]
|
473
|
-
expect(second_arg).to be_kind_of(Core::GoalTemplate)
|
474
|
-
expect(second_arg.relation).to eq(Core::Equals.instance)
|
475
|
-
expect(second_arg.args[0]).to eq(:cup)
|
476
|
-
expect(second_arg.args[1]).to be_kind_of(Core::FormalRef)
|
477
|
-
expect(second_arg.args[1].name).to eq('t')
|
463
|
+
expect(result.formals[0]).to match(/^t_/)
|
464
|
+
goal_expr = result.expression
|
465
|
+
expect(goal_expr).to be_kind_of(Core::Goal)
|
466
|
+
expect(goal_expr.relation).to eq(Rela::Disj2.instance)
|
478
467
|
end
|
479
468
|
|
480
|
-
|
481
|
-
defrel('teacupo', 't'
|
469
|
+
let(:defrel_teacupo) do
|
470
|
+
defrel('teacupo', ['t'], disj2(unify(:tea, t), unify(:cup, t)))
|
482
471
|
end
|
483
472
|
|
484
473
|
it "supports the invokation of a 'defrel' and passes frame 1:83" do
|
@@ -502,8 +491,8 @@ module MiniKraken
|
|
502
491
|
defrel_teacupo
|
503
492
|
result = run_star(%w[x y],
|
504
493
|
disj2(
|
505
|
-
conj2(teacupo(x),
|
506
|
-
conj2(
|
494
|
+
conj2(teacupo(x), unify('#t', y)),
|
495
|
+
conj2(unify('#f', x), unify('#t', y))))
|
507
496
|
|
508
497
|
# Order of solutions differs from RS book
|
509
498
|
expect(result.car).to eq(cons(:tea, cons(true)))
|
@@ -544,7 +533,7 @@ module MiniKraken
|
|
544
533
|
defrel_teacupo
|
545
534
|
result = run_star(%w[x y], disj2(
|
546
535
|
conj2(teacupo(x), teacupo(x)),
|
547
|
-
conj2(
|
536
|
+
conj2(unify('#f', x), teacupo(y))))
|
548
537
|
|
549
538
|
# Order of solutions differs from RS book
|
550
539
|
expected = '((:tea _0) (:cup _0) (false :tea) (false :cup))'
|
@@ -564,7 +553,7 @@ module MiniKraken
|
|
564
553
|
defrel_teacupo
|
565
554
|
result = run_star(%w[x y], conde(
|
566
555
|
[teacupo(x), teacupo(x)],
|
567
|
-
[
|
556
|
+
[unify('#f', x), teacupo(y)]))
|
568
557
|
|
569
558
|
# Order of solutions differs from RS book
|
570
559
|
expected = '((:tea _0) (:cup _0) (false :tea) (false :cup))'
|
@@ -578,8 +567,8 @@ module MiniKraken
|
|
578
567
|
# ((== 'split x) (== 'pea y))
|
579
568
|
# ((== 'red x) (== 'bean y)))) ;; => ((split pea)(red bean))
|
580
569
|
result = run_star(%w[x y], conde(
|
581
|
-
[
|
582
|
-
[
|
570
|
+
[unify(:split, x), unify(:pea, y)],
|
571
|
+
[unify(:red, x), unify(:bean, y)]))
|
583
572
|
|
584
573
|
expected = '((:split :pea) (:red :bean))'
|
585
574
|
expect(result.to_s).to eq(expected)
|
@@ -593,8 +582,8 @@ module MiniKraken
|
|
593
582
|
# ('oil x))) ;; => (oil)
|
594
583
|
|
595
584
|
result = run_star('x', conde(
|
596
|
-
[
|
597
|
-
|
585
|
+
[unify(:olive, x), _fail],
|
586
|
+
unify(:oil, x)))
|
598
587
|
|
599
588
|
expect(result.to_s).to eq('(:oil)')
|
600
589
|
end
|
@@ -607,8 +596,8 @@ module MiniKraken
|
|
607
596
|
# ((== x y)))) ;; => ((_0 _1)(_0 _0))
|
608
597
|
|
609
598
|
result = run_star(%w[x y], conde(
|
610
|
-
[fresh(%w[z],
|
611
|
-
[
|
599
|
+
[fresh(%w[z], unify(:lentil, z))],
|
600
|
+
[unify(x, y)]))
|
612
601
|
|
613
602
|
expect(result.to_s).to eq('((_0 _1) (_0 _0))')
|
614
603
|
end
|
@@ -621,9 +610,9 @@ module MiniKraken
|
|
621
610
|
# ((== 'green x) (== 'lentil y))))
|
622
611
|
# ;; => ((split pea)(red bean)(green lentil))
|
623
612
|
result = run_star(%w[x y], conde(
|
624
|
-
[
|
625
|
-
[
|
626
|
-
[
|
613
|
+
[unify(:split, x), unify(:pea, y)],
|
614
|
+
[unify(:red, x), unify(:bean, y)],
|
615
|
+
[unify(:green, x), unify(:lentil, y)]))
|
627
616
|
|
628
617
|
expected = '((:split :pea) (:red :bean) (:green :lentil))'
|
629
618
|
expect(result.to_s).to eq(expected)
|