2017-06-26 15:33:07 +02:00
|
|
|
package expressions
|
2017-06-26 14:23:50 +02:00
|
|
|
|
2017-06-26 15:06:55 +02:00
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
)
|
2017-06-26 14:23:50 +02:00
|
|
|
|
2017-06-26 15:33:07 +02:00
|
|
|
type Context struct {
|
|
|
|
Variables map[string]interface{}
|
|
|
|
}
|
|
|
|
|
2017-06-26 14:23:50 +02:00
|
|
|
type Expression struct {
|
|
|
|
value func(Context) (interface{}, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func EvaluateExpr(expr string, ctx Context) (interface{}, error) {
|
|
|
|
lexer := newLexer([]byte(expr + ";"))
|
|
|
|
n := yyParse(lexer)
|
|
|
|
if n != 0 {
|
|
|
|
return nil, fmt.Errorf("parse error in %s", expr)
|
|
|
|
}
|
|
|
|
return lexer.val(ctx), nil
|
|
|
|
}
|
2017-06-26 15:06:55 +02:00
|
|
|
|
|
|
|
func GenericCompare(a, b reflect.Value) int {
|
|
|
|
if a.Interface() == b.Interface() {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
ak, bk := a.Kind(), b.Kind()
|
|
|
|
// _ = ak.Convert
|
|
|
|
switch a.Kind() {
|
|
|
|
case reflect.Bool:
|
|
|
|
if b.Kind() == reflect.Bool {
|
|
|
|
switch {
|
|
|
|
case a.Bool() && b.Bool():
|
|
|
|
return 0
|
|
|
|
case a.Bool():
|
|
|
|
return 1
|
|
|
|
case b.Bool():
|
|
|
|
return -1
|
|
|
|
default:
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
if hasIntKind(b) {
|
|
|
|
if a.Int() < b.Int() {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
if a.Int() > b.Int() {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
if hasFloatKind(b) {
|
|
|
|
return GenericCompare(reflect.ValueOf(float64(a.Int())), b)
|
|
|
|
}
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
if hasIntKind(b) {
|
|
|
|
b = reflect.ValueOf(float64(b.Int()))
|
|
|
|
}
|
|
|
|
if hasFloatKind(b) {
|
|
|
|
if a.Float() < b.Float() {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
if a.Float() > b.Float() {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("unimplemented: comparison of %v<%s> with %v<%s>", a, ak, b, bk))
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func hasIntKind(n reflect.Value) bool {
|
|
|
|
switch n.Kind() {
|
|
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func hasFloatKind(n reflect.Value) bool {
|
|
|
|
switch n.Kind() {
|
|
|
|
case reflect.Float32, reflect.Float64:
|
|
|
|
return true
|
|
|
|
default:
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|