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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec7b984a9f0c857f74c8a8989c5da2072398775573b7ca6679d99f96ef13eac1
4
- data.tar.gz: cdebdebae82c424b9ae701f959765f0905322798a371e2aec42ed9a229e35a4f
3
+ metadata.gz: 672521fbc6627e2767bfe4d6ce38dd66243736fee451e857ec7ef45d0f8905fe
4
+ data.tar.gz: 6835bb1d91bb6e867417faba0d6904734295f9a7bab612c6a78fcfbcdc41f84a
5
5
  SHA512:
6
- metadata.gz: 2ce3553527adeebef7adc69ec5a861fe65f9f451e54a81e23f00769923ced6b6a6011846ae3e9a673c8b9094a7dcce6ea6f8d263d55c8f543ef0de309e34c11c
7
- data.tar.gz: 90b45061cde1119ad648359063682f411f9e5705a294340976bd027561b1d94da7afbfc9d0d27dce67942e1407d4d4ea40df85cf3fe67c9fca998d22052b6187
6
+ metadata.gz: bd5b5b2d2493b4ec8f8293c5f786be1a7739d05bee5d4733d48edb16713d1df4097be5a6e85127c2c90cf395da877b57ef07a607167b8f5bb1732dbc2a367610
7
+ data.tar.gz: 6661aadbe8bd778283e91f31181651e32296150d282575697fee1f5c240ea46168c5107baf33d9b590d6a449ec89b2f41e69340b81cb9b9e3692954af155083b
@@ -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:
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'set'
4
4
  require_relative 'atomic_term'
5
- require_relative 'composite_term'
5
+ require_relative 'cons_cell'
6
6
 
7
7
  module MiniKraken
8
8
  module Core
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniKraken
4
+ module Core
5
+ # Abstract class that is a generalization for goal actual arguments or
6
+ # for arguments of goal template.
7
+ class BaseArg
8
+ end # class
9
+ end # module
10
+ end # module
@@ -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
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'singleton'
4
4
  require_relative 'duck_fiber'
5
+ require_relative 'fail'
5
6
  require_relative 'goal'
6
7
  require_relative 'goal_relation'
7
8
  require_relative 'outcome'
@@ -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 iem that can be
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MiniKraken
4
- VERSION = '0.1.10'
4
+ VERSION = '0.1.11'
5
5
  end
@@ -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.10
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-13 00:00:00.000000000 Z
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