mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-12 18:51:02 +08:00
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
package optimizer
|
|
|
|
import (
|
|
. "github.com/expr-lang/expr/ast"
|
|
"github.com/expr-lang/expr/parser/operator"
|
|
)
|
|
|
|
/*
|
|
predicateCombination is a visitor that combines multiple predicate calls into a single call.
|
|
For example, the following expression:
|
|
|
|
all(x, x > 1) && all(x, x < 10) -> all(x, x > 1 && x < 10)
|
|
any(x, x > 1) || any(x, x < 10) -> any(x, x > 1 || x < 10)
|
|
none(x, x > 1) && none(x, x < 10) -> none(x, x > 1 || x < 10)
|
|
*/
|
|
type predicateCombination struct{}
|
|
|
|
func (v *predicateCombination) Visit(node *Node) {
|
|
if op, ok := (*node).(*BinaryNode); ok && operator.IsBoolean(op.Operator) {
|
|
if left, ok := op.Left.(*BuiltinNode); ok {
|
|
if combinedOp, ok := combinedOperator(left.Name, op.Operator); ok {
|
|
if right, ok := op.Right.(*BuiltinNode); ok && right.Name == left.Name {
|
|
if left.Arguments[0].Type() == right.Arguments[0].Type() && left.Arguments[0].String() == right.Arguments[0].String() {
|
|
predicate := &PredicateNode{
|
|
Node: &BinaryNode{
|
|
Operator: combinedOp,
|
|
Left: left.Arguments[1].(*PredicateNode).Node,
|
|
Right: right.Arguments[1].(*PredicateNode).Node,
|
|
},
|
|
}
|
|
v.Visit(&predicate.Node)
|
|
patchCopyType(node, &BuiltinNode{
|
|
Name: left.Name,
|
|
Arguments: []Node{
|
|
left.Arguments[0],
|
|
predicate,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func combinedOperator(fn, op string) (string, bool) {
|
|
switch {
|
|
case fn == "all" && (op == "and" || op == "&&"):
|
|
return op, true
|
|
case fn == "any" && (op == "or" || op == "||"):
|
|
return op, true
|
|
case fn == "none" && (op == "and" || op == "&&"):
|
|
switch op {
|
|
case "and":
|
|
return "or", true
|
|
case "&&":
|
|
return "||", true
|
|
}
|
|
}
|
|
return "", false
|
|
}
|