mini_kraken 0.1.10 → 0.1.11
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/CHANGELOG.md +15 -0
- data/README.md +11 -3
- data/lib/mini_kraken/core/association_walker.rb +1 -1
- data/lib/mini_kraken/core/base_arg.rb +10 -0
- data/lib/mini_kraken/core/def_relation.rb +49 -0
- data/lib/mini_kraken/core/disj2.rb +1 -0
- data/lib/mini_kraken/core/formal_arg.rb +22 -0
- data/lib/mini_kraken/core/formal_ref.rb +24 -0
- data/lib/mini_kraken/core/goal_arg.rb +5 -3
- data/lib/mini_kraken/core/goal_template.rb +60 -0
- data/lib/mini_kraken/core/k_boolean.rb +31 -0
- data/lib/mini_kraken/glue/run_star_expression.rb +1 -0
- data/lib/mini_kraken/version.rb +1 -1
- data/spec/core/def_relation_spec.rb +96 -0
- data/spec/core/goal_template_spec.rb +74 -0
- data/spec/core/k_boolean_spec.rb +107 -0
- data/spec/glue/run_star_expression_spec.rb +108 -0
- data/spec/support/factory_methods.rb +8 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 672521fbc6627e2767bfe4d6ce38dd66243736fee451e857ec7ef45d0f8905fe
|
4
|
+
data.tar.gz: 6835bb1d91bb6e867417faba0d6904734295f9a7bab612c6a78fcfbcdc41f84a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd5b5b2d2493b4ec8f8293c5f786be1a7739d05bee5d4733d48edb16713d1df4097be5a6e85127c2c90cf395da877b57ef07a607167b8f5bb1732dbc2a367610
|
7
|
+
data.tar.gz: 6661aadbe8bd778283e91f31181651e32296150d282575697fee1f5c240ea46168c5107baf33d9b590d6a449ec89b2f41e69340b81cb9b9e3692954af155083b
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## [0.1.11] - 2020-06-10
|
2
|
+
- Supports `defrel`, taht is, the capability to define new relations by combining other relations.
|
3
|
+
- Covers frames from "The Reasoned Scheme" book up to frame [1:87]
|
4
|
+
|
5
|
+
### New
|
6
|
+
- Class `BaseArg` a generalization of goal or goal template argument.
|
7
|
+
- Class `DefRelation` A specialization of `Relation` class aimed for user-defined relation.
|
8
|
+
- Class `FormalArg` to represent goal template argument(s).
|
9
|
+
- Class `FormalRef` an allusion to a formal argument in a goal template.
|
10
|
+
- Class `GoalTemplate` a representation of a goal parametrized with formal arguments.
|
11
|
+
- Class `KBoolean` a MiniKraken representation of a boolean value.
|
12
|
+
|
13
|
+
### CHANGED
|
14
|
+
- File `README.md` minor change: added more TODO's.
|
15
|
+
|
1
16
|
## [0.1.10] - 2020-06-10
|
2
17
|
- Supports frames from "The Reasoned Scheme" book up to frame [1:81]
|
3
18
|
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
### What is __mini_kraken__ ?
|
7
7
|
An implemention of the [miniKanren](http://minikanren.org/) relational programming language in Ruby.
|
8
8
|
*miniKanren* is a small language for relational (logic) programming.
|
9
|
-
Based on the reference implementation, in Scheme from the "The Reasoned Schemer" book.
|
9
|
+
Based on the reference implementation, in Scheme from the "The Reasoned Schemer" book.
|
10
10
|
Daniel P. Friedman, William E. Byrd, Oleg Kiselyov, and Jason Hemann: "The Reasoned Schemer", Second Edition,
|
11
11
|
ISBN: 9780262535519, (2018), MIT Press.
|
12
12
|
|
@@ -15,13 +15,21 @@ ISBN: 9780262535519, (2018), MIT Press.
|
|
15
15
|
- [X] run\*
|
16
16
|
- [X] fresh
|
17
17
|
- [X] conj2
|
18
|
-
- [X] disj2
|
18
|
+
- [X] disj2
|
19
|
+
- [X] defrel
|
19
20
|
|
20
21
|
### TODO
|
21
|
-
- [ ] defrel
|
22
22
|
- [ ] conde
|
23
23
|
- [ ] Occurs check
|
24
24
|
|
25
|
+
List-centric relations from Chapter 2
|
26
|
+
- [ ] caro
|
27
|
+
- [ ] cdro
|
28
|
+
- [ ] conso
|
29
|
+
- [ ] nullo
|
30
|
+
- [ ] pairo
|
31
|
+
- [ ] singletono
|
32
|
+
|
25
33
|
## Installation
|
26
34
|
|
27
35
|
Add this line to your application's Gemfile:
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'relation'
|
4
|
+
|
5
|
+
module MiniKraken
|
6
|
+
module Core
|
7
|
+
# A relation that is parametrized with generic formal arguments
|
8
|
+
# and a goal template expression.
|
9
|
+
class DefRelation < Relation
|
10
|
+
# @return [Array<FormalArg>] formal arguments of this DefRelation
|
11
|
+
attr_reader :formals
|
12
|
+
|
13
|
+
# @return [GoalTemplate] goal template
|
14
|
+
attr_reader :goal_template
|
15
|
+
|
16
|
+
# @param aName [String] name of def relation
|
17
|
+
# @param aGoalTemplate [GoalTemplate]
|
18
|
+
def initialize(aName, aGoalTemplate, theFormals, alternateName = nil)
|
19
|
+
super(aName, alternateName)
|
20
|
+
@formals = validated_formals(theFormals)
|
21
|
+
@goal_template = validated_goal_template(aGoalTemplate)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Number of arguments for the relation.
|
25
|
+
# @return [Integer]
|
26
|
+
def arity
|
27
|
+
formals.size
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param actuals [Array<Term>] A two-elements array
|
31
|
+
# @param anEnv [Vocabulary] A vocabulary object
|
32
|
+
# @return [Fiber<Outcome>] A Fiber(-like) instance that yields Outcomes
|
33
|
+
def solver_for(actuals, anEnv)
|
34
|
+
goal = goal_template.instantiate(formals, actuals)
|
35
|
+
goal.attain(anEnv)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def validated_formals(theFormals)
|
41
|
+
theFormals
|
42
|
+
end
|
43
|
+
|
44
|
+
def validated_goal_template(aGoalTemplate)
|
45
|
+
aGoalTemplate
|
46
|
+
end
|
47
|
+
end # class
|
48
|
+
end # module
|
49
|
+
end # module
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MiniKraken
|
4
|
+
module Core
|
5
|
+
# The generalization of any iem that can be
|
6
|
+
# passed as arugement to a goal.
|
7
|
+
class FormalArg
|
8
|
+
# @return [String]
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
def initialize(aName)
|
12
|
+
@name = validated_name(aName)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def validated_name(aName)
|
18
|
+
aName
|
19
|
+
end
|
20
|
+
end # class
|
21
|
+
end # module
|
22
|
+
end # module
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_arg'
|
4
|
+
|
5
|
+
module MiniKraken
|
6
|
+
module Core
|
7
|
+
# A formal reference represents the occurrence of a formal argument name in a
|
8
|
+
# goal template argument list.
|
9
|
+
class FormalRef < BaseArg
|
10
|
+
# @return [String]
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
def initialize(aName)
|
14
|
+
@name = validated_name(aName)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def validated_name(aName)
|
20
|
+
aName
|
21
|
+
end
|
22
|
+
end # class
|
23
|
+
end # module
|
24
|
+
end # module
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'base_arg'
|
4
|
+
|
3
5
|
module MiniKraken
|
4
6
|
module Core
|
5
|
-
# The generalization of any
|
6
|
-
# passed as arugement to a goal
|
7
|
-
class GoalArg
|
7
|
+
# The generalization of any item that can be
|
8
|
+
# passed as arugement to a goal object
|
9
|
+
class GoalArg < BaseArg
|
8
10
|
end # class
|
9
11
|
end # module
|
10
12
|
end # module
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_arg'
|
4
|
+
|
5
|
+
module MiniKraken
|
6
|
+
module Core
|
7
|
+
# A meta-goal that is parametrized with generic formal arguments.
|
8
|
+
# The individual goals are instantiated when the formal arguments
|
9
|
+
# are bound to goal arguments
|
10
|
+
class GoalTemplate < BaseArg
|
11
|
+
# @return [Array<BaseArg>}] Arguments of goal template.
|
12
|
+
attr_reader :args
|
13
|
+
|
14
|
+
# @return [Relation] Main relation for the goal template
|
15
|
+
attr_reader :relation
|
16
|
+
|
17
|
+
def initialize(aRelation, theArgs)
|
18
|
+
@relation = validated_relation(aRelation)
|
19
|
+
@args = validated_args(theArgs)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param formals [Array<FormalArg>] Array of formal arguments
|
23
|
+
# @param actuals [Array<GoalArg>] Array of actual arguments
|
24
|
+
# @return [Goal] instantiate a goal object given the actuals and environment
|
25
|
+
def instantiate(formals, actuals)
|
26
|
+
formals2actuals = {}
|
27
|
+
formals.each_with_index do |frml, i|
|
28
|
+
formals2actuals[frml.name] = actuals[i]
|
29
|
+
end
|
30
|
+
|
31
|
+
do_instantiate(formals2actuals)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def validated_relation(aRelation)
|
37
|
+
aRelation
|
38
|
+
end
|
39
|
+
|
40
|
+
def validated_args(theArgs)
|
41
|
+
theArgs
|
42
|
+
end
|
43
|
+
|
44
|
+
def do_instantiate(formals2actuals)
|
45
|
+
goal_args = []
|
46
|
+
args.each do |arg|
|
47
|
+
if arg.kind_of?(FormalRef)
|
48
|
+
goal_args << formals2actuals[arg.name]
|
49
|
+
elsif arg.kind_of?(GoalTemplate)
|
50
|
+
goal_args << arg.send(:do_instantiate, formals2actuals)
|
51
|
+
else
|
52
|
+
goal_args << arg
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
Goal.new(relation, goal_args)
|
57
|
+
end
|
58
|
+
end # class
|
59
|
+
end # module
|
60
|
+
end # module
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'atomic_term'
|
4
|
+
|
5
|
+
module MiniKraken
|
6
|
+
module Core
|
7
|
+
# A specialized atomic term that represents an boolean (true/false) value.
|
8
|
+
# in MiniKraken
|
9
|
+
class KBoolean < AtomicTerm
|
10
|
+
# @param aValue [Boolean, Symbol] Ruby representation of boolean value
|
11
|
+
def initialize(aValue)
|
12
|
+
super(validated_value(aValue))
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def validated_value(aValue)
|
18
|
+
case aValue
|
19
|
+
when true, false
|
20
|
+
aValue
|
21
|
+
when :"#t", '#t'
|
22
|
+
true
|
23
|
+
when :"#f", '#f'
|
24
|
+
false
|
25
|
+
else
|
26
|
+
raise StandardError, "Invalid boolean literal '#{aValue}'"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end # class
|
30
|
+
end # module
|
31
|
+
end # module
|
@@ -7,6 +7,7 @@ require_relative 'fresh_env'
|
|
7
7
|
module MiniKraken
|
8
8
|
module Glue
|
9
9
|
class RunStarExpression
|
10
|
+
# @return [FreshEnv] The environment in which run* variables will reside.
|
10
11
|
attr_reader :env
|
11
12
|
|
12
13
|
# @param var_names [String, Array<String>] One variable name or an array of names
|
data/lib/mini_kraken/version.rb
CHANGED
@@ -0,0 +1,96 @@
|
|
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
|
@@ -0,0 +1,74 @@
|
|
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/k_symbol'
|
10
|
+
require_relative '../../lib/mini_kraken/core/variable_ref'
|
11
|
+
# require_relative '../../lib/mini_kraken/core/environment'
|
12
|
+
|
13
|
+
# Load the class under test
|
14
|
+
require_relative '../../lib/mini_kraken/core/goal_template'
|
15
|
+
|
16
|
+
|
17
|
+
module MiniKraken
|
18
|
+
module Core
|
19
|
+
describe GoalTemplate do
|
20
|
+
let(:tea) { KSymbol.new(:tea) }
|
21
|
+
let(:t_ref) { FormalRef.new('t') }
|
22
|
+
subject { GoalTemplate.new(Equals.instance, [tea, t_ref]) }
|
23
|
+
|
24
|
+
context 'Initialization:' do
|
25
|
+
it 'should be initialized with a relation and args' do
|
26
|
+
expect { GoalTemplate.new(Equals.instance, [tea, t_ref]) }.not_to raise_error
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should know its relation' do
|
30
|
+
expect(subject.relation).to eq(Equals.instance)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should know its arguments' do
|
34
|
+
expect(subject.args[0]).to eq(tea)
|
35
|
+
expect(subject.args[1]).to eq(t_ref)
|
36
|
+
end
|
37
|
+
end # context
|
38
|
+
|
39
|
+
context 'Provided services:' do
|
40
|
+
let(:formal_t) { FormalArg.new('t') }
|
41
|
+
let(:cup) { KSymbol.new(:cup) }
|
42
|
+
let(:ref_x) { VariableRef.new('x') }
|
43
|
+
# let(:env) { Environment.new }
|
44
|
+
|
45
|
+
it 'should instantiate a single-node goal' do
|
46
|
+
expect(subject.instantiate([formal_t], [cup])).to be_kind_of(Goal)
|
47
|
+
goal = subject.instantiate([formal_t], [cup])
|
48
|
+
expect(goal.relation).to eq(Equals.instance)
|
49
|
+
expect(goal.actuals[0]).to eq(tea)
|
50
|
+
expect(goal.actuals[1]).to eq(cup)
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should instantiate a multiple-nodes goal' do
|
54
|
+
sub_tmp1 = GoalTemplate.new(Equals.instance, [tea, t_ref])
|
55
|
+
sub_tmp2 = GoalTemplate.new(Equals.instance, [cup, t_ref])
|
56
|
+
template = GoalTemplate.new(Disj2.instance, [sub_tmp1, sub_tmp2])
|
57
|
+
|
58
|
+
goal = template.instantiate([formal_t], [ref_x])
|
59
|
+
expect(goal.relation).to eq(Disj2.instance)
|
60
|
+
subgoal1 = goal.actuals[0]
|
61
|
+
expect(subgoal1).to be_kind_of(Goal)
|
62
|
+
expect(subgoal1.relation).to eq(Equals.instance)
|
63
|
+
expect(subgoal1.actuals[0]).to eq(tea)
|
64
|
+
expect(subgoal1.actuals[1]).to eq(ref_x)
|
65
|
+
subgoal2 = goal.actuals[1]
|
66
|
+
expect(subgoal2).to be_kind_of(Goal)
|
67
|
+
expect(subgoal2.relation).to eq(Equals.instance)
|
68
|
+
expect(subgoal2.actuals[0]).to eq(cup)
|
69
|
+
expect(subgoal2.actuals[1]).to eq(ref_x)
|
70
|
+
end
|
71
|
+
end # context
|
72
|
+
end # describe
|
73
|
+
end # module
|
74
|
+
end # module
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../spec_helper' # Use the RSpec framework
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
# Load the class under test
|
7
|
+
require_relative '../../lib/mini_kraken/core/k_boolean'
|
8
|
+
|
9
|
+
module MiniKraken
|
10
|
+
module Core
|
11
|
+
describe KBoolean do
|
12
|
+
subject { KBoolean.new('#t') }
|
13
|
+
|
14
|
+
context 'Initialization:' do
|
15
|
+
it 'could be created with a Ruby true/false value' do
|
16
|
+
expect { KBoolean.new(true) }.not_to raise_error
|
17
|
+
expect { KBoolean.new(false) }.not_to raise_error
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'could be created with a Ruby Symbol value' do
|
21
|
+
expect { KBoolean.new(:"#t") }.not_to raise_error
|
22
|
+
expect { KBoolean.new(:"#f") }.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'could be created with a Ruby String value' do
|
26
|
+
expect { KBoolean.new('#t') }.not_to raise_error
|
27
|
+
expect { KBoolean.new('#f') }.not_to raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should know its value' do
|
31
|
+
expect(subject.value).to eq(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should know that it is a ground term' do
|
35
|
+
env = double('mock-env')
|
36
|
+
expect(subject.ground?(env)).to be_truthy
|
37
|
+
end
|
38
|
+
end # context
|
39
|
+
|
40
|
+
context 'Provided services:' do
|
41
|
+
it 'should know whether it is equal to another instance' do
|
42
|
+
# Same type, same value
|
43
|
+
other = KBoolean.new(true)
|
44
|
+
expect(subject).to be_eql(other)
|
45
|
+
|
46
|
+
other = KBoolean.new(:"#t")
|
47
|
+
expect(subject).to be_eql(other)
|
48
|
+
|
49
|
+
other = KBoolean.new('#t')
|
50
|
+
expect(subject).to be_eql(other)
|
51
|
+
|
52
|
+
# Same type, other value
|
53
|
+
another = KBoolean.new(false)
|
54
|
+
expect(subject).not_to be_eql(another)
|
55
|
+
|
56
|
+
# Same type, other value
|
57
|
+
another = KBoolean.new(:"#f")
|
58
|
+
expect(subject).not_to be_eql(another)
|
59
|
+
|
60
|
+
# Same type, other value
|
61
|
+
another = KBoolean.new('#f')
|
62
|
+
expect(subject).not_to be_eql(another)
|
63
|
+
|
64
|
+
# Different type, same value
|
65
|
+
yet_another = OpenStruct.new(value: true)
|
66
|
+
expect(subject).not_to be_eql(yet_another)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should know whether it has same value than other object' do
|
70
|
+
# Same type, same value
|
71
|
+
other = KBoolean.new(true)
|
72
|
+
expect(subject == other).to be_truthy
|
73
|
+
|
74
|
+
other = KBoolean.new(:"#t")
|
75
|
+
expect(subject == other).to be_truthy
|
76
|
+
|
77
|
+
other = KBoolean.new('#t')
|
78
|
+
expect(subject == other).to be_truthy
|
79
|
+
|
80
|
+
# Same type, other value
|
81
|
+
another = KBoolean.new(false)
|
82
|
+
expect(subject == another).to be_falsy
|
83
|
+
|
84
|
+
another = KBoolean.new(:"#f")
|
85
|
+
expect(subject == another).to be_falsy
|
86
|
+
|
87
|
+
another = KBoolean.new('#f')
|
88
|
+
expect(subject == another).to be_falsy
|
89
|
+
|
90
|
+
# Same duck type, same value
|
91
|
+
yet_another = OpenStruct.new(value: true)
|
92
|
+
expect(subject == yet_another).to be_truthy
|
93
|
+
|
94
|
+
# Different duck type, different value
|
95
|
+
still_another = OpenStruct.new(value: false)
|
96
|
+
expect(subject == still_another).to be_falsy
|
97
|
+
|
98
|
+
# Default Ruby representation, same value
|
99
|
+
expect(subject == true).to be_truthy
|
100
|
+
|
101
|
+
# Default Ruby representation, different value
|
102
|
+
expect(subject == false).to be_falsy
|
103
|
+
end
|
104
|
+
end # context
|
105
|
+
end # describe
|
106
|
+
end # module
|
107
|
+
end # module
|
@@ -3,9 +3,13 @@
|
|
3
3
|
require_relative '../spec_helper' # Use the RSpec framework
|
4
4
|
require_relative '../../lib/mini_kraken/core/goal'
|
5
5
|
require_relative '../../lib/mini_kraken/core/conj2'
|
6
|
+
require_relative '../../lib/mini_kraken/core/def_relation'
|
6
7
|
require_relative '../../lib/mini_kraken/core/disj2'
|
7
8
|
require_relative '../../lib/mini_kraken/core/equals'
|
8
9
|
require_relative '../../lib/mini_kraken/core/fail'
|
10
|
+
require_relative '../../lib/mini_kraken/core/formal_arg'
|
11
|
+
require_relative '../../lib/mini_kraken/core/formal_ref'
|
12
|
+
require_relative '../../lib/mini_kraken/core/goal_template'
|
9
13
|
require_relative '../../lib/mini_kraken/core/succeed'
|
10
14
|
|
11
15
|
require_relative '../support/factory_methods'
|
@@ -49,14 +53,18 @@ module MiniKraken
|
|
49
53
|
end # context
|
50
54
|
|
51
55
|
context 'Provided services:' do
|
56
|
+
let(:k_false) { k_boolean(false) }
|
57
|
+
let(:k_true) { k_boolean(true) }
|
52
58
|
let(:bean) { k_symbol(:bean) }
|
53
59
|
let(:corn) { k_symbol(:corn) }
|
60
|
+
let(:cup) { k_symbol(:cup) }
|
54
61
|
let(:meal) { k_symbol(:meal) }
|
55
62
|
let(:oil) { k_symbol(:oil) }
|
56
63
|
let(:olive) { k_symbol(:olive) }
|
57
64
|
let(:red) { k_symbol(:red) }
|
58
65
|
let(:soup) { k_symbol(:soup) }
|
59
66
|
let(:split) { k_symbol(:split) }
|
67
|
+
let(:tea) { k_symbol(:tea) }
|
60
68
|
let(:virgin) { k_symbol(:virgin) }
|
61
69
|
let(:ref_q) { Core::VariableRef.new('q') }
|
62
70
|
let(:ref_r) { Core::VariableRef.new('r') }
|
@@ -66,6 +74,16 @@ module MiniKraken
|
|
66
74
|
let(:ref_t) { Core::VariableRef.new('t') }
|
67
75
|
let(:ref_u) { Core::VariableRef.new('u') }
|
68
76
|
let(:ref_z) { Core::VariableRef.new('z') }
|
77
|
+
let(:t_ref) { Core::FormalRef.new('t') }
|
78
|
+
let(:equals_tea) { Core::GoalTemplate.new(Core::Equals.instance, [tea, t_ref]) }
|
79
|
+
let(:equals_cup) { Core::GoalTemplate.new(Core::Equals.instance, [cup, t_ref]) }
|
80
|
+
let(:g_template) { Core::GoalTemplate.new(Core::Disj2.instance, [equals_tea, equals_cup]) }
|
81
|
+
let(:formal_t) { Core::FormalArg.new('t') }
|
82
|
+
|
83
|
+
# Reasoned S2, frame 1:82
|
84
|
+
# (defrel (teacupo t)
|
85
|
+
# (disj2 (== 'tea t) (== 'cup t)))
|
86
|
+
let(:teacupo_rel) { Core::DefRelation.new('teacupo', g_template, [formal_t]) }
|
69
87
|
|
70
88
|
it 'should return a null list with the fail goal' do
|
71
89
|
# Reasoned S2, frame 1:7
|
@@ -781,6 +799,96 @@ module MiniKraken
|
|
781
799
|
expect(result.car.car).to eq(split)
|
782
800
|
expect(result.car.cdr.car).to eq(pea)
|
783
801
|
end
|
802
|
+
|
803
|
+
it 'should solve expression with defrel' do
|
804
|
+
teacupo_goal = Core::Goal.new(teacupo_rel, [ref_x])
|
805
|
+
|
806
|
+
# Reasoned S2, frame 1:83
|
807
|
+
# (run* x
|
808
|
+
# (teacupo x)) ;; => ((tea cup))
|
809
|
+
instance = RunStarExpression.new('x', teacupo_goal)
|
810
|
+
|
811
|
+
result = instance.run
|
812
|
+
expect(result.car).to eq(tea)
|
813
|
+
expect(result.cdr.car).to eq(cup)
|
814
|
+
end
|
815
|
+
|
816
|
+
it 'should solve expression with defrel and booleans' do
|
817
|
+
teacupo_goal = Core::Goal.new(teacupo_rel, [ref_x])
|
818
|
+
expr2 = equals_goal(k_true, ref_y)
|
819
|
+
subgoal1 = conj2_goal(teacupo_goal, expr2)
|
820
|
+
expr3 = equals_goal(k_false, ref_x)
|
821
|
+
expr4 = equals_goal(k_true, ref_y)
|
822
|
+
subgoal2 = conj2_goal(expr3, expr4)
|
823
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
824
|
+
# Reasoned S2, frame 1:84
|
825
|
+
# (run* (x y)
|
826
|
+
# (disj2
|
827
|
+
# (conj2 (teacupo x) (== #t y))
|
828
|
+
# (conj2 (== #f x) (== #t y))) ;; => ((#f #t)(tea #t) (cup #t))
|
829
|
+
instance = RunStarExpression.new(%w[x y], goal)
|
830
|
+
|
831
|
+
result = instance.run
|
832
|
+
# Order of solutions differs from RS book
|
833
|
+
expect(result.car).to eq(cons(tea, cons(true)))
|
834
|
+
expect(result.cdr.car).to eq(cons(cup, cons(true)))
|
835
|
+
expect(result.cdr.cdr.car).to eq(cons(false, cons(true)))
|
836
|
+
end
|
837
|
+
|
838
|
+
it 'should solve expression with two variable and defrel' do
|
839
|
+
teacupo_goal1 = Core::Goal.new(teacupo_rel, [ref_x])
|
840
|
+
teacupo_goal2 = Core::Goal.new(teacupo_rel, [ref_y])
|
841
|
+
|
842
|
+
# Reasoned S2, frame 1:85
|
843
|
+
# (run* (x y)
|
844
|
+
# (teacupo x)
|
845
|
+
# (teacupo y)) ;; => ((tea tea)(tea cup)(cup tea)(cup c))
|
846
|
+
instance = RunStarExpression.new(%w[x y], [teacupo_goal1, teacupo_goal2])
|
847
|
+
|
848
|
+
result = instance.run
|
849
|
+
expect(result.car).to eq(cons(tea, cons(tea)))
|
850
|
+
expect(result.cdr.car).to eq(cons(tea, cons(cup)))
|
851
|
+
expect(result.cdr.cdr.car).to eq(cons(cup, cons(tea)))
|
852
|
+
expect(result.cdr.cdr.cdr.car).to eq(cons(cup, cons(cup)))
|
853
|
+
end
|
854
|
+
|
855
|
+
it 'should solve expression with two variable and defrel' do
|
856
|
+
teacupo_goal1 = Core::Goal.new(teacupo_rel, [ref_x])
|
857
|
+
teacupo_goal2 = Core::Goal.new(teacupo_rel, [ref_x])
|
858
|
+
|
859
|
+
# Reasoned S2, frame 1:86
|
860
|
+
# (run* (x y)
|
861
|
+
# (teacupo x)
|
862
|
+
# (teacupo x)) ;; => ((tea _0)(cup _0))
|
863
|
+
instance = RunStarExpression.new(%w[x y], [teacupo_goal1, teacupo_goal2])
|
864
|
+
|
865
|
+
result = instance.run
|
866
|
+
expect(result.car).to eq(cons(tea, cons(any_value(0))))
|
867
|
+
expect(result.cdr.car).to eq(cons(cup, cons(any_value(0))))
|
868
|
+
end
|
869
|
+
|
870
|
+
it 'should solve expression with defrel and booleans' do
|
871
|
+
teacupo_goal1 = Core::Goal.new(teacupo_rel, [ref_x])
|
872
|
+
teacupo_goal2 = Core::Goal.new(teacupo_rel, [ref_x])
|
873
|
+
subgoal1 = conj2_goal(teacupo_goal1, teacupo_goal2)
|
874
|
+
expr3 = equals_goal(k_false, ref_x)
|
875
|
+
expr4 = Core::Goal.new(teacupo_rel, [ref_y])
|
876
|
+
subgoal2 = conj2_goal(expr3, expr4)
|
877
|
+
goal = disj2_goal(subgoal1, subgoal2)
|
878
|
+
# Reasoned S2, frame 1:87
|
879
|
+
# (run* (x y)
|
880
|
+
# (disj2
|
881
|
+
# (conj2 (teacupo x) (teacupo x))
|
882
|
+
# (conj2 (== #f x) (teacupo y)))) ;; => ((#f tea)(#f cup)(tea _0)(cup _0))
|
883
|
+
instance = RunStarExpression.new(%w[x y], goal)
|
884
|
+
|
885
|
+
result = instance.run
|
886
|
+
# Order of solutions differs from RS book
|
887
|
+
expect(result.car).to eq(cons(tea, cons(any_value(0))))
|
888
|
+
expect(result.cdr.car).to eq(cons(cup, cons(any_value(0))))
|
889
|
+
expect(result.cdr.cdr.car).to eq(cons(false, cons(tea)))
|
890
|
+
expect(result.cdr.cdr.cdr.car).to eq(cons(false, cons(cup)))
|
891
|
+
end
|
784
892
|
end # context
|
785
893
|
end # describe
|
786
894
|
end # module
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative '../../lib/mini_kraken/core/any_value'
|
4
4
|
require_relative '../../lib/mini_kraken/core/cons_cell'
|
5
|
+
require_relative '../../lib/mini_kraken/core/k_boolean'
|
5
6
|
require_relative '../../lib/mini_kraken/core/k_symbol'
|
6
7
|
require_relative '../../lib/mini_kraken/core/variable'
|
7
8
|
require_relative '../../lib/mini_kraken/core/variable_ref'
|
@@ -50,6 +51,13 @@ module MiniKraken
|
|
50
51
|
Core::Goal.new(Core::Disj2.instance, [g1, g2])
|
51
52
|
end
|
52
53
|
|
54
|
+
# Factory method for constructing a KBoolean instance
|
55
|
+
# @param aValue [Boolean]
|
56
|
+
# @return [Core::KBoolean]
|
57
|
+
def k_boolean(aValue)
|
58
|
+
Core::KBoolean.new(aValue)
|
59
|
+
end
|
60
|
+
|
53
61
|
# Factory method for constructing a KSymbol instance
|
54
62
|
# @param aSymbol [Symbol]
|
55
63
|
# @return [Core::KSymbol]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mini_kraken
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dimitri Geshef
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,21 +72,27 @@ files:
|
|
72
72
|
- lib/mini_kraken/core/association.rb
|
73
73
|
- lib/mini_kraken/core/association_walker.rb
|
74
74
|
- lib/mini_kraken/core/atomic_term.rb
|
75
|
+
- lib/mini_kraken/core/base_arg.rb
|
75
76
|
- lib/mini_kraken/core/binary_relation.rb
|
76
77
|
- lib/mini_kraken/core/composite_goal.rb
|
77
78
|
- lib/mini_kraken/core/composite_term.rb
|
78
79
|
- lib/mini_kraken/core/conj2.rb
|
79
80
|
- lib/mini_kraken/core/cons_cell.rb
|
81
|
+
- lib/mini_kraken/core/def_relation.rb
|
80
82
|
- lib/mini_kraken/core/designation.rb
|
81
83
|
- lib/mini_kraken/core/disj2.rb
|
82
84
|
- lib/mini_kraken/core/duck_fiber.rb
|
83
85
|
- lib/mini_kraken/core/environment.rb
|
84
86
|
- lib/mini_kraken/core/equals.rb
|
85
87
|
- lib/mini_kraken/core/fail.rb
|
88
|
+
- lib/mini_kraken/core/formal_arg.rb
|
89
|
+
- lib/mini_kraken/core/formal_ref.rb
|
86
90
|
- lib/mini_kraken/core/freshness.rb
|
87
91
|
- lib/mini_kraken/core/goal.rb
|
88
92
|
- lib/mini_kraken/core/goal_arg.rb
|
89
93
|
- lib/mini_kraken/core/goal_relation.rb
|
94
|
+
- lib/mini_kraken/core/goal_template.rb
|
95
|
+
- lib/mini_kraken/core/k_boolean.rb
|
90
96
|
- lib/mini_kraken/core/k_integer.rb
|
91
97
|
- lib/mini_kraken/core/k_symbol.rb
|
92
98
|
- lib/mini_kraken/core/nullary_relation.rb
|
@@ -105,12 +111,15 @@ files:
|
|
105
111
|
- spec/core/association_walker_spec.rb
|
106
112
|
- spec/core/conj2_spec.rb
|
107
113
|
- spec/core/cons_cell_spec.rb
|
114
|
+
- spec/core/def_relation_spec.rb
|
108
115
|
- spec/core/disj2_spec.rb
|
109
116
|
- spec/core/duck_fiber_spec.rb
|
110
117
|
- spec/core/environment_spec.rb
|
111
118
|
- spec/core/equals_spec.rb
|
112
119
|
- spec/core/fail_spec.rb
|
113
120
|
- spec/core/goal_spec.rb
|
121
|
+
- spec/core/goal_template_spec.rb
|
122
|
+
- spec/core/k_boolean_spec.rb
|
114
123
|
- spec/core/k_symbol_spec.rb
|
115
124
|
- spec/core/outcome_spec.rb
|
116
125
|
- spec/core/succeed_spec.rb
|
@@ -151,12 +160,15 @@ test_files:
|
|
151
160
|
- spec/core/association_walker_spec.rb
|
152
161
|
- spec/core/conj2_spec.rb
|
153
162
|
- spec/core/cons_cell_spec.rb
|
163
|
+
- spec/core/def_relation_spec.rb
|
154
164
|
- spec/core/disj2_spec.rb
|
155
165
|
- spec/core/duck_fiber_spec.rb
|
156
166
|
- spec/core/environment_spec.rb
|
157
167
|
- spec/core/equals_spec.rb
|
158
168
|
- spec/core/fail_spec.rb
|
159
169
|
- spec/core/goal_spec.rb
|
170
|
+
- spec/core/goal_template_spec.rb
|
171
|
+
- spec/core/k_boolean_spec.rb
|
160
172
|
- spec/core/k_symbol_spec.rb
|
161
173
|
- spec/core/outcome_spec.rb
|
162
174
|
- spec/core/succeed_spec.rb
|