func EvaluateUnaryExpr(expr *ast.UnaryExpr, context *Context) ast.Value { var val ast.Value = nil switch t := expr.Expr.(type) { case *ast.BinaryExpr: val = EvaluateBinaryExpr(t, context) case *ast.UnaryExpr: val = EvaluateUnaryExpr(t, context) case *ast.Variable: if varVal, ok := context.GetVariable(t.Name); ok { val = varVal.(ast.Expr) } default: val = ast.Value(t) } switch expr.Op.Type { case ast.T_NOP: // do nothing case ast.T_LOGICAL_NOT: if bVal, ok := val.(ast.BooleanValue); ok { val = ast.NewBoolean(bVal.Boolean()) } case ast.T_MINUS: switch n := val.(type) { case *ast.Number: n.Value = -n.Value } } return val }
func EvaluateExprInBooleanContext(anyexpr ast.Expr, context *Context) ast.Value { switch expr := anyexpr.(type) { case *ast.BinaryExpr: return EvaluateBinaryExprInBooleanContext(expr, context) case *ast.UnaryExpr: return EvaluateUnaryExprInBooleanContext(expr, context) default: if bval, ok := expr.(ast.BooleanValue); ok { return ast.NewBoolean(bval.Boolean()) } } return nil }
func EvaluateUnaryExprInBooleanContext(expr *ast.UnaryExpr, context *Context) ast.Value { var val ast.Value = nil switch t := expr.Expr.(type) { case *ast.BinaryExpr: val = EvaluateBinaryExpr(t, context) case *ast.UnaryExpr: val = EvaluateUnaryExpr(t, context) default: val = ast.Value(t) } switch expr.Op.Type { case ast.T_LOGICAL_NOT: if bval, ok := val.(ast.BooleanValue); ok { return ast.NewBoolean(bval.Boolean()) } else { panic(fmt.Errorf("BooleanValue interface is not support for %+v", val)) } } return val }
func Compute(op *ast.Op, a ast.Value, b ast.Value) ast.Value { if op == nil { panic("op can't be nil") } switch op.Type { case ast.T_EQUAL: switch ta := a.(type) { case *ast.Boolean: switch tb := b.(type) { case *ast.Boolean: return ast.NewBoolean(ta.Value == tb.Value) } case *ast.Number: switch tb := b.(type) { case *ast.Number: if IsComparable(ta, tb) { return ast.NewBoolean(ta.Value == tb.Value) } else { panic("Can't compare number (unit different)") } } } case ast.T_UNEQUAL: switch ta := a.(type) { case *ast.Boolean: switch tb := b.(type) { case *ast.Boolean: return ast.NewBoolean(ta.Value != tb.Value) } case *ast.Number: switch tb := b.(type) { case *ast.Number: if IsComparable(ta, tb) { return ast.NewBoolean(ta.Value != tb.Value) } else { panic("Can't compare number (unit different)") } } } case ast.T_GT: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: if IsComparable(ta, tb) { return ast.NewBoolean(ta.Value > tb.Value) } else { panic("Can't compare number (unit different)") } } } case ast.T_GE: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: if IsComparable(ta, tb) { return ast.NewBoolean(ta.Value >= tb.Value) } else { panic("Can't compare number (unit different)") } } } case ast.T_LT: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: if IsComparable(ta, tb) { return ast.NewBoolean(ta.Value < tb.Value) } else { panic("Can't compare number (unit different)") } } } case ast.T_LE: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: if IsComparable(ta, tb) { return ast.NewBoolean(ta.Value <= tb.Value) } else { panic("Can't compare number (unit different)") } } } case ast.T_LOGICAL_AND: switch ta := a.(type) { case *ast.Boolean: switch tb := b.(type) { case *ast.Boolean: return ast.NewBoolean(ta.Value && tb.Value) // For other data type, we cast to boolean default: if bv, ok := b.(ast.BooleanValue); ok { return ast.NewBoolean(bv.Boolean()) } } } case ast.T_LOGICAL_OR: switch ta := a.(type) { case *ast.Boolean: switch tb := b.(type) { case *ast.Boolean: return ast.NewBoolean(ta.Value || tb.Value) // For other data type, we cast to boolean default: if bv, ok := b.(ast.BooleanValue); ok { return ast.NewBoolean(bv.Boolean()) } } } /* arith expr */ case ast.T_PLUS: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: return NumberAddNumber(ta, tb) case *ast.HexColor: return HexColorAddNumber(tb, ta) } case *ast.HexColor: switch tb := b.(type) { case *ast.Number: return HexColorAddNumber(ta, tb) } case *ast.RGBColor: switch tb := b.(type) { case *ast.Number: return RGBColorAddNumber(ta, tb) } case *ast.RGBAColor: switch tb := b.(type) { case *ast.Number: return RGBAColorAddNumber(ta, tb) } } case ast.T_MINUS: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: return NumberSubNumber(ta, tb) } case *ast.HexColor: switch tb := b.(type) { case *ast.Number: return HexColorSubNumber(ta, tb) } case *ast.RGBColor: switch tb := b.(type) { case *ast.Number: return RGBColorSubNumber(ta, tb) } case *ast.RGBAColor: switch tb := b.(type) { case *ast.Number: return RGBAColorSubNumber(ta, tb) } } case ast.T_DIV: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: return NumberDivNumber(ta, tb) } case *ast.HexColor: switch tb := b.(type) { case *ast.Number: return HexColorDivNumber(ta, tb) } case *ast.RGBColor: switch tb := b.(type) { case *ast.Number: return RGBColorDivNumber(ta, tb) } case *ast.RGBAColor: switch tb := b.(type) { case *ast.Number: return RGBAColorDivNumber(ta, tb) } } case ast.T_MUL: switch ta := a.(type) { case *ast.Number: switch tb := b.(type) { case *ast.Number: return NumberMulNumber(ta, tb) } case *ast.HexColor: switch tb := b.(type) { case *ast.Number: return HexColorMulNumber(ta, tb) } case *ast.RGBColor: switch tb := b.(type) { case *ast.Number: return RGBColorMulNumber(ta, tb) } case *ast.RGBAColor: switch tb := b.(type) { case *ast.Number: return RGBAColorMulNumber(ta, tb) } } } return nil }