mini_kraken 0.2.03 → 0.3.03

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +378 -333
  3. data/CHANGELOG.md +48 -0
  4. data/README.md +29 -21
  5. data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
  6. data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
  7. data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
  8. data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
  9. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  10. data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
  11. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  12. data/lib/mini_kraken/composite/composite_term.rb +27 -0
  13. data/lib/mini_kraken/composite/cons_cell.rb +301 -0
  14. data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
  15. data/lib/mini_kraken/composite/list.rb +32 -0
  16. data/lib/mini_kraken/core/all_core.rb +8 -0
  17. data/lib/mini_kraken/core/any_value.rb +31 -7
  18. data/lib/mini_kraken/core/arity.rb +69 -0
  19. data/lib/mini_kraken/core/association.rb +29 -4
  20. data/lib/mini_kraken/core/association_copy.rb +50 -0
  21. data/lib/mini_kraken/core/base_term.rb +13 -0
  22. data/lib/mini_kraken/core/blackboard.rb +315 -0
  23. data/lib/mini_kraken/core/bookmark.rb +46 -0
  24. data/lib/mini_kraken/core/context.rb +492 -0
  25. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  26. data/lib/mini_kraken/core/entry.rb +40 -0
  27. data/lib/mini_kraken/core/fail.rb +20 -18
  28. data/lib/mini_kraken/core/fusion.rb +29 -0
  29. data/lib/mini_kraken/core/goal.rb +20 -29
  30. data/lib/mini_kraken/core/log_var.rb +22 -0
  31. data/lib/mini_kraken/core/log_var_ref.rb +108 -0
  32. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  33. data/lib/mini_kraken/core/parametrized_term.rb +68 -0
  34. data/lib/mini_kraken/core/relation.rb +14 -28
  35. data/lib/mini_kraken/core/scope.rb +67 -0
  36. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  37. data/lib/mini_kraken/core/specification.rb +48 -0
  38. data/lib/mini_kraken/core/succeed.rb +21 -17
  39. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  40. data/lib/mini_kraken/core/term.rb +15 -4
  41. data/lib/mini_kraken/glue/dsl.rb +44 -88
  42. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  43. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  44. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  45. data/lib/mini_kraken/rela/conde.rb +143 -0
  46. data/lib/mini_kraken/rela/conj2.rb +65 -0
  47. data/lib/mini_kraken/rela/def_relation.rb +93 -0
  48. data/lib/mini_kraken/rela/disj2.rb +70 -0
  49. data/lib/mini_kraken/rela/fresh.rb +98 -0
  50. data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
  51. data/lib/mini_kraken/rela/unify.rb +265 -0
  52. data/lib/mini_kraken/version.rb +1 -1
  53. data/mini_kraken.gemspec +2 -2
  54. data/spec/.rubocop.yml +1 -1
  55. data/spec/atomic/atomic_term_spec.rb +98 -0
  56. data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
  57. data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
  58. data/spec/composite/cons_cell_spec.rb +225 -0
  59. data/spec/{core → composite}/cons_cell_visitor_spec.rb +36 -20
  60. data/spec/composite/list_spec.rb +50 -0
  61. data/spec/core/any_value_spec.rb +52 -0
  62. data/spec/core/arity_spec.rb +92 -0
  63. data/spec/core/association_copy_spec.rb +69 -0
  64. data/spec/core/association_spec.rb +31 -4
  65. data/spec/core/blackboard_spec.rb +287 -0
  66. data/spec/core/bookmark_spec.rb +40 -0
  67. data/spec/core/context_spec.rb +245 -0
  68. data/spec/core/core_spec.rb +40 -0
  69. data/spec/core/duck_fiber_spec.rb +16 -46
  70. data/spec/core/fail_spec.rb +5 -6
  71. data/spec/core/goal_spec.rb +22 -12
  72. data/spec/core/log_var_ref_spec.rb +105 -0
  73. data/spec/core/log_var_spec.rb +64 -0
  74. data/spec/core/nullary_relation_spec.rb +33 -0
  75. data/spec/core/parametrized_tem_spec.rb +39 -0
  76. data/spec/core/relation_spec.rb +33 -0
  77. data/spec/core/scope_spec.rb +73 -0
  78. data/spec/core/solver_adapter_spec.rb +70 -0
  79. data/spec/core/specification_spec.rb +43 -0
  80. data/spec/core/succeed_spec.rb +5 -5
  81. data/spec/core/symbol_table_spec.rb +142 -0
  82. data/spec/glue/dsl_chap1_spec.rb +88 -144
  83. data/spec/glue/dsl_chap2_spec.rb +454 -19
  84. data/spec/glue/run_star_expression_spec.rb +81 -906
  85. data/spec/rela/conde_spec.rb +153 -0
  86. data/spec/rela/conj2_spec.rb +123 -0
  87. data/spec/rela/def_relation_spec.rb +119 -0
  88. data/spec/rela/disj2_spec.rb +117 -0
  89. data/spec/rela/fresh_spec.rb +147 -0
  90. data/spec/rela/unify_spec.rb +369 -0
  91. data/spec/support/factory_atomic.rb +29 -0
  92. data/spec/support/factory_composite.rb +21 -0
  93. data/spec/support/factory_methods.rb +11 -26
  94. metadata +98 -70
  95. data/lib/mini_kraken/core/association_walker.rb +0 -183
  96. data/lib/mini_kraken/core/atomic_term.rb +0 -67
  97. data/lib/mini_kraken/core/base_arg.rb +0 -10
  98. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  99. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  100. data/lib/mini_kraken/core/composite_term.rb +0 -41
  101. data/lib/mini_kraken/core/conde.rb +0 -143
  102. data/lib/mini_kraken/core/conj2.rb +0 -79
  103. data/lib/mini_kraken/core/cons_cell.rb +0 -82
  104. data/lib/mini_kraken/core/cons_cell_visitor.rb +0 -102
  105. data/lib/mini_kraken/core/def_relation.rb +0 -53
  106. data/lib/mini_kraken/core/designation.rb +0 -55
  107. data/lib/mini_kraken/core/disj2.rb +0 -72
  108. data/lib/mini_kraken/core/environment.rb +0 -73
  109. data/lib/mini_kraken/core/equals.rb +0 -193
  110. data/lib/mini_kraken/core/formal_arg.rb +0 -22
  111. data/lib/mini_kraken/core/formal_ref.rb +0 -25
  112. data/lib/mini_kraken/core/freshness.rb +0 -45
  113. data/lib/mini_kraken/core/goal_arg.rb +0 -12
  114. data/lib/mini_kraken/core/goal_template.rb +0 -102
  115. data/lib/mini_kraken/core/k_boolean.rb +0 -35
  116. data/lib/mini_kraken/core/outcome.rb +0 -63
  117. data/lib/mini_kraken/core/variable.rb +0 -41
  118. data/lib/mini_kraken/core/variable_ref.rb +0 -84
  119. data/lib/mini_kraken/core/vocabulary.rb +0 -446
  120. data/lib/mini_kraken/glue/fresh_env.rb +0 -103
  121. data/lib/mini_kraken/glue/fresh_env_factory.rb +0 -83
  122. data/spec/core/association_walker_spec.rb +0 -192
  123. data/spec/core/conde_spec.rb +0 -147
  124. data/spec/core/conj2_spec.rb +0 -114
  125. data/spec/core/cons_cell_spec.rb +0 -107
  126. data/spec/core/def_relation_spec.rb +0 -97
  127. data/spec/core/disj2_spec.rb +0 -99
  128. data/spec/core/environment_spec.rb +0 -142
  129. data/spec/core/equals_spec.rb +0 -317
  130. data/spec/core/goal_template_spec.rb +0 -74
  131. data/spec/core/outcome_spec.rb +0 -56
  132. data/spec/core/variable_ref_spec.rb +0 -30
  133. data/spec/core/variable_spec.rb +0 -35
  134. data/spec/core/vocabulary_spec.rb +0 -219
  135. data/spec/glue/fresh_env_factory_spec.rb +0 -97
  136. data/spec/glue/fresh_env_spec.rb +0 -62
