wongi-engine 0.3.5 → 0.3.7

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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +80 -0
  4. data/.travis.yml +8 -15
  5. data/Gemfile +4 -0
  6. data/README.md +3 -3
  7. data/Rakefile +1 -2
  8. data/examples/ex01.rb +1 -1
  9. data/examples/ex02.rb +3 -7
  10. data/examples/graphviz.rb +1 -1
  11. data/examples/rdf.rb +1 -1
  12. data/examples/timeline.rb +6 -6
  13. data/lib/wongi-engine/alpha_memory.rb +5 -9
  14. data/lib/wongi-engine/beta/aggregate_node.rb +93 -0
  15. data/lib/wongi-engine/beta/assignment_node.rb +10 -18
  16. data/lib/wongi-engine/beta/beta_memory.rb +20 -9
  17. data/lib/wongi-engine/beta/beta_node.rb +14 -22
  18. data/lib/wongi-engine/beta/filter_node.rb +12 -15
  19. data/lib/wongi-engine/beta/join_node.rb +47 -61
  20. data/lib/wongi-engine/beta/ncc_node.rb +17 -20
  21. data/lib/wongi-engine/beta/ncc_partner.rb +17 -17
  22. data/lib/wongi-engine/beta/neg_node.rb +37 -37
  23. data/lib/wongi-engine/beta/optional_node.rb +53 -60
  24. data/lib/wongi-engine/beta/or_node.rb +6 -9
  25. data/lib/wongi-engine/beta/production_node.rb +6 -9
  26. data/lib/wongi-engine/beta.rb +1 -0
  27. data/lib/wongi-engine/compiler.rb +38 -22
  28. data/lib/wongi-engine/core_ext.rb +11 -20
  29. data/lib/wongi-engine/data_overlay.rb +23 -26
  30. data/lib/wongi-engine/dsl/action/assign_action.rb +1 -1
  31. data/lib/wongi-engine/dsl/action/base.rb +1 -4
  32. data/lib/wongi-engine/dsl/action/error_generator.rb +9 -9
  33. data/lib/wongi-engine/dsl/action/simple_action.rb +14 -10
  34. data/lib/wongi-engine/dsl/action/simple_collector.rb +10 -25
  35. data/lib/wongi-engine/dsl/action/statement_generator.rb +15 -14
  36. data/lib/wongi-engine/dsl/action/trace_action.rb +9 -9
  37. data/lib/wongi-engine/dsl/any_rule.rb +16 -20
  38. data/lib/wongi-engine/dsl/assuming.rb +8 -15
  39. data/lib/wongi-engine/dsl/builder.rb +13 -12
  40. data/lib/wongi-engine/dsl/clause/aggregate.rb +21 -0
  41. data/lib/wongi-engine/dsl/clause/assign.rb +4 -4
  42. data/lib/wongi-engine/dsl/clause/fact.rb +10 -6
  43. data/lib/wongi-engine/dsl/clause/gen.rb +3 -5
  44. data/lib/wongi-engine/dsl/clause/generic.rb +7 -9
  45. data/lib/wongi-engine/dsl/generated.rb +6 -12
  46. data/lib/wongi-engine/dsl/ncc_subrule.rb +6 -9
  47. data/lib/wongi-engine/dsl/query.rb +12 -15
  48. data/lib/wongi-engine/dsl/rule.rb +45 -50
  49. data/lib/wongi-engine/dsl.rb +30 -16
  50. data/lib/wongi-engine/enumerators.rb +2 -1
  51. data/lib/wongi-engine/error.rb +6 -7
  52. data/lib/wongi-engine/filter/asserting_test.rb +4 -7
  53. data/lib/wongi-engine/filter/equality_test.rb +15 -18
  54. data/lib/wongi-engine/filter/filter_test.rb +3 -6
  55. data/lib/wongi-engine/filter/greater_than_or_equal_test.rb +5 -2
  56. data/lib/wongi-engine/filter/greater_than_test.rb +15 -18
  57. data/lib/wongi-engine/filter/inequality_test.rb +15 -18
  58. data/lib/wongi-engine/filter/less_than_or_equal_test.rb +5 -2
  59. data/lib/wongi-engine/filter/less_than_test.rb +15 -18
  60. data/lib/wongi-engine/filter.rb +1 -1
  61. data/lib/wongi-engine/graph.rb +13 -20
  62. data/lib/wongi-engine/network/collectable.rb +10 -14
  63. data/lib/wongi-engine/network/debug.rb +16 -24
  64. data/lib/wongi-engine/network.rb +110 -129
  65. data/lib/wongi-engine/ruleset.rb +18 -20
  66. data/lib/wongi-engine/template.rb +31 -30
  67. data/lib/wongi-engine/token.rb +33 -33
  68. data/lib/wongi-engine/version.rb +1 -1
  69. data/lib/wongi-engine/wme.rb +17 -23
  70. data/lib/wongi-engine/wme_match_data.rb +5 -9
  71. data/lib/wongi-engine.rb +0 -4
  72. data/spec/action_class_spec.rb +43 -49
  73. data/spec/beta_node_spec.rb +2 -8
  74. data/spec/bug_specs/issue_4_spec.rb +12 -20
  75. data/spec/dataset_spec.rb +3 -6
  76. data/spec/filter_specs/assert_test_spec.rb +12 -31
  77. data/spec/filter_specs/greater_than_equality_test_spec.rb +2 -5
  78. data/spec/filter_specs/less_test_spec.rb +7 -17
  79. data/spec/filter_specs/less_than_equality_test_spec.rb +3 -6
  80. data/spec/generation_spec.rb +45 -54
  81. data/spec/high_level_spec.rb +95 -141
  82. data/spec/network_spec.rb +77 -68
  83. data/spec/overlay_spec.rb +4 -5
  84. data/spec/rule_specs/aggregate_spec.rb +197 -0
  85. data/spec/rule_specs/any_rule_spec.rb +73 -19
  86. data/spec/rule_specs/assign_spec.rb +10 -16
  87. data/spec/rule_specs/assuming_spec.rb +10 -17
  88. data/spec/rule_specs/maybe_rule_spec.rb +4 -15
  89. data/spec/rule_specs/ncc_spec.rb +48 -65
  90. data/spec/rule_specs/negative_rule_spec.rb +13 -27
  91. data/spec/rule_specs/or_rule_spec.rb +3 -13
  92. data/spec/ruleset_spec.rb +11 -17
  93. data/spec/simple_action_spec.rb +4 -14
  94. data/spec/wme_spec.rb +14 -21
  95. data/wongi-engine.gemspec +22 -22
  96. metadata +19 -41
  97. data/.hgignore +0 -7
  98. data/spec/dsl_spec.rb +0 -9
