2018-05-21 21:13:54 +00:00
package interpreter
import (
"fmt"
"regexp"
2018-05-21 21:20:06 +00:00
"github.com/influxdata/platform/query/ast"
"github.com/influxdata/platform/query/semantic"
"github.com/influxdata/platform/query/values"
2018-05-21 21:13:54 +00:00
"github.com/pkg/errors"
)
2018-07-11 20:03:14 +00:00
// Interpreter used to interpret a Flux program
type Interpreter struct {
values [ ] values . Value
options * Scope
globals * Scope
2018-05-21 21:13:54 +00:00
}
2018-07-11 20:03:14 +00:00
// NewInterpreter instantiates a new Flux Interpreter
func NewInterpreter ( options , builtins map [ string ] values . Value ) * Interpreter {
optionScope := NewScopeWithValues ( options )
globalScope := optionScope . NestWithValues ( builtins )
interpreter := new ( Interpreter )
interpreter . options = optionScope
interpreter . globals = globalScope
return interpreter
2018-05-21 21:13:54 +00:00
}
2018-07-11 20:03:14 +00:00
// Return gives the return value from the block
func ( itrp * Interpreter ) Return ( ) values . Value {
return itrp . globals . Return ( )
}
// GlobalScope returns a pointer to the global scope of the program.
// That is the scope nested directly below the options scope.
func ( itrp * Interpreter ) GlobalScope ( ) * Scope {
return itrp . globals
}
// SetVar adds a variable binding to the global scope
func ( itrp * Interpreter ) SetVar ( name string , val values . Value ) {
itrp . globals . Set ( name , val )
}
// SideEffects returns the evaluated expressions of a Flux program
func ( itrp * Interpreter ) SideEffects ( ) [ ] values . Value {
return itrp . values
}
// Option returns a Flux option by name
func ( itrp * Interpreter ) Option ( name string ) values . Value {
return itrp . options . Get ( name )
}
// SetOption sets a new option binding
func ( itrp * Interpreter ) SetOption ( name string , val values . Value ) {
itrp . options . Set ( name , val )
}
// Eval evaluates the expressions composing a Flux program.
func ( itrp * Interpreter ) Eval ( program * semantic . Program ) error {
return itrp . eval ( program )
}
func ( itrp * Interpreter ) eval ( program * semantic . Program ) error {
topLevelScope := itrp . globals
2018-05-21 21:13:54 +00:00
for _ , stmt := range program . Body {
2018-07-11 20:03:14 +00:00
val , err := itrp . doStatement ( stmt , topLevelScope )
2018-06-28 23:52:45 +00:00
if err != nil {
2018-05-21 21:13:54 +00:00
return err
}
2018-06-28 23:52:45 +00:00
if val != nil {
itrp . values = append ( itrp . values , val )
}
2018-05-21 21:13:54 +00:00
}
return nil
}
2018-06-28 23:52:45 +00:00
// doStatement returns the resolved value of a top-level statement
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doStatement ( stmt semantic . Statement , scope * Scope ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
scope . SetReturn ( values . InvalidValue )
switch s := stmt . ( type ) {
2018-06-21 21:54:31 +00:00
case * semantic . OptionStatement :
2018-07-11 20:03:14 +00:00
return itrp . doOptionStatement ( s . Declaration . ( * semantic . NativeVariableDeclaration ) , scope )
2018-05-21 21:13:54 +00:00
case * semantic . NativeVariableDeclaration :
2018-06-28 23:52:45 +00:00
return itrp . doVariableDeclaration ( s , scope )
2018-05-21 21:13:54 +00:00
case * semantic . ExpressionStatement :
v , err := itrp . doExpression ( s . Expression , scope )
if err != nil {
2018-06-28 23:52:45 +00:00
return nil , err
2018-05-21 21:13:54 +00:00
}
scope . SetReturn ( v )
2018-06-28 23:52:45 +00:00
return v , nil
2018-05-21 21:13:54 +00:00
case * semantic . BlockStatement :
nested := scope . Nest ( )
for i , stmt := range s . Body {
2018-06-28 23:52:45 +00:00
_ , err := itrp . doStatement ( stmt , nested )
if err != nil {
return nil , err
2018-05-21 21:13:54 +00:00
}
// Validate a return statement is the last statement
if _ , ok := stmt . ( * semantic . ReturnStatement ) ; ok {
if i != len ( s . Body ) - 1 {
2018-06-28 23:52:45 +00:00
return nil , errors . New ( "return statement is not the last statement in the block" )
2018-05-21 21:13:54 +00:00
}
}
}
2018-07-11 20:03:14 +00:00
// 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.
2018-05-21 21:13:54 +00:00
scope . SetReturn ( nested . Return ( ) )
case * semantic . ReturnStatement :
v , err := itrp . doExpression ( s . Argument , scope )
if err != nil {
2018-06-28 23:52:45 +00:00
return nil , err
2018-05-21 21:13:54 +00:00
}
scope . SetReturn ( v )
default :
2018-06-28 23:52:45 +00:00
return nil , fmt . Errorf ( "unsupported statement type %T" , stmt )
2018-05-21 21:13:54 +00:00
}
2018-06-28 23:52:45 +00:00
return nil , nil
2018-05-21 21:13:54 +00:00
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doOptionStatement ( declaration * semantic . NativeVariableDeclaration , scope * Scope ) ( values . Value , error ) {
value , err := itrp . doExpression ( declaration . Init , scope )
if err != nil {
return nil , err
}
itrp . options . Set ( declaration . Identifier . Name , value )
return value , nil
}
func ( itrp * Interpreter ) doVariableDeclaration ( declaration * semantic . NativeVariableDeclaration , scope * Scope ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
value , err := itrp . doExpression ( declaration . Init , scope )
if err != nil {
2018-06-28 23:52:45 +00:00
return nil , err
2018-05-21 21:13:54 +00:00
}
scope . Set ( declaration . Identifier . Name , value )
2018-06-28 23:52:45 +00:00
return value , nil
2018-05-21 21:13:54 +00:00
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doExpression ( expr semantic . Expression , scope * Scope ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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 :
2018-06-28 23:52:45 +00:00
return & function {
2018-05-21 21:13:54 +00:00
e : e ,
scope : scope . Nest ( ) ,
} , nil
default :
return nil , fmt . Errorf ( "unsupported expression %T" , expr )
}
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doArray ( a * semantic . ArrayExpression , scope * Scope ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doObject ( m * semantic . ObjectExpression , scope * Scope ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doLiteral ( lit semantic . Literal ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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 "<anonymous function>"
}
}
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
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doCall ( call * semantic . CallExpression , scope * Scope ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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.
2018-06-28 23:52:45 +00:00
if af , ok := f . ( * function ) ; ok {
2018-05-21 21:13:54 +00:00
af . itrp = itrp
f = af
}
// Call the function
2018-06-28 23:52:45 +00:00
value , err := f . Call ( argObj )
if err != nil {
return nil , err
}
if f . HasSideEffect ( ) {
itrp . values = append ( itrp . values , value )
}
return value , nil
2018-05-21 21:13:54 +00:00
}
2018-07-11 20:03:14 +00:00
func ( itrp * Interpreter ) doArguments ( args * semantic . ObjectExpression , scope * Scope ) ( values . Object , error ) {
2018-05-21 21:13:54 +00:00
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
}
2018-07-11 20:03:14 +00:00
// TODO(Josh): Scope methods should be private
2018-05-21 21:13:54 +00:00
type Scope struct {
parent * Scope
values map [ string ] values . Value
returnValue values . Value
}
func NewScope ( ) * Scope {
return & Scope {
values : make ( map [ string ] values . Value ) ,
}
}
2018-07-11 20:03:14 +00:00
func NewScopeWithValues ( vals map [ string ] values . Value ) * Scope {
cp := make ( map [ string ] values . Value , len ( vals ) )
for k , v := range vals {
cp [ k ] = v
}
2018-05-21 21:13:54 +00:00
return & Scope {
2018-07-11 20:03:14 +00:00
values : cp ,
}
}
func ( s * Scope ) Get ( name string ) values . Value {
return s . values [ name ]
}
func ( s * Scope ) Set ( name string , value values . Value ) {
s . values [ name ] = value
}
func ( s * Scope ) Values ( ) map [ string ] values . Value {
cp := make ( map [ string ] values . Value , len ( s . values ) )
for k , v := range s . values {
cp [ k ] = v
}
return cp
}
func ( s * Scope ) SetValues ( vals map [ string ] values . Value ) {
for k , v := range vals {
s . values [ k ] = v
2018-05-21 21:13:54 +00:00
}
}
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
}
// 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
}
2018-07-11 20:03:14 +00:00
func ( s * Scope ) NestWithValues ( values map [ string ] values . Value ) * Scope {
c := NewScopeWithValues ( values )
c . parent = s
return c
}
2018-05-21 21:13:54 +00:00
// 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 )
2018-07-11 20:03:14 +00:00
itrp * Interpreter
2018-05-21 21:13:54 +00:00
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Type ( ) semantic . Type {
2018-05-21 21:13:54 +00:00
return f . e . Type ( )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Str ( ) string {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . String ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Int ( ) int64 {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Int ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) UInt ( ) uint64 {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . UInt ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Float ( ) float64 {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Float ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Bool ( ) bool {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Bool ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Time ( ) values . Time {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Time ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Duration ( ) values . Duration {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Duration ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Regexp ( ) * regexp . Regexp {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Regexp ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Array ( ) values . Array {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Function ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Object ( ) values . Object {
2018-05-21 21:13:54 +00:00
panic ( values . UnexpectedKind ( semantic . Object , semantic . Object ) )
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Function ( ) values . Function {
2018-05-21 21:13:54 +00:00
return f
}
2018-06-28 23:52:45 +00:00
func ( f * function ) Equal ( rhs values . Value ) bool {
if f . Type ( ) != rhs . Type ( ) {
return false
}
v , ok := rhs . ( * function )
return ok && ( f == v )
}
func ( f * function ) HasSideEffect ( ) bool {
// Function definitions do not produce side effects.
// Only a function call expression can produce side effects.
return false
}
2018-05-21 21:13:54 +00:00
2018-06-28 23:52:45 +00:00
func ( f * function ) Call ( argsObj values . Object ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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
}
2018-06-28 23:52:45 +00:00
func ( f * function ) doCall ( args Arguments ) ( values . Value , error ) {
2018-05-21 21:13:54 +00:00
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 :
2018-06-28 23:52:45 +00:00
_ , err := f . itrp . doStatement ( n , f . scope )
2018-05-21 21:13:54 +00:00
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.
2018-06-28 23:52:45 +00:00
func ( f * function ) Resolve ( ) ( semantic . Node , error ) {
2018-05-21 21:13:54 +00:00
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 )
}
2018-06-21 21:54:31 +00:00
case * semantic . OptionStatement :
node , err := f . resolveIdentifiers ( n . Declaration )
if err != nil {
return nil , err
}
n . Declaration = node . ( semantic . VariableDeclaration )
2018-05-21 21:13:54 +00:00
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 {
2018-07-06 21:38:05 +00:00
GetAll ( ) [ ] string
2018-05-21 21:13:54 +00:00
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 {
2018-07-18 22:02:21 +00:00
if obj == nil {
return new ( arguments )
}
2018-05-21 21:13:54 +00:00
return & arguments {
obj : obj ,
used : make ( map [ string ] bool , obj . Len ( ) ) ,
}
}
func NewArguments ( obj values . Object ) Arguments {
return newArguments ( obj )
}
2018-07-06 21:38:05 +00:00
func ( a * arguments ) GetAll ( ) [ ] string {
args := make ( [ ] string , 0 , a . obj . Len ( ) )
a . obj . Range ( func ( name string , v values . Value ) {
args = append ( args , name )
} )
return args
}
2018-05-21 21:13:54 +00:00
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
2018-07-18 22:02:21 +00:00
if a . obj != nil {
a . obj . Range ( func ( k string , v values . Value ) {
if ! a . used [ k ] {
unused = append ( unused , k )
}
} )
}
2018-05-21 21:13:54 +00:00
return unused
}