@@ -1,67 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'term'
4
- require_relative 'freshness'
5
-
6
- module MiniKraken
7
- module Core
8
- # An atomic term is an elementary Minikraken term that cannot be
9
- # decomposed into simpler MiniKraken data value(s).
10
- class AtomicTerm < Term
11
- # @return [Object] Internal representation of a MiniKraken data value
12
- attr_reader :value
13
-
14
- # @param aValue [Object] Ruby representation of MiniKraken data value
15
- def initialize(aValue)
16
- super()
17
- @value = aValue
18
- @value.freeze
19
- end
20
-
21
- # An atomic term is by definition a ground term: since it doesn't contain
22
- # any bound variable (in Prolog sense).
23
- # @param _env [Vocabulary]
24
- # @return [Freshness]
25
- def freshness(_env)
26
- Freshness.new(:ground, self)
27
- end
28
-
29
- # An atomic term is a ground term: by definition it doesn't contain
30
- # any fresh variable.
31
- # @param _env [Vocabulary]
32
- # @return [FalseClass]
33
- def fresh?(_env)
34
- false
35
- end
36
-
37
- # An atomic term is a ground term: by definition it doesn't contain
38
- # any fresh variable.
39
- # @param _env [Vocabulary]
40
- # @return [TrueClass]
41
- def ground?(_env)
42
- true
43
- end
44
-
45
- # @return [AtomicTerm]
46
- def quote(_env)
47
- self
48
- end
49
-
50
- # Data equality testing
51
- # @return [Boolean]
52
- def ==(other)
53
- if other.respond_to?(:value)
54
- value == other.value
55
- else
56
- value == other
57
- end
58
- end
59
-
60
- # Type and data equality testing
61
- # @return [Boolean]
62
- def eql?(other)
63
- (self.class == other.class) && value.eql?(other.value)
64
- end
65
- end # class
66
- end # module
67
- end # module
@@ -1,10 +0,0 @@
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
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'relation'
4
- require_relative 'composite_term'
5
-
6
- module MiniKraken
7
- module Core
8
- class BinaryRelation < Relation
9
- # @param aName [String] Name of the relation.
10
- # @param alternateName [String, NilClass] Alternative name (optional).
11
- def initialize(aName, alternateName = nil)
12
- super(aName, alternateName)
13
- freeze
14
- end
15
-
16
- # Number of arguments for the relation.
17
- # @return [Integer]
18
- def arity
19
- 2
20
- end
21
-
22
- protected
23
-
24
- # table: Commute
25
- # |arg1 | arg2 | arg2.ground? || Commute |
26
- # | isa? Atomic | isa? Atomic | dont_care || Yes |
27
- # | isa? Atomic | isa? CompositeTerm | dont_care || Yes |
28
- # | isa? Atomic | isa? VariableRef | dont_care || Yes |
29
- # | isa? CompositeTerm | isa? Atomic | true || No |
30
- # | isa? CompositeTerm | isa? CompositeTerm | false || Yes |
31
- # | isa? CompositeTerm | isa? CompositeTerm | true || No |
32
- # | isa? CompositeTerm | isa? VariableRef | dont_care || Yes |
33
- # | isa? VariableRef | isa? Atomic | dont_care || No |
34
- # | isa? VariableRef | isa? CompositeTerm | dont_care || No |
35
- # | isa? VariableRef | isa? VariableRef | false || Yes |
36
- # | isa? VariableRef | isa? VariableRef | true || No |
37
- def commute_cond(arg1, arg2, env)
38
- commuting = true
39
- arg2_is_var_ref = arg2.kind_of?(VariableRef)
40
-
41
- if arg1.kind_of?(CompositeTerm)
42
- if arg2_is_var_ref
43
- commuting = true
44
- else
45
- commuting = !arg2.ground?(env)
46
- end
47
- elsif arg1.kind_of?(VariableRef)
48
- if arg2_is_var_ref
49
- commuting = !arg2.ground?(env)
50
- else
51
- commuting = false
52
- end
53
- end
54
-
55
- if commuting
56
- [arg2, arg1]
57
- else
58
- [arg1, arg2]
59
- end
60
- end
61
- end # class
62
- end # module
63
- end # module
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'environment'
4
-
5
- module MiniKraken
6
- module Core
7
- class CompositeGoal
8
- # @return [Operator] The operator corresponding to this goal
9
- attr_reader :operator
10
-
11
- # @return [Array<Goal>] The child goals (sub-goals)
12
- attr_reader :children
13
-
14
- # @param anOperator [Operator] The operator corresponding to this goal
15
- # @param theChildren [Array<Goal>] The child goals (sub-goals)
16
- def initialize(anOperator, theChildren)
17
- @operator = anOperator
18
- @children = validated_children(theChildren)
19
- end
20
-
21
- # Attempt to achieve the goal for a given context (environment)
22
- # @param anEnv [Environment] The context in which the goal take place.
23
- # @return [Fiber<Outcome>] A Fiber object that will generate the results.
24
- def attain(anEnv)
25
- operator.solver_for(children, anEnv)
26
- end
27
-
28
- private
29
-
30
- def validated_children(theChildren)
31
- my_arity = operator.arity
32
- if args.size != my_arity
33
- err_msg = "Goal has #{theChildren.size} arguments, expected #{my_arity}"
34
- raise StandardError, err_msg
35
- end
36
-
37
- prefix = 'Invalid goal argument '
38
- theChildren.each do |subg|
39
- raise StandardError, prefix + subg.to_s unless subg.kind_of?(Goal)
40
- end
41
-
42
- theChildren.dup
43
- end
44
- end # class
45
- end # module
46
- end # module
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'term'
4
- require_relative 'freshness'
5
-
6
- module MiniKraken
7
- module Core
8
- # An composite term is an Minikraken term that can be
9
- # decomposed into simpler MiniKraken data value(s).
10
- class CompositeTerm < Term
11
- # Abstract method (to override). Return the child terms.
12
- # @return [Array<Term>]
13
- def children
14
- raise NotImplementedError, 'This method must re-defined in subclass(es).'
15
- end
16
-
17
- # A composite term is fresh when all its members are nil or all non-nil members
18
- # are all fresh
19
- # A composite term is bound when it is not fresh and not ground
20
- # A composite term is a ground term when all its non-nil members are ground.
21
- # @param _env [Vocabulary]
22
- # @return [Freshness]
23
- def freshness(_env)
24
- env.freshness_composite(self)
25
- end
26
-
27
- # @param env [Environment]
28
- # @return [Boolean]
29
- def fresh?(env)
30
- env.fresh_value?(self)
31
- end
32
-
33
- # A composite is ground if all its children are ground
34
- def ground?(anEnv)
35
- children.all? do |child|
36
- child.nil? || child.ground?(anEnv)
37
- end
38
- end
39
- end # class
40
- end # module
41
- end # module
@@ -1,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
- require_relative 'conj2'
5
- require_relative 'duck_fiber'
6
- require_relative 'fail'
7
- require_relative 'goal'
8
- require_relative 'goal_relation'
9
- require_relative 'outcome'
10
-
11
- unless MiniKraken::Core.constants(false).include? :Conde
12
- module MiniKraken
13
- module Core
14
- # A polyadic relation (i.e. it can takes an arbitrary number of argumentt)
15
- # that behaves as the disjunction of its arguments.
16
- # It succeeds if at least one of its goal arguments succeeds.
17
- class Conde < GoalRelation
18
- include Singleton
19
-
20
- def initialize
21
- super('conde', nil)
22
- end
23
-
24
- # A relation is polyadic when it accepts an arbitrary number of arguments.
25
- # @return [TrueClass]
26
- def polyadic?
27
- true
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 that yields Outcomes objects
33
- def solver_for(actuals, anEnv)
34
- args = *validated_args(actuals)
35
- Fiber.new { cond(args, anEnv) }
36
- end
37
-
38
- # Yields [Outcome, NilClass] result of the disjunction
39
- # @param goals [Array<Goal>] Array of goals
40
- # @param voc [Vocabulary] A vocabulary object
41
- def cond(goals, voc)
42
- # require 'debug'
43
- success = false
44
-
45
- goals.each do |g|
46
- fiber = nil
47
-
48
- case g
49
- when Core::Goal
50
- fiber = g.attain(voc)
51
- when Core::Environment
52
- fiber = g.attain(voc)
53
- when Array
54
- conjunct = conjunction(g)
55
- fiber = conjunct.attain(voc)
56
- when Core::ConsCell
57
- goal_array = to_goal_array(g)
58
- conjunct = conjunction(goal_array)
59
- fiber = conjunct.attain(voc)
60
- end
61
- loop do
62
- outcome = fiber.resume
63
- break unless outcome
64
-
65
- outcome.parent = voc unless outcome.parent
66
- if outcome.success?
67
- success = true
68
- Fiber.yield outcome
69
- outcome.clear
70
- end
71
- end
72
- end
73
-
74
- Fiber.yield Outcome.new(:"#u", voc) unless success
75
- Fiber.yield nil
76
- end
77
-
78
- private
79
-
80
- def validated_args(actuals)
81
- result = []
82
-
83
- actuals.each do |arg|
84
- case arg
85
- when Core::Goal
86
- result << arg
87
-
88
- when Core::Environment
89
- result << arg
90
-
91
- when Array
92
- result << validated_args(arg)
93
-
94
- else
95
- prefix = "#{name} expects goal as argument, found a "
96
- raise StandardError, prefix + "'#{arg.class}'"
97
- end
98
- end
99
-
100
- result
101
- end
102
-
103
- def conjunction(goal_array)
104
- result = nil
105
-
106
- loop do
107
- conjunctions = []
108
- goal_array.each_slice(2) do |uno_duo|
109
- if uno_duo.size == 2
110
- conjunctions << Core::Goal.new(Core::Conj2.instance, uno_duo)
111
- else
112
- conjunctions << uno_duo[0]
113
- end
114
- end
115
- if conjunctions.size == 1
116
- result = conjunctions[0]
117
- break
118
- end
119
- goal_array = conjunctions
120
- end
121
-
122
- result
123
- end
124
-
125
- def to_goal_array(aCons)
126
- array = []
127
- curr_node = aCons
128
- loop do
129
- array << curr_node.car if curr_node.car.kind_of?(Core::Goal)
130
- break unless curr_node.cdr
131
- break unless curr_node.car.kind_of?(Core::Goal)
132
-
133
- curr_node = curr_node.cdr
134
- end
135
-
136
- array
137
- end
138
- end # class
139
-
140
- Conde.instance.freeze
141
- end # module
142
- end # module
143
- end # unless
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'singleton'
4
- require_relative 'duck_fiber'
5
- require_relative 'goal'
6
- require_relative 'goal_relation'
7
- require_relative 'outcome'
8
-
9
- unless MiniKraken::Core.constants(false).include? :Conj2
10
- module MiniKraken
11
- module Core
12
- # The conjunction is a relation that accepts only goal(s) as its two
13
- # arguments. It succeeds if and only both its goal arguments succeeds.
14
- class Conj2 < GoalRelation
15
- include Singleton
16
-
17
- def initialize
18
- super('conj2', nil)
19
- end
20
-
21
- # @param actuals [Array<Term>] A two-elements array
22
- # @param anEnv [Vocabulary] A vocabulary object
23
- # @return [Fiber<Outcome>] A Fiber that yields Outcomes objects
24
- def solver_for(actuals, anEnv)
25
- g1, g2 = *validated_args(actuals)
26
- Fiber.new { conjunction(g1, g2, anEnv) }
27
- end
28
-
29
- # Yields [Outcome, NilClass] result of the conjunction
30
- # @param g1 [Goal] First goal argument
31
- # @param g2 [Goal] Second goal argument
32
- # @param voc [Vocabulary] A vocabulary object
33
- def conjunction(g1, g2, voc)
34
- # require 'debug'
35
- if g1.relation.kind_of?(Fail) || g2.relation.kind_of?(Fail)
36
- Fiber.yield Outcome.new(:"#u", voc)
37
- else
38
- outcome1 = nil
39
- outcome2 = nil
40
- f1 = g1.attain(voc)
41
- loop do
42
- outcome1 = f1.resume
43
- break unless outcome1
44
-
45
- outcome1.parent = voc unless outcome1.parent
46
- if outcome1.success?
47
- f2 = g2.attain(outcome1)
48
- loop do
49
- outcome2 = f2.resume
50
- break unless outcome2
51
-
52
- outcome2.parent = voc unless outcome2.parent
53
- if outcome2.success?
54
- res = Outcome.new(:"#s", voc)
55
- res.merge(outcome1)
56
- res.merge(outcome2)
57
- Fiber.yield res
58
- else
59
- Fiber.yield outcome2
60
- end
61
- outcome2.clear
62
- end
63
- else
64
- Fiber.yield outcome1
65
- end
66
- if outcome1.success? && (outcome2&.success? || outcome2.nil?)
67
- voc.clear
68
- end
69
- end
70
- end
71
-
72
- Fiber.yield nil
73
- end
74
- end # class
75
-
76
- Conj2.instance.freeze
77
- end # module
78
- end # module
79
- end # unless