@@ -1,33 +1,29 @@
1
1
  module Wongi::Engine
2
2
  module DSL
3
3
  class AnyRule
4
+ attr_reader :variants
4
5
 
5
- attr_reader :variants
6
-
7
- def initialize &block
8
- @variants = []
9
- if block
10
- instance_eval &block
6
+ def initialize(&block)
7
+ @variants = []
8
+ instance_eval(&block) if block
11
9
  end
12
- end
13
10
 
14
- def option &block
15
- var = VariantRule.new
16
- var.forall &block
17
- variants << var
18
- end
11
+ def option(&block)
12
+ var = VariantRule.new
13
+ var.forall(&block)
14
+ variants << var
15
+ end
19
16
 
20
- def compile context
21
- context.tap { |c| c.or_node(variants) }
17
+ def compile(context)
18
+ context.tap { |c| c.or_node(variants) }
19
+ end
22
20
  end
23
21
 
24
- end
25
-
26
22
  class VariantRule < Rule
27
- def initialize name = nil
28
- super
29
- @current_section = :forall
23
+ def initialize(name = nil)
24
+ super
25
+ @current_section = :forall
26
+ end
30
27
  end
31
28
  end
32
- end
33
29
  end
@@ -1,31 +1,24 @@
1
1
  module Wongi::Engine
