mini_kraken 0.2.02 → 0.3.02

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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +378 -333
  3. data/CHANGELOG.md +52 -0
  4. data/README.md +19 -19
  5. data/lib/mini_kraken.rb +0 -1
  6. data/lib/mini_kraken/atomic/all_atomic.rb +5 -0
  7. data/lib/mini_kraken/atomic/atomic_term.rb +96 -0
  8. data/lib/mini_kraken/atomic/k_boolean.rb +42 -0
  9. data/lib/mini_kraken/{core → atomic}/k_integer.rb +2 -5
  10. data/lib/mini_kraken/atomic/k_string.rb +17 -0
  11. data/lib/mini_kraken/{core → atomic}/k_symbol.rb +4 -8
  12. data/lib/mini_kraken/composite/all_composite.rb +4 -0
  13. data/lib/mini_kraken/composite/composite_term.rb +27 -0
  14. data/lib/mini_kraken/composite/cons_cell.rb +299 -0
  15. data/lib/mini_kraken/composite/cons_cell_visitor.rb +50 -0
  16. data/lib/mini_kraken/composite/list.rb +32 -0
  17. data/lib/mini_kraken/core/all_core.rb +8 -0
  18. data/lib/mini_kraken/core/any_value.rb +31 -7
  19. data/lib/mini_kraken/core/arity.rb +69 -0
  20. data/lib/mini_kraken/core/association.rb +29 -4
  21. data/lib/mini_kraken/core/association_copy.rb +50 -0
  22. data/lib/mini_kraken/core/base_term.rb +13 -0
  23. data/lib/mini_kraken/core/blackboard.rb +315 -0
  24. data/lib/mini_kraken/core/bookmark.rb +46 -0
  25. data/lib/mini_kraken/core/context.rb +492 -0
  26. data/lib/mini_kraken/core/duck_fiber.rb +21 -19
  27. data/lib/mini_kraken/core/entry.rb +40 -0
  28. data/lib/mini_kraken/core/fail.rb +20 -18
  29. data/lib/mini_kraken/core/fusion.rb +29 -0
  30. data/lib/mini_kraken/core/goal.rb +20 -29
  31. data/lib/mini_kraken/core/log_var.rb +22 -0
  32. data/lib/mini_kraken/core/log_var_ref.rb +108 -0
  33. data/lib/mini_kraken/core/nullary_relation.rb +2 -9
  34. data/lib/mini_kraken/core/parametrized_term.rb +61 -0
  35. data/lib/mini_kraken/core/relation.rb +14 -28
  36. data/lib/mini_kraken/core/scope.rb +67 -0
  37. data/lib/mini_kraken/core/solver_adapter.rb +58 -0
  38. data/lib/mini_kraken/core/specification.rb +48 -0
  39. data/lib/mini_kraken/core/succeed.rb +21 -17
  40. data/lib/mini_kraken/core/symbol_table.rb +137 -0
  41. data/lib/mini_kraken/core/term.rb +15 -4
  42. data/lib/mini_kraken/glue/dsl.rb +45 -81
  43. data/lib/mini_kraken/glue/run_star_expression.rb +28 -30
  44. data/lib/mini_kraken/rela/all_rela.rb +8 -0
  45. data/lib/mini_kraken/rela/binary_relation.rb +30 -0
  46. data/lib/mini_kraken/rela/conde.rb +143 -0
  47. data/lib/mini_kraken/rela/conj2.rb +65 -0
  48. data/lib/mini_kraken/rela/def_relation.rb +93 -0
  49. data/lib/mini_kraken/rela/disj2.rb +70 -0
  50. data/lib/mini_kraken/rela/fresh.rb +98 -0
  51. data/lib/mini_kraken/{core → rela}/goal_relation.rb +7 -9
  52. data/lib/mini_kraken/rela/unify.rb +258 -0
  53. data/lib/mini_kraken/version.rb +1 -1
  54. data/mini_kraken.gemspec +2 -2
  55. data/spec/.rubocop.yml +1 -1
  56. data/spec/atomic/atomic_term_spec.rb +98 -0
  57. data/spec/{core → atomic}/k_boolean_spec.rb +19 -34
  58. data/spec/{core → atomic}/k_symbol_spec.rb +3 -16
  59. data/spec/composite/cons_cell_spec.rb +225 -0
  60. data/spec/composite/cons_cell_visitor_spec.rb +158 -0
  61. data/spec/composite/list_spec.rb +50 -0
  62. data/spec/core/any_value_spec.rb +52 -0
  63. data/spec/core/arity_spec.rb +92 -0
  64. data/spec/core/association_copy_spec.rb +69 -0
  65. data/spec/core/association_spec.rb +31 -4
  66. data/spec/core/blackboard_spec.rb +287 -0
  67. data/spec/core/bookmark_spec.rb +40 -0
  68. data/spec/core/context_spec.rb +245 -0
  69. data/spec/core/core_spec.rb +40 -0
  70. data/spec/core/duck_fiber_spec.rb +16 -46
  71. data/spec/core/fail_spec.rb +5 -6
  72. data/spec/core/goal_spec.rb +24 -14
  73. data/spec/core/log_var_ref_spec.rb +105 -0
  74. data/spec/core/log_var_spec.rb +64 -0
  75. data/spec/core/nullary_relation_spec.rb +33 -0
  76. data/spec/core/parametrized_tem_spec.rb +39 -0
  77. data/spec/core/relation_spec.rb +33 -0
  78. data/spec/core/scope_spec.rb +73 -0
  79. data/spec/core/solver_adapter_spec.rb +70 -0
  80. data/spec/core/specification_spec.rb +43 -0
  81. data/spec/core/succeed_spec.rb +5 -5
  82. data/spec/core/symbol_table_spec.rb +142 -0
  83. data/spec/glue/dsl_chap1_spec.rb +96 -144
  84. data/spec/glue/dsl_chap2_spec.rb +350 -0
  85. data/spec/glue/run_star_expression_spec.rb +82 -906
  86. data/spec/rela/conde_spec.rb +153 -0
  87. data/spec/rela/conj2_spec.rb +123 -0
  88. data/spec/rela/def_relation_spec.rb +119 -0
  89. data/spec/rela/disj2_spec.rb +117 -0
  90. data/spec/rela/fresh_spec.rb +147 -0
  91. data/spec/rela/unify_spec.rb +369 -0
  92. data/spec/support/factory_atomic.rb +29 -0
  93. data/spec/support/factory_composite.rb +21 -0
  94. data/spec/support/factory_methods.rb +11 -26
  95. metadata +100 -64
  96. data/lib/mini_kraken/core/association_walker.rb +0 -183
  97. data/lib/mini_kraken/core/atomic_term.rb +0 -67
  98. data/lib/mini_kraken/core/base_arg.rb +0 -10
  99. data/lib/mini_kraken/core/binary_relation.rb +0 -63
  100. data/lib/mini_kraken/core/composite_goal.rb +0 -46
  101. data/lib/mini_kraken/core/composite_term.rb +0 -41
  102. data/lib/mini_kraken/core/conde.rb +0 -143
  103. data/lib/mini_kraken/core/conj2.rb +0 -79
  104. data/lib/mini_kraken/core/cons_cell.rb +0 -82
  105. data/lib/mini_kraken/core/def_relation.rb +0 -50
  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 -156
  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 -62
  115. data/lib/mini_kraken/core/k_boolean.rb +0 -35
  116. data/lib/mini_kraken/core/outcome.rb +0 -53
  117. data/lib/mini_kraken/core/variable.rb +0 -41
  118. data/lib/mini_kraken/core/variable_ref.rb +0 -78
  119. data/lib/mini_kraken/core/vocabulary.rb +0 -442
  120. data/lib/mini_kraken/glue/fresh_env.rb +0 -75
  121. data/spec/core/association_walker_spec.rb +0 -192
  122. data/spec/core/conde_spec.rb +0 -147
  123. data/spec/core/conj2_spec.rb +0 -114
  124. data/spec/core/cons_cell_spec.rb +0 -107
  125. data/spec/core/def_relation_spec.rb +0 -96
  126. data/spec/core/disj2_spec.rb +0 -99
  127. data/spec/core/environment_spec.rb +0 -142
  128. data/spec/core/equals_spec.rb +0 -304
  129. data/spec/core/goal_template_spec.rb +0 -74
  130. data/spec/core/outcome_spec.rb +0 -48
  131. data/spec/core/variable_ref_spec.rb +0 -27
  132. data/spec/core/variable_spec.rb +0 -35
  133. data/spec/core/vocabulary_spec.rb +0 -219
  134. 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,25 +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 '../core/goal_template'
