rv := reflect .ValueOf (value )
if rv .Kind () == reflect .Slice {
index := node .value .(int )
if index < 0 {
index += rv .Len ()
}
if index < rv .Len () && index >= 0 {
v := rv .Index (index )
return v .Interface (), nil
}
}
return nil , nil
case ASTKeyValPair :
return intr .Execute (node .children [0 ], value )
case ASTLiteral :
return node .value , nil
case ASTMultiSelectHash :
if value == nil {
return nil , nil
}
collected := make (map [string ]interface {})
for _ , child := range node .children {
current , err := intr .Execute (child , value )
if err != nil {
return nil , err
}
key := child .value .(string )
collected [key ] = current
}
return collected , nil
case ASTMultiSelectList :
if value == nil {
return nil , nil
}
collected := []interface {}{}
for _ , child := range node .children {
current , err := intr .Execute (child , value )
if err != nil {
return nil , err
}
collected = append (collected , current )
}
return collected , nil
case ASTOrExpression :
matched , err := intr .Execute (node .children [0 ], value )
if err != nil {
return nil , err
}
if isFalse (matched ) {
matched , err = intr .Execute (node .children [1 ], value )
if err != nil {
return nil , err
}
}
return matched , nil
case ASTAndExpression :
matched , err := intr .Execute (node .children [0 ], value )
if err != nil {
return nil , err
}
if isFalse (matched ) {
return matched , nil
}
return intr .Execute (node .children [1 ], value )
case ASTNotExpression :
matched , err := intr .Execute (node .children [0 ], value )
if err != nil {
return nil , err
}
if isFalse (matched ) {
return true , nil
}
return false , nil
case ASTPipe :
result := value
var err error
for _ , child := range node .children {
result , err = intr .Execute (child , result )
if err != nil {
return nil , err
}
}
return result , nil
case ASTProjection :
left , err := intr .Execute (node .children [0 ], value )
if err != nil {
return nil , err
}
sliceType , ok := left .([]interface {})
if !ok {
if isSliceType (left ) {
return intr .projectWithReflection (node , left )
}
return nil , nil
}
collected := []interface {}{}
var current interface {}
for _ , element := range sliceType {
current , err = intr .Execute (node .children [1 ], element )
if err != nil {
return nil , err
}
if current != nil {
collected = append (collected , current )
}
}
return collected , nil
case ASTSubexpression , ASTIndexExpression :
left , err := intr .Execute (node .children [0 ], value )
if err != nil {
return nil , err
}
return intr .Execute (node .children [1 ], left )
case ASTSlice :
sliceType , ok := value .([]interface {})
if !ok {
if isSliceType (value ) {
return intr .sliceWithReflection (node , value )
}
return nil , nil
}
parts := node .value .([]*int )
sliceParams := make ([]sliceParam , 3 )
for i , part := range parts {
if part != nil {
sliceParams [i ].Specified = true
sliceParams [i ].N = *part
}
}
return slice (sliceType , sliceParams )
case ASTValueProjection :
left , err := intr .Execute (node .children [0 ], value )
if err != nil {
return nil , nil
}
mapType , ok := left .(map [string ]interface {})
if !ok {
return nil , nil
}
values := make ([]interface {}, len (mapType ))
for _ , value := range mapType {
values = append (values , value )
}
collected := []interface {}{}
for _ , element := range values {
current , err := intr .Execute (node .children [1 ], element )
if err != nil {
return nil , err
}
if current != nil {
collected = append (collected , current )
}
}
return collected , nil
}
return nil , errors .New ("Unknown AST node: " + node .nodeType .String ())
}
func (intr *treeInterpreter ) fieldFromStruct (key string , value interface {}) (interface {}, error ) {
rv := reflect .ValueOf (value )
first , n := utf8 .DecodeRuneInString (key )
fieldName := string (unicode .ToUpper (first )) + key [n :]
if rv .Kind () == reflect .Struct {
v := rv .FieldByName (fieldName )
if !v .IsValid () {
return nil , nil
}
return v .Interface (), nil