2
-
3
2
  class UndefinedBaseRule < StandardError
4
- def initialize rule_name
5
- @rule_name = rule_name
6
- end
7
-
8
- def message
9
- "undefined production #@rule_name"
3
+ def initialize(rule_name)
4
+ super("undefined production #{rule_name}")
10
5
  end
11
6
  end
12
7
 
13
8
  class AssumingClause
14
-
15
9
  attr_reader :base_rule_name
16
10
 
17
- def initialize base_rule_name
11
+ def initialize(base_rule_name)
18
12
  @base_rule_name = base_rule_name
19
13
  end
20
14
 
21
- def compile context
15
+ def compile(context)
22
16
  base_production = context.rete.productions[base_rule_name]
23
- raise UndefinedBaseRule.new(base_rule_name) unless base_production
24
- raise DefinitionError.new("'assuming' cannot be preceded by other matchers") unless context.node.root?
25
- raise StandardError.new("missing base context") unless base_production.compilation_context
17
+ raise UndefinedBaseRule, base_rule_name unless base_production
18
+ raise DefinitionError, "'assuming' cannot be preceded by other matchers" unless context.node.root?
19
+ raise StandardError, "missing base context" unless base_production.compilation_context
20
+
26
21
  base_production.compilation_context.dup
27
22
  end
28
-
29
23
  end
30
-
31
24
  end
@@ -1,14 +1,13 @@
1
1
  module Wongi::Engine::DSL
2
2
  class Builder
3
-
4
3
  def initialize
5
4
  @current_section = nil
6
5
  @current_clause = nil
7
6
  @clauses = []
8
7
  end
9
8
 
10
- def build &definition
11
- instance_eval &definition
9
+ def build(&definition)
10
+ instance_eval(&definition)
12
11
  @clauses.each do |c|
13
12
  Wongi::Engine::DSL.sections[c[:section]] ||= Class.new do
14
13
  include Generated
@@ -16,32 +15,34 @@ module Wongi::Engine::DSL
16
15
  Wongi::Engine::DSL.sections[c[:section]].create_dsl_method(c)
17
16
  end
18
17
  end
19
-
20
- def section s
18
+
19
+ def section(s)
21
20
  @current_section = s
22
21
  end
23
-
24
- def clause *c
22
+
23
+ def clause(*c)
25
24
  @current_clause = c
26
25
  end
27
-
28
- def action klass = nil, &block
26
+
27
+ def action(klass = nil, &block)
29
28
  raise DefinitionError, "Cannot create an action without a clause" if @current_clause.nil?
29
+
30
30
  @clauses << { section: @current_section, clause: @current_clause, action: klass || block }
31
31
  @current_clause = nil
32
32
  end
33
33
 
34
- def body klass = nil, &block
34
+ def body(klass = nil, &block)
35
35
  raise DefinitionError, "Cannot create a body without a clause" if @current_clause.nil?
36
+
36
37
  @clauses << { section: @current_section, clause: @current_clause, body: klass || block }
37
38
  @current_clause = nil
38
39
  end
39
40
 
40
- def accept klass
41
+ def accept(klass)
41
42
  raise DefinitionError, "Cannot create an acceptor without a clause" if @current_clause.nil?
43
+
42
44
  @clauses << { section: @current_section, clause: @current_clause, accept: klass }
43
45
  @current_clause = nil
44
46
  end
45
-
46
47
  end
47
48
  end
