Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func parseExpr(expr string) (*Expr, error) {
return nil, err
}
sortPriority(e)
_, p.expr = e.Optimize()
return p, nil
}
func (p *Expr) parseExprNode(expr *string, e ExprNode) error {
Expand Down Expand Up @@ -262,6 +263,7 @@ type ExprNode interface {
SetRightOperand(ExprNode)
String() string
Run(context.Context, string, *TagExpr) interface{}
Optimize() (bool, ExprNode)
}

// var _ ExprNode = new(exprBackground)
Expand Down
12 changes: 12 additions & 0 deletions spec_func.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ func (f *funcExprNode) Run(ctx context.Context, currField string, tagExpr *TagEx
return realValue(f.fn(args...), f.boolOpposite, f.signOpposite)
}

func (f *funcExprNode) Optimize() (bool, ExprNode) {
return false, f
}

// --------------------------- Built-in function ---------------------------
func init() {
funcList["regexp"] = readRegexpFuncExprNode
Expand Down Expand Up @@ -282,6 +286,10 @@ func (re *regexpFuncExprNode) Run(ctx context.Context, currField string, tagExpr
return false
}

func (re *regexpFuncExprNode) Optimize() (bool, ExprNode) {
return false, re
}

type sprintfFuncExprNode struct {
exprBackground
format string
Expand Down Expand Up @@ -342,3 +350,7 @@ func (se *sprintfFuncExprNode) Run(ctx context.Context, currField string, tagExp
}
return fmt.Sprintf(se.format, args...)
}

func (se *sprintfFuncExprNode) Optimize() (bool, ExprNode) {
return false, se
}
33 changes: 33 additions & 0 deletions spec_operand.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,19 @@ func (ge *groupExprNode) Run(ctx context.Context, currField string, tagExpr *Tag
return realValue(ge.rightOperand.Run(ctx, currField, tagExpr), ge.boolOpposite, ge.signOpposite)
}

func (ge *groupExprNode) Optimize() (bool, ExprNode) {
if ge.rightOperand == nil {
return true, &nilExprNode{val: nil}
}

optimize, node := ge.rightOperand.Optimize()
if optimize {
ge.rightOperand = node
}

return false, ge
}

type boolExprNode struct {
exprBackground
val bool
Expand Down Expand Up @@ -91,6 +104,10 @@ func (be *boolExprNode) Run(ctx context.Context, currField string, tagExpr *TagE
return be.val
}

func (be *boolExprNode) Optimize() (bool, ExprNode) {
return false, be
}

type stringExprNode struct {
exprBackground
val interface{}
Expand All @@ -115,6 +132,10 @@ func (se *stringExprNode) Run(ctx context.Context, currField string, tagExpr *Ta
return se.val
}

func (se *stringExprNode) Optimize() (bool, ExprNode) {
return false, se
}

type digitalExprNode struct {
exprBackground
val interface{}
Expand Down Expand Up @@ -144,6 +165,10 @@ func (de *digitalExprNode) Run(ctx context.Context, currField string, tagExpr *T
return de.val
}

func (de *digitalExprNode) Optimize() (bool, ExprNode) {
return true, de
}

type nilExprNode struct {
exprBackground
val interface{}
Expand All @@ -153,6 +178,10 @@ func (ne *nilExprNode) String() string {
return "<nil>"
}

func (ne *nilExprNode) Optimize() (bool, ExprNode) {
return false, ne
}

var nilRegexp = regexp.MustCompile(`^nil([\)\],\|&!= \t]{1}|$)`)

func readNilExprNode(expr *string) ExprNode {
Expand Down Expand Up @@ -197,6 +226,10 @@ func (ve *variableExprNode) Run(ctx context.Context, variableName string, _ *Tag
}
}

func (ve *variableExprNode) Optimize() (bool, ExprNode) {
return false, ve
}

var variableRegex = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*`)

func readVariableExprNode(expr *string) ExprNode {
Expand Down
144 changes: 144 additions & 0 deletions spec_operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,40 @@ func (ae *additionExprNode) Run(ctx context.Context, currField string, tagExpr *
return v0
}


func (ae *additionExprNode) Optimize() (bool, ExprNode) {
lsucc, newLeft := ae.leftOperand.Optimize()
if lsucc {
ae.leftOperand = newLeft
}

rSucc, newRight := ae.rightOperand.Optimize()
if rSucc {
ae.rightOperand = newRight
}

if lsucc && rSucc {
if _, ok := ae.leftOperand.(*selectorExprNode); !ok { // note
if _, iok := ae.rightOperand.(*selectorExprNode); !iok {
v0 := ae.leftOperand.Run(context.Background(), "", nil)
v1 := ae.rightOperand.Run(context.Background(), "", nil)

if s0, ok := toFloat64(v0, false); ok {
s1, _ := toFloat64(v1, true)
return true, &digitalExprNode{val: s0 + s1}
}
if s0, ok := toString(v0, false); ok {
s1, _ := toString(v1, true)
return true, &digitalExprNode{val: s0 + s1}
}
return true, &digitalExprNode{val: v0}
}
}
}

return false, ae
}

type multiplicationExprNode struct{ exprBackground }

func (ae *multiplicationExprNode) String() string {
Expand All @@ -58,6 +92,31 @@ func (ae *multiplicationExprNode) Run(ctx context.Context, currField string, tag
return v0 * v1
}


func (ae *multiplicationExprNode) Optimize() (bool, ExprNode) {
lsucc, newLeft := ae.leftOperand.Optimize()
if lsucc {
ae.leftOperand = newLeft
}

rSucc, newRight := ae.rightOperand.Optimize()
if rSucc {
ae.rightOperand = newRight
}

if lsucc && rSucc {
v1, _ := toFloat64(ae.rightOperand.Run(context.Background(), "", nil), true)
if v1 == 0 {
return true, &digitalExprNode{val: math.NaN()}
}
v0, _ := toFloat64(ae.leftOperand.Run(context.Background(), "", nil), true)
return true, &digitalExprNode{val: v0 * v1}
}

return false, ae
}


type divisionExprNode struct{ exprBackground }

func (de *divisionExprNode) String() string {
Expand All @@ -75,6 +134,30 @@ func (de *divisionExprNode) Run(ctx context.Context, currField string, tagExpr *
return v0 / v1
}


func (de *divisionExprNode) Optimize() (bool, ExprNode) {
lsucc, newLeft := de.leftOperand.Optimize()
if lsucc {
de.leftOperand = newLeft
}

rSucc, newRight := de.rightOperand.Optimize()
if rSucc {
de.rightOperand = newRight
}

if lsucc && rSucc {
v1, _ := toFloat64(de.rightOperand.Run(context.Background(), "", nil), true)
if v1 == 0 {
return true, &digitalExprNode{val: math.NaN()}
}
v0, _ := toFloat64(de.leftOperand.Run(context.Background(), "", nil), true)
return true, &digitalExprNode{val: v0 / v1}
}

return false, de
}

type subtractionExprNode struct{ exprBackground }

func (de *subtractionExprNode) String() string {
Expand All @@ -89,6 +172,31 @@ func (de *subtractionExprNode) Run(ctx context.Context, currField string, tagExp
return v0 - v1
}


func (de *subtractionExprNode) Optimize() (bool, ExprNode) {
lsucc, newLeft := de.leftOperand.Optimize()
if lsucc {
de.leftOperand = newLeft
}

rSucc, newRight := de.rightOperand.Optimize()
if rSucc {
de.rightOperand = newRight
}

if lsucc && rSucc {
if _, ok := de.leftOperand.(*selectorExprNode); !ok {
if _, iok := de.rightOperand.(*selectorExprNode); !iok {
v0, _ := toFloat64(de.leftOperand.Run(context.Background(), "", nil), true)
v1, _ := toFloat64(de.rightOperand.Run(context.Background(), "", nil), true)
return true, &digitalExprNode{val: v0 - v1}
}
}
}

return false, de
}

type remainderExprNode struct{ exprBackground }

func (re *remainderExprNode) String() string {
Expand All @@ -106,6 +214,10 @@ func (re *remainderExprNode) Run(ctx context.Context, currField string, tagExpr
return float64(int64(v0) % int64(v1))
}

func (re *remainderExprNode) Optimize() (bool, ExprNode) {
return false, re
}

type equalExprNode struct{ exprBackground }

func (ee *equalExprNode) String() string {
Expand Down Expand Up @@ -143,6 +255,10 @@ func (ee *equalExprNode) Run(ctx context.Context, currField string, tagExpr *Tag
return false
}

func (ee *equalExprNode) Optimize() (bool, ExprNode) {
return false, ee
}

type notEqualExprNode struct{ equalExprNode }

func (ne *notEqualExprNode) String() string {
Expand All @@ -155,6 +271,10 @@ func (ne *notEqualExprNode) Run(ctx context.Context, currField string, tagExpr *
return !ne.equalExprNode.Run(ctx, currField, tagExpr).(bool)
}

func (ne *notEqualExprNode) Optimize() (bool, ExprNode) {
return false, ne
}

type greaterExprNode struct{ exprBackground }

func (ge *greaterExprNode) String() string {
Expand All @@ -180,6 +300,10 @@ func (ge *greaterExprNode) Run(ctx context.Context, currField string, tagExpr *T
return false
}

func (ge *greaterExprNode) Optimize() (bool, ExprNode) {
return false, ge
}

type greaterEqualExprNode struct{ exprBackground }

func (ge *greaterEqualExprNode) String() string {
Expand All @@ -205,6 +329,10 @@ func (ge *greaterEqualExprNode) Run(ctx context.Context, currField string, tagEx
return false
}

func (ge *greaterEqualExprNode) Optimize() (bool, ExprNode) {
return false, ge
}

type lessExprNode struct{ exprBackground }

func (le *lessExprNode) String() string {
Expand All @@ -230,6 +358,10 @@ func (le *lessExprNode) Run(ctx context.Context, currField string, tagExpr *TagE
return false
}

func (le *lessExprNode) Optimize() (bool, ExprNode) {
return false, le
}

type lessEqualExprNode struct{ exprBackground }

func (le *lessEqualExprNode) String() string {
Expand All @@ -255,6 +387,10 @@ func (le *lessEqualExprNode) Run(ctx context.Context, currField string, tagExpr
return false
}

func (le *lessEqualExprNode) Optimize() (bool, ExprNode) {
return false, le
}

type andExprNode struct{ exprBackground }

func (ae *andExprNode) String() string {
Expand All @@ -272,6 +408,10 @@ func (ae *andExprNode) Run(ctx context.Context, currField string, tagExpr *TagEx
return true
}

func (ae *andExprNode) Optimize() (bool, ExprNode) {
return false, ae
}

type orExprNode struct{ exprBackground }

func (oe *orExprNode) String() string {
Expand All @@ -288,3 +428,7 @@ func (oe *orExprNode) Run(ctx context.Context, currField string, tagExpr *TagExp
}
return false
}

func (oe *orExprNode) Optimize() (bool, ExprNode) {
return false, oe
}
8 changes: 8 additions & 0 deletions spec_range.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ func (re *rangeKvExprNode) Run(ctx context.Context, _ string, _ *TagExpr) interf
return realValue(v, re.boolOpposite, re.signOpposite)
}

func (re *rangeKvExprNode) Optimize() (bool, ExprNode) {
return false, re
}

type rangeFuncExprNode struct {
exprBackground
object ExprNode
Expand Down Expand Up @@ -148,3 +152,7 @@ func (e *rangeFuncExprNode) Run(ctx context.Context, currField string, tagExpr *
}
return r
}

func (re *rangeFuncExprNode) Optimize() (bool, ExprNode) {
return false, re
}
4 changes: 4 additions & 0 deletions spec_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,7 @@ func (se *selectorExprNode) Run(ctx context.Context, currField string, tagExpr *
v := tagExpr.getValue(field, subFields)
return realValue(v, se.boolOpposite, se.signOpposite)
}

func (se *selectorExprNode) Optimize() (bool, ExprNode) {
return false, se
}