wongi-engine 0.3.6 → 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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +80 -0
- data/.travis.yml +6 -16
- data/Gemfile +4 -0
- data/README.md +3 -3
- data/Rakefile +1 -2
- data/examples/ex01.rb +1 -1
- data/examples/ex02.rb +3 -7
- data/examples/graphviz.rb +1 -1
- data/examples/rdf.rb +1 -1
- data/examples/timeline.rb +6 -6
- data/lib/wongi-engine/alpha_memory.rb +5 -9
- data/lib/wongi-engine/beta/aggregate_node.rb +93 -0
- data/lib/wongi-engine/beta/assignment_node.rb +10 -18
- data/lib/wongi-engine/beta/beta_memory.rb +20 -9
- data/lib/wongi-engine/beta/beta_node.rb +14 -22
- data/lib/wongi-engine/beta/filter_node.rb +12 -15
- data/lib/wongi-engine/beta/join_node.rb +47 -61
- data/lib/wongi-engine/beta/ncc_node.rb +17 -20
- data/lib/wongi-engine/beta/ncc_partner.rb +17 -17
- data/lib/wongi-engine/beta/neg_node.rb +37 -37
- data/lib/wongi-engine/beta/optional_node.rb +53 -60
- data/lib/wongi-engine/beta/or_node.rb +6 -9
- data/lib/wongi-engine/beta/production_node.rb +6 -9
- data/lib/wongi-engine/beta.rb +1 -0
- data/lib/wongi-engine/compiler.rb +38 -22
- data/lib/wongi-engine/core_ext.rb +11 -20
- data/lib/wongi-engine/data_overlay.rb +23 -26
- data/lib/wongi-engine/dsl/action/assign_action.rb +1 -1
- data/lib/wongi-engine/dsl/action/base.rb +1 -4
- data/lib/wongi-engine/dsl/action/error_generator.rb +9 -9
- data/lib/wongi-engine/dsl/action/simple_action.rb +14 -10
- data/lib/wongi-engine/dsl/action/simple_collector.rb +10 -25
- data/lib/wongi-engine/dsl/action/statement_generator.rb +15 -14
- data/lib/wongi-engine/dsl/action/trace_action.rb +9 -9
- data/lib/wongi-engine/dsl/any_rule.rb +16 -20
- data/lib/wongi-engine/dsl/assuming.rb +8 -15
- data/lib/wongi-engine/dsl/builder.rb +13 -12
- data/lib/wongi-engine/dsl/clause/aggregate.rb +21 -0
- data/lib/wongi-engine/dsl/clause/assign.rb +4 -4
- data/lib/wongi-engine/dsl/clause/fact.rb +10 -6
- data/lib/wongi-engine/dsl/clause/gen.rb +3 -5
- data/lib/wongi-engine/dsl/clause/generic.rb +7 -9
- data/lib/wongi-engine/dsl/generated.rb +6 -12
- data/lib/wongi-engine/dsl/ncc_subrule.rb +6 -9
- data/lib/wongi-engine/dsl/query.rb +12 -15
- data/lib/wongi-engine/dsl/rule.rb +45 -50
- data/lib/wongi-engine/dsl.rb +30 -16
- data/lib/wongi-engine/enumerators.rb +2 -1
- data/lib/wongi-engine/error.rb +6 -7
- data/lib/wongi-engine/filter/asserting_test.rb +4 -7
- data/lib/wongi-engine/filter/equality_test.rb +15 -18
- data/lib/wongi-engine/filter/filter_test.rb +3 -6
- data/lib/wongi-engine/filter/greater_than_or_equal_test.rb +5 -2
- data/lib/wongi-engine/filter/greater_than_test.rb +15 -18
- data/lib/wongi-engine/filter/inequality_test.rb +15 -18
- data/lib/wongi-engine/filter/less_than_or_equal_test.rb +5 -2
- data/lib/wongi-engine/filter/less_than_test.rb +15 -18
- data/lib/wongi-engine/filter.rb +1 -1
- data/lib/wongi-engine/graph.rb +13 -20
- data/lib/wongi-engine/network/collectable.rb +10 -14
- data/lib/wongi-engine/network/debug.rb +16 -24
- data/lib/wongi-engine/network.rb +110 -129
- data/lib/wongi-engine/ruleset.rb +18 -20
- data/lib/wongi-engine/template.rb +31 -30
- data/lib/wongi-engine/token.rb +33 -33
- data/lib/wongi-engine/version.rb +1 -1
- data/lib/wongi-engine/wme.rb +17 -23
- data/lib/wongi-engine/wme_match_data.rb +5 -9
- data/lib/wongi-engine.rb +0 -4
- data/spec/action_class_spec.rb +43 -49
- data/spec/beta_node_spec.rb +2 -8
- data/spec/bug_specs/issue_4_spec.rb +12 -20
- data/spec/dataset_spec.rb +3 -6
- data/spec/filter_specs/assert_test_spec.rb +12 -31
- data/spec/filter_specs/greater_than_equality_test_spec.rb +2 -5
- data/spec/filter_specs/less_test_spec.rb +7 -17
- data/spec/filter_specs/less_than_equality_test_spec.rb +3 -6
- data/spec/generation_spec.rb +45 -54
- data/spec/high_level_spec.rb +95 -141
- data/spec/network_spec.rb +77 -68
- data/spec/overlay_spec.rb +4 -5
- data/spec/rule_specs/aggregate_spec.rb +197 -0
- data/spec/rule_specs/any_rule_spec.rb +4 -19
- data/spec/rule_specs/assign_spec.rb +10 -16
- data/spec/rule_specs/assuming_spec.rb +10 -17
- data/spec/rule_specs/maybe_rule_spec.rb +4 -15
- data/spec/rule_specs/ncc_spec.rb +48 -65
- data/spec/rule_specs/negative_rule_spec.rb +13 -27
- data/spec/rule_specs/or_rule_spec.rb +3 -13
- data/spec/ruleset_spec.rb +11 -17
- data/spec/simple_action_spec.rb +4 -14
- data/spec/wme_spec.rb +14 -21
- data/wongi-engine.gemspec +22 -22
- metadata +16 -37
- data/.hgignore +0 -7
- 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
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
def option(&block)
|
12
|
+
var = VariantRule.new
|
13
|
+
var.forall(&block)
|
14
|
+
variants << var
|
15
|
+
end
|
19
16
|
|
20
|
-
|
21
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
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
|
5
|
-
|
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
|
11
|
+
def initialize(base_rule_name)
|
18
12
|
@base_rule_name = base_rule_name
|
19
13
|
end
|
20
14
|
|
21
|
-
def compile
|
15
|
+
def compile(context)
|
22
16
|
base_production = context.rete.productions[base_rule_name]
|
23
|
-
raise UndefinedBaseRule
|
24
|
-
raise DefinitionError
|
25
|
-
raise StandardError
|
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
|
11
|
-
instance_eval
|
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
|
18
|
+
|
19
|
+
def section(s)
|
21
20
|
@current_section = s
|
22
21
|
end
|
23
|
-
|
24
|
-
def clause
|
22
|
+
|
23
|
+
def clause(*c)
|
25
24
|
@current_clause = c
|
26
25
|
end
|
27
|
-
|
28
|
-
def action
|
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
|
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
|
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
|
-
|
6
|
-
@
|
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
|
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
|
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 = [
|
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
|
-
|
51
|
+
|
52
|
+
def compile(context)
|
51
53
|
tests, assignment = parse_variables(context)
|
52
|
-
raise DefinitionError
|
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
|
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
|
-
|
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
|
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
|
6
|
+
def initialize(*args, &block)
|
8
7
|
@args = args
|
9
8
|
@block = block
|
10
9
|
end
|
11
10
|
|
12
|
-
def import_into
|
11
|
+
def import_into(rete)
|
13
12
|
if action.respond_to? :call
|
14
13
|
self
|
15
14
|
else
|
16
|
-
action.new(
|
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
|
29
|
-
action.call
|
27
|
+
def compile(*args)
|
28
|
+
action.call(*args)
|
30
29
|
end
|
31
30
|
|
32
|
-
def execute
|
33
|
-
action.call
|
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
|
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
|
13
|
+
instance_exec(*args, &body)
|
17
14
|
|
18
15
|
elsif acceptor
|
19
16
|
|
20
|
-
rule.accept acceptor.new(
|
17
|
+
rule.accept acceptor.new(*args, &block)
|
21
18
|
|
22
19
|
elsif action
|
23
20
|
|
24
|
-
c = Clause::Generic.new
|
21
|
+
c = Clause::Generic.new(*args, &block)
|
25
22
|
c.name = clause.first
|
26
23
|
c.action = action
|
27
|
-
c.rule =
|
24
|
+
c.rule = rule
|
28
25
|
rule.accept c
|
29
26
|
|
30
27
|
end
|
31
|
-
|
32
28
|
end
|
33
29
|
|
34
|
-
clause[1
|
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
|
-
|
6
|
-
|
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
|
-
|
13
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
12
|
+
def parameters
|
13
|
+
@parameters ||= []
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
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
|
-
|
20
|
+
def sections
|
21
|
+
@sections ||= []
|
22
|
+
end
|
23
|
+
end
|
27
24
|
|
28
|
-
|
29
|
-
|
25
|
+
section :forall, :for_all
|
26
|
+
section :make, :do!
|
30
27
|
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
def initialize(name)
|
29
|
+
@name = name
|
30
|
+
@current_section = nil
|
34
31
|
Rule.sections.each { |section| acceptors[section] ||= [] }
|
35
|
-
|
32
|
+
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
def acceptors
|
35
|
+
@acceptors ||= {}
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
def conditions
|
39
|
+
acceptors[:forall] ||= []
|
40
|
+
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
def conditions=(c)
|
43
|
+
acceptors[:forall] = c
|
44
|
+
end
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
def actions
|
47
|
+
acceptors[:make] ||= []
|
48
|
+
end
|
52
49
|
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
def actions=(a)
|
51
|
+
acceptors[:make] = a
|
52
|
+
end
|
56
53
|
|
57
|
-
|
58
|
-
|
59
|
-
|
54
|
+
def import_into(rete)
|
55
|
+
self.class.new(@name).tap do |copy|
|
56
|
+
copy.conditions = conditions
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
68
|
+
def install(rete)
|
69
|
+
rete.install_rule(self)
|
70
|
+
end
|
74
71
|
|
75
|
-
|
76
|
-
|
72
|
+
def accept(stuff)
|
73
|
+
acceptors[@current_section] << stuff
|
74
|
+
end
|
77
75
|
end
|
78
|
-
|
79
|
-
|
80
|
-
end
|
81
76
|
end
|
82
77
|
end
|
data/lib/wongi-engine/dsl.rb
CHANGED
@@ -1,43 +1,39 @@
|
|
1
1
|
module Wongi::Engine
|
2
2
|
module DSL
|
3
|
-
|
4
|
-
|
5
|
-
def sections
|
3
|
+
module_function def sections
|
6
4
|
@sections ||= {}
|
7
5
|
end
|
8
6
|
|
9
|
-
def ruleset
|
7
|
+
module_function def ruleset(name = nil, &definition)
|
10
8
|
rs = Ruleset.new
|
11
|
-
if
|
12
|
-
|
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
|
14
|
+
module_function def rule(name = nil, &definition)
|
19
15
|
r = Rule.new name
|
20
|
-
r.instance_eval
|
16
|
+
r.instance_eval(&definition)
|
21
17
|
r
|
22
18
|
end
|
23
19
|
|
24
|
-
def query
|
20
|
+
module_function def query(name, &definition)
|
25
21
|
q = Query.new name
|
26
|
-
q.instance_eval
|
22
|
+
q.instance_eval(&definition)
|
27
23
|
q
|
28
24
|
end
|
29
25
|
|
30
|
-
def dsl
|
31
|
-
Builder.new.build
|
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!
|
18
|
+
collection.reject!(&:deleted?)
|
18
19
|
end
|
19
20
|
end
|
20
21
|
end
|
data/lib/wongi-engine/error.rb
CHANGED
@@ -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
|
-
|
14
|
-
|
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
|