package jmespath

import (
	
	
	
	
)
This is a tree based interpreter. It walks the AST and directly interprets the AST to search through a JSON document.

type treeInterpreter struct {
	fCall *functionCaller
}

func () *treeInterpreter {
	 := treeInterpreter{}
	.fCall = newFunctionCaller()
	return &
}

type expRef struct {
	ref ASTNode
}
Execute takes an ASTNode and input data and interprets the AST directly. It will produce the result of applying the JMESPath expression associated with the ASTNode to the input data "value".
func ( *treeInterpreter) ( ASTNode,  interface{}) (interface{}, error) {
	switch .nodeType {
	case ASTComparator:
		,  := .(.children[0], )
		if  != nil {
			return nil, 
		}
		,  := .(.children[1], )
		if  != nil {
			return nil, 
		}
		switch .value {
		case tEQ:
			return objsEqual(, ), nil
		case tNE:
			return !objsEqual(, ), nil
		}
		,  := .(float64)
		if ! {
			return nil, nil
		}
		,  := .(float64)
		if ! {
			return nil, nil
		}
		switch .value {
		case tGT:
			return  > , nil
		case tGTE:
			return  >= , nil
		case tLT:
			return  < , nil
		case tLTE:
			return  <= , nil
		}
	case ASTExpRef:
		return expRef{ref: .children[0]}, nil
	case ASTFunctionExpression:
		 := []interface{}{}
		for ,  := range .children {
			,  := .(, )
			if  != nil {
				return nil, 
			}
			 = append(, )
		}
		return .fCall.CallFunction(.value.(string), , )
	case ASTField:
		if ,  := .(map[string]interface{});  {
			 := .value.(string)
			return [], nil
		}
		return .fieldFromStruct(.value.(string), )
	case ASTFilterProjection:
		,  := .(.children[0], )
		if  != nil {
			return nil, nil
		}
		,  := .([]interface{})
		if ! {
			if isSliceType() {
				return .filterProjectionWithReflection(, )
			}
			return nil, nil
		}
		 := .children[2]
		 := []interface{}{}
		for ,  := range  {
			,  := .(, )
			if  != nil {
				return nil, 
			}
			if !isFalse() {
				,  := .(.children[1], )
				if  != nil {
					return nil, 
				}
				if  != nil {
					 = append(, )
				}
			}
		}
		return , nil
	case ASTFlatten:
		,  := .(.children[0], )
		if  != nil {
			return nil, nil
		}
		,  := .([]interface{})
If we can't type convert to []interface{}, there's a chance this could still work via reflection if we're dealing with user provided types.
			if isSliceType() {
				return .flattenWithReflection()
			}
			return nil, nil
		}
		 := []interface{}{}
		for ,  := range  {
			if ,  := .([]interface{});  {
				 = append(, ...)
			} else if isSliceType() {
				 := []interface{}{}
				 := reflect.ValueOf()
				for  := 0;  < .Len(); ++ {
					 = append(, .Index().Interface())
				}
				 = append(, ...)
			} else {
				 = append(, )
			}
		}
		return , nil
	case ASTIdentity, ASTCurrentNode:
		return , nil
	case ASTIndex:
		if ,  := .([]interface{});  {
			 := .value.(int)
			if  < 0 {
				 += len()
			}
			if  < len() &&  >= 0 {
				return [], nil
			}
			return nil, nil
Otherwise try via reflection.
		 := reflect.ValueOf()
		if .Kind() == reflect.Slice {
			 := .value.(int)
			if  < 0 {
				 += .Len()
			}
			if  < .Len() &&  >= 0 {
				 := .Index()
				return .Interface(), nil
			}
		}
		return nil, nil
	case ASTKeyValPair:
		return .(.children[0], )
	case ASTLiteral:
		return .value, nil
	case ASTMultiSelectHash:
		if  == nil {
			return nil, nil
		}
		 := make(map[string]interface{})
		for ,  := range .children {
			,  := .(, )
			if  != nil {
				return nil, 
			}
			 := .value.(string)
			[] = 
		}
		return , nil
	case ASTMultiSelectList:
		if  == nil {
			return nil, nil
		}
		 := []interface{}{}
		for ,  := range .children {
			,  := .(, )
			if  != nil {
				return nil, 
			}
			 = append(, )
		}
		return , nil
	case ASTOrExpression:
		,  := .(.children[0], )
		if  != nil {
			return nil, 
		}
		if isFalse() {
			,  = .(.children[1], )
			if  != nil {
				return nil, 
			}
		}
		return , nil
	case ASTAndExpression:
		,  := .(.children[0], )
		if  != nil {
			return nil, 
		}
		if isFalse() {
			return , nil
		}
		return .(.children[1], )
	case ASTNotExpression:
		,  := .(.children[0], )
		if  != nil {
			return nil, 
		}
		if isFalse() {
			return true, nil
		}
		return false, nil
	case ASTPipe:
		 := 
		var  error
		for ,  := range .children {
			,  = .(, )
			if  != nil {
				return nil, 
			}
		}
		return , nil
	case ASTProjection:
		,  := .(.children[0], )
		if  != nil {
			return nil, 
		}
		,  := .([]interface{})
		if ! {
			if isSliceType() {
				return .projectWithReflection(, )
			}
			return nil, nil
		}
		 := []interface{}{}
		var  interface{}
		for ,  := range  {
			,  = .(.children[1], )
			if  != nil {
				return nil, 
			}
			if  != nil {
				 = append(, )
			}
		}
		return , nil
	case ASTSubexpression, ASTIndexExpression:
		,  := .(.children[0], )
		if  != nil {
			return nil, 
		}
		return .(.children[1], )
	case ASTSlice:
		,  := .([]interface{})
		if ! {
			if isSliceType() {
				return .sliceWithReflection(, )
			}
			return nil, nil
		}
		 := .value.([]*int)
		 := make([]sliceParam, 3)
		for ,  := range  {
			if  != nil {
				[].Specified = true
				[].N = *
			}
		}
		return slice(, )
	case ASTValueProjection:
		,  := .(.children[0], )
		if  != nil {
			return nil, nil
		}
		,  := .(map[string]interface{})
		if ! {
			return nil, nil
		}
		 := make([]interface{}, len())
		for ,  := range  {
			 = append(, )
		}
		 := []interface{}{}
		for ,  := range  {
			,  := .(.children[1], )
			if  != nil {
				return nil, 
			}
			if  != nil {
				 = append(, )
			}
		}
		return , nil
	}
	return nil, errors.New("Unknown AST node: " + .nodeType.String())
}

func ( *treeInterpreter) ( string,  interface{}) (interface{}, error) {
	 := reflect.ValueOf()
	,  := utf8.DecodeRuneInString()
	 := string(unicode.ToUpper()) + [:]
	if .Kind() == reflect.Struct {
		 := .FieldByName()
		if !.IsValid() {
			return nil, nil
		}
		return .Interface(), nil
Handle multiple levels of indirection?
		if .IsNil() {
			return nil, nil
		}
		 = .Elem()
		 := .FieldByName()
		if !.IsValid() {
			return nil, nil
		}
		return .Interface(), nil
	}
	return nil, nil
}

func ( *treeInterpreter) ( interface{}) (interface{}, error) {
	 := reflect.ValueOf()
	 := []interface{}{}
	for  := 0;  < .Len(); ++ {
		 := .Index().Interface()
Then insert the contents of the element slice into the flattened slice, i.e flattened = append(flattened, mySlice...)
			 := reflect.ValueOf()
			for  := 0;  < .Len(); ++ {
				 = append(
					, .Index().Interface())
			}
		} else {
			 = append(, )
		}
	}
	return , nil
}

func ( *treeInterpreter) ( ASTNode,  interface{}) (interface{}, error) {
	 := reflect.ValueOf()
	 := .value.([]*int)
	 := make([]sliceParam, 3)
	for ,  := range  {
		if  != nil {
			[].Specified = true
			[].N = *
		}
	}
	 := []interface{}{}
	for  := 0;  < .Len(); ++ {
		 := .Index().Interface()
		 = append(, )
	}
	return slice(, )
}

func ( *treeInterpreter) ( ASTNode,  interface{}) (interface{}, error) {
	 := .children[2]
	 := []interface{}{}
	 := reflect.ValueOf()
	for  := 0;  < .Len(); ++ {
		 := .Index().Interface()
		,  := .Execute(, )
		if  != nil {
			return nil, 
		}
		if !isFalse() {
			,  := .Execute(.children[1], )
			if  != nil {
				return nil, 
			}
			if  != nil {
				 = append(, )
			}
		}
	}
	return , nil
}

func ( *treeInterpreter) ( ASTNode,  interface{}) (interface{}, error) {
	 := []interface{}{}
	 := reflect.ValueOf()
	for  := 0;  < .Len(); ++ {
		 := .Index().Interface()
		,  := .Execute(.children[1], )
		if  != nil {
			return nil, 
		}
		if  != nil {
			 = append(, )
		}
	}
	return , nil