package interpreter import ( "fmt" "regexp" "github.com/influxdata/platform/query/ast" "github.com/influxdata/platform/query/semantic" "github.com/influxdata/platform/query/values" "github.com/pkg/errors" ) func Eval(program *semantic.Program, scope *Scope) error { itrp := interpreter{} return itrp.eval(program, scope) } type interpreter struct { } func (itrp interpreter) eval(program *semantic.Program, scope *Scope) error { for _, stmt := range program.Body { if err := itrp.doStatement(stmt, scope); err != nil { return err } } return nil } func (itrp interpreter) doStatement(stmt semantic.Statement, scope *Scope) error { scope.SetReturn(values.InvalidValue) switch s := stmt.(type) { case *semantic.OptionStatement: if err := itrp.doStatement(s.Declaration, scope); err != nil { return err } case *semantic.NativeVariableDeclaration: if err := itrp.doVariableDeclaration(s, scope); err != nil { return err } case *semantic.ExpressionStatement: v, err := itrp.doExpression(s.Expression, scope) if err != nil { return err } scope.SetReturn(v) case *semantic.BlockStatement: nested := scope.Nest() for i, stmt := range s.Body { if err := itrp.doStatement(stmt, nested); err != nil { return err } // Validate a return statement is the last statement if _, ok := stmt.(*semantic.ReturnStatement); ok { if i != len(s.Body)-1 { return errors.New("return statement is not the last statement in the block") } } } // Propgate any return value from the nested scope out. // Since a return statement is always last we do not have to worry about overriding an existing return value. scope.SetReturn(nested.Return()) case *semantic.ReturnStatement: v, err := itrp.doExpression(s.Argument, scope) if err != nil { return err } scope.SetReturn(v) default: return fmt.Errorf("unsupported statement type %T", stmt) } return nil } func (itrp interpreter) doVariableDeclaration(declaration *semantic.NativeVariableDeclaration, scope *Scope) error { value, err := itrp.doExpression(declaration.Init, scope) if err != nil { return err } scope.Set(declaration.Identifier.Name, value) return nil } func (itrp interpreter) doExpression(expr semantic.Expression, scope *Scope) (values.Value, error) { switch e := expr.(type) { case semantic.Literal: return itrp.doLiteral(e) case *semantic.ArrayExpression: return itrp.doArray(e, scope) case *semantic.IdentifierExpression: value, ok := scope.Lookup(e.Name) if !ok { return nil, fmt.Errorf("undefined identifier %q", e.Name) } return value, nil case *semantic.CallExpression: v, err := itrp.doCall(e, scope) if err != nil { // Determine function name return nil, errors.Wrapf(err, "error calling function %q", functionName(e)) } return v, nil case *semantic.MemberExpression: obj, err := itrp.doExpression(e.Object, scope) if err != nil { return nil, err } v, ok := obj.Object().Get(e.Property) if !ok { return nil, fmt.Errorf("object has no property %q", e.Property) } return v, nil case *semantic.ObjectExpression: return itrp.doObject(e, scope) case *semantic.UnaryExpression: v, err := itrp.doExpression(e.Argument, scope) if err != nil { return nil, err } switch e.Operator { case ast.NotOperator: if v.Type() != semantic.Bool { return nil, fmt.Errorf("operand to unary expression is not a boolean value, got %v", v.Type()) } return values.NewBoolValue(!v.Bool()), nil case ast.SubtractionOperator: switch t := v.Type(); t { case semantic.Int: return values.NewIntValue(-v.Int()), nil case semantic.Float: return values.NewFloatValue(-v.Float()), nil case semantic.Duration: return values.NewDurationValue(-v.Duration()), nil default: return nil, fmt.Errorf("operand to unary expression is not a number value, got %v", v.Type()) } default: return nil, fmt.Errorf("unsupported operator %q to unary expression", e.Operator) } case *semantic.BinaryExpression: l, err := itrp.doExpression(e.Left, scope) if err != nil { return nil, err } r, err := itrp.doExpression(e.Right, scope) if err != nil { return nil, err } bf, err := values.LookupBinaryFunction(values.BinaryFuncSignature{ Operator: e.Operator, Left: l.Type(), Right: r.Type(), }) if err != nil { return nil, err } return bf(l, r), nil case *semantic.LogicalExpression: l, err := itrp.doExpression(e.Left, scope) if err != nil { return nil, err } if l.Type() != semantic.Bool { return nil, fmt.Errorf("left operand to logcial expression is not a boolean value, got %v", l.Type()) } left := l.Bool() if e.Operator == ast.AndOperator && !left { // Early return return values.NewBoolValue(false), nil } else if e.Operator == ast.OrOperator && left { // Early return return values.NewBoolValue(true), nil } r, err := itrp.doExpression(e.Right, scope) if err != nil { return nil, err } if r.Type() != semantic.Bool { return nil, errors.New("right operand to logcial expression is not a boolean value") } right := r.Bool() switch e.Operator { case ast.AndOperator: return values.NewBoolValue(left && right), nil case ast.OrOperator: return values.NewBoolValue(left || right), nil default: return nil, fmt.Errorf("invalid logical operator %v", e.Operator) } case *semantic.FunctionExpression: return function{ e: e, scope: scope.Nest(), }, nil default: return nil, fmt.Errorf("unsupported expression %T", expr) } } func (itrp interpreter) doArray(a *semantic.ArrayExpression, scope *Scope) (values.Value, error) { elements := make([]values.Value, len(a.Elements)) elementType := semantic.EmptyArrayType.ElementType() for i, el := range a.Elements { v, err := itrp.doExpression(el, scope) if err != nil { return nil, err } if i == 0 { elementType = v.Type() } if elementType != v.Type() { return nil, fmt.Errorf("cannot mix types in an array, found both %v and %v", elementType, v.Type()) } elements[i] = v } return values.NewArrayWithBacking(elementType, elements), nil } func (itrp interpreter) doObject(m *semantic.ObjectExpression, scope *Scope) (values.Value, error) { obj := values.NewObject() for _, p := range m.Properties { v, err := itrp.doExpression(p.Value, scope) if err != nil { return nil, err } if _, ok := obj.Get(p.Key.Name); ok { return nil, fmt.Errorf("duplicate key in object: %q", p.Key.Name) } obj.Set(p.Key.Name, v) } return obj, nil } func (itrp interpreter) doLiteral(lit semantic.Literal) (values.Value, error) { switch l := lit.(type) { case *semantic.DateTimeLiteral: return values.NewTimeValue(values.Time(l.Value.UnixNano())), nil case *semantic.DurationLiteral: return values.NewDurationValue(values.Duration(l.Value)), nil case *semantic.FloatLiteral: return values.NewFloatValue(l.Value), nil case *semantic.IntegerLiteral: return values.NewIntValue(l.Value), nil case *semantic.UnsignedIntegerLiteral: return values.NewUIntValue(l.Value), nil case *semantic.StringLiteral: return values.NewStringValue(l.Value), nil case *semantic.RegexpLiteral: return values.NewRegexpValue(l.Value), nil case *semantic.BooleanLiteral: return values.NewBoolValue(l.Value), nil default: return nil, fmt.Errorf("unknown literal type %T", lit) } } func functionName(call *semantic.CallExpression) string { switch callee := call.Callee.(type) { case *semantic.IdentifierExpression: return callee.Name case *semantic.MemberExpression: return callee.Property default: return "" } } func DoFunctionCall(f func(args Arguments) (values.Value, error), argsObj values.Object) (values.Value, error) { args := NewArguments(argsObj) v, err := f(args) if err != nil { return nil, err } if unused := args.listUnused(); len(unused) > 0 { return nil, fmt.Errorf("unused arguments %v", unused) } return v, nil } func (itrp interpreter) doCall(call *semantic.CallExpression, scope *Scope) (values.Value, error) { callee, err := itrp.doExpression(call.Callee, scope) if err != nil { return nil, err } if callee.Type().Kind() != semantic.Function { return nil, fmt.Errorf("cannot call function, value is of type %v", callee.Type()) } f := callee.Function() argObj, err := itrp.doArguments(call.Arguments, scope) if err != nil { return nil, err } // Check if the function is an interpFunction and rebind it. if af, ok := f.(function); ok { af.itrp = itrp f = af } // Call the function return f.Call(argObj) } func (itrp interpreter) doArguments(args *semantic.ObjectExpression, scope *Scope) (values.Object, error) { obj := values.NewObject() if args == nil || len(args.Properties) == 0 { return obj, nil } for _, p := range args.Properties { value, err := itrp.doExpression(p.Value, scope) if err != nil { return nil, err } if _, ok := obj.Get(p.Key.Name); ok { return nil, fmt.Errorf("duplicate keyword parameter specified: %q", p.Key.Name) } obj.Set(p.Key.Name, value) } return obj, nil } type Scope struct { parent *Scope values map[string]values.Value returnValue values.Value } func NewScope() *Scope { return &Scope{ values: make(map[string]values.Value), } } func NewScopeWithValues(values map[string]values.Value) *Scope { return &Scope{ values: values, } } func (s *Scope) Lookup(name string) (values.Value, bool) { if s == nil { return nil, false } v, ok := s.values[name] if !ok { return s.parent.Lookup(name) } return v, ok } func (s *Scope) Set(name string, value values.Value) { s.values[name] = value } // SetReturn sets the return value of this scope. func (s *Scope) SetReturn(value values.Value) { s.returnValue = value } // Return reports the return value for this scope. If no return value has been set a value with type semantic.TInvalid is returned. func (s *Scope) Return() values.Value { return s.returnValue } func (s *Scope) Names() []string { if s == nil { return nil } names := s.parent.Names() for k := range s.values { names = append(names, k) } return names } // Nest returns a new nested scope. func (s *Scope) Nest() *Scope { c := NewScope() c.parent = s return c } // Copy returns a copy of the scope and its parents. func (s *Scope) Copy() *Scope { c := NewScope() // copy parent values into new scope curr := s for curr != nil { // copy values for k, v := range curr.values { c.values[k] = v } curr = curr.parent } return c } func (s *Scope) Range(f func(k string, v values.Value)) { for k, v := range s.values { f(k, v) } if s.parent != nil { s.parent.Range(f) } } // Value represents any value that can be the result of evaluating any expression. type Value interface { // Type reports the type of value Type() semantic.Type // Value returns the actual value represented. Value() interface{} // Property returns a new value which is a property of this value. Property(name string) (values.Value, error) } type value struct { t semantic.Type v interface{} } func (v value) Type() semantic.Type { return v.t } func (v value) Value() interface{} { return v.v } func (v value) Property(name string) (values.Value, error) { return nil, fmt.Errorf("property %q does not exist", name) } func (v value) String() string { return fmt.Sprintf("%v", v.v) } type function struct { e *semantic.FunctionExpression scope *Scope call func(Arguments) (values.Value, error) itrp interpreter } func (f function) Type() semantic.Type { return f.e.Type() } func (f function) Str() string { panic(values.UnexpectedKind(semantic.Object, semantic.String)) } func (f function) Int() int64 { panic(values.UnexpectedKind(semantic.Object, semantic.Int)) } func (f function) UInt() uint64 { panic(values.UnexpectedKind(semantic.Object, semantic.UInt)) } func (f function) Float() float64 { panic(values.UnexpectedKind(semantic.Object, semantic.Float)) } func (f function) Bool() bool { panic(values.UnexpectedKind(semantic.Object, semantic.Bool)) } func (f function) Time() values.Time { panic(values.UnexpectedKind(semantic.Object, semantic.Time)) } func (f function) Duration() values.Duration { panic(values.UnexpectedKind(semantic.Object, semantic.Duration)) } func (f function) Regexp() *regexp.Regexp { panic(values.UnexpectedKind(semantic.Object, semantic.Regexp)) } func (f function) Array() values.Array { panic(values.UnexpectedKind(semantic.Object, semantic.Function)) } func (f function) Object() values.Object { panic(values.UnexpectedKind(semantic.Object, semantic.Object)) } func (f function) Function() values.Function { return f } func (f function) Call(argsObj values.Object) (values.Value, error) { args := newArguments(argsObj) v, err := f.doCall(args) if err != nil { return nil, err } if unused := args.listUnused(); len(unused) > 0 { return nil, fmt.Errorf("unused arguments %s", unused) } return v, nil } func (f function) doCall(args Arguments) (values.Value, error) { for _, p := range f.e.Params { if p.Default == nil { v, err := args.GetRequired(p.Key.Name) if err != nil { return nil, err } f.scope.Set(p.Key.Name, v) } else { v, ok := args.Get(p.Key.Name) if !ok { // Use default value var err error v, err = f.itrp.doExpression(p.Default, f.scope) if err != nil { return nil, err } } f.scope.Set(p.Key.Name, v) } } switch n := f.e.Body.(type) { case semantic.Expression: return f.itrp.doExpression(n, f.scope) case semantic.Statement: err := f.itrp.doStatement(n, f.scope) if err != nil { return nil, err } v := f.scope.Return() if v.Type() == semantic.Invalid { return nil, errors.New("function has no return value") } return v, nil default: return nil, fmt.Errorf("unsupported function body type %T", f.e.Body) } } // Resolver represents a value that can resolve itself type Resolver interface { Resolve() (semantic.Node, error) } func ResolveFunction(f values.Function) (*semantic.FunctionExpression, error) { resolver, ok := f.(Resolver) if !ok { return nil, errors.New("function is not resolvable") } resolved, err := resolver.Resolve() if err != nil { return nil, err } fn, ok := resolved.(*semantic.FunctionExpression) if !ok { return nil, errors.New("resolved function is not a function") } return fn, nil } // Resolve rewrites the function resolving any identifiers not listed in the function params. func (f function) Resolve() (semantic.Node, error) { n := f.e.Copy() node, err := f.resolveIdentifiers(n) if err != nil { return nil, err } return node, nil } func (f function) resolveIdentifiers(n semantic.Node) (semantic.Node, error) { switch n := n.(type) { case *semantic.IdentifierExpression: for _, p := range f.e.Params { if n.Name == p.Key.Name { // Identifier is a parameter do not resolve return n, nil } } v, ok := f.scope.Lookup(n.Name) if !ok { return nil, fmt.Errorf("name %q does not exist in scope", n.Name) } return resolveValue(v) case *semantic.BlockStatement: for i, s := range n.Body { node, err := f.resolveIdentifiers(s) if err != nil { return nil, err } n.Body[i] = node.(semantic.Statement) } case *semantic.OptionStatement: node, err := f.resolveIdentifiers(n.Declaration) if err != nil { return nil, err } n.Declaration = node.(semantic.VariableDeclaration) case *semantic.ExpressionStatement: node, err := f.resolveIdentifiers(n.Expression) if err != nil { return nil, err } n.Expression = node.(semantic.Expression) case *semantic.ReturnStatement: node, err := f.resolveIdentifiers(n.Argument) if err != nil { return nil, err } n.Argument = node.(semantic.Expression) case *semantic.NativeVariableDeclaration: node, err := f.resolveIdentifiers(n.Init) if err != nil { return nil, err } n.Init = node.(semantic.Expression) case *semantic.CallExpression: node, err := f.resolveIdentifiers(n.Arguments) if err != nil { return nil, err } n.Arguments = node.(*semantic.ObjectExpression) case *semantic.FunctionExpression: node, err := f.resolveIdentifiers(n.Body) if err != nil { return nil, err } n.Body = node case *semantic.BinaryExpression: node, err := f.resolveIdentifiers(n.Left) if err != nil { return nil, err } n.Left = node.(semantic.Expression) node, err = f.resolveIdentifiers(n.Right) if err != nil { return nil, err } n.Right = node.(semantic.Expression) case *semantic.UnaryExpression: node, err := f.resolveIdentifiers(n.Argument) if err != nil { return nil, err } n.Argument = node.(semantic.Expression) case *semantic.LogicalExpression: node, err := f.resolveIdentifiers(n.Left) if err != nil { return nil, err } n.Left = node.(semantic.Expression) node, err = f.resolveIdentifiers(n.Right) if err != nil { return nil, err } n.Right = node.(semantic.Expression) case *semantic.ArrayExpression: for i, el := range n.Elements { node, err := f.resolveIdentifiers(el) if err != nil { return nil, err } n.Elements[i] = node.(semantic.Expression) } case *semantic.ObjectExpression: for i, p := range n.Properties { node, err := f.resolveIdentifiers(p) if err != nil { return nil, err } n.Properties[i] = node.(*semantic.Property) } case *semantic.ConditionalExpression: node, err := f.resolveIdentifiers(n.Test) if err != nil { return nil, err } n.Test = node.(semantic.Expression) node, err = f.resolveIdentifiers(n.Alternate) if err != nil { return nil, err } n.Alternate = node.(semantic.Expression) node, err = f.resolveIdentifiers(n.Consequent) if err != nil { return nil, err } n.Consequent = node.(semantic.Expression) case *semantic.Property: node, err := f.resolveIdentifiers(n.Value) if err != nil { return nil, err } n.Value = node.(semantic.Expression) } return n, nil } func resolveValue(v values.Value) (semantic.Node, error) { switch k := v.Type().Kind(); k { case semantic.String: return &semantic.StringLiteral{ Value: v.Str(), }, nil case semantic.Int: return &semantic.IntegerLiteral{ Value: v.Int(), }, nil case semantic.UInt: return &semantic.UnsignedIntegerLiteral{ Value: v.UInt(), }, nil case semantic.Float: return &semantic.FloatLiteral{ Value: v.Float(), }, nil case semantic.Bool: return &semantic.BooleanLiteral{ Value: v.Bool(), }, nil case semantic.Time: return &semantic.DateTimeLiteral{ Value: v.Time().Time(), }, nil case semantic.Regexp: return &semantic.RegexpLiteral{ Value: v.Regexp(), }, nil case semantic.Duration: return &semantic.DurationLiteral{ Value: v.Duration().Duration(), }, nil case semantic.Function: resolver, ok := v.Function().(Resolver) if !ok { return nil, fmt.Errorf("function is not resolvable %T", v.Function()) } return resolver.Resolve() case semantic.Array: arr := v.Array() node := new(semantic.ArrayExpression) node.Elements = make([]semantic.Expression, arr.Len()) var err error arr.Range(func(i int, el values.Value) { if err != nil { return } var n semantic.Node n, err = resolveValue(el) if err != nil { return } node.Elements[i] = n.(semantic.Expression) }) if err != nil { return nil, err } return node, nil case semantic.Object: obj := v.Object() node := new(semantic.ObjectExpression) node.Properties = make([]*semantic.Property, 0, obj.Len()) var err error obj.Range(func(k string, v values.Value) { if err != nil { return } var n semantic.Node n, err = resolveValue(v) if err != nil { return } node.Properties = append(node.Properties, &semantic.Property{ Key: &semantic.Identifier{Name: k}, Value: n.(semantic.Expression), }) }) if err != nil { return nil, err } return node, nil default: return nil, fmt.Errorf("cannot resove value of type %v", k) } } func ToStringArray(a values.Array) ([]string, error) { if a.Type().ElementType() != semantic.String { return nil, fmt.Errorf("cannot convert array of %v to an array of strings", a.Type().ElementType()) } strs := make([]string, a.Len()) a.Range(func(i int, v values.Value) { strs[i] = v.Str() }) return strs, nil } // Arguments provides access to the keyword arguments passed to a function. // semantic.The Get{Type} methods return three values: the typed value of the arg, // whether the argument was specified and any errors about the argument type. // semantic.The GetRequired{Type} methods return only two values, the typed value of the arg and any errors, a missing argument is considered an error in this case. type Arguments interface { Get(name string) (values.Value, bool) GetRequired(name string) (values.Value, error) GetString(name string) (string, bool, error) GetInt(name string) (int64, bool, error) GetFloat(name string) (float64, bool, error) GetBool(name string) (bool, bool, error) GetFunction(name string) (values.Function, bool, error) GetArray(name string, t semantic.Kind) (values.Array, bool, error) GetObject(name string) (values.Object, bool, error) GetRequiredString(name string) (string, error) GetRequiredInt(name string) (int64, error) GetRequiredFloat(name string) (float64, error) GetRequiredBool(name string) (bool, error) GetRequiredFunction(name string) (values.Function, error) GetRequiredArray(name string, t semantic.Kind) (values.Array, error) GetRequiredObject(name string) (values.Object, error) // listUnused returns the list of provided arguments that were not used by the function. listUnused() []string } type arguments struct { obj values.Object used map[string]bool } func newArguments(obj values.Object) *arguments { return &arguments{ obj: obj, used: make(map[string]bool, obj.Len()), } } func NewArguments(obj values.Object) Arguments { return newArguments(obj) } func (a *arguments) Get(name string) (values.Value, bool) { a.used[name] = true v, ok := a.obj.Get(name) return v, ok } func (a *arguments) GetRequired(name string) (values.Value, error) { a.used[name] = true v, ok := a.obj.Get(name) if !ok { return nil, fmt.Errorf("missing required keyword argument %q", name) } return v, nil } func (a *arguments) GetString(name string) (string, bool, error) { v, ok, err := a.get(name, semantic.String, false) if err != nil || !ok { return "", ok, err } return v.Str(), ok, nil } func (a *arguments) GetRequiredString(name string) (string, error) { v, _, err := a.get(name, semantic.String, true) if err != nil { return "", err } return v.Str(), nil } func (a *arguments) GetInt(name string) (int64, bool, error) { v, ok, err := a.get(name, semantic.Int, false) if err != nil || !ok { return 0, ok, err } return v.Int(), ok, nil } func (a *arguments) GetRequiredInt(name string) (int64, error) { v, _, err := a.get(name, semantic.Int, true) if err != nil { return 0, err } return v.Int(), nil } func (a *arguments) GetFloat(name string) (float64, bool, error) { v, ok, err := a.get(name, semantic.Float, false) if err != nil || !ok { return 0, ok, err } return v.Float(), ok, nil } func (a *arguments) GetRequiredFloat(name string) (float64, error) { v, _, err := a.get(name, semantic.Float, true) if err != nil { return 0, err } return v.Float(), nil } func (a *arguments) GetBool(name string) (bool, bool, error) { v, ok, err := a.get(name, semantic.Bool, false) if err != nil || !ok { return false, ok, err } return v.Bool(), ok, nil } func (a *arguments) GetRequiredBool(name string) (bool, error) { v, _, err := a.get(name, semantic.Bool, true) if err != nil { return false, err } return v.Bool(), nil } func (a *arguments) GetArray(name string, t semantic.Kind) (values.Array, bool, error) { v, ok, err := a.get(name, semantic.Array, false) if err != nil || !ok { return nil, ok, err } arr := v.Array() if arr.Type().ElementType() != t { return nil, true, fmt.Errorf("keyword argument %q should be of an array of type %v, but got an array of type %v", name, t, arr.Type()) } return v.Array(), ok, nil } func (a *arguments) GetRequiredArray(name string, t semantic.Kind) (values.Array, error) { v, _, err := a.get(name, semantic.Array, true) if err != nil { return nil, err } arr := v.Array() if arr.Type().ElementType() != t { return nil, fmt.Errorf("keyword argument %q should be of an array of type %v, but got an array of type %v", name, t, arr.Type()) } return arr, nil } func (a *arguments) GetFunction(name string) (values.Function, bool, error) { v, ok, err := a.get(name, semantic.Function, false) if err != nil || !ok { return nil, ok, err } return v.Function(), ok, nil } func (a *arguments) GetRequiredFunction(name string) (values.Function, error) { v, _, err := a.get(name, semantic.Function, true) if err != nil { return nil, err } return v.Function(), nil } func (a *arguments) GetObject(name string) (values.Object, bool, error) { v, ok, err := a.get(name, semantic.Object, false) if err != nil || !ok { return nil, ok, err } return v.Object(), ok, nil } func (a *arguments) GetRequiredObject(name string) (values.Object, error) { v, _, err := a.get(name, semantic.Object, true) if err != nil { return nil, err } return v.Object(), nil } func (a *arguments) get(name string, kind semantic.Kind, required bool) (values.Value, bool, error) { a.used[name] = true v, ok := a.obj.Get(name) if !ok { if required { return nil, false, fmt.Errorf("missing required keyword argument %q", name) } return nil, false, nil } if v.Type().Kind() != kind { return nil, true, fmt.Errorf("keyword argument %q should be of kind %v, but got %v", name, kind, v.Type().Kind()) } return v, true, nil } func (a *arguments) listUnused() []string { var unused []string a.obj.Range(func(k string, v values.Value) { if !a.used[k] { unused = append(unused, k) } }) return unused }