-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheval.go
More file actions
81 lines (65 loc) · 1.21 KB
/
eval.go
File metadata and controls
81 lines (65 loc) · 1.21 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
package boolal
type EvalOption struct {
FallbackValue bool
}
type EvalOptionModifier func(o *EvalOption)
func WithOption(opt EvalOption) EvalOptionModifier {
return func(o *EvalOption) { *o = opt }
}
func WithFallbackAs(v bool) EvalOptionModifier {
return func(o *EvalOption) { o.FallbackValue = v }
}
func eval(data map[string]bool, op UnaryOp, opt EvalOption) bool {
neg := op.Name != ""
if op.Al != nil {
return neg != op.Al.Eval(data, WithOption(opt))
}
var v, ok bool
switch op.Var {
case truth:
v = true
case falsity:
v = false
default:
if v, ok = data[op.Var]; !ok {
v = opt.FallbackValue
}
}
return neg != v
}
func (e *Expr) Eval(data map[string]bool, modifiers ...EvalOptionModifier) bool {
opt := EvalOption{
FallbackValue: false,
}
for _, m := range modifiers {
m(&opt)
}
rst := eval(data, e.Lhs, opt)
for _, next := range e.Rhs {
var (
ops []UnaryOp = nil
neg bool
)
if len(next.And) > 0 {
neg = true
ops = next.And
} else {
neg = false
ops = next.Or
}
if len(ops) == 0 {
continue
}
if neg != rst {
rst = !neg
continue
}
for _, v := range ops {
if neg != eval(data, v, opt) {
rst = !neg
break
}
}
}
return rst
}