@@ -0,0 +1,21 @@
1
+ module Wongi::Engine
2
+ module DSL::Clause
3
+ class Aggregate < Has
4
+ attr_reader :map, :function, :assign
5
+
6
+ def initialize(s, p, o, options = {})
7
+ member = options[:on]
8
+ @map = options[:map]
9
+ @function = options[:function]
10
+ @assign = options[:assign]
11
+ @map ||= -> { _1.send(member) }
12
+ super
13
+ end
14
+
15
+ def compile(context)
16
+ tests, assignment = parse_variables(context)
17
+ context.tap { |c| c.aggregate_node(self, tests, assignment, map, function, assign) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,13 +1,13 @@
1
1
  module Wongi::Engine
2
2
  module DSL::Clause
3
3
  class Assign
4
-
5
- def initialize variable, &body
6
- @variable, @body = variable, body
4
+ def initialize(variable, &body)
5
+ @variable = variable
6
+ @body = body
7
7
  raise DefinitionError, "#{variable} is not a variable" unless Template.variable?(variable)
8
8
  end
9
9
 
10
- def compile context
10
+ def compile(context)
11
11
  context.tap { |c| c.assignment_node(@variable, @body) }
12
12
  end
13
13
  end
@@ -4,12 +4,13 @@ module Wongi::Engine
4
4
  include CoreExt
5
5
  attr_predicate :debug
6
6
 
7
- def initialize(s, p, o, options = { })
7
+ def initialize(s, p, o, options = {})
8
8
  time = options[:time] || 0
9
9
  @unsafe = options[:unsafe] || false
10
10
  debug! if options[:debug]
11
11
  raise "Cannot work with continuous time" unless time.integer?
12
- raise "Cannot look into the future" if time > 0
12
+ raise "Cannot look into the future" if time.positive?
13
+
13
14
  super(s, p, o, time)
14
15
  end
15
16
 
@@ -26,7 +27,7 @@ module Wongi::Engine
26
27
 
27
28
  def parse_variables(context)
28
29
  tests = []
29
- assignment_mapping = [:subject, :predicate, :object].map do |member|
30
+ assignment_mapping = %i[subject predicate object].map do |member|
30
31
  value = send(member)
31
32
  if Template.variable?(value)
32
33
  if context.declares_variable?(value)
@@ -47,9 +48,11 @@ module Wongi::Engine
47
48
 
48
49
  class Neg < Has
49
50
  attr_reader :unsafe
50
- def compile context
51
+
52
+ def compile(context)
51
53
  tests, assignment = parse_variables(context)
52
- raise DefinitionError.new("Negative matches may not introduce new variables: #{assignment.variables}") unless assignment.root?
54
+ raise DefinitionError, "Negative matches may not introduce new variables: #{assignment.variables}" unless assignment.root?
55
+
53
56
  context.tap { |c| c.neg_node(self, tests, unsafe) }
54
57
  end
55
58
 
@@ -59,10 +62,11 @@ module Wongi::Engine
59
62
  end
60
63
 
61
64
  class Opt < Has
62
- def compile context
65
+ def compile(context)
63
66
  tests, assignment = parse_variables(context)
64
67
  context.tap { |c| c.opt_node(self, tests, assignment) }
65
68
  end
69
+
66
70
  def inspect
67
71
  "<?#{subject.inspect} #{predicate.inspect} #{object.inspect}>"
68
72
  end
@@ -1,17 +1,15 @@
1
1
  module Wongi::Engine
2
2
  module DSL::Clause
3
3
  class Gen
4
-
5
- def initialize s, p, o
6
- @triple = Template.new( s, p, o )
4
+ def initialize(s, p, o)
5
+ @triple = Template.new(s, p, o)
7
6
  end
8
7
 
9
- def import_into rete
8
+ def import_into(rete)
10
9
  generator = DSL::Action::StatementGenerator.new @triple
11
10
  generator.rete = rete
12
11
  generator
13
12
  end
14
-
15
13
  end
16
14
  end
17
15
  end
@@ -1,19 +1,18 @@
1
1
  module Wongi::Engine
2
2
  module DSL::Clause
3
3
  class Generic
4
-
5
4
  attr_accessor :name, :action, :rule
6
5
 
7
- def initialize *args, &block
6
+ def initialize(*args, &block)
8
7
  @args = args
9
8
  @block = block
10
9
  end
11
10
 
12
- def import_into rete
11
+ def import_into(rete)
13
12
  if action.respond_to? :call
14
13
  self
15
14
  else
16
- action.new( *@args, &@block ).tap do |a|
15
+ action.new(*@args, &@block).tap do |a|
17
16
  a.name = name if a.respond_to? :name=
18
17
  a.rule = rule if a.respond_to? :rule=
19
18
  a.rete = rete if a.respond_to? :rete=
@@ -25,14 +24,13 @@ module Wongi::Engine
25
24
  raise e1
26
25
  end
27
26
 
28
- def compile *args
29
- action.call *args
27
+ def compile(*args)
28
+ action.call(*args)
30
29
  end
31
30
 
32
- def execute *args
33
- action.call *args
31
+ def execute(*args)
32
+ action.call(*args)
34
33
  end
35
-
36
34
  end
37
35
  end
38
36
  end
@@ -1,40 +1,35 @@
1
1
  module Wongi::Engine::DSL
2
2
  module Generated
3
-
4
3
  module ClassMethods
5
- def create_dsl_method extension
6
-
4
+ def create_dsl_method(extension)
7
5
  clause = extension[:clause]
8
6
  action = extension[:action]
9
7
  body = extension[:body]
10
8
  acceptor = extension[:accept]
11
9
 
12
10
  define_method clause.first do |*args, &block|
13
-
14
11
  if body
15
12
 
16
- instance_exec *args, &body
13
+ instance_exec(*args, &body)
17
14
 
18
15
  elsif acceptor
19
16
 
20
- rule.accept acceptor.new( *args, &block )
17
+ rule.accept acceptor.new(*args, &block)
21
18
 
22
19
  elsif action
23
20
 
24
- c = Clause::Generic.new *args, &block
21
+ c = Clause::Generic.new(*args, &block)
25
22
  c.name = clause.first
26
23
  c.action = action
27
- c.rule = self.rule
24
+ c.rule = rule
28
25
  rule.accept c
29
26
 
30
27
  end
31
-
32
28
  end
33
29
 
34
- clause[1..-1].each do |al|
30
+ clause[1..].each do |al|
35
31
  alias_method al, clause.first
36
32
  end
37
-
38
33
  end
39
34
  end
40
35
 
@@ -43,6 +38,5 @@ module Wongi::Engine::DSL
43
38
  def self.included(base)
44
39
  base.extend ClassMethods
45
40
  end
46
-
47
41
  end
48
42
  end
@@ -1,17 +1,14 @@
1
1
  module Wongi::Engine
2
2
  module DSL
3
3
  class NccSubrule < Rule
4
-
5
- def initialize name = nil, &block
6
- super
7
- if block
8
- forall &block
4
+ def initialize(name = nil, &block)
5
+ super
6
+ forall(&block) if block
9
7
  end
10
- end
11
8
 
12
- def compile context
13
- context.tap { |c| c.ncc_node(self, false) }
9
+ def compile(context)
10
+ context.tap { |c| c.ncc_node(self, false) }
11
+ end
14
12
  end
15
13
  end
16
- end
17
14
  end
@@ -1,24 +1,21 @@
1
1
  module Wongi::Engine
2
2
  module DSL
3
3
  class Query < Rule
4
+ def search_on(*terms)
5
+ terms.each { |term| parameters << term }
6
+ end
4
7
 
5
- def search_on *terms
6
- terms.each { |term| parameters << term }
7
- end
8
-
9
- def import_into model
10
- super.tap { |copy| copy.search_on *parameters }
11
- end
8
+ def import_into(model)
9
+ super.tap { |copy| copy.search_on(*parameters) }
10
+ end
12
11
 
13
- def parameters
14
- @parameters ||= []
15
- end
12
+ def parameters
13
+ @parameters ||= []
14
+ end
16
15
 
17
- def install( rete )
18
- rete.install_query( self )
16
+ def install(rete)
17
+ rete.install_query(self)
18
+ end
19
19
  end
20
-
21
- end
22
-
23
20
  end
24
21
  end
@@ -1,82 +1,77 @@
1
1
  module Wongi::Engine
2
2
  module DSL
3
3
  class Rule
4
+ attr_reader :name
4
5
 
5
- attr_reader :name
6
+ class << self
7
+ def section(s, *aliases)
8
+ return if sections.include?(s)
6
9
 
7
- class << self
8
-
9
- def section s, *aliases
10
- unless sections.include?(s)
11
10
  sections << s
12
11
  define_method s do |&d|
13
12
  @current_section = s
14
13
  section = DSL.sections[s].new
15
14
  section.rule = self
16
- section.instance_eval &d
15
+ section.instance_eval(&d)
17
16
  end
18
17
  aliases.each { |a| alias_method a, s }
19
18
  end
20
- end
21
-
22
- def sections
23
- @sections ||= []
24
- end
25
19
 
26
- end
20
+ def sections
21
+ @sections ||= []
22
+ end
23
+ end
27
24
 
28
- section :forall, :for_all
29
- section :make, :do!
25
+ section :forall, :for_all
26
+ section :make, :do!
30
27
 
31
- def initialize name
32
- @name = name
33
- @current_section = nil
28
+ def initialize(name)
29
+ @name = name
30
+ @current_section = nil
34
31
  Rule.sections.each { |section| acceptors[section] ||= [] }
35
- end
32
+ end
36
33
 
37
- def acceptors
38
- @acceptors ||= {}
39
- end
34
+ def acceptors
35
+ @acceptors ||= {}
36
+ end
40
37
 
41
- def conditions
42
- acceptors[:forall] ||= []
43
- end
38
+ def conditions
39
+ acceptors[:forall] ||= []
40
+ end
44
41
 
45
- def conditions= c
46
- acceptors[:forall] = c
47
- end
42
+ def conditions=(c)
43
+ acceptors[:forall] = c
44
+ end
48
45
 
49
- def actions
50
- acceptors[:make] ||= []
51
- end
46
+ def actions
47
+ acceptors[:make] ||= []
48
+ end
52
49
 
53
- def actions= a
54
- acceptors[:make] = a
55
- end
50
+ def actions=(a)
51
+ acceptors[:make] = a
52
+ end
56
53
 
57
- def import_into rete
58
- self.class.new( @name ).tap do |copy|
59
- copy.conditions = conditions
54
+ def import_into(rete)
55
+ self.class.new(@name).tap do |copy|
56
+ copy.conditions = conditions
60
57
 
61
- copy.actions = actions.map do |action|
62
- if action.respond_to? :import_into
63
- action.import_into(rete)
64
- else
65
- action
58
+ copy.actions = actions.map do |action|
59
+ if action.respond_to? :import_into
60
+ action.import_into(rete)
61
+ else
62
+ action
63
+ end
66
64
  end
67
65
  end
68
66
  end
69
- end
70
67
 
71
- def install( rete )
72
- rete.install_rule( self )
73
- end
68
+ def install(rete)
69
+ rete.install_rule(self)
70
+ end
74
71
 
75
- def accept stuff
76
- acceptors[@current_section] << stuff
72
+ def accept(stuff)
73
+ acceptors[@current_section] << stuff
74
+ end
77
75
  end
78
-
79
-
80
- end
81
76
  end
82
77
  end
@@ -1,43 +1,39 @@
1
1
  module Wongi::Engine
2
2
  module DSL
3
- extend self
4
-
5
- def sections
3
+ module_function def sections
6
4
  @sections ||= {}
7
5
  end
8
6
 
9
- def ruleset name = nil, &definition
7
+ module_function def ruleset(name = nil, &definition)
10
8
  rs = Ruleset.new
11
- if ! name.nil?
12
- rs.name name
13
- end
14
- rs.instance_eval &definition if block_given?
9
+ rs.name name if name
10
+ rs.instance_eval(&definition) if block_given?
15
11
  rs
16
12
  end
17
13
 
18
- def rule name = nil, &definition
14
+ module_function def rule(name = nil, &definition)
19
15
  r = Rule.new name
20
- r.instance_eval &definition
16
+ r.instance_eval(&definition)
21
17
  r
22
18
  end
23
19
 
24
- def query name, &definition
20
+ module_function def query(name, &definition)
25
21
  q = Query.new name
26
- q.instance_eval &definition
22
+ q.instance_eval(&definition)
27
23
  q
28
24
  end
29
25
 
30
- def dsl &definition
31
- Builder.new.build &definition
26
+ module_function def dsl(&definition)
27
+ Builder.new.build(&definition)
32
28
  end
33
29
  end
34
-
35
30
  end
36
31
 
37
32
  require 'wongi-engine/dsl/generated'
38
33
  require 'wongi-engine/dsl/builder'
39
34
  require 'wongi-engine/dsl/clause/generic'
40
35
  require 'wongi-engine/dsl/clause/fact'
36
+ require 'wongi-engine/dsl/clause/aggregate'
41
37
  require 'wongi-engine/dsl/clause/assign'
42
38
  require 'wongi-engine/dsl/clause/gen'
43
39
  require 'wongi-engine/dsl/action/base'
@@ -90,10 +86,28 @@ module Wongi::Engine::DSL
90
86
  clause :gte
91
87
  accept Wongi::Engine::GreaterThanOrEqualTest
92
88
 
89
+ clause :aggregate
90
+ accept Clause::Aggregate
91
+
92
+ clause :least, :min
93
+ body { |s, p, o, opts|
94
+ aggregate s, p, o, on: opts[:on], function: :min, assign: opts[:assign]
95
+ }
96
+
97
+ clause :greatest, :max
98
+ body { |s, p, o, opts|
99
+ aggregate s, p, o, on: opts[:on], function: :max, assign: opts[:assign]
100
+ }
101
+
102
+ clause :count
103
+ body { |s, p, o, opts|
104
+ aggregate s, p, o, map: ->(_) { 1 }, function: -> { _1.inject(&:+) }, assign: opts[:assign]
105
+ }
106
+
93
107
  clause :assert, :dynamic
94
108
  accept Wongi::Engine::AssertingTest
95
109
 
96
- clause :assign, :introduce
110
+ clause :assign, :introduce, :let
97
111
  accept Clause::Assign
98
112
 
99
113
  clause :asserted, :added
@@ -8,13 +8,14 @@ module Wongi::Engine
8
8
  end
9
9
  end
10
10
  end
11
+
11
12
  class DeleteSafeEnumerator
12
13
  def self.new(collection)
13
14
  Enumerator.new do |y|
14
15
  collection.dup.each do |e|
15
16
  y << e unless e.deleted?
16
17
  end
17
- collection.reject! &:deleted?
18
+ collection.reject!(&:deleted?)
18
19
  end
19
20
  end
20
21
  end
@@ -1,22 +1,21 @@
1
1
  module Wongi::Engine
2
-
3
2
  class Error < StandardError
4
-
5
3
  end
6
4
 
7
5
  class DefinitionError < Error
8
-
9
6
  end
10
7
 
11
8
  class ReteError
12
9
  attr_reader :token, :message
13
- def initialize token, message, literate
14
- @token, @message, @literate = token, message, literate
10
+
11
+ def initialize(token, message, literate)
12
+ @token = token
13
+ @message = message
14
+ @literate = literate
15
15
  end
16
+
16
17
  def literate?
17
18
  @literate
18
19
  end
19
20
  end
20
-
21
-
22
21
  end