-
-
Notifications
You must be signed in to change notification settings - Fork 63
Expand file tree
/
Copy pathrule_compiler.rb
More file actions
88 lines (70 loc) · 1.81 KB
/
Copy pathrule_compiler.rb
File metadata and controls
88 lines (70 loc) · 1.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
require 'dry/core/constants'
require 'dry/logic/rule'
module Dry
module Logic
class RuleCompiler
include Core::Constants
attr_reader :predicates
def initialize(predicates)
@predicates = predicates
end
def call(ast)
ast.map { |node| visit(node) }
end
def visit(node)
name, nodes = node
send(:"visit_#{name}", nodes)
end
def visit_check(node)
keys, predicate = node
Operations::Check.new(visit(predicate), keys: keys)
end
def visit_not(node)
Operations::Negation.new(visit(node))
end
def visit_key(node)
name, predicate = node
Operations::Key.new(visit(predicate), name: name)
end
def visit_attr(node)
name, predicate = node
Operations::Attr.new(visit(predicate), name: name)
end
def visit_part(node)
Operations::Part.new(*call(node))
end
def visit_set(node)
Operations::Set.new(*call(node))
end
def visit_each(node)
Operations::Each.new(visit(node))
end
def visit_predicate(node)
name, params = node
predicate = Rule::Predicate.new(predicates[name])
if params.size > 1
args = params.map(&:last).reject { |val| val == Undefined }
predicate.curry(*args)
else
predicate
end
end
def visit_and(node)
left, right = node
visit(left).and(visit(right))
end
def visit_or(node)
left, right = node
visit(left).or(visit(right))
end
def visit_xor(node)
left, right = node
visit(left).xor(visit(right))
end
def visit_implication(node)
left, right = node
visit(left).then(visit(right))
end
end
end
end