コード例 #1
0
ファイル: vm.go プロジェクト: chrislusf/qlbridge
// MultiNode evaluator
//
//     A   IN   (b,c,d)
//
func walkMulti(ctx expr.EvalContext, node *expr.MultiArgNode) (value.Value, bool) {

	a, aok := Eval(ctx, node.Args[0])
	//u.Infof("multi:  %T:%v  %v", a, a, node.Operator)
	if !aok {
		u.Infof("Could not evaluate args, %#v", node.Args[0])
		return value.BoolValueFalse, false
	}
	switch node.Operator.T {
	case lex.TokenIN:
		for i := 1; i < len(node.Args); i++ {
			v, ok := Eval(ctx, node.Args[i])
			if ok {
				//u.Debugf("in? %v %v", a, v)
				if eq, err := value.Equal(a, v); eq && err == nil {
					return value.NewBoolValue(true), true
				}
			} else {
				u.Warnf("could not evaluate arg: %v", node.Args[i])
			}
		}
		return value.NewBoolValue(false), true
	default:
		u.Warnf("tri node walk not implemented:   %#v", node)
	}

	return value.NewNilValue(), false
}
コード例 #2
0
ファイル: vm.go プロジェクト: chrislusf/qlbridge
func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode) (value.Value, bool) {

	a, ok := Eval(ctx, node.Arg)
	if !ok {
		u.Infof("whoops, %#v", node)
		return a, false
	}
	switch node.Operator.T {
	case lex.TokenNegate:
		switch argVal := a.(type) {
		case value.BoolValue:
			//u.Infof("found urnary bool:  res=%v   expr=%v", !argVal.v, node.StringAST())
			return value.NewBoolValue(!argVal.Val()), true
		default:
			//u.Errorf("urnary type not implementedUnknonwn node type:  %T", argVal)
			panic(ErrUnknownNodeType)
		}
	case lex.TokenMinus:
		if an, aok := a.(value.NumericValue); aok {
			return value.NewNumberValue(-an.Float()), true
		}
	default:
		u.Warnf("urnary not implemented:   %#v", node)
	}

	return value.NewNilValue(), false
}
コード例 #3
0
ファイル: vm.go プロジェクト: allisonmorgan/qlbridge
func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode) (value.Value, bool) {

	a, ok := Eval(ctx, node.Arg)
	if !ok {
		switch node.Operator.T {
		case lex.TokenExists:
			return value.NewBoolValue(false), true
		case lex.TokenNegate:
			return value.NewBoolValue(true), true
		}
		u.Debugf("unary could not evaluate for[ %s ] and %#v", node.String(), node)
		return a, false
	}

	switch node.Operator.T {
	case lex.TokenNegate:
		switch argVal := a.(type) {
		case value.BoolValue:
			//u.Debugf("found unary bool:  res=%v   expr=%v", !argVal.Val(), node)
			return value.NewBoolValue(!argVal.Val()), true
		case nil, value.NilValue:
			return value.NewBoolValue(false), false
		default:
			u.LogThrottle(u.WARN, 5, "unary type not implemented. Unknonwn node type: %T:%v node=%s", argVal, argVal, node.String())
			return value.NewNilValue(), false
		}
	case lex.TokenMinus:
		if an, aok := a.(value.NumericValue); aok {
			return value.NewNumberValue(-an.Float()), true
		}
	case lex.TokenExists:
		switch a.(type) {
		case nil, value.NilValue:
			return value.NewBoolValue(false), true
		}
		if a.Nil() {
			return value.NewBoolValue(false), true
		}
		return value.NewBoolValue(true), true
	default:
		u.Warnf("urnary not implemented for type %s %#v", node.Operator.T.String(), node)
	}

	return value.NewNilValue(), false
}
コード例 #4
0
ファイル: vm.go プロジェクト: allisonmorgan/qlbridge
// TriNode evaluator
//
//     A   BETWEEN   B  AND C
//
func walkTri(ctx expr.EvalContext, node *expr.TriNode) (value.Value, bool) {

	a, aok := Eval(ctx, node.Args[0])
	b, bok := Eval(ctx, node.Args[1])
	c, c*k := Eval(ctx, node.Args[2])
	//u.Infof("tri:  %T:%v  %v  %T:%v   %T:%v", a, a, node.Operator, b, b, c, c)
	if !aok {
		return value.BoolValueFalse, false
	}
	if !bok || !c*k {
		u.Debugf("Could not evaluate args, %#v", node.String())
		return value.BoolValueFalse, false
	}
	if a == nil || b == nil || c == nil {
		return value.BoolValueFalse, false
	}
	switch node.Operator.T {
	case lex.TokenBetween:
		switch a.Type() {
		case value.IntType:
			//u.Infof("found tri:  %v %v %v  expr=%v", a, b, c, node.StringAST())
			if aiv, ok := a.(value.IntValue); ok {
				if biv, ok := b.(value.IntValue); ok {
					if civ, ok := c.(value.IntValue); ok {
						if aiv.Int() > biv.Int() && aiv.Int() < civ.Int() {
							return value.NewBoolValue(true), true
						} else {
							return value.NewBoolValue(false), true
						}
					}
				}
			}
			return value.BoolValueFalse, false
		case value.NumberType:
			//u.Infof("found tri:  %v %v %v  expr=%v", a, b, c, node.StringAST())
			if afv, ok := a.(value.NumberValue); ok {
				if bfv, ok := b.(value.NumberValue); ok {
					if cfv, ok := c.(value.NumberValue); ok {
						if afv.Float() > bfv.Float() && afv.Float() < cfv.Float() {
							return value.NewBoolValue(true), false
						} else {
							return value.NewBoolValue(false), true
						}
					}
				}
			}
			return value.BoolValueFalse, false
		default:
			u.Warnf("between not implemented for type %s %#v", a.Type().String(), node)
		}
	default:
		u.Warnf("tri node walk not implemented:   %#v", node)
	}

	return value.NewNilValue(), false
}
コード例 #5
0
ファイル: vm.go プロジェクト: allisonmorgan/qlbridge
func Eval(ctx expr.EvalContext, arg expr.Node) (value.Value, bool) {
	//u.Debugf("Eval() node=%T  %v", arg, arg)
	// can we switch to arg.Type()
	switch argVal := arg.(type) {
	case *expr.NumberNode:
		return numberNodeToValue(argVal)
	case *expr.BinaryNode:
		return walkBinary(ctx, argVal)
	case *expr.UnaryNode:
		return walkUnary(ctx, argVal)
	case *expr.TriNode:
		return walkTri(ctx, argVal)
	case *expr.ArrayNode:
		return walkArray(ctx, argVal)
	case *expr.FuncNode:
		return walkFunc(ctx, argVal)
	case *expr.IdentityNode:
		return walkIdentity(ctx, argVal)
	case *expr.StringNode:
		return value.NewStringValue(argVal.Text), true
	case nil:
		return nil, false
	case *expr.NullNode:
		// WHERE (`users.user_id` != NULL)
		return value.NewNilValue(), true
	case *expr.ValueNode:
		if argVal.Value == nil {
			return nil, false
		}
		switch val := argVal.Value.(type) {
		case *value.NilValue, value.NilValue:
			return nil, false
		case value.SliceValue:
			//u.Warnf("got slice? %#v", argVal)
			return val, true
		}
		u.Errorf("Unknonwn node type:  %#v", argVal.Value)
		panic(ErrUnknownNodeType)
	default:
		u.Errorf("Unknonwn node type:  %#v", arg)
		panic(ErrUnknownNodeType)
	}
}
コード例 #6
0
ファイル: vm.go プロジェクト: kyledj/qlbridge
func walkUnary(ctx expr.EvalContext, node *expr.UnaryNode) (value.Value, bool) {

	a, ok := Eval(ctx, node.Arg)
	if !ok {
		if node.Operator.T == lex.TokenExists {
			return value.NewBoolValue(false), true
		}
		u.Debugf("unary could not evaluate %#v", node)
		return a, false
	}

	switch node.Operator.T {
	case lex.TokenNegate:
		switch argVal := a.(type) {
		case value.BoolValue:
			//u.Infof("found unary bool:  res=%v   expr=%v", !argVal.v, node.StringAST())
			return value.NewBoolValue(!argVal.Val()), true
		case nil, value.NilValue:
			return value.NewBoolValue(false), false
		default:
			u.Errorf("unary type not implemented. Unknonwn node type: %T:%v", argVal, argVal)
			panic(ErrUnknownNodeType)
		}
	case lex.TokenMinus:
		if an, aok := a.(value.NumericValue); aok {
			return value.NewNumberValue(-an.Float()), true
		}
	case lex.TokenExists:
		switch a.(type) {
		case nil, value.NilValue:
			return value.NewBoolValue(false), true
		}
		return value.NewBoolValue(true), true
	default:
		u.Warnf("urnary not implemented for type %s %#v", node.Operator.T.String(), node)
	}

	return value.NewNilValue(), false
}
コード例 #7
0
ファイル: vm.go プロジェクト: kyledj/qlbridge
func walkFunc(ctx expr.EvalContext, node *expr.FuncNode) (value.Value, bool) {

	//u.Debugf("walkFunc node: %v", node.StringAST())

	// we create a set of arguments to pass to the function, first arg
	// is this Context
	var ok bool
	funcArgs := make([]reflect.Value, 0)
	if ctx != nil {
		funcArgs = append(funcArgs, reflect.ValueOf(ctx))
	} else {
		var nilArg expr.EvalContext
		funcArgs = append(funcArgs, reflect.ValueOf(&nilArg).Elem())
	}
	for _, a := range node.Args {

		//u.Debugf("arg %v  %T %v", a, a, a)

		var v interface{}

		switch t := a.(type) {
		case *expr.StringNode: // String Literal
			v = value.NewStringValue(t.Text)
		case *expr.IdentityNode: // Identity node = lookup in context

			if t.IsBooleanIdentity() {
				v = value.NewBoolValue(t.Bool())
			} else {
				v, ok = ctx.Get(t.Text)
				//u.Infof("%#v", ctx.Row())
				//u.Debugf("get '%s'? %T %v %v", t.String(), v, v, ok)
				if !ok {
					// nil arguments are valid
					v = value.NewNilValue()
				}
			}

		case *expr.NumberNode:
			v, ok = numberNodeToValue(t)
		case *expr.FuncNode:
			//u.Debugf("descending to %v()", t.Name)
			v, ok = walkFunc(ctx, t)
			if !ok {
				//return value.NewNilValue(), false
				// nil arguments are valid
				v = value.NewNilValue()
			}
			//u.Debugf("result of %v() = %v, %T", t.Name, v, v)
		case *expr.UnaryNode:
			v, ok = walkUnary(ctx, t)
			if !ok {
				// nil arguments are valid ??
				v = value.NewNilValue()
			}
		case *expr.BinaryNode:
			v, ok = walkBinary(ctx, t)
		case *expr.ValueNode:
			v = t.Value
		default:
			panic(fmt.Errorf("expr: unknown func arg type"))
		}

		if v == nil {
			//u.Warnf("Nil vals?  %v  %T  arg:%T", v, v, a)
			// What do we do with Nil Values?
			switch a.(type) {
			case *expr.StringNode: // String Literal
				u.Warnf("NOT IMPLEMENTED T:%T v:%v", a, a)
			case *expr.IdentityNode: // Identity node = lookup in context
				v = value.NewStringValue("")
			default:
				u.Warnf("un-handled type:  %v  %T", v, v)
			}

			funcArgs = append(funcArgs, reflect.ValueOf(v))
		} else {
			//u.Debugf(`found func arg:  "%v"  %T  arg:%T`, v, v, a)
			funcArgs = append(funcArgs, reflect.ValueOf(v))
		}

	}
	// Get the result of calling our Function (Value,bool)
	//u.Debugf("Calling func:%v(%v) %v", node.F.Name, funcArgs, node.F.F)
	fnRet := node.F.F.Call(funcArgs)
	//u.Debugf("fnRet: %v    ok?%v", fnRet, fnRet[1].Bool())
	// check if has an error response?
	if len(fnRet) > 1 && !fnRet[1].Bool() {
		// What do we do if not ok?
		return value.EmptyStringValue, false
	}
	//u.Debugf("response %v %v  %T", node.F.Name, fnRet[0].Interface(), fnRet[0].Interface())
	return fnRet[0].Interface().(value.Value), true
}