Skip to content

Commit

Permalink
Added 'unchecked' mode to expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
Knetic committed Nov 5, 2016
1 parent 62e0e29 commit 93f778d
Showing 1 changed file with 44 additions and 21 deletions.
65 changes: 44 additions & 21 deletions EvaluableExpression.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ type EvaluableExpression struct {
*/
QueryDateFormat string

/*
Whether or not to safely check types when evaluating.
If true, this library will return error messages when invalid types are used.
If false, the library will panic when operators encounter types they can't use.
This is exclusively for users who need to squeeze every ounce of speed out of the library as they can,
and you should only set this to false if you know exactly what you're doing.
*/
ChecksTypes bool

tokens []ExpressionToken
evaluationStages *evaluationStage
inputExpression string
Expand Down Expand Up @@ -68,6 +78,7 @@ func NewEvaluableExpressionFromTokens(tokens []ExpressionToken) (*EvaluableExpre
return nil, err
}

ret.ChecksTypes = true
return ret, nil
}

Expand All @@ -89,16 +100,27 @@ func NewEvaluableExpressionWithFunctions(expression string, functions map[string
return nil, err
}

err = checkBalance(ret.tokens)
if err != nil {
return nil, err
}

err = checkExpressionSyntax(ret.tokens)
if err != nil {
return nil, err
}

ret.tokens, err = optimizeTokens(ret.tokens)
if err != nil {
return nil, err
}

ret.evaluationStages, err = planStages(ret.tokens)
if err != nil {
return nil, err
}

ret.ChecksTypes = true
return ret, nil
}

Expand Down Expand Up @@ -133,45 +155,46 @@ func (this EvaluableExpression) Eval(parameters Parameters) (interface{}, error)
if parameters != nil {
parameters = &sanitizedParameters{parameters}
}
return evaluateStage(this.evaluationStages, parameters)
return this.evaluateStage(this.evaluationStages, parameters)
}

func evaluateStage(stage *evaluationStage, parameters Parameters) (interface{}, error) {
func (this EvaluableExpression) evaluateStage(stage *evaluationStage, parameters Parameters) (interface{}, error) {

var left, right interface{}
var err error

if stage.leftStage != nil {
left, err = evaluateStage(stage.leftStage, parameters)
left, err = this.evaluateStage(stage.leftStage, parameters)
if err != nil {
return nil, err
}
}

if stage.rightStage != nil {
right, err = evaluateStage(stage.rightStage, parameters)
right, err = this.evaluateStage(stage.rightStage, parameters)
if err != nil {
return nil, err
}
}

// type checks
if stage.typeCheck == nil {

err = typeCheck(stage.leftTypeCheck, left, stage.symbol, stage.typeErrorFormat)
if err != nil {
return nil, err
}

err = typeCheck(stage.rightTypeCheck, right, stage.symbol, stage.typeErrorFormat)
if err != nil {
return nil, err
}
} else {
// special case where the type check needs to know both sides to determine if the operator can handle it
if !stage.typeCheck(left, right) {
errorMsg := fmt.Sprintf(stage.typeErrorFormat, left, stage.symbol.String())
return nil, errors.New(errorMsg)
if this.ChecksTypes {
if stage.typeCheck == nil {

err = typeCheck(stage.leftTypeCheck, left, stage.symbol, stage.typeErrorFormat)
if err != nil {
return nil, err
}

err = typeCheck(stage.rightTypeCheck, right, stage.symbol, stage.typeErrorFormat)
if err != nil {
return nil, err
}
} else {
// special case where the type check needs to know both sides to determine if the operator can handle it
if !stage.typeCheck(left, right) {
errorMsg := fmt.Sprintf(stage.typeErrorFormat, left, stage.symbol.String())
return nil, errors.New(errorMsg)
}
}
}

Expand Down

0 comments on commit 93f778d

Please sign in to comment.