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,37 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'specification'
4
+ require_relative 'context'
5
+
3
6
  module MiniKraken
4
7
  module Core
5
- class Relation
6
- # @return [String] Name of the relation.
7
- attr_reader :name
8
-
9
- # @return [String, NilClass] Optional alternative name of the relation.
10
- attr_reader :alt_name
11
-
12
- # @param aName [String] Name of the relation.
13
- # @param alternateName [String, NilClass] Alternative name (optional).
14
- def initialize(aName, alternateName = nil)
15
- @name = aName
16
- @alt_name = alternateName
17
- end
18
-
19
- # A relation is polyadic when it accepts an arbitrary number of arguments.
20
- # Most built-in relation takes a fixed number of arguments (= arity).
21
- # @return [Boolean]
22
- def polyadic?
23
- false
24
- end
25
-
26
- # Number of arguments for the relation.
27
- # @return [Integer]
28
- def arity
8
+ # Formally, a n-relation over R, where R represents the cartesian product
9
+ # (A1 x A2 x ... An) is a subset of R.
10
+ # In other words, a n-relation is a subset of all tuples represented by R.
11
+ # In MiniKraken, a n-relation is an object that indicates whether a given
12
+ # tuple -of length n- is valid (or non valid).
13
+ class Relation < Specification
14
+ # Abstract method to override in subclass(es).
15
+ # @param actuals [Array<Term>] Argument count must
16
+ # @param ctx [Core::Context] Runtime context
17
+ # @return [#resume] A Fiber-like object that yields Context.
18
+ def solver_for(actuals, ctx)
29
19
  raise NotImplementedError
30
20
  end
31
-
32
- def inspect
33
- alt_name || name
34
- end
35
21
  end # class
36
22
  end # module
37
23
  end # module
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'log_var'
4
+
5
+ module MiniKraken
6
+ module Core
7
+ # A scope is a name space that corresponds either to a specific
8
+ # delimited region in MiniKraken source code or to an activation record
9
+ # of a relation or a relation definition.
10
+ # It contains a map of names to the objects they name (e.g. logical var)
11
+ class Scope
12
+ # The parent (enclosing) scope.
13
+ # @return [Scope, NilClass]
14
+ attr_accessor :parent
15
+
16
+ # Mapping from user-defined name to related definition
17
+ # (say, a logical variable object)
18
+ # @return [Hash{String => LogVar}] Pairs of the kind
19
+ attr_reader :defns
20
+
21
+ # Construct a scope instance.
22
+ # TODO: extend with defrel and procedure
23
+ # @param aParent [Scope, NilClass] Parent scope to this one.
24
+ def initialize(aParent = nil)
25
+ @parent = aParent
26
+ @defns = {}
27
+ end
28
+
29
+ # Add a new logical variable to the scope.
30
+ # @param anEntry [LogVar]
31
+ # @return [LogVar] the variable
32
+ def insert(anEntry)
33
+ e = validated_entry(anEntry)
34
+ e.suffix = default_suffix if e.kind_of?(LogVar)
35
+ defns[e.name] = e
36
+
37
+ e
38
+ end
39
+
40
+ # Returns a string with a human-readable representation of the object.
41
+ # @return [String]
42
+ def inspect
43
+ +"#<#{self.class}:#{object_id.to_s(16)}>"
44
+ end
45
+
46
+ private
47
+
48
+ def validated_entry(anEntry)
49
+ name = anEntry.name
50
+ unless name.kind_of?(String) && !name.empty?
51
+ err_msg = 'Invalid variable name argument.'
52
+ raise StandardError, err_msg
53
+ end
54
+ if defns.include?(name)
55
+ err_msg = "Variable with name '#{name}' already exists."
56
+ raise StandardError, err_msg
57
+ end
58
+
59
+ anEntry
60
+ end
61
+
62
+ def default_suffix
63
+ @default_suffix ||= "_#{object_id.to_s(16)}"
64
+ end
65
+ end # class
66
+ end # module
67
+ end # module
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiniKraken
4
+ module Core
5
+ # A wrapper around a "solver" object.
6
+ # A solver in MiniKraken is Fiber or an object that quacks like
7
+ # a Fiber in that its has a 'resume' method.
8
+ # To be a solver, the adaptee object must yield a Context or nil.
9
+ # A SolverAdapter implements a customized resume method that
10
+ # acts as an "execute around" method for the adaptee's ´resume´ method.
11
+ class SolverAdapter
12
+ # @return [#resume] A Fiber-like object as adaptee
13
+ attr_reader :adaptee
14
+
15
+ # ->(adapter, aContext) do
16
+ # aContext.push_bookmark(adapter.adaptee)
17
+ # result = adapter.adaptee.resume
18
+ # aContext.pop_bookmark
19
+ # result
20
+ # end
21
+ # @return [Proc] lambda to execute when resume is called
22
+ attr_reader :around_resume
23
+
24
+ # Constructor.
25
+ # @param fib [#resume] A Fiber-like object
26
+ def initialize(fib, &blk)
27
+ @adaptee = validated_adaptee(fib)
28
+ @around_resume = blk if block_given?
29
+ end
30
+
31
+ # Update the bookmarks and resume the Fiber
32
+ # @param aContext [Core::Context]
33
+ # @return [Core::Context, NilClass]
34
+ def resume(aContext)
35
+ ctx = validated_ctx(aContext)
36
+ if around_resume
37
+ around_resume.call(self, ctx)
38
+ else
39
+ adaptee.resume
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def validated_adaptee(fib)
46
+ raise StandardError, 'No resume method' unless fib.respond_to?(:resume)
47
+
48
+ fib
49
+ end
50
+
51
+ def validated_ctx(aContext)
52
+ raise StandardError unless aContext.kind_of?(Context)
53
+
54
+ aContext
55
+ end
56
+ end # class
57
+ end # module
58
+ end # module
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'arity'
4
+
5
+ module MiniKraken
6
+ module Core
7
+ class Specification
8
+ # @return [String] Name of the specification object.
9
+ attr_reader :name
10
+
11
+ # @return [Arity] arity = allowed number of arguments
12
+ attr_reader :arity
13
+
14
+ # @param aName [String] Name of the relation.
15
+ # @param anArity [Arity, Integer] Arity of the relation.
16
+ def initialize(aName, anArity)
17
+ @name = aName
18
+ @arity = anArity.is_a?(Integer) ? Arity.new(anArity, anArity) : anArity
19
+ end
20
+
21
+ # A relation is variadic when it accepts an arbitrary number of arguments.
22
+ # Most built-in relation takes a fixed number of arguments (= arity).
23
+ # @return [Boolean]
24
+ def variadic?
25
+ arity.variadic?
26
+ end
27
+
28
+ def inspect
29
+ name + "[#{arity.low}]"
30
+ end
31
+
32
+ # Control that the number of actual arguments matches
33
+ # the relation's arity.
34
+ # Raise an exception if the check fails
35
+ # @param actuals [Array<Term>] Actuals from a goal.
36
+ # @return [Array<Term>] Input array if compatible with arity.
37
+ def check_arity(actuals)
38
+ unless arity.match?(actuals.size)
39
+ msg1 = "Count of arguments (#{actuals.size})"
40
+ msg2 = " is out of allowed range (#{arity.low}, #{arity.high})."
41
+ raise StandardError, msg1 + msg2
42
+ end
43
+
44
+ actuals
45
+ end
46
+ end # class
47
+ end # module
48
+ end # module
@@ -4,23 +4,27 @@ require 'singleton'
4
4
  require_relative 'duck_fiber'
5
5
  require_relative 'nullary_relation'
6
6
 
7
- unless MiniKraken::Core.constants(false).include? :Succeed
8
- module MiniKraken
9
- module Core
10
- # A nullary relation that unconditionally always fails.
11
- class Succeed < NullaryRelation
12
- include Singleton
7
+ module MiniKraken
8
+ module Core
9
+ # A nullary relation that always returns success outcomes.
10
+ class Succeed < NullaryRelation
11
+ include Singleton
13
12
 
14
- def initialize
15
- super('succeed', '#s')
16
- end
13
+ # Constructor. Initialize the relation's name & freeze it...
14
+ def initialize
15
+ super('succeed')
16
+ end
17
17
 
18
- def solver_for(_actuals, _env)
19
- DuckFiber.new(:success)
20
- end
21
- end # class
22
-
23
- Succeed.instance.freeze
24
- end # module
18
+ # Returns a Fiber-like object (a DuckFiber).
19
+ # When that object receives the message resume, it will
20
+ # return a success context.
21
+ # @param _actuals [Array] MUST be empty array for nullary relation.
22
+ # @param ctx [Core::Context] Runtime context
23
+ # @return [Core::DuckFiber]
24
+ def solver_for(_actuals, ctx)
25
+ # Important: every `solver_for` call will result in a distinct Context.
26
+ DuckFiber.new(-> { ctx.succeeded! })
27
+ end
28
+ end # class
25
29
  end # module
26
- end # unless
30
+ end # module
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'scope'
4
+
5
+ module MiniKraken
6
+ module Core
7
+ # A symbol table is basically a mapping from a name onto an object
8
+ # that holds information associated with that name. It is a data structure
9
+ # that keeps track of variables and their respective scope where they are
10
+ # declared. The key requirements for the symbol are:
11
+ # - To perform fast lookup operations: given a name, retrieve the corresponding
12
+ # object.
13
+ # - To allow the efficient insertion of names and related information
14
+ # - To support the nesting of scopes
15
+ # - To handle the entry scope and exit scope events,
16
+ # - To cope with variable redefinition in nested scope
17
+ # The terminology 'symbol table' comes from the compiler design
18
+ # community.
19
+ class SymbolTable
20
+ # Mapping between a name and the scope(s) where it is defined
21
+ # @return [Hash{String => Array<Scope>}]
22
+ attr_reader :name2scopes
23
+
24
+ # @return [Scope] The top-level scope (= root of the tree of scopes)
25
+ attr_reader :root
26
+
27
+ # @return [Scope] The current scope.
28
+ attr_reader :current_scope
29
+
30
+ # Build symbol table with given scope as root.
31
+ # @param aScope [Core::Scope,NilClass] The top-level Scope
32
+ def initialize(aScope = nil)
33
+ @name2scopes = {}
34
+ init_root(aScope) # Set default (global) scope
35
+ end
36
+
37
+ # Returns iff there is no entry in the symbol table
38
+ # @return [Boolean]
39
+ def empty?
40
+ name2scopes.empty?
41
+ end
42
+
43
+ # Use this method to signal the interpreter that a given scope
44
+ # to be a child of current scope and to be itself the new current scope.
45
+ # @param aScope [Core::Scope] the Scope that
46
+ def enter_scope(aScope)
47
+ aScope.parent = current_scope
48
+ @current_scope = aScope
49
+ end
50
+
51
+ def leave_scope
52
+ # TODO: take dependencies between scopes into account
53
+
54
+ current_scope.defns.each_pair do |nm, _item|
55
+ scopes = name2scopes[nm]
56
+ if scopes.size == 1
57
+ name2scopes.delete(nm)
58
+ else
59
+ scopes.pop
60
+ name2scopes[nm] = scopes
61
+ end
62
+ end
63
+ raise StandardError, 'Cannot remove root scope.' if current_scope == root
64
+
65
+ @current_scope = current_scope.parent
66
+ end
67
+
68
+ # Add an entry with given name to current scope.
69
+ # @param anEntry [LogVar]
70
+ # @return [String] Internal name of the entry
71
+ def insert(anEntry)
72
+ current_scope.insert(anEntry)
73
+ name = anEntry.name
74
+ if name2scopes.include?(name)
75
+ name2scopes[name] << current_scope
76
+ else
77
+ name2scopes[name] = [current_scope]
78
+ end
79
+
80
+ anEntry.i_name
81
+ end
82
+
83
+ # Search for the object with the given name
84
+ # @param aName [String]
85
+ # @return [Core::LogVar]
86
+ def lookup(aName)
87
+ scopes = name2scopes.fetch(aName, nil)
88
+ return nil if scopes.nil?
89
+
90
+ sc = scopes.last
91
+ sc.defns[aName]
92
+ end
93
+
94
+ # Search for the object with the given i_name
95
+ # @param anIName [String]
96
+ # @return [Core::LogVar]
97
+ def lookup_i_name(anIName)
98
+ found = nil
99
+ scope = current_scope
100
+
101
+ begin
102
+ found = scope.defns.values.find { |e| e.i_name == anIName }
103
+ break if found
104
+
105
+ scope = scope.parent
106
+ end while scope
107
+
108
+ found
109
+ end
110
+
111
+ # Return all variables defined in the current .. root chain.
112
+ # Variables are sorted top-down and left-to-right.
113
+ def all_variables
114
+ vars = []
115
+ skope = current_scope
116
+ while skope
117
+ vars_of_scope = skope.defns.select { |_, item| item.kind_of?(LogVar) }
118
+ vars = vars_of_scope.values.concat(vars)
119
+ skope = skope.parent
120
+ end
121
+
122
+ vars
123
+ end
124
+
125
+ private
126
+
127
+ def init_root(aScope)
128
+ @root = valid_scope(aScope)
129
+ @current_scope = @root
130
+ end
131
+
132
+ def valid_scope(aScope)
133
+ aScope.nil? ? Scope.new : aScope
134
+ end
135
+ end # class
136
+ end # module
137
+ end # module
@@ -1,12 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'goal_arg'
3
+ require_relative 'base_term'
4
4
 
5
5
  module MiniKraken
6
6
  module Core
7
- # The generalization of any data value that can be
8
- # passed as arugement to a goal.
9
- class Term < GoalArg
7
+ # The generalization of any object that can be:
8
+ # - passed as argument to a goal.
9
+ # - passed as argument to a MiniKraken procedure
10
+ # - contained in a compositer term,
11
+ # - associated with a logical variable.
12
+ class Term < BaseTerm
13
+ # Abstract method.
14
+ # Make a copy of self with all the variable reference being
15
+ # replaced by the corresponding value in the Hash.
16
+ # @param _substitutions [Hash {String => Term}]
17
+ # @return [Term]
18
+ def dup_cond(_substitutions)
19
+ raise NotImplementedError, "Not implementation for #{self.class}."
20
+ end
10
21
  end # class
11
22
  end # module
12
23
  end # module
@@ -1,26 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
- require_relative '../core/any_value'
5
- require_relative '../core/conde'
6
- require_relative '../core/conj2'
7
- require_relative '../core/cons_cell'
8
- require_relative '../core/def_relation'
9
- require_relative '../core/disj2'
10
- require_relative '../core/equals'
11
- require_relative '../core/fail'
12
- require_relative '../core/formal_arg'
13
- require_relative '../core/formal_ref'
14
- require_relative '../glue/fresh_env'
15
- require_relative '../glue/fresh_env_factory'
16
- require_relative '../core/goal_template'
17
- require_relative '../core/k_boolean'
18
- require_relative '../core/k_symbol'
19
- require_relative '../core/succeed'
20
- require_relative '../core/variable_ref'
21
- require_relative 'fresh_env'
22
- require_relative 'run_star_expression'
23
4
 
5
+ require_relative '../core/all_core'
6
+ require_relative '../atomic/all_atomic'
7
+ require_relative '../composite/cons_cell'
8
+ require_relative '../rela/all_rela'
9
+ require_relative 'run_star_expression'
24
10
 
25
11
  module MiniKraken
26
12
  module Glue
@@ -30,14 +16,13 @@ module MiniKraken
30
16
  module DSL
31
17
  # A run* expression tries to find all the solutions
32
18
  # that meet the given goal.
33
- # @return [Core::ConsCell] A list of solutions
19
+ # @return [Composite::ConsCell] A list of solutions
34
20
  def run_star(var_names, goal)
35
21
  program = RunStarExpression.new(var_names, goal)
36
22
  program.run
37
23
  end
38
24
 
39
25
  def conde(*goals)
40
- # require 'debug'
41
26
  args = goals.map do |goal_maybe|
42
27
  if goal_maybe.kind_of?(Array)
43
28
  goal_maybe.map { |g| convert(g) }
@@ -46,7 +31,7 @@ module MiniKraken
46
31
  end
47
32
  end
48
33
 
49
- Core::Goal.new(Core::Conde.instance, args)
34
+ Core::Goal.new(Rela::Conde.instance, args)
50
35
  end
51
36
 
52
37
  # conj2 stands for conjunction of two arguments.
@@ -56,35 +41,32 @@ module MiniKraken
56
41
  # @param arg2 [Core::Goal]
57
42
  # @return [Core::Failure|Core::Success]
58
43
  def conj2(arg1, arg2)
59
- goal_class.new(Core::Conj2.instance, [convert(arg1), convert(arg2)])
44
+ goal_class.new(Rela::Conj2.instance, [convert(arg1), convert(arg2)])
60
45
  end
61
46
 
62
47
  def cons(car_item, cdr_item = nil)
63
48
  tail = cdr_item.nil? ? cdr_item : convert(cdr_item)
64
- Core::ConsCell.new(convert(car_item), tail)
49
+ Composite::ConsCell.new(convert(car_item), tail)
65
50
  end
66
51
 
67
- def defrel(relationName, theFormals, &aGoalTemplateExpr)
68
- start_defrel
52
+ def null_list
53
+ Composite::ConsCell.new(nil, nil)
54
+ end
69
55
 
56
+ def defrel(relationName, theFormals, aGoalExpr)
70
57
  case theFormals
71
58
  when String
72
- @defrel_formals << theFormals
59
+ formals = [theFormals]
73
60
  when Array
74
- @defrel_formals.merge(theFormals)
61
+ formals = theFormals
75
62
  end
76
63
 
77
- formals = @defrel_formals.map { |name| Core::FormalArg.new(name) }
78
- g_template = aGoalTemplateExpr.call
79
- result = Core::DefRelation.new(relationName, g_template, formals)
80
- add_defrel(result)
81
-
82
- end_defrel
83
- result
64
+ rela = Rela::DefRelation.new(relationName, aGoalExpr, formals)
65
+ add_defrel(rela)
84
66
  end
85
67
 
86
68
  def disj2(arg1, arg2)
87
- goal_class.new(Core::Disj2.instance, [convert(arg1), convert(arg2)])
69
+ goal_class.new(Rela::Disj2.instance, [convert(arg1), convert(arg2)])
88
70
  end
89
71
 
90
72
  # @return [Core::Fail] A goal that unconditionally fails.
@@ -92,43 +74,26 @@ module MiniKraken
92
74
  goal_class.new(Core::Fail.instance, [])
93
75
  end
94
76
 
95
- def equals(arg1, arg2)
96
- # require 'debug'
97
- goal_class.new(Core::Equals.instance, [convert(arg1), convert(arg2)])
77
+ def unify(arg1, arg2)
78
+ goal_class.new(Rela::Unify.instance, [convert(arg1), convert(arg2)])
98
79
  end
99
80
 
100
- def fresh(var_names, goal)
101
- vars = nil
102
- if @dsl_mode == :defrel
103
- if var_names.kind_of?(String)
104
- vars = [var_names]
105
- else
106
- vars = var_names
107
- end
108
- FreshEnvFactory.new(vars, goal)
109
- else
110
- if var_names.kind_of?(String) || var_names.kind_of?(Core::VariableRef)
111
- vars = [var_names]
112
- else
113
- vars = var_names
114
- end
115
-
116
- FreshEnv.new(vars, goal)
117
- end
81
+ # @return [Core::Goal]
82
+ def fresh(names, subgoal)
83
+ # puts "#{__callee__} #{names}"
84
+ Rela::Fresh.build_goal(names, subgoal)
118
85
  end
119
86
 
120
87
  def list(*members)
121
88
  return null if members.empty?
122
89
 
123
- head = nil
124
- members.reverse_each { |elem| head = Core::ConsCell.new(convert(elem), head) }
125
-
126
- head
90
+ converted = members.map { |e| convert(e) }
91
+ Composite::List.make_list(converted)
127
92
  end
128
93
 
129
94
  # @return [ConsCell] Returns an empty list, that is, a pair whose members are nil.
130
95
  def null
131
- Core::ConsCell.new(nil, nil)
96
+ Composite::ConsCell.null
132
97
  end
133
98
 
134
99
  # @return [Core::Succeed] A goal that unconditionally succeeds.
@@ -143,38 +108,29 @@ module MiniKraken
143
108
 
144
109
  case anArgument
145
110
  when Symbol
146
- if anArgument.id2name =~ /_\d+/
147
- rank = anArgument.id2name.slice(1..-1).to_i
148
- any_val = Core::AnyValue.allocate
149
- any_val.instance_variable_set(:@rank, rank)
150
- converted = any_val
151
- elsif anArgument.id2name =~ /^"#[ft]"$/
152
- converted = Core::KBoolean.new(anArgument)
153
- else
154
- converted = Core::KSymbol.new(anArgument)
111
+ case anArgument.id2name
112
+ when /_\d+/
113
+ rank = anArgument.id2name.slice(1..-1).to_i
114
+ any_val = Core::AnyValue.allocate
115
+ any_val.instance_variable_set(:@rank, rank)
116
+ converted = any_val
117
+ when /^"#[ft]"$/
118
+ converted = Atomic::KBoolean.new(anArgument)
119
+ else
120
+ converted = Atomic::KSymbol.new(anArgument)
155
121
  end
156
122
  when String
157
123
  if anArgument =~ /^#[ft]$/
158
- converted = Core::KBoolean.new(anArgument)
124
+ converted = Atomic::KBoolean.new(anArgument)
159
125
  else
160
126
  msg = "Internal error: undefined conversion for #{anArgument.class}"
161
127
  raise StandardError, msg
162
128
  end
163
129
  when false, true
164
- converted = Core::KBoolean.new(anArgument)
165
- when Core::KBoolean
166
- converted = anArgument
167
- when Core::FormalRef
168
- converted = anArgument
169
- when FreshEnv
170
- converted = anArgument
171
- when Core::Goal
172
- converted = anArgument
173
- when Core::GoalTemplate
174
- converted = anArgument
175
- when Core::VariableRef
130
+ converted = Atomic::KBoolean.new(anArgument)
131
+ when NilClass, Atomic::KBoolean, Atomic::KSymbol
176
132
  converted = anArgument
177
- when Core::ConsCell
133
+ when Core::Goal, Core::LogVarRef, Composite::ConsCell
178
134
  converted = anArgument
179
135
  else
180
136
  msg = "Internal error: undefined conversion for #{anArgument.class}"
@@ -204,7 +160,7 @@ module MiniKraken
204
160
  end
205
161
 
206
162
  def add_defrel(aDefRelation)
207
- @defrels = {} unless instance_variable_defined?(:@defrels)
163
+ @defrels ||= {}
208
164
  @defrels[aDefRelation.name] = aDefRelation
209
165
  end
210
166
 
@@ -215,7 +171,7 @@ module MiniKraken
215
171
  result = super(mth, *args)
216
172
  rescue NameError
217
173
  name = mth.id2name
218
- @defrels = {} unless instance_variable_defined?(:@defrels)
174
+ @defrels ||= {}
219
175
  if @defrels.include?(name)
220
176
  def_relation = @defrels[name]
221
177
  result = Core::Goal.new(def_relation, args.map { |el| convert(el) })
@@ -224,7 +180,7 @@ module MiniKraken
224
180
  if @dsl_mode == :defrel && @defrel_formals.include?(name)
225
181
  result = Core::FormalRef.new(name)
226
182
  else
227
- result = Core::VariableRef.new(name)
183
+ result = Core::LogVarRef.new(name)
228
184
  end
229
185
  end
230
186
  end