16
- require_relative '../core/k_boolean'
17
- require_relative '../core/k_symbol'
18
- require_relative '../core/succeed'
19
- require_relative '../core/variable_ref'
20
- require_relative 'fresh_env'
21
- require_relative 'run_star_expression'
22
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'
23
10
 
24
11
  module MiniKraken
25
12
  module Glue
@@ -29,23 +16,22 @@ module MiniKraken
29
16
  module DSL
30
17
  # A run* expression tries to find all the solutions
31
18
  # that meet the given goal.
32
- # @return [Core::ConsCell] A list of solutions
19
+ # @return [Composite::ConsCell] A list of solutions
33
20
  def run_star(var_names, goal)
34
21
  program = RunStarExpression.new(var_names, goal)
35
22
  program.run
36
23
  end
37
24
 
38
25
  def conde(*goals)
39
- # require 'debug'
40
26
  args = goals.map do |goal_maybe|
41
27
  if goal_maybe.kind_of?(Array)
42
- goal_maybe.map { |g| convert(g)}
28
+ goal_maybe.map { |g| convert(g) }
43
29
  else
44
30
  convert(goal_maybe)
45
31
  end
46
32
  end
47
33
 
48
- Core::Goal.new(Core::Conde.instance, args)
34
+ Core::Goal.new(Rela::Conde.instance, args)
49
35
  end
50
36
 
51
37
  # conj2 stands for conjunction of two arguments.
@@ -55,35 +41,31 @@ module MiniKraken
55
41
  # @param arg2 [Core::Goal]
56
42
  # @return [Core::Failure|Core::Success]
57
43
  def conj2(arg1, arg2)
58
- goal_class.new(Core::Conj2.instance, [convert(arg1), convert(arg2)])
44
+ goal_class.new(Rela::Conj2.instance, [convert(arg1), convert(arg2)])
59
45
  end
60
46
 
61
47
  def cons(car_item, cdr_item = nil)
62
48
  tail = cdr_item.nil? ? cdr_item : convert(cdr_item)
63
- Core::ConsCell.new(convert(car_item), tail)
49
+ Composite::ConsCell.new(convert(car_item), tail)
64
50
  end
65
51
 
66
- def defrel(relationName, theFormals, &aGoalTemplateExpr)
67
- start_defrel
52
+ def null_list
53
+ Composite::ConsCell.new(nil, nil)
54
+ end
68
55
 
56
+ def defrel(relationName, theFormals, aGoalExpr)
69
57
  case theFormals
70
58
  when String
71
- @defrel_formals << theFormals
59
+ formals = [theFormals]
72
60
  when Array
73
- @defrel_formals.merge(theFormals)
61
+ formals = theFormals
74
62
  end
75
-
76
- formals = @defrel_formals.map { |name| Core::FormalArg.new(name) }
77
- g_template = aGoalTemplateExpr.call
78
- result = Core::DefRelation.new(relationName, g_template, formals)
79
- add_defrel(result)
80
-
81
- end_defrel
82
- result
63
+ rela = Rela::DefRelation.new(relationName, aGoalExpr, formals)
64
+ add_defrel(rela)
83
65
  end
84
66
 
85
67
  def disj2(arg1, arg2)
86
- goal_class.new(Core::Disj2.instance, [convert(arg1), convert(arg2)])
68
+ goal_class.new(Rela::Disj2.instance, [convert(arg1), convert(arg2)])
87
69
  end
88
70
 
89
71
  # @return [Core::Fail] A goal that unconditionally fails.
@@ -91,35 +73,26 @@ module MiniKraken
91
73
  goal_class.new(Core::Fail.instance, [])
92
74
  end
93
75
 
94
- def equals(arg1, arg2)
95
- # require 'debug'
96
- goal_class.new(Core::Equals.instance, [convert(arg1), convert(arg2)])
76
+ def unify(arg1, arg2)
77
+ goal_class.new(Rela::Unify.instance, [convert(arg1), convert(arg2)])
97
78
  end
98
79
 
99
- def fresh(var_names, goal)
100
- vars = nil
101
-
102
- if var_names.kind_of?(String) || var_names.kind_of?(Core::VariableRef)
103
- vars = [var_names]
104
- else
105
- vars = var_names
106
- end
107
-
108
- FreshEnv.new(vars, goal)
80
+ # @return [Core::Goal]
81
+ def fresh(names, subgoal)
82
+ # puts "#{__callee__} #{names}"
83
+ Rela::Fresh.build_goal(names, subgoal)
109
84
  end
110
85
 
111
86
  def list(*members)
112
87
  return null if members.empty?
113
88
 
114
- head = nil
115
- members.reverse_each { |elem| head = Core::ConsCell.new(convert(elem), head) }
116
-
117
- head
89
+ converted = members.map { |e| convert(e) }
90
+ Composite::List.make_list(converted)
118
91
  end
119
92
 
120
93
  # @return [ConsCell] Returns an empty list, that is, a pair whose members are nil.
121
94
  def null
122
- Core::ConsCell.new(nil, nil)
95
+ Composite::ConsCell.null
123
96
  end
124
97
 
125
98
  # @return [Core::Succeed] A goal that unconditionally succeeds.
@@ -134,38 +107,29 @@ module MiniKraken
134
107
 
135
108
  case anArgument
136
109
  when Symbol
137
- if anArgument.id2name =~ /_\d+/
138
- rank = anArgument.id2name.slice(1..-1).to_i
139
- any_val = Core::AnyValue.allocate
140
- any_val.instance_variable_set(:@rank, rank)
141
- converted = any_val
142
- elsif anArgument.id2name =~ /^"#[ft]"$/
143
- converted = Core::KBoolean.new(anArgument)
144
- else
145
- converted = Core::KSymbol.new(anArgument)
110
+ case anArgument.id2name
111
+ when /_\d+/
112
+ rank = anArgument.id2name.slice(1..-1).to_i
113
+ any_val = Core::AnyValue.allocate
114
+ any_val.instance_variable_set(:@rank, rank)
115
+ converted = any_val
116
+ when /^"#[ft]"$/
117
+ converted = Atomic::KBoolean.new(anArgument)
118
+ else
119
+ converted = Atomic::KSymbol.new(anArgument)
146
120
  end
147
121
  when String
148
122
  if anArgument =~ /^#[ft]$/
149
- converted = Core::KBoolean.new(anArgument)
123
+ converted = Atomic::KBoolean.new(anArgument)
150
124
  else
151
125
  msg = "Internal error: undefined conversion for #{anArgument.class}"
152
126
  raise StandardError, msg
153
127
  end
154
128
  when false, true
155
- converted = Core::KBoolean.new(anArgument)
156
- when Core::KBoolean
157
- converted = anArgument
158
- when Core::FormalRef
159
- converted = anArgument
160
- when FreshEnv
161
- converted = anArgument
162
- when Core::Goal
163
- converted = anArgument
164
- when Core::GoalTemplate
165
- converted = anArgument
166
- when Core::VariableRef
129
+ converted = Atomic::KBoolean.new(anArgument)
130
+ when NilClass, Atomic::KBoolean, Atomic::KSymbol
167
131
  converted = anArgument
168
- when Core::ConsCell
132
+ when Core::Goal, Core::LogVarRef, Composite::ConsCell
169
133
  converted = anArgument
170
134
  else
171
135
  msg = "Internal error: undefined conversion for #{anArgument.class}"
@@ -195,7 +159,7 @@ module MiniKraken
195
159
  end
196
160
 
197
161
  def add_defrel(aDefRelation)
198
- @defrels = {} unless instance_variable_defined?(:@defrels)
162
+ @defrels ||= {}
199
163
  @defrels[aDefRelation.name] = aDefRelation
200
164
  end
201
165
 
@@ -206,7 +170,7 @@ module MiniKraken
206
170
  result = super(mth, *args)
207
171
  rescue NameError
208
172
  name = mth.id2name
209
- @defrels = {} unless instance_variable_defined?(:@defrels)
173
+ @defrels ||= {}
210
174
  if @defrels.include?(name)
211
175
  def_relation = @defrels[name]
212
176
  result = Core::Goal.new(def_relation, args.map { |el| convert(el) })
@@ -215,7 +179,7 @@ module MiniKraken
215
179
  if @dsl_mode == :defrel && @defrel_formals.include?(name)
216
180
  result = Core::FormalRef.new(name)
217
181
  else
218
- result = Core::VariableRef.new(name)
182
+ result = Core::LogVarRef.new(name)
219
183
  end
220
184
  end
221
185
  end