package interp

//go:generate go run ../internal/cmd/genop/genop.go

import (
	
	
	
	
	
	
)

// bltn type defines functions which run at CFG execution.
type bltn func(f *frame) bltn

// bltnGenerator type defines a builtin generator function.
type bltnGenerator func(n *node)

var builtin = [...]bltnGenerator{
	aNop:          nop,
	aAddr:         addr,
	aAssign:       assign,
	aAdd:          add,
	aAddAssign:    addAssign,
	aAnd:          and,
	aAndAssign:    andAssign,
	aAndNot:       andNot,
	aAndNotAssign: andNotAssign,
	aBitNot:       bitNot,
	aCall:         call,
	aCallSlice:    call,
	aCase:         _case,
	aCompositeLit: arrayLit,
	aDec:          dec,
	aEqual:        equal,
	aGetFunc:      getFunc,
	aGreater:      greater,
	aGreaterEqual: greaterEqual,
	aInc:          inc,
	aLand:         land,
	aLor:          lor,
	aLower:        lower,
	aLowerEqual:   lowerEqual,
	aMul:          mul,
	aMulAssign:    mulAssign,
	aNeg:          neg,
	aNot:          not,
	aNotEqual:     notEqual,
	aOr:           or,
	aOrAssign:     orAssign,
	aPos:          pos,
	aQuo:          quo,
	aQuoAssign:    quoAssign,
	aRange:        _range,
	aRecv:         recv,
	aRem:          rem,
	aRemAssign:    remAssign,
	aReturn:       _return,
	aSend:         send,
	aShl:          shl,
	aShlAssign:    shlAssign,
	aShr:          shr,
	aShrAssign:    shrAssign,
	aSlice:        slice,
	aSlice0:       slice0,
	aStar:         deref,
	aSub:          sub,
	aSubAssign:    subAssign,
	aTypeAssert:   typeAssertShort,
	aXor:          xor,
	aXorAssign:    xorAssign,
}

var receiverStripperRxp *regexp.Regexp

func init() {
	 := `func\(((.*?(, |\)))(.*))`
	var  error
	receiverStripperRxp,  = regexp.Compile()
	if  != nil {
		panic()
	}
}

type valueInterface struct {
	node  *node
	value reflect.Value
}

var floatType, complexType reflect.Type

func init() {
	floatType = reflect.ValueOf(0.0).Type()
	complexType = reflect.ValueOf(complex(0, 0)).Type()
}

func ( *Interpreter) ( *node,  *frame) {
	if  == nil {
		return
	}
	var  *frame
	if  == nil {
		 = .frame
	} else {
		 = newFrame(, len(.types), .runid())
	}
	.mutex.RLock()
	 := reflect.ValueOf(.done)
	.mutex.RUnlock()

	.mutex.Lock()
	.done = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: }
	.mutex.Unlock()

	for ,  := range .types {
		.data[] = reflect.New().Elem()
	}
	runCfg(.start, , , nil)
}

func isExecNode( *node,  bltn) bool {
	if  == nil || .exec == nil ||  == nil {
		return false
	}

	 := reflect.ValueOf(.exec).Pointer()
	 := reflect.ValueOf().Pointer()
	return  == 
}

// originalExecNode looks in the tree of nodes for the node which has exec,
// aside from n, in order to know where n "inherited" that exec from.
func originalExecNode( *node,  bltn) *node {
	 := reflect.ValueOf().Pointer()
	var  *node
	 := make(map[int64]struct{})
	 := 
	for {
		 = .anc
		if  == nil {
			break
		}
		if ,  := [.index];  {
			continue
		}

		.Walk(func( *node) bool {
			if ,  := [.index];  {
				return true
			}
			[.index] = struct{}{}
			if .index == .index {
				return true
			}
			if .exec == nil {
				return true
			}
			if reflect.ValueOf(.exec).Pointer() ==  {
				 = 
				return false
			}
			return true
		}, nil)

		if  != nil {
			break
		}
	}

	return 
}

// cloned from net/http/server.go , so we can enforce a similar behavior:
// in the stdlib, this error is used as sentinel in panic triggered e.g. on
// request cancellation, in order to catch it and suppress it in a following defer.
// in yaegi, we use it to suppress a "panic" log message that happens in the
// same circumstances.
var errAbortHandler = errors.New("net/http: abort Handler")

// Functions set to run during execution of CFG.

func panicFunc( *scope) string {
	if  == nil {
		return ""
	}
	 := .def
	if  == nil {
		return .pkgID
	}
	switch .kind {
	case funcDecl:
		if  := .child[1]; .kind == identExpr {
			return .pkgID + "." + .ident
		}
	case funcLit:
		if .anc != nil {
			return (.anc.scope) + ".func"
		}
	}
	return .pkgID
}

// runCfg executes a node AST by walking its CFG and running node builtin at each step.
func runCfg( *node,  *frame, ,  *node) {
	var  bltn
	defer func() {
		.mutex.Lock()
		.recovered = recover()
		for ,  := range .deferred {
			[0].Call([1:])
		}
		if .recovered != nil {
			 := originalExecNode(, )
			if  == nil {
				 = 
			}
			,  := .recovered.(error)
			// in this specific case, the stdlib would/will suppress the panic, so we
			// suppress the logging here accordingly, to get a similar and consistent
			// behavior.
			if ! || .Error() != errAbortHandler.Error() {
				fmt.Fprintln(.interp.stderr, .cfgErrorf("panic: %s(...)", panicFunc(.scope)))
			}
			.mutex.Unlock()
			panic(.recovered)
		}
		.mutex.Unlock()
	}()

	 := .interp.debugger
	if  == nil {
		for  := .exec;  != nil && .runid() == .interp.runid(); {
			 = ()
		}
		return
	}

	if .exec == nil {
		return
	}

	.enterCall(, , )
	defer .exitCall(, , )

	for ,  := , .exec; .runid() == .interp.runid(); {
		if .exec(, ) {
			break
		}

		 = ()
		if  == nil {
			break
		}

		if  == nil {
			 = originalExecNode(, )
			continue
		}

		switch {
		case isExecNode(.tnext, ):
			 = .tnext
		case isExecNode(.fnext, ):
			 = .fnext
		default:
			 = originalExecNode(, )
		}
	}
}

func stripReceiverFromArgs( string) (string, error) {
	 := receiverStripperRxp.FindStringSubmatch()
	if len() < 5 {
		return "", errors.New("error while matching method signature")
	}
	if [3] == ")" {
		return fmt.Sprintf("func()%s", [4]), nil
	}
	return fmt.Sprintf("func(%s", [4]), nil
}

func typeAssertShort( *node) {
	typeAssert(, true, false)
}

func typeAssertLong( *node) {
	typeAssert(, true, true)
}

func typeAssertStatus( *node) {
	typeAssert(, false, true)
}

func typeAssert( *node, ,  bool) {
	,  := .child[0], .child[1]
	 := genValue() // input value
	var ,  func(*frame) reflect.Value
	 := false
	switch {
	case  && :
		 = genValue(.anc.child[0])       // returned result
		 = genValue(.anc.child[1])       // returned status
		 = .anc.child[1].ident != "_" // do not assign status to "_"
	case  && !:
		 = genValue() // returned result
	case ! && :
		 = genValue(.anc.child[1])       // returned status
		 = .anc.child[1].ident != "_" // do not assign status to "_"
	}

	 := .typ // type to assert or convert to
	 := .id()
	 := .refType(nil) // type to assert
	 := getExec(.tnext)

	switch {
	case isInterfaceSrc():
		.exec = func( *frame) bltn {
			 := ()
			,  := .Interface().(valueInterface)
			if  {
				defer func() {
					().SetBool()
				}()
			}
			if ! {
				if ! {
					panic(.cfgErrorf("interface conversion: nil is not %v", ))
				}
				return 
			}
			if .typ.cat == valueT {
				 = reflect.ValueOf()
			}
			if .node.typ.id() ==  {
				if  {
					().Set()
				}
				return 
			}
			 := .node.typ.methods()
			 := .methods()
			if len() < len() {
				 = false
				if ! {
					panic(.cfgErrorf("interface conversion: %v is not %v", .node.typ.id(), ))
				}
				return 
			}

			for ,  := range  {
				var  string
				,  = []
				if ! {
					return 
				}
				// As far as we know this equality check can fail because they are two ways to
				// represent the signature of a method: one where the receiver appears before the
				// func keyword, and one where it is just a func signature, and the receiver is
				// seen as the first argument. That's why if that equality fails, we try harder to
				// compare them afterwards. Hopefully that is the only reason this equality can fail.
				if  ==  {
					continue
				}
				 := lookupFieldOrMethod(.node.typ, )
				if  == nil {
					 = false
					return 
				}

				var  error
				,  = stripReceiverFromArgs()
				if  != nil {
					 = false
					return 
				}

				if  !=  {
					 = false
					return 
				}
			}

			if  {
				().Set()
			}
			return 
		}
	case isInterface():
		.exec = func( *frame) bltn {
			var  reflect.Type
			 := ()
			,  := .Interface().(valueInterface)
			if  {
				defer func() {
					().SetBool()
				}()
			}
			if  && .node.typ.cat != valueT {
				 := .node.typ.methods()
				 := .methods()
				if len() < len() {
					 = false
					return 
				}

				for ,  := range  {
					var  string
					,  = []
					if ! {
						return 
					}
					if  !=  {
						 = false
						return 
					}
				}

				if  {
					().Set(genInterfaceWrapper(.node, )())
				}
				 = true
				return 
			}

			if  {
				 = .value
				 = .node.typ.rtype
			} else {
				 = .Elem()
				 = .Type()
				 = true
			}
			 = .IsValid()
			if ! {
				if ! {
					panic(.cfgErrorf("interface conversion: interface {} is nil, not %s", .String()))
				}
				return 
			}
			 = canAssertTypes(, )
			if ! {
				if ! {
					 := firstMissingMethod(, )
					panic(.cfgErrorf("interface conversion: %s is not %s: missing method %s", .String(), .String(), ))
				}
				return 
			}
			if  {
				().Set()
			}
			return 
		}
	case isEmptyInterface(.child[0].typ):
		.exec = func( *frame) bltn {
			var  bool
			if  {
				defer func() {
					().SetBool()
				}()
			}
			 := ()
			 := .Interface()
			 := reflect.TypeOf()

			if ,  := .(valueInterface);  {
				 = .value.Type()
				 = .value.Interface()
			}
			 = canAssertTypes(, )
			if ! {
				if ! {
					// TODO(mpl): think about whether this should ever happen.
					if  == nil {
						panic(.cfgErrorf("interface conversion: interface {} is nil, not %s", .String()))
					}
					panic(.cfgErrorf("interface conversion: interface {} is %s, not %s", .String(), .String()))
				}
				return 
			}
			if  {
				if isInterfaceSrc() {
					// TODO(mpl): this requires more work. the wrapped node is not complete enough.
					().Set(reflect.ValueOf(valueInterface{.child[0], reflect.ValueOf()}))
				} else {
					().Set(reflect.ValueOf())
				}
			}
			return 
		}
	case .child[0].typ.cat == valueT || .child[0].typ.cat == errorT:
		.exec = func( *frame) bltn {
			 := ().Elem()
			 := .IsValid()
			if  {
				defer func() {
					().SetBool()
				}()
			}
			if ! {
				if ! {
					panic(.cfgErrorf("interface conversion: interface {} is nil, not %s", .String()))
				}
				return 
			}
			 = valueInterfaceValue()
			if  := .Type(); .Kind() == reflect.Struct && .Field(0).Name == "IValue" {
				// Value is retrieved from an interface wrapper.
				 = .Field(0).Elem()
			}
			 = canAssertTypes(.Type(), )
			if ! {
				if ! {
					 := firstMissingMethod(.Type(), )
					panic(.cfgErrorf("interface conversion: %s is not %s: missing method %s", .Type().String(), .String(), ))
				}
				return 
			}
			if  {
				().Set()
			}
			return 
		}
	default:
		.exec = func( *frame) bltn {
			,  := ().Interface().(valueInterface)
			if  {
				defer func() {
					().SetBool()
				}()
			}
			if ! || !.value.IsValid() {
				 = false
				if ! {
					panic(.cfgErrorf("interface conversion: interface {} is nil, not %s", .String()))
				}
				return 
			}

			 = canAssertTypes(.value.Type(), )
			if ! {
				if ! {
					panic(.cfgErrorf("interface conversion: interface {} is %s, not %s", .value.Type().String(), .String()))
				}
				return 
			}
			if  {
				().Set(.value)
			}
			return 
		}
	}
}

func canAssertTypes(,  reflect.Type) bool {
	if  == nil {
		return false
	}
	if  ==  {
		return true
	}
	if .Kind() == reflect.Interface && .Implements() {
		return true
	}
	if  == nil {
		return false
	}
	if .AssignableTo() {
		return true
	}
	return false
}

func firstMissingMethod(,  reflect.Type) string {
	for  := 0;  < .NumMethod(); ++ {
		 := .Method().Name
		if ,  := .MethodByName(); ! {
			return 
		}
	}
	return ""
}

func convert( *node) {
	 := genValue()
	 := .child[1]
	 := .child[0].typ.frameType()
	 := getExec(.tnext)

	if .isNil() { // convert nil to type
		// TODO(mpl): Try to completely remove, as maybe frameType already does the job for interfaces.
		if isInterfaceSrc(.child[0].typ) && !isEmptyInterface(.child[0].typ) {
			 = valueInterfaceType
		}
		.exec = func( *frame) bltn {
			().Set(reflect.New().Elem())
			return 
		}
		return
	}

	 := true
	var  func(*frame) reflect.Value
	switch {
	case isFuncSrc(.typ):
		 = genFunctionWrapper()
	default:
		 = genValue()
	}

	for ,  := range .interp.hooks.convert {
		if .typ.rtype == nil {
			continue
		}

		 := (.typ.rtype, )
		if  == nil {
			continue
		}
		.exec = func( *frame) bltn {
			((), ())
			return 
		}
		return
	}

	.exec = func( *frame) bltn {
		if  {
			().Set(().Convert())
		} else {
			().Set(())
		}
		return 
	}
}

// assignFromCall assigns values from a function call.
func assignFromCall( *node) {
	 := .lastChild()
	 := len(.child) - 1
	if .anc.kind == varDecl && .child[-1].isType(.scope) {
		// Ignore the type in the assignment if it is part of a variable declaration.
		--
	}
	 := make([]func(*frame) reflect.Value, )
	for  := range  {
		if .child[].ident == "_" {
			continue
		}
		[] = genValue(.child[])
	}
	 := getExec(.tnext)
	.exec = func( *frame) bltn {
		for ,  := range  {
			if  == nil {
				continue
			}
			 := .data[.findex+]
			 := .child[]
			if .kind == defineXStmt && !.redeclared {
				// Recreate destination value in case of define statement,
				// to preserve previous value possibly in use by a closure.
				 := getFrame(, .level).data
				[.findex] = reflect.New([.findex].Type()).Elem()
				[.findex].Set()
				continue
			}
			().Set()
		}
		return 
	}
}

func assign( *node) {
	 := getExec(.tnext)
	 := make([]func(*frame) reflect.Value, .nleft)
	 := make([]func(*frame) reflect.Value, .nleft)
	 := make([]func(*frame) reflect.Value, .nleft)
	var  int
	if .nright > 0 {
		 = len(.child) - .nright
	}

	for  := 0;  < .nleft; ++ {
		,  := .child[], .child[+]
		if isNamedFuncSrc(.typ) {
			[] = genFuncValue()
		} else {
			[] = genDestValue(.typ, )
		}
		if isMapEntry() {
			if isInterfaceSrc(.child[1].typ) { // key
				[] = genValueInterface(.child[1])
			} else {
				[] = genValue(.child[1])
			}
			[] = genValue(.child[0])
		} else {
			[] = genValue()
		}
	}

	if .nleft == 1 {
		// Single assign operation.
		switch , ,  := [0], [0], [0]; {
		case .child[0].ident == "_":
			.exec = func( *frame) bltn {
				return 
			}
		case  != nil:
			.exec = func( *frame) bltn {
				().SetMapIndex((), ())
				return 
			}
		case .kind == defineStmt:
			 := .level
			 := .findex
			.exec = func( *frame) bltn {
				 := getFrame(, ).data
				[] = reflect.New([].Type()).Elem()
				[].Set(())
				return 
			}
		default:
			.exec = func( *frame) bltn {
				().Set(())
				return 
			}
		}
		return
	}

	// Multi assign operation.
	 := make([]reflect.Type, .nright)
	 := make([]int, .nright)
	 := make([]int, .nright)

	for  := range  {
		var  reflect.Type
		switch  := .child[+].typ; {
		case isInterfaceSrc():
			 = valueInterfaceType
		default:
			 = .TypeOf()
		}
		[] = 
		[] = .child[].findex
		[] = .child[].level
	}

	if .kind == defineStmt {
		// Handle a multiple var declararation / assign. It cannot be a swap.
		.exec = func( *frame) bltn {
			for ,  := range  {
				if .child[].ident == "_" {
					continue
				}
				 := getFrame(, []).data
				 := []
				[] = reflect.New([].Type()).Elem()
				[].Set(())
			}
			return 
		}
		return
	}

	// To handle possible swap in multi-assign:
	// evaluate and copy all values in assign right hand side into temporary
	// then evaluate assign left hand side and copy temporary into it
	.exec = func( *frame) bltn {
		 := make([]reflect.Value, len())
		for ,  := range  {
			if .child[].ident == "_" {
				continue
			}
			[] = reflect.New([]).Elem()
			[].Set(())
		}
		for ,  := range  {
			if .child[].ident == "_" {
				continue
			}
			if  := [];  != nil {
				().SetMapIndex((), []) // Assign a map entry
			} else {
				().Set([]) // Assign a var or array/slice entry
			}
		}
		return 
	}
}

func not( *node) {
	 := genValue()
	 := genValue(.child[0])
	 := getExec(.tnext)

	if .fnext != nil {
		 := getExec(.fnext)
		.exec = func( *frame) bltn {
			if !().Bool() {
				().SetBool(true)
				return 
			}
			().SetBool(false)
			return 
		}
	} else {
		.exec = func( *frame) bltn {
			().SetBool(!().Bool())
			return 
		}
	}
}

func addr( *node) {
	 := genValue()
	 := getExec(.tnext)
	 := .child[0]
	 := genValue()

	if isInterfaceSrc(.typ) || isPtrSrc(.typ) {
		 := .findex
		 := .level
		.exec = func( *frame) bltn {
			getFrame(, ).data[] = ().Addr()
			return 
		}
		return
	}

	.exec = func( *frame) bltn {
		().Set(().Addr())
		return 
	}
}

func deref( *node) {
	 := genValue(.child[0])
	 := getExec(.tnext)
	 := .findex
	 := .level

	if .fnext != nil {
		 := getExec(.fnext)
		.exec = func( *frame) bltn {
			 := ().Elem()
			if .Bool() {
				getFrame(, ).data[] = 
				return 
			}
			return 
		}
	} else {
		.exec = func( *frame) bltn {
			getFrame(, ).data[] = ().Elem()
			return 
		}
	}
}

func _print( *node) {
	 := .child[1:]
	 := make([]func(*frame) reflect.Value, len())
	for ,  := range  {
		[] = genValue()
	}
	 := .interp.stdout

	genBuiltinDeferWrapper(, , nil, func( []reflect.Value) []reflect.Value {
		for ,  := range  {
			if  > 0 {
				fmt.Fprintf(, " ")
			}
			fmt.Fprintf(, "%v", )
		}
		return nil
	})
}

func _println( *node) {
	 := .child[1:]
	 := make([]func(*frame) reflect.Value, len())
	for ,  := range  {
		[] = genValue()
	}
	 := .interp.stdout

	genBuiltinDeferWrapper(, , nil, func( []reflect.Value) []reflect.Value {
		for ,  := range  {
			if  > 0 {
				fmt.Fprintf(, " ")
			}
			fmt.Fprintf(, "%v", )
		}
		fmt.Fprintln(, "")
		return nil
	})
}

func _recover( *node) {
	 := getExec(.tnext)
	 := genValue()

	.exec = func( *frame) bltn {
		if .anc.recovered == nil {
			// TODO(mpl): maybe we don't need that special case, and we're just forgetting to unwrap the valueInterface somewhere else.
			if isEmptyInterface(.typ) {
				return 
			}
			().Set(reflect.ValueOf(valueInterface{}))
			return 
		}

		if isEmptyInterface(.typ) {
			().Set(reflect.ValueOf(.anc.recovered))
		} else {
			().Set(reflect.ValueOf(valueInterface{, reflect.ValueOf(.anc.recovered)}))
		}
		.anc.recovered = nil
		return 
	}
}

func _panic( *node) {
	 := genValue(.child[1])

	.exec = func( *frame) bltn {
		panic(())
	}
}

func genBuiltinDeferWrapper( *node, ,  []func(*frame) reflect.Value,  func([]reflect.Value) []reflect.Value) {
	 := getExec(.tnext)

	if .anc.kind == deferStmt {
		.exec = func( *frame) bltn {
			 := make([]reflect.Value, len()+1)
			 := make([]reflect.Type, len())
			for ,  := range  {
				[+1] = ()
				[] = [+1].Type()
			}
			 := make([]reflect.Type, len())
			for ,  := range  {
				[] = ().Type()
			}

			 := reflect.FuncOf(, , false)
			[0] = reflect.MakeFunc(, )
			.deferred = append([][]reflect.Value{}, .deferred...)
			return 
		}
		return
	}

	.exec = func( *frame) bltn {
		 := make([]reflect.Value, len())
		for ,  := range  {
			[] = ()
		}

		 := ()

		for ,  := range  {
			[]().Set()
		}
		return 
	}
}

func genFunctionWrapper( *node) func(*frame) reflect.Value {
	var  *node
	var  bool

	if ,  = .val.(*node); ! {
		return genValueAsFunctionWrapper()
	}
	 := .child[3].start
	 := len(.typ.ret)
	var  func(*frame) reflect.Value

	if .recv != nil {
		 = genValueRecv()
	}
	 := .typ.TypeOf()

	return func( *frame) reflect.Value {
		return reflect.MakeFunc(, func( []reflect.Value) []reflect.Value {
			// Allocate and init local frame. All values to be settable and addressable.
			 := newFrame(, len(.types), .runid())
			 := .data
			for ,  := range .types {
				[] = reflect.New().Elem()
			}

			if  == nil {
				 = [:]
			} else {
				// Copy method receiver as first argument.
				,  := (), []
				,  := .Kind(), .Kind()
				for {
					,  := .Interface().(valueInterface)
					if ! {
						break
					}
					 = .value
					 = .Kind()
				}
				switch {
				case  == reflect.Ptr &&  != reflect.Ptr:
					.Set(.Elem())
				case  != reflect.Ptr &&  == reflect.Ptr:
					.Set(.Addr())
				default:
					.Set()
				}
				 = [+1:]
			}

			// Copy function input arguments in local frame.
			for ,  := range  {
				if  >= len() {
					// In case of unused arg, there may be not even a frame entry allocated, just skip.
					break
				}
				 := .typ.arg[]
				switch {
				case isEmptyInterface() || .TypeOf() == valueInterfaceType:
					[].Set()
				case isInterfaceSrc():
					[].Set(reflect.ValueOf(valueInterface{value: .Elem()}))
				default:
					[].Set()
				}
			}

			// Interpreter code execution.
			runCfg(, , , )

			return .data[:]
		})
	}
}

func genInterfaceWrapper( *node,  reflect.Type) func(*frame) reflect.Value {
	 := genValue()
	if  == nil || .Kind() != reflect.Interface || .NumMethod() == 0 || .typ.cat == valueT {
		return 
	}
	 := .typ.cat
	if  != structT {
		// Always force wrapper generation for struct types, as they may contain
		// embedded interface fields which require wrapping, even if reported as
		// implementing typ by reflect.
		if  := .typ.frameType();  != nil && .Implements() {
			return 
		}
	}

	// Retrieve methods from the interface wrapper, which is a struct where all fields
	// except the first define the methods to implement.
	// As the field name was generated with a prefixed first character (in order to avoid
	// collisions with method names), this first character is ignored in comparisons.
	 := getWrapper(, )
	 := .NumField() - 1
	 := make([]string, )
	 := make([]*node, )
	 := make([][]int, )
	for  := 0;  < ; ++ {
		[] = .Field( + 1).Name[1:]
		[], [] = .typ.lookupMethod([])
		if [] == nil && .typ.cat != nilT {
			// interpreted method not found, look for binary method, possibly embedded
			_, [], _, _ = .typ.lookupBinMethod([])
		}
	}

	return func( *frame) reflect.Value {
		 := ()
		if  != structT && .Type().Implements() {
			return 
		}
		switch .Kind() {
		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
			if .IsNil() {
				return reflect.New().Elem()
			}
		}
		var  *node
		if ,  := .Interface().(valueInterface);  {
			 = .node
		}
		 = getConcreteValue()
		 := reflect.New().Elem()
		.Field(0).Set()
		for ,  := range  {
			if  == nil {
				// First direct method lookup on field.
				if  := methodByName(, [], []); .IsValid() {
					.Field( + 1).Set()
					continue
				}
				if  == nil {
					panic(.cfgErrorf("method not found: %s", []))
				}
				// Method lookup in embedded valueInterface.
				,  := .typ.lookupMethod([])
				if  != nil {
					 := *
					.recv = &receiver{, , }
					.Field( + 1).Set(genFunctionWrapper(&)())
					continue
				}
				panic(.cfgErrorf("method not found: %s", []))
			}
			 := *
			.recv = &receiver{, , []}
			.Field( + 1).Set(genFunctionWrapper(&)())
		}
		return 
	}
}

// methodByName returns the method corresponding to name on value, or nil if not found.
// The search is extended on valueInterface wrapper if present.
// If valid, the returned value is a method function with the receiver already set
// (no need to pass it at call).
func methodByName( reflect.Value,  string,  []int) ( reflect.Value) {
	if ,  := .Interface().(valueInterface);  {
		if  = getConcreteValue(.value).MethodByName(); .IsValid() {
			return
		}
	}
	if  = .MethodByName(); .IsValid() {
		return
	}
	for .Kind() == reflect.Ptr {
		 = .Elem()
		if checkFieldIndex(.Type(), ) {
			 = .FieldByIndex()
		}
		if  = .MethodByName(); .IsValid() {
			return
		}
	}
	return
}

func checkFieldIndex( reflect.Type,  []int) bool {
	if len() == 0 {
		return false
	}
	 := 
	for .Kind() == reflect.Ptr {
		 = .Elem()
	}
	if .Kind() != reflect.Struct {
		return false
	}
	 := [0]
	if  >= .NumField() {
		return false
	}
	if len() > 1 {
		return (.Field().Type, [1:])
	}
	return true
}

func call( *node) {
	 := .anc.kind == goStmt
	 := .child[0]
	 := genValue()
	var  []func(*frame) reflect.Value

	 := len(.typ.ret)
	 := variadicPos()
	 := .child[1:]
	 := getExec(.tnext)
	 := getExec(.fnext)
	 := .action == aCallSlice // callSlice implies variadic call with ellipsis.

	// Compute input argument value functions.
	for ,  := range  {
		var  *itype
		if  >= 0 &&  >=  {
			 = .typ.arg[].val
		} else {
			 = .typ.arg[]
		}
		switch {
		case isBinCall(, .scope):
			// Handle nested function calls: pass returned values as arguments.
			 := .child[0].typ.rtype.NumOut()
			for  := 0;  < ; ++ {
				 := .findex + 
				if  || !isInterfaceSrc() || isEmptyInterface() {
					 = append(, func( *frame) reflect.Value { return .data[] })
					continue
				}
				 = append(, func( *frame) reflect.Value {
					return reflect.ValueOf(valueInterface{value: .data[]})
				})
			}
		case isRegularCall():
			// Arguments are return values of a nested function call.
			 := .child[0]
			for  := range .typ.ret {
				 := .findex + 
				if  || !isInterfaceSrc() || isEmptyInterface() {
					 = append(, func( *frame) reflect.Value { return .data[] })
					continue
				}
				 = append(, func( *frame) reflect.Value {
					return reflect.ValueOf(valueInterface{node: .typ.ret[].node, value: .data[]})
				})
			}
		default:
			if .kind == basicLit || .rval.IsValid() {
				 := .TypeOf()
				convertLiteralValue(, )
			}
			switch {
			case :
				 = append(, genValue())
			case isInterfaceSrc() && (!isEmptyInterface() || len(.typ.method) > 0):
				 = append(, genValueInterface())
			case isInterfaceBin():
				 = append(, genInterfaceWrapper(, .rtype))
			case isFuncSrc():
				 = append(, genFuncValue())
			default:
				 = append(, genValue())
			}
		}
	}

	// Compute output argument value functions.
	 := .typ.ret
	 := make([]func(*frame) reflect.Value, len())
	switch .anc.kind {
	case defineXStmt, assignXStmt:
		 := .level
		for  := range  {
			 := .anc.child[]
			switch {
			case .ident == "_":
				// Skip assigning return value to blank var.
			case isInterfaceSrc(.typ) && !isEmptyInterface(.typ) && !isInterfaceSrc([]):
				[] = genValueInterfaceValue()
			default:
				 := .findex + 
				[] = func( *frame) reflect.Value { return getFrame(, ).data[] }
			}
		}
	case returnStmt:
		// Function call from a return statement: forward return values (always at frame start).
		for  := range  {
			 := .findex + 
			// Set the return value location in return value of caller frame.
			[] = func( *frame) reflect.Value { return .data[] }
		}
	default:
		// Multiple return values frame index are indexed from the node frame index.
		 := .level
		for  := range  {
			 := .findex + 
			[] = func( *frame) reflect.Value { return getFrame(, ).data[] }
		}
	}

	if .anc.kind == deferStmt {
		// Store function call in frame for deferred execution.
		 = genFunctionWrapper()
		.exec = func( *frame) bltn {
			 := make([]reflect.Value, len()+1)
			[0] = ()
			for ,  := range  {
				[+1] = ()
			}
			.deferred = append([][]reflect.Value{}, .deferred...)
			return 
		}
		return
	}

	.exec = func( *frame) bltn {
		.mutex.Lock()
		 := ()
		,  := .Interface().(*node)
		if  {
			 = .rval
		}
		.mutex.Unlock()

		// Call bin func if defined
		if .IsValid() {
			var  func([]reflect.Value) []reflect.Value

			// Lambda definitions are necessary here. Due to reflect internals,
			// having `callf = bf.Call` or `callf = bf.CallSlice` does not work.
			//nolint:gocritic
			if  {
				 = func( []reflect.Value) []reflect.Value { return .CallSlice() }
			} else {
				 = func( []reflect.Value) []reflect.Value { return .Call() }
			}

			if  {
				// Goroutine's arguments should be copied.
				 := make([]reflect.Value, len())
				for ,  := range  {
					 := ()
					[] = reflect.New(.Type()).Elem()
					[].Set()
				}

				go ()
				return 
			}

			 := make([]reflect.Value, len())
			for ,  := range  {
				[] = ()
			}
			 := ()
			for ,  := range  {
				if  != nil {
					().Set([])
				}
			}
			if  != nil && ![0].Bool() {
				return 
			}
			return 
		}

		 := newFrame(, len(.types), .runid())
		var  reflect.Value

		// Init return values
		for ,  := range  {
			if  != nil {
				.data[] = ()
			} else {
				.data[] = reflect.New(.types[]).Elem()
			}
		}

		// Init local frame values
		for ,  := range .types[:] {
			.data[+] = reflect.New().Elem()
		}

		// Init variadic argument vector
		if  >= 0 {
			 = .data[+]
		}

		// Copy input parameters from caller
		if  := .data[:]; len() > 0 {
			for ,  := range  {
				switch {
				case  >= 0 &&  >= :
					if ().Type() == .Type() {
						.Set(())
					} else {
						.Set(reflect.Append(, ()))
					}
				default:
					 := ()
					if .IsZero() && [].Kind() != reflect.Interface {
						// Work around a recursive struct zero interface issue.
						// Once there is a better way to handle this case, the dest can just be set.
						continue
					}
					if ,  := .Interface().(*node);  && .recv != nil {
						// An interpreted method is passed as value in a function call.
						// It must be wrapped now, otherwise the receiver will be missing
						// at the method call (#1332).
						// TODO (marc): wrapping interpreted functions should be always done
						// everywhere at runtime to simplify the whole code,
						// but it requires deeper refactoring.
						[] = genFunctionWrapper()()
						continue
					}
					[].Set()
				}
			}
		}

		// Execute function body
		if  {
			go runCfg(.child[3].start, , , )
			return 
		}
		runCfg(.child[3].start, , , )

		// Handle branching according to boolean result
		if  != nil && !.data[0].Bool() {
			return 
		}
		return 
	}
}

func getFrame( *frame,  int) *frame {
	switch  {
	case globalFrame:
		return .root
	case 0:
		return 
	case 1:
		return .anc
	case 2:
		return .anc.anc
	}
	for ;  > 0; -- {
		 = .anc
	}
	return 
}

// Callbin calls a function from a bin import, accessible through reflect.
func callBin( *node) {
	 := getExec(.tnext)
	 := getExec(.fnext)
	 := .child[1:]
	 := .child[0]
	 := genValue()
	var  []func(*frame) reflect.Value
	 := .typ.rtype
	 := wrappedType()
	 := -1
	if .IsVariadic() {
		 = .NumIn() - 1
	}
	// A method signature obtained from reflect.Type includes receiver as 1st arg, except for interface types.
	 := 0
	if  := .recv;  != nil && !isInterface(.node.typ) {
		if  > 0 || .NumIn() > len() {
			 = 1
		}
	}

	// getMapType returns a reflect type suitable for interface wrapper for functions
	// with some special processing in case of interface{} argument, i.e. fmt.Printf.
	var  func(*itype) reflect.Type
	if ,  := .interp.mapTypes[.rval];  {
		 = func( *itype) reflect.Type {
			for ,  := range  {
				if .implements(&itype{cat: valueT, rtype: }) {
					return 
				}
			}
			return nil
		}
	}

	// Determine if we should use `Call` or `CallSlice` on the function Value.
	 := func( reflect.Value,  []reflect.Value) []reflect.Value { return .Call() }
	if .action == aCallSlice {
		 = func( reflect.Value,  []reflect.Value) []reflect.Value { return .CallSlice() }
	}

	for ,  := range  {
		switch {
		case isBinCall(, .scope):
			// Handle nested function calls: pass returned values as arguments
			 := .child[0].typ.rtype.NumOut()
			for  := 0;  < ; ++ {
				 := .findex + 
				 = append(, func( *frame) reflect.Value { return valueInterfaceValue(.data[]) })
			}
		case isRegularCall():
			// Handle nested function calls: pass returned values as arguments
			for  := range .child[0].typ.ret {
				 := .findex + 
				 = append(, func( *frame) reflect.Value { return valueInterfaceValue(.data[]) })
			}
		default:
			if .kind == basicLit || .rval.IsValid() {
				// Convert literal value (untyped) to function argument type (if not an interface{})
				var  reflect.Type
				if  >= 0 && + >=  {
					 = .In().Elem()
				} else {
					 = .In( + )
				}
				convertLiteralValue(, )
				if !reflect.ValueOf(.val).IsValid() { //  Handle "nil"
					.val = reflect.Zero()
				}
			}

			if  != nil && isInterfaceSrc(.arg[]) {
				 = append(, genValueInterface())
				break
			}

			// defType is the target type for a potential interface wrapper.
			var  reflect.Type
			if  >= 0 && + >=  {
				 = .In()
			} else {
				 = .In( + )
			}
			if  != nil {
				if  := (.typ);  != nil {
					 = 
				}
			}

			switch {
			case isEmptyInterface(.typ):
				 = append(, genValue())
			case isInterfaceSrc(.typ):
				 = append(, genValueInterfaceValue())
			case isFuncSrc(.typ):
				 = append(, genFunctionWrapper())
			case .typ.cat == arrayT || .typ.cat == variadicT:
				if isEmptyInterface(.typ.val) {
					 = append(, genValueArray())
				} else {
					 = append(, genInterfaceWrapper(, ))
				}
			case isPtrSrc(.typ):
				if .typ.val.cat == valueT {
					 = append(, genValue())
				} else {
					 = append(, genInterfaceWrapper(, ))
				}
			case .typ.cat == valueT:
				 = append(, genValue())
			default:
				 = append(, genInterfaceWrapper(, ))
			}
		}
	}
	 := len()

	switch {
	case .anc.kind == deferStmt:
		// Store function call in frame for deferred execution.
		.exec = func( *frame) bltn {
			 := make([]reflect.Value, +1)
			[0] = ()
			for ,  := range  {
				[+1] = getBinValue(, , )
			}
			.deferred = append([][]reflect.Value{}, .deferred...)
			return 
		}
	case .anc.kind == goStmt:
		// Execute function in a goroutine, discard results.
		.exec = func( *frame) bltn {
			 := make([]reflect.Value, )
			for ,  := range  {
				[] = getBinValue(, , )
			}
			go ((), )
			return 
		}
	case  != nil:
		// Handle branching according to boolean result.
		 := .findex
		 := .level
		.exec = func( *frame) bltn {
			 := make([]reflect.Value, )
			for ,  := range  {
				[] = getBinValue(, , )
			}
			 := ((), )
			 := [0].Bool()
			getFrame(, ).data[].SetBool()
			if  {
				return 
			}
			return 
		}
	default:
		switch .anc.action {
		case aAssignX:
			// The function call is part of an assign expression, store results direcly
			// to assigned location, to avoid an additional frame copy.
			// The optimization of aAssign is handled in assign(), and should not
			// be handled here.
			 := make([]func(*frame) reflect.Value, .NumOut())
			for  := range  {
				 := .anc.child[]
				if .ident == "_" {
					continue
				}
				if isInterfaceSrc(.typ) {
					[] = genValueInterfaceValue()
				} else {
					[] = genValue()
				}
			}
			.exec = func( *frame) bltn {
				 := make([]reflect.Value, )
				for ,  := range  {
					[] = getBinValue(, , )
				}
				 := ((), )
				for ,  := range  {
					if  == nil {
						continue // Skip assign "_".
					}
					 := .anc.child[]
					if .anc.kind == defineXStmt && !.redeclared {
						// In case of a define statement, the destination value in the frame
						// must be recreated. This is necessary to preserve the previous value
						// which may be still used in a separate closure.
						 := getFrame(, .level).data
						[.findex] = reflect.New([.findex].Type()).Elem()
						[.findex].Set([])
						continue
					}
					().Set([])
				}
				return 
			}
		case aReturn:
			// The function call is part of a return statement, store output results
			// directly in the frame location of outputs of the current function.
			 := childPos()
			.exec = func( *frame) bltn {
				 := make([]reflect.Value, )
				for ,  := range  {
					[] = getBinValue(, , )
				}
				 := ((), )
				for ,  := range  {
					 := .data[+]
					if ,  := .Interface().(valueInterface);  {
						 = reflect.ValueOf(valueInterface{value: })
					}
					.Set()
				}
				return 
			}
		default:
			.exec = func( *frame) bltn {
				 := make([]reflect.Value, )
				for ,  := range  {
					[] = getBinValue(, , )
				}
				 := ((), )
				for  := 0;  < len(); ++ {
					 := []
					if .Kind() == reflect.Func {
						getFrame(, .level).data[.findex+] = 
						continue
					}
					 := getFrame(, .level).data[.findex+]
					if ,  := .Interface().(valueInterface);  {
						 = reflect.ValueOf(valueInterface{value: })
					}
					.Set()
				}
				return 
			}
		}
	}
}

func getIndexBinMethod( *node) {
	// dest := genValue(n)
	 := .findex
	 := .level
	 := .val.(int)
	 := genValue(.child[0])
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		// Can not use .Set() because dest type contains the receiver and source not
		// dest(f).Set(value(f).Method(m))
		getFrame(, ).data[] = ().Method()
		return 
	}
}

func getIndexBinElemMethod( *node) {
	 := .findex
	 := .level
	 := .val.(int)
	 := genValue(.child[0])
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		// Can not use .Set() because dest type contains the receiver and source not
		getFrame(, ).data[] = ().Elem().Method()
		return 
	}
}

func getIndexBinPtrMethod( *node) {
	 := .findex
	 := .level
	 := .val.(int)
	 := genValue(.child[0])
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		// Can not use .Set() because dest type contains the receiver and source not
		getFrame(, ).data[] = ().Addr().Method()
		return 
	}
}

// getIndexArray returns array value from index.
func getIndexArray( *node) {
	 := getExec(.tnext)
	 := genValueArray(.child[0]) // array
	 := .findex
	 := .level

	if .child[1].rval.IsValid() { // constant array index
		 := int(vInt(.child[1].rval))
		if .fnext != nil {
			 := getExec(.fnext)
			.exec = func( *frame) bltn {
				 := ().Index()
				getFrame(, ).data[] = 
				if .Bool() {
					return 
				}
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Index()
				return 
			}
		}
	} else {
		 := genValueInt(.child[1]) // array index

		if .fnext != nil {
			 := getExec(.fnext)
			.exec = func( *frame) bltn {
				,  := ()
				 := ().Index(int())
				getFrame(, ).data[] = 
				if .Bool() {
					return 
				}
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				,  := ()
				getFrame(, ).data[] = ().Index(int())
				return 
			}
		}
	}
}

// getIndexMap retrieves map value from index.
func getIndexMap( *node) {
	 := genValue()
	 := genValue(.child[0]) // map
	 := getExec(.tnext)
	 := reflect.New(.child[0].typ.frameType().Elem()).Elem()

	if .child[1].rval.IsValid() { // constant map index
		 := .child[1].rval

		switch {
		case .fnext != nil:
			 := getExec(.fnext)
			.exec = func( *frame) bltn {
				if  := ().MapIndex(); .IsValid() && .Bool() {
					().SetBool(true)
					return 
				}
				().Set()
				return 
			}
		default:
			.exec = func( *frame) bltn {
				if  := ().MapIndex(); .IsValid() {
					().Set()
				} else {
					().Set()
				}
				return 
			}
		}
	} else {
		 := genValue(.child[1]) // map index

		switch {
		case .fnext != nil:
			 := getExec(.fnext)
			.exec = func( *frame) bltn {
				if  := ().MapIndex(()); .IsValid() && .Bool() {
					().SetBool(true)
					return 
				}
				().Set()
				return 
			}
		default:
			.exec = func( *frame) bltn {
				if  := ().MapIndex(()); .IsValid() {
					().Set()
				} else {
					().Set()
				}
				return 
			}
		}
	}
}

// getIndexMap2 retrieves map value from index and set status.
func getIndexMap2( *node) {
	 := genValue(.anc.child[0])   // result
	 := genValue(.child[0])     // map
	 := genValue(.anc.child[1]) // status
	 := getExec(.tnext)
	 := .anc.child[0].ident != "_"
	 := .anc.child[1].ident != "_"

	if ! && ! {
		nop()
		return
	}
	if .child[1].rval.IsValid() { // constant map index
		 := .child[1].rval
		switch {
		case !:
			.exec = func( *frame) bltn {
				 := ().MapIndex()
				().SetBool(.IsValid())
				return 
			}
		default:
			.exec = func( *frame) bltn {
				 := ().MapIndex()
				if .IsValid() {
					().Set()
				}
				if  {
					().SetBool(.IsValid())
				}
				return 
			}
		}
	} else {
		 := genValue(.child[1]) // map index
		switch {
		case !:
			.exec = func( *frame) bltn {
				 := ().MapIndex(())
				().SetBool(.IsValid())
				return 
			}
		default:
			.exec = func( *frame) bltn {
				 := ().MapIndex(())
				if .IsValid() {
					().Set()
				}
				if  {
					().SetBool(.IsValid())
				}
				return 
			}
		}
	}
}

// getFunc compiles a closure function generator for anonymous functions.
func getFunc( *node) {
	 := .findex
	 := .level
	 := getExec(.tnext)
	 := len(.typ.ret)

	.exec = func( *frame) bltn {
		 := .clone()
		 := getFrame(, ).data[]

		 := reflect.MakeFunc(.typ.TypeOf(), func( []reflect.Value) []reflect.Value {
			// Allocate and init local frame. All values to be settable and addressable.
			 := newFrame(, len(.types), .runid())
			 := .data
			for ,  := range .types {
				[] = reflect.New().Elem()
			}
			 = [:]

			// Copy function input arguments in local frame.
			for ,  := range  {
				if  >= len() {
					// In case of unused arg, there may be not even a frame entry allocated, just skip.
					break
				}
				 := .typ.arg[]
				switch {
				case isEmptyInterface() || .TypeOf() == valueInterfaceType:
					[].Set()
				case isInterfaceSrc():
					[].Set(reflect.ValueOf(valueInterface{value: .Elem()}))
				default:
					[].Set()
				}
			}

			// Interpreter code execution.
			runCfg(.child[3].start, , , )

			.mutex.Lock()
			getFrame(, ).data[] = 
			.mutex.Unlock()

			return .data[:]
		})

		.mutex.Lock()
		getFrame(, ).data[] = 
		.mutex.Unlock()

		return 
	}
}

func getMethod( *node) {
	 := .findex
	 := .level
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		 := *(.val.(*node))
		.val = &
		.recv = .recv
		getFrame(, ).data[] = genFuncValue(&)()
		return 
	}
}

func getMethodByName( *node) {
	 := getExec(.tnext)
	 := genValue(.child[0])
	 := .child[1].ident
	 := .findex
	 := .level

	.exec = func( *frame) bltn {
		// The interface object must be directly accessible, or embedded in a struct (exported anonymous field).
		 := ()
		,  := ().Interface().(valueInterface)
		if ! {
			// Search the first embedded valueInterface.
			for .Kind() == reflect.Ptr {
				 = .Elem()
			}
			for  := 0;  < .NumField(); ++ {
				 := .Type().Field()
				if !.Anonymous || !.IsExported() {
					continue
				}
				if ,  = .Field().Interface().(valueInterface);  {
					break
					// TODO: should we keep track of all the vals that are indeed valueInterface,
					// so that later on we can call MethodByName on all of them until one matches?
				}
			}
			if ! {
				panic(.cfgErrorf("invalid interface value %v", ))
			}
		}
		// Traverse nested interface values to get the concrete value.
		for {
			,  := .value.Interface().(valueInterface)
			if ! {
				break
			}
			 = 
		}

		if  := .value.MethodByName(); .IsValid() {
			getFrame(, ).data[] = 
			return 
		}

		 := .node.typ
		if .node == nil && .cat == valueT {
			// It happens with a var of empty interface type, that has value of concrete type
			// from runtime, being asserted to "user-defined" interface.
			if ,  := .rtype.MethodByName(); ! {
				panic(.cfgErrorf("method not found: %s", ))
			}
			return 
		}

		// Finally search method recursively in embedded valueInterfaces.
		, ,  := lookupMethodValue(, )
		if .IsValid() {
			getFrame(, ).data[] = 
			return 
		}
		if  == nil {
			panic(.cfgErrorf("method not found: %s", ))
		}

		 := *
		.val = &
		.recv = &receiver{nil, .value, }
		getFrame(, ).data[] = genFuncValue(&)()
		return 
	}
}

// lookupMethodValue recursively looks within val for the method with the given
// name. If a runtime value is found, it is returned in r, otherwise it is returned
// in m, with li as the list of recursive field indexes.
func lookupMethodValue( valueInterface,  string) ( reflect.Value,  *node,  []int) {
	if  = .value.MethodByName(); .IsValid() {
		return
	}
	if ,  = .node.typ.lookupMethod();  != nil {
		return
	}
	if !isStruct(.node.typ) {
		return
	}
	 := .value
	for .Type().Kind() == reflect.Ptr {
		 = .Elem()
	}
	 := .NumField()
	for  := 0;  < ; ++ {
		,  := .Field().Interface().(valueInterface)
		if ! {
			continue
		}
		if , ,  = (, );  != nil {
			 = append([]int{}, ...)
			return
		}
	}
	return
}

func getIndexSeq( *node) {
	 := genValue(.child[0])
	 := .val.([]int)
	 := getExec(.tnext)
	 := .findex
	 := .level

	// Note:
	// Here we have to store the result using
	//    f.data[i] = value(...)
	// instead of normal
	//    dest(f).Set(value(...)
	// because the value returned by FieldByIndex() must be preserved
	// for possible future Set operations on the struct field (avoid a
	// dereference from Set, resulting in setting a copy of the
	// original field).

	if .fnext != nil {
		 := getExec(.fnext)
		.exec = func( *frame) bltn {
			 := ()
			 := .FieldByIndex()
			getFrame(, ).data[] = 
			if .Bool() {
				return 
			}
			return 
		}
	} else {
		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .FieldByIndex()
			return 
		}
	}
}

func getPtrIndexSeq( *node) {
	 := .val.([]int)
	 := getExec(.tnext)
	 := genValue(.child[0])
	 := .findex
	 := .level

	if .fnext != nil {
		 := getExec(.fnext)
		.exec = func( *frame) bltn {
			 := ().Elem().FieldByIndex()
			getFrame(, ).data[] = 
			if .Bool() {
				return 
			}
			return 
		}
	} else {
		.exec = func( *frame) bltn {
			getFrame(, ).data[] = ().Elem().FieldByIndex()
			return 
		}
	}
}

func getIndexSeqField( *node) {
	 := genValue(.child[0])
	 := .val.([]int)
	 := .findex
	 := .level
	 := getExec(.tnext)

	if .fnext != nil {
		 := getExec(.fnext)
		if .child[0].typ.TypeOf().Kind() == reflect.Ptr {
			.exec = func( *frame) bltn {
				 := ().Elem().FieldByIndex()
				getFrame(, ).data[] = 
				if .Bool() {
					return 
				}
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				 := ().FieldByIndex()
				getFrame(, ).data[] = 
				if .Bool() {
					return 
				}
				return 
			}
		}
	} else {
		if .child[0].typ.TypeOf().Kind() == reflect.Ptr {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Elem().FieldByIndex()
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().FieldByIndex()
				return 
			}
		}
	}
}

func getIndexSeqPtrMethod( *node) {
	 := genValue(.child[0])
	 := .val.([]int)
	 := [1:]
	 := [0]
	 := .findex
	 := .level
	 := getExec(.tnext)

	if .child[0].typ.TypeOf().Kind() == reflect.Ptr {
		if len() == 0 {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Method()
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Elem().FieldByIndex().Addr().Method()
				return 
			}
		}
	} else {
		if len() == 0 {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Addr().Method()
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().FieldByIndex().Addr().Method()
				return 
			}
		}
	}
}

func getIndexSeqMethod( *node) {
	 := genValue(.child[0])
	 := .val.([]int)
	 := [1:]
	 := [0]
	 := .findex
	 := .level
	 := getExec(.tnext)

	if .child[0].typ.TypeOf().Kind() == reflect.Ptr {
		if len() == 0 {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Elem().Method()
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Elem().FieldByIndex().Method()
				return 
			}
		}
	} else {
		if len() == 0 {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().Method()
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				getFrame(, ).data[] = ().FieldByIndex().Method()
				return 
			}
		}
	}
}

func neg( *node) {
	 := genValue()
	 := genValue(.child[0])
	 := getExec(.tnext)
	 := .typ.concrete().TypeOf()
	 := .typ.TypeOf().Kind() == reflect.Interface

	switch .typ.TypeOf().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if  {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(-().Int()).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetInt(-().Int())
			return 
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if  {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(-().Uint()).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetUint(-().Uint())
			return 
		}
	case reflect.Float32, reflect.Float64:
		if  {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(-().Float()).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetFloat(-().Float())
			return 
		}
	case reflect.Complex64, reflect.Complex128:
		if  {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(-().Complex()).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetComplex(-().Complex())
			return 
		}
	}
}

func pos( *node) {
	 := genValue()
	 := genValue(.child[0])
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		().Set(())
		return 
	}
}

func bitNot( *node) {
	 := genValue()
	 := genValue(.child[0])
	 := getExec(.tnext)
	 := .typ.concrete().TypeOf()
	 := .typ.TypeOf().Kind() == reflect.Interface

	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if  {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(^().Int()).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetInt(^().Int())
			return 
		}
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if  {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(^().Uint()).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetUint(^().Uint())
			return 
		}
	}
}

func land( *node) {
	 := genValue(.child[0])
	 := genValue(.child[1])
	 := getExec(.tnext)
	 := genValue()
	 := .typ.concrete().TypeOf()
	 := .typ.TypeOf().Kind() == reflect.Interface

	if .fnext != nil {
		 := getExec(.fnext)
		.exec = func( *frame) bltn {
			if ().Bool() && ().Bool() {
				().SetBool(true)
				return 
			}
			().SetBool(false)
			return 
		}
		return
	}
	if  {
		.exec = func( *frame) bltn {
			().Set(reflect.ValueOf(().Bool() && ().Bool()).Convert())
			return 
		}
		return
	}
	.exec = func( *frame) bltn {
		().SetBool(().Bool() && ().Bool())
		return 
	}
}

func lor( *node) {
	 := genValue(.child[0])
	 := genValue(.child[1])
	 := getExec(.tnext)
	 := genValue()
	 := .typ.concrete().TypeOf()
	 := .typ.TypeOf().Kind() == reflect.Interface

	if .fnext != nil {
		 := getExec(.fnext)
		.exec = func( *frame) bltn {
			if ().Bool() || ().Bool() {
				().SetBool(true)
				return 
			}
			().SetBool(false)
			return 
		}
		return
	}
	if  {
		.exec = func( *frame) bltn {
			().Set(reflect.ValueOf(().Bool() || ().Bool()).Convert())
			return 
		}
		return
	}
	.exec = func( *frame) bltn {
		().SetBool(().Bool() || ().Bool())
		return 
	}
}

func nop( *node) {
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		return 
	}
}

func branch( *node) {
	 := getExec(.tnext)
	 := getExec(.fnext)
	 := genValue()

	.exec = func( *frame) bltn {
		if ().Bool() {
			return 
		}
		return 
	}
}

func _return( *node) {
	 := .child
	 := .val.(*node)
	 := make([]func(*frame) reflect.Value, len())
	for ,  := range  {
		switch  := .typ.ret[]; .cat {
		case errorT:
			[] = genInterfaceWrapper(, .TypeOf())
		case funcT:
			[] = genValue()
		case valueT:
			switch .rtype.Kind() {
			case reflect.Interface:
				[] = genInterfaceWrapper(, .TypeOf())
				continue
			case reflect.Func:
				[] = genFunctionWrapper()
				continue
			}
			fallthrough
		default:
			switch {
			case isInterfaceSrc():
				if len(.field) == 0 {
					// empty interface case.
					// we can't let genValueInterface deal with it, because we call on c,
					// not on n, which means that the interfaceT knowledge is lost.
					[] = genValue()
					break
				}
				[] = genValueInterface()
			case .typ.untyped:
				[] = genValueAs(, .TypeOf())
			default:
				[] = genValue()
			}
		}
	}

	switch len() {
	case 0:
		.exec = nil
	case 1:
		switch {
		case ![0].rval.IsValid() && [0].kind == binaryExpr:
			// No additional runtime operation is necessary for constants (not in frame) or
			// binary expressions (stored directly at the right location in frame).
			.exec = nil
		case isCall([0]) && .child[0].typ.id() == .typ.ret[0].id():
			// Calls are optmized as long as no type conversion is involved.
			.exec = nil
		default:
			// Regular return: store the value to return at to start of the frame.
			 := [0]
			.exec = func( *frame) bltn {
				.data[0].Set(())
				return nil
			}
		}
	case 2:
		,  := [0], [1]
		.exec = func( *frame) bltn {
			.data[0].Set(())
			.data[1].Set(())
			return nil
		}
	default:
		.exec = func( *frame) bltn {
			for ,  := range  {
				.data[].Set(())
			}
			return nil
		}
	}
}

func arrayLit( *node) {
	 := valueGenerator(, .findex)
	 := getExec(.tnext)
	 := .child
	if .nleft == 1 {
		 = .child[1:]
	}

	 := make([]func(*frame) reflect.Value, len())
	 := make([]int, len())
	var ,  int

	 := .typ.resolveAlias()
	for ,  := range  {
		if .kind == keyValueExpr {
			[] = genDestValue(.val, .child[1])
			[] = int(vInt(.child[0].rval))
		} else {
			[] = genDestValue(.val, )
			[] = 
		}
		 = [] + 1
		if  >  {
			 = 
		}
	}

	 := .typ.frameType()
	 := .Kind()
	.exec = func( *frame) bltn {
		var  reflect.Value
		if  == reflect.Slice {
			 = reflect.MakeSlice(, , )
		} else {
			, _ = .typ.zero()
		}
		for ,  := range  {
			.Index([]).Set(())
		}
		().Set()
		return 
	}
}

func mapLit( *node) {
	 := valueGenerator(, .findex)
	 := getExec(.tnext)
	 := .child
	if .nleft == 1 {
		 = .child[1:]
	}
	 := .typ.frameType()
	 := make([]func(*frame) reflect.Value, len())
	 := make([]func(*frame) reflect.Value, len())
	for ,  := range  {
		[] = genDestValue(.typ.key, .child[0])
		[] = genDestValue(.typ.val, .child[1])
	}

	.exec = func( *frame) bltn {
		 := reflect.MakeMap()
		for ,  := range  {
			.SetMapIndex((), []())
		}
		().Set()
		return 
	}
}

func compositeBinMap( *node) {
	 := valueGenerator(, .findex)
	 := getExec(.tnext)
	 := .child
	if .nleft == 1 {
		 = .child[1:]
	}
	 := .typ.frameType()
	 := make([]func(*frame) reflect.Value, len())
	 := make([]func(*frame) reflect.Value, len())
	for ,  := range  {
		convertLiteralValue(.child[0], .Key())
		convertLiteralValue(.child[1], .Elem())
		[] = genValue(.child[0])

		if isFuncSrc(.child[1].typ) {
			[] = genFunctionWrapper(.child[1])
		} else {
			[] = genValue(.child[1])
		}
	}

	.exec = func( *frame) bltn {
		 := reflect.MakeMap()
		for ,  := range  {
			.SetMapIndex((), []())
		}
		().Set()
		return 
	}
}

func compositeBinSlice( *node) {
	 := valueGenerator(, .findex)
	 := getExec(.tnext)
	 := .child
	if .nleft == 1 {
		 = .child[1:]
	}

	 := make([]func(*frame) reflect.Value, len())
	 := make([]int, len())
	 := .typ.rtype.Elem()
	var ,  int

	for ,  := range  {
		if .kind == keyValueExpr {
			convertLiteralValue(.child[1], )
			[] = genValue(.child[1])
			[] = int(vInt(.child[0].rval))
		} else {
			convertLiteralValue(, )
			[] = genValue()
			[] = 
		}
		 = [] + 1
		if  >  {
			 = 
		}
	}

	 := .typ.frameType()
	 := .Kind()
	.exec = func( *frame) bltn {
		var  reflect.Value
		if  == reflect.Slice {
			 = reflect.MakeSlice(, , )
		} else {
			, _ = .typ.zero()
		}
		for ,  := range  {
			.Index([]).Set(())
		}
		().Set()
		return 
	}
}

// doCompositeBinStruct creates and populates a struct object from a binary type.
func doCompositeBinStruct( *node,  bool) {
	 := getExec(.tnext)
	 := valueGenerator(, .findex)
	 := .typ.rtype
	if .typ.cat == ptrT || .typ.cat == linkedT {
		 = .typ.val.rtype
	}
	 := .child
	if  {
		 = .child[1:]
	}
	 := make([]func(*frame) reflect.Value, len())
	 := make([][]int, len())
	for ,  := range  {
		if .kind == keyValueExpr {
			if ,  := .FieldByName(.child[0].ident);  {
				[] = .Index
				convertLiteralValue(.child[1], .Type)
				if isFuncSrc(.child[1].typ) {
					[] = genFunctionWrapper(.child[1])
				} else {
					[] = genValue(.child[1])
				}
			}
		} else {
			[] = []int{}
			if isFuncSrc(.typ) && len(.child) > 1 {
				convertLiteralValue(.child[1], .Field().Type)
				[] = genFunctionWrapper(.child[1])
			} else {
				convertLiteralValue(, .Field().Type)
				[] = genValue()
			}
		}
	}

	 := .findex
	 := .level

	.exec = func( *frame) bltn {
		 := reflect.New().Elem()
		for ,  := range  {
			.FieldByIndex([]).Set(())
		}
		 := ()
		switch {
		case .Kind() == reflect.Ptr:
			.Set(.Addr())
		default:
			getFrame(, ).data[] = 
		}
		return 
	}
}

func compositeBinStruct( *node)       { doCompositeBinStruct(, true) }
func compositeBinStructNotype( *node) { doCompositeBinStruct(, false) }

func destType( *node) *itype {
	switch .anc.kind {
	case assignStmt, defineStmt:
		return .anc.child[0].typ
	default:
		return .typ
	}
}

func doComposite( *node,  bool,  bool) {
	 := valueGenerator(, .findex)
	 := getExec(.tnext)
	 := .typ
	if .cat == ptrT || .cat == linkedT {
		 = .val
	}
	 := .child
	if  {
		 = .child[1:]
	}
	 := isInterfaceSrc(destType())

	 := make(map[int]func(*frame) reflect.Value)
	for ,  := range  {
		var  *node
		var  int
		if  {
			 = .child[1]
			 = .fieldIndex(.child[0].ident)
		} else {
			 = 
			 = 
		}
		 := .field[].typ
		 := .TypeOf()
		convertLiteralValue(, )
		switch {
		case .typ.cat == nilT:
			[] = func(*frame) reflect.Value { return reflect.New().Elem() }
		case isNamedFuncSrc(.typ):
			[] = genValueAsFunctionWrapper()
		case isInterfaceSrc() && (!isEmptyInterface() || len(.typ.method) > 0):
			[] = genValueInterface()
		case isInterface():
			[] = genInterfaceWrapper(, )
		default:
			[] = genValue()
		}
	}

	 := .findex
	 := .level
	 := .TypeOf()

	.exec = func( *frame) bltn {
		 := reflect.New().Elem()
		for ,  := range  {
			.Field().Set(())
		}
		 := ()
		switch {
		case .Kind() == reflect.Ptr:
			.Set(.Addr())
		case :
			if len(destType().field) > 0 {
				.Set(reflect.ValueOf(valueInterface{, }))
				break
			}
			.Set()
		default:
			getFrame(, ).data[] = 
		}
		return 
	}
}

// doCompositeLit creates and populates a struct object.
func doCompositeLit( *node,  bool) {
	doComposite(, , false)
}

func compositeLit( *node)       { doCompositeLit(, true) }
func compositeLitNotype( *node) { doCompositeLit(, false) }

// doCompositeLitKeyed creates a struct Object, filling fields from sparse key-values.
func doCompositeLitKeyed( *node,  bool) {
	doComposite(, , true)
}

func compositeLitKeyed( *node)       { doCompositeLitKeyed(, true) }
func compositeLitKeyedNotype( *node) { doCompositeLitKeyed(, false) }

func empty( *node) {}

var rat = reflect.ValueOf((*[]rune)(nil)).Type().Elem() // runes array type

func _range( *node) {
	 := .child[0].findex // array index location in frame
	 :=  - 1        // shallow array for range, always just behind index0
	 :=  - 1        // additional location to store string char position
	 := getExec(.fnext)
	 := getExec(.tnext)

	var  func(*frame) reflect.Value
	var  *node
	if len(.child) == 4 {
		 = .child[2]
		 := .child[1].findex // array value location in frame
		if isString(.typ.TypeOf()) {
			// Special variant of "range" for string, where the index indicates the byte position
			// of the rune in the string, rather than the index of the rune in array.
			 := reflect.TypeOf("")
			 = genValueAs(, rat) // range on string iterates over runes
			.exec = func( *frame) bltn {
				 := .data[]
				 := .data[]
				.SetInt(.Int() + 1)
				 := int(.Int())
				if  >= .Len() {
					return 
				}
				// Compute byte position of the rune in string
				 := .Slice(0, ).Convert().Len()
				.data[].SetInt(int64())
				.data[].Set(.Index())
				return 
			}
		} else {
			 = genValueRangeArray()
			.exec = func( *frame) bltn {
				 := .data[]
				 := .data[]
				.SetInt(.Int() + 1)
				 := int(.Int())
				if  >= .Len() {
					return 
				}
				.data[].Set(.Index())
				return 
			}
		}
	} else {
		 = .child[1]
		if isString(.typ.TypeOf()) {
			 = genValueAs(, rat) // range on string iterates over runes
		} else {
			 = genValueRangeArray()
		}
		.exec = func( *frame) bltn {
			 := .data[]
			.SetInt(.Int() + 1)
			if int(.Int()) >= .data[].Len() {
				return 
			}
			return 
		}
	}

	// Init sequence
	 := .exec
	 := 
	if isString(.typ.TypeOf()) && len(.child) == 4 {
		 = 
	}
	.child[0].exec = func( *frame) bltn {
		.data[] = () // set array shallow copy for range
		.data[].SetInt(-1)  // assing index value
		return 
	}
}

func rangeChan( *node) {
	 := .child[0].findex        // element index location in frame
	 := genValue(.child[1]) // chan
	 := getExec(.fnext)
	 := getExec(.tnext)

	.exec = func( *frame) bltn {
		.mutex.RLock()
		 := .done
		.mutex.RUnlock()

		, ,  := reflect.Select([]reflect.SelectCase{, {Dir: reflect.SelectRecv, Chan: ()}})
		if  == 0 {
			return nil
		}
		if ! {
			return 
		}
		.data[].Set()
		return 
	}
}

func rangeMap( *node) {
	 := .child[0].findex // map index location in frame
	 :=  - 1        // iterator for range, always just behind index0
	 := getExec(.fnext)
	 := getExec(.tnext)

	var  func(*frame) reflect.Value
	if len(.child) == 4 {
		 := .child[1].findex  // map value location in frame
		 = genValue(.child[2]) // map
		.exec = func( *frame) bltn {
			 := .data[].Interface().(*reflect.MapIter)
			if !.Next() {
				return 
			}
			.data[].Set(.Key())
			.data[].Set(.Value())
			return 
		}
	} else {
		 = genValue(.child[1]) // map
		.exec = func( *frame) bltn {
			 := .data[].Interface().(*reflect.MapIter)
			if !.Next() {
				return 
			}
			.data[].Set(.Key())
			return 
		}
	}

	// Init sequence
	 := .exec
	.child[0].exec = func( *frame) bltn {
		.data[].Set(reflect.ValueOf(().MapRange()))
		return 
	}
}

func _case( *node) {
	 := getExec(.tnext)

	// TODO(mpl): a lot of what is done in typeAssert should probably be redone/reused here.
	switch {
	case .anc.anc.kind == typeSwitch:
		 := getExec(.fnext)
		 := .anc.anc // switch node
		 := make([]*itype, len(.child)-1)
		for  := range  {
			[] = .child[].typ
		}
		 := genValue(.child[1].lastChild().child[0])

		if len(.child[1].child) != 2 {
			// no assign in switch guard
			if len(.child) <= 1 {
				.exec = func( *frame) bltn { return  }
			} else {
				.exec = func( *frame) bltn {
					 := ().Interface()
					,  := .(valueInterface)
					// TODO(mpl): I'm assuming here that !ok means that we're dealing with the empty
					// interface case. But maybe we should make sure by checking the relevant cat
					// instead? later. Use t := v.Type(); t.Kind() == reflect.Interface , like above.
					if ! {
						var  string
						if  != nil {
							 = strings.ReplaceAll(reflect.TypeOf().String(), " {}", "{}")
						}
						for ,  := range  {
							// TODO(mpl): we should actually use canAssertTypes, but need to find a valid
							// rtype for typ. Plus we need to refactor with typeAssert().
							// weak check instead for now.
							if  == nil {
								if .cat == nilT {
									return 
								}
								continue
							}
							if  == .id() {
								return 
							}
						}
						return 
					}
					if  := .node;  != nil {
						for ,  := range  {
							if .typ.id() == .id() {
								return 
							}
						}
					}
					return 
				}
			}
			break
		}

		// assign in switch guard
		 := genValue(.lastChild().child[0])
		switch len() {
		case 0:
			// default clause: assign var to interface value
			.exec = func( *frame) bltn {
				().Set(())
				return 
			}
		case 1:
			// match against 1 type: assign var to concrete value
			 := [0]
			.exec = func( *frame) bltn {
				 := ()
				if !.IsValid() {
					// match zero value against nil
					if .cat == nilT {
						return 
					}
					return 
				}
				if  := .Type(); .Kind() == reflect.Interface {
					if .cat == nilT && .IsNil() {
						return 
					}
					 := .TypeOf()
					if  == nil {
						return 
					}
					 := .Elem()
					if .String() == .String() && implementsInterface(, ) {
						().Set()
						return 
					}
					 := .Interface()
					if  != nil && .String() == reflect.TypeOf().String() {
						().Set()
						return 
					}
					if .cat == valueT && .Kind() == reflect.Interface && .IsValid() && .Type().Implements() {
						().Set()
						return 
					}
					return 
				}
				if ,  := .Interface().(valueInterface);  {
					if .node != nil {
						if .node.typ.id() == .id() {
							().Set(.value)
							return 
						}
					}
					return 
				}
				if .Type() == .TypeOf() {
					().Set()
					return 
				}
				return 
			}

		default:
			.exec = func( *frame) bltn {
				 := ()
				if  := .Type(); .Kind() == reflect.Interface {
					for ,  := range  {
						if .cat == nilT && .IsNil() {
							return 
						}
						 := .TypeOf()
						if  == nil {
							continue
						}
						 := .Elem()
						if .String() == .String() && implementsInterface(, ) {
							().Set()
							return 
						}
						 := .Interface()
						if  != nil && .String() == reflect.TypeOf().String() {
							().Set()
							return 
						}
						if .cat == valueT && .Kind() == reflect.Interface && .IsValid() && .Type().Implements() {
							().Set()
							return 
						}
					}
					return 
				}
				if ,  := .Interface().(valueInterface);  {
					if  := .node;  != nil {
						for ,  := range  {
							if .typ.id() == .id() {
								().Set()
								return 
							}
						}
					}
					return 
				}
				 := .Type()
				for ,  := range  {
					if  == .TypeOf() {
						().Set()
						return 
					}
				}
				return 
			}
		}

	case len(.child) <= 1: // default clause
		.exec = func( *frame) bltn { return  }

	default:
		 := getExec(.fnext)
		 := len(.anc.anc.child)
		 := genValue(.anc.anc.child[-2])
		 := make([]func(*frame) reflect.Value, len(.child)-1)
		for  := range  {
			[] = genValue(.child[])
		}
		.exec = func( *frame) bltn {
			 := ()
			for ,  := range  {
				 := ()
				if !.Type().AssignableTo(.Type()) {
					 = .Convert(.Type())
				}
				if .Interface() == .Interface() {
					return 
				}
			}
			return 
		}
	}
}

func implementsInterface( reflect.Value,  *itype) bool {
	 := .Type()
	if .cat == valueT {
		return .Implements(.rtype)
	}
	 := &itype{cat: valueT, rtype: }
	if .methods().contains(.methods()) {
		return true
	}
	,  := .Interface().(valueInterface)
	if ! {
		return false
	}
	return .node != nil && .node.typ.methods().contains(.methods())
}

func appendSlice( *node) {
	 := genValueOutput(, .typ.rtype)
	 := getExec(.tnext)
	 := genValue(.child[1])
	 := genValue(.child[2])

	if isString(.child[2].typ.TypeOf()) {
		 := reflect.TypeOf([]byte{})
		.exec = func( *frame) bltn {
			().Set(reflect.AppendSlice((), ().Convert()))
			return 
		}
	} else {
		.exec = func( *frame) bltn {
			().Set(reflect.AppendSlice((), ()))
			return 
		}
	}
}

func _append( *node) {
	if len(.child) == 3 {
		,  := .child[1], .child[2]
		if (.typ.cat == valueT || .typ.cat == valueT) && .typ.rtype == .typ.rtype ||
			isArray(.typ) && .typ.elem().id() == .typ.elem().id() ||
			isByteArray(.typ.TypeOf()) && isString(.typ.TypeOf()) {
			appendSlice()
			return
		}
	}

	 := genValueOutput(, .typ.rtype)
	 := genValue(.child[1])
	 := getExec(.tnext)

	switch  := len(.child); {
	case  == 2:
		.exec = func( *frame) bltn {
			().Set(())
			return 
		}
	case  > 3:
		 := .child[2:]
		 := len()
		 := make([]func(*frame) reflect.Value, )
		for ,  := range  {
			switch  := .typ.elem(); {
			case isInterfaceSrc() && (!isEmptyInterface() || len(.typ.method) > 0):
				[] = genValueInterface()
			case isInterfaceBin():
				[] = genInterfaceWrapper(, .rtype)
			case .typ.untyped:
				[] = genValueAs(, .child[1].typ.TypeOf().Elem())
			default:
				[] = genValue()
			}
		}

		.exec = func( *frame) bltn {
			 := make([]reflect.Value, )
			for ,  := range  {
				[] = ()
			}
			().Set(reflect.Append((), ...))
			return 
		}
	default:
		var  func(*frame) reflect.Value
		switch  := .typ.elem(); {
		case isInterfaceSrc() && (!isEmptyInterface() || len(.child[2].typ.method) > 0):
			 = genValueInterface(.child[2])
		case isInterfaceBin():
			 = genInterfaceWrapper(.child[2], .rtype)
		case .child[2].typ.untyped:
			 = genValueAs(.child[2], .child[1].typ.TypeOf().Elem())
		default:
			 = genValue(.child[2])
		}

		.exec = func( *frame) bltn {
			().Set(reflect.Append((), ()))
			return 
		}
	}
}

func _cap( *node) {
	 := genValueOutput(, reflect.TypeOf(int(0)))
	 := genValue(.child[1])
	 := getExec(.tnext)

	if wantEmptyInterface() {
		.exec = func( *frame) bltn {
			().Set(reflect.ValueOf(().Cap()))
			return 
		}
		return
	}
	.exec = func( *frame) bltn {
		().SetInt(int64(().Cap()))
		return 
	}
}

func _copy( *node) {
	 := []func(*frame) reflect.Value{genValueArray(.child[1]), genValue(.child[2])}
	 := []func(*frame) reflect.Value{genValueOutput(, reflect.TypeOf(0))}

	genBuiltinDeferWrapper(, , , func( []reflect.Value) []reflect.Value {
		 := reflect.Copy([0], [1])
		return []reflect.Value{reflect.ValueOf()}
	})
}

func _close( *node) {
	 := []func(*frame) reflect.Value{genValue(.child[1])}

	genBuiltinDeferWrapper(, , nil, func( []reflect.Value) []reflect.Value {
		[0].Close()
		return nil
	})
}

func _complex( *node) {
	 := genValueOutput(, reflect.TypeOf(complex(0, 0)))
	,  := .child[1], .child[2]
	convertLiteralValue(, floatType)
	convertLiteralValue(, floatType)
	 := genValue()
	 := genValue()
	 := getExec(.tnext)

	 := .typ.TypeOf()
	if isComplex() {
		if wantEmptyInterface() {
			.exec = func( *frame) bltn {
				().Set(reflect.ValueOf(complex(().Float(), ().Float())))
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			().SetComplex(complex(().Float(), ().Float()))
			return 
		}
		return
	}
	// Not a complex type: ignore imaginary part
	.exec = func( *frame) bltn {
		().Set(().Convert())
		return 
	}
}

func _imag( *node) {
	 := genValueOutput(, reflect.TypeOf(float64(0)))
	convertLiteralValue(.child[1], complexType)
	 := genValue(.child[1])
	 := getExec(.tnext)

	if wantEmptyInterface() {
		.exec = func( *frame) bltn {
			().Set(reflect.ValueOf(imag(().Complex())))
			return 
		}
		return
	}
	.exec = func( *frame) bltn {
		().SetFloat(imag(().Complex()))
		return 
	}
}

func _real( *node) {
	 := genValueOutput(, reflect.TypeOf(float64(0)))
	convertLiteralValue(.child[1], complexType)
	 := genValue(.child[1])
	 := getExec(.tnext)

	if wantEmptyInterface() {
		.exec = func( *frame) bltn {
			().Set(reflect.ValueOf(real(().Complex())))
			return 
		}
		return
	}
	.exec = func( *frame) bltn {
		().SetFloat(real(().Complex()))
		return 
	}
}

func _delete( *node) {
	 := genValue(.child[1]) // map
	 := genValue(.child[2]) // key
	 := []func(*frame) reflect.Value{, }
	var  reflect.Value

	genBuiltinDeferWrapper(, , nil, func( []reflect.Value) []reflect.Value {
		[0].SetMapIndex([1], )
		return nil
	})
}

func capConst( *node) {
	// There is no Cap() method for reflect.Type, just return Len() instead.
	lenConst()
}

func lenConst( *node) {
	.rval = reflect.New(reflect.TypeOf(int(0))).Elem()
	 := .child[1]
	if .rval.IsValid() {
		.rval.SetInt(int64(len(vString(.rval))))
		return
	}
	 := .typ.TypeOf()
	for .Kind() == reflect.Ptr {
		 = .Elem()
	}
	.rval.SetInt(int64(.Len()))
}

func _len( *node) {
	 := genValueOutput(, reflect.TypeOf(int(0)))
	 := genValue(.child[1])
	if isPtr(.child[1].typ) {
		 := 
		 = func( *frame) reflect.Value {
			 := ().Elem()
			for .Kind() == reflect.Ptr {
				 = .Elem()
			}
			return 
		}
	}
	 := getExec(.tnext)

	if wantEmptyInterface() {
		.exec = func( *frame) bltn {
			().Set(reflect.ValueOf(().Len()))
			return 
		}
		return
	}
	.exec = func( *frame) bltn {
		().SetInt(int64(().Len()))
		return 
	}
}

func _new( *node) {
	 := getExec(.tnext)
	 := .child[1].typ
	 := .TypeOf()
	 := genValueOutput(, reflect.PtrTo())

	if isInterfaceSrc() && (!isEmptyInterface() || len(.method) > 0) {
		 = zeroInterfaceValue().Type()
	}

	.exec = func( *frame) bltn {
		 := reflect.New()
		if ,  := .Interface().(*valueInterface);  {
			.node = 
		}
		().Set()
		return 
	}
}

// _make allocates and initializes a slice, a map or a chan.
func _make( *node) {
	 := getExec(.tnext)
	 := .child[1].typ.frameType()
	 := genValueOutput(, )

	switch .Kind() {
	case reflect.Array, reflect.Slice:
		 := genValue(.child[2])

		switch len(.child) {
		case 3:
			.exec = func( *frame) bltn {
				 := int(vInt(()))
				().Set(reflect.MakeSlice(, , ))
				return 
			}
		case 4:
			 := genValue(.child[3])
			.exec = func( *frame) bltn {
				().Set(reflect.MakeSlice(, int(vInt(())), int(vInt(()))))
				return 
			}
		}

	case reflect.Chan:
		switch len(.child) {
		case 2:
			.exec = func( *frame) bltn {
				().Set(reflect.MakeChan(, 0))
				return 
			}
		case 3:
			 := genValue(.child[2])
			.exec = func( *frame) bltn {
				().Set(reflect.MakeChan(, int(vInt(()))))
				return 
			}
		}

	case reflect.Map:
		switch len(.child) {
		case 2:
			.exec = func( *frame) bltn {
				().Set(reflect.MakeMap())
				return 
			}
		case 3:
			 := genValue(.child[2])
			.exec = func( *frame) bltn {
				().Set(reflect.MakeMapWithSize(, int(vInt(()))))
				return 
			}
		}
	}
}

func reset( *node) {
	 := getExec(.tnext)

	switch  := len(.child) - 1;  {
	case 1:
		 := .child[0].typ.frameType()
		 := .child[0].findex
		.exec = func( *frame) bltn {
			.data[] = reflect.New().Elem()
			return 
		}
	case 2:
		,  := .child[0], .child[1]
		,  := .findex, .findex
		,  := .typ.frameType(), .typ.frameType()
		.exec = func( *frame) bltn {
			.data[] = reflect.New().Elem()
			.data[] = reflect.New().Elem()
			return 
		}
	default:
		 := make([]reflect.Type, )
		 := make([]int, )
		for ,  := range .child[:] {
			[] = .findex
			[] = .typ.frameType()
		}
		.exec = func( *frame) bltn {
			for ,  := range  {
				.data[] = reflect.New([]).Elem()
			}
			return 
		}
	}
}

// recv reads from a channel.
func recv( *node) {
	 := genValue(.child[0])
	 := getExec(.tnext)
	 := .findex
	 := .level

	if .interp.cancelChan {
		// Cancellable channel read
		if .fnext != nil {
			 := getExec(.fnext)
			.exec = func( *frame) bltn {
				// Fast: channel read doesn't block
				 := ()
				if ,  := .TryRecv();  {
					getFrame(, ).data[] = 
					if .Bool() {
						return 
					}
					return 
				}
				// Slow: channel read blocks, allow cancel
				.mutex.RLock()
				 := .done
				.mutex.RUnlock()

				, ,  := reflect.Select([]reflect.SelectCase{, {Dir: reflect.SelectRecv, Chan: }})
				if  == 0 {
					return nil
				}
				if .Bool() {
					return 
				}
				return 
			}
		} else {
			.exec = func( *frame) bltn {
				// Fast: channel read doesn't block
				 := ()
				if ,  := .TryRecv();  {
					getFrame(, ).data[] = 
					return 
				}
				// Slow: channel is blocked, allow cancel
				.mutex.RLock()
				 := .done
				.mutex.RUnlock()

				var  int
				, getFrame(, ).data[], _ = reflect.Select([]reflect.SelectCase{, {Dir: reflect.SelectRecv, Chan: }})
				if  == 0 {
					return nil
				}
				return 
			}
		}
	} else {
		// Blocking channel read (less overhead)
		if .fnext != nil {
			 := getExec(.fnext)
			.exec = func( *frame) bltn {
				if ,  := ().Recv(); .Bool() {
					getFrame(, ).data[] = 
					return 
				}
				return 
			}
		} else {
			 := .findex
			.exec = func( *frame) bltn {
				getFrame(, ).data[], _ = ().Recv()
				return 
			}
		}
	}
}

func recv2( *node) {
	 := genValue(.child[0])    // chan
	 := genValue(.anc.child[0]) // result
	 := genValue(.anc.child[1])  // status
	 := getExec(.tnext)

	if .interp.cancelChan {
		// Cancellable channel read
		.exec = func( *frame) bltn {
			, ,  := (), (), ()
			//  Fast: channel read doesn't block
			if ,  := .TryRecv();  {
				.Set()
				.SetBool(true)
				return 
			}
			// Slow: channel is blocked, allow cancel
			.mutex.RLock()
			 := .done
			.mutex.RUnlock()

			, ,  := reflect.Select([]reflect.SelectCase{, {Dir: reflect.SelectRecv, Chan: }})
			if  == 0 {
				return nil
			}
			.Set()
			.SetBool()
			return 
		}
	} else {
		// Blocking channel read (less overhead)
		.exec = func( *frame) bltn {
			,  := ().Recv()
			().Set()
			().SetBool()
			return 
		}
	}
}

func convertLiteralValue( *node,  reflect.Type) {
	switch {
	case .typ.cat == nilT:
		// Create a zero value of target type.
		.rval = reflect.New().Elem()
	case !(.kind == basicLit || .rval.IsValid()) ||  == nil || .Kind() == reflect.Interface ||  == valueInterfaceType || .Kind() == reflect.Slice && .Elem().Kind() == reflect.Interface:
		// Skip non-constant values, undefined target type or interface target type.
	case .rval.IsValid():
		// Convert constant value to target type.
		convertConstantValue()
		.rval = .rval.Convert()
	default:
		// Create a zero value of target type.
		.rval = reflect.New().Elem()
	}
}

func convertConstantValue( *node) {
	if !.rval.IsValid() {
		return
	}
	,  := .rval.Interface().(constant.Value)
	if ! {
		return
	}

	var  reflect.Value

	switch .Kind() {
	case constant.Bool:
		 = reflect.ValueOf(constant.BoolVal())
	case constant.String:
		 = reflect.ValueOf(constant.StringVal())
	case constant.Int:
		,  := constant.Int64Val()
		if ! {
			panic(.cfgErrorf("constant %s overflows int64", .ExactString()))
		}
		 = reflect.ValueOf(int())
	case constant.Float:
		,  := constant.Float64Val()
		 = reflect.ValueOf()
	case constant.Complex:
		,  := constant.Float64Val(constant.Real())
		,  := constant.Float64Val(constant.Imag())
		 = reflect.ValueOf(complex(, ))
	}

	.rval = .Convert(.typ.TypeOf())
}

// Write to a channel.
func send( *node) {
	 := getExec(.tnext)
	,  := .child[0], .child[1]
	 := genValue() // Send channel.
	 := genDestValue(.typ.val, )

	if !.interp.cancelChan {
		// Send is non-cancellable, has the least overhead.
		.exec = func( *frame) bltn {
			().Send(())
			return 
		}
		return
	}

	// Send is cancellable, may have some overhead.
	.exec = func( *frame) bltn {
		,  := (), ()
		// Fast: send on channel doesn't block.
		if  := .TrySend();  {
			return 
		}
		// Slow: send on channel blocks, allow cancel.
		.mutex.RLock()
		 := .done
		.mutex.RUnlock()

		, ,  := reflect.Select([]reflect.SelectCase{, {Dir: reflect.SelectSend, Chan: , Send: }})
		if  == 0 {
			return nil
		}
		return 
	}
}

func clauseChanDir( *node) (*node, *node, *node, reflect.SelectDir) {
	 := reflect.SelectDefault
	var , ,  *node
	var  bool

	.Walk(func( *node) bool {
		switch .action {
		case aRecv:
			 = reflect.SelectRecv
			 = .child[0]
			switch .anc.action {
			case aAssign:
				 = .anc.child[0]
			case aAssignX:
				 = .anc.child[0]
				 = .anc.child[1]
			}
			 = true
		case aSend:
			 = reflect.SelectSend
			 = .child[0]
			 = .child[1]
			 = true
		}
		return !
	}, nil)
	return , , , 
}

func _select( *node) {
	 := len(.child)
	 := make([]*node, )
	 := make([]*node, )
	 := make([]*node, )
	 := make([]bltn, )
	 := make([]func(*frame) reflect.Value, )
	 := make([]func(*frame) reflect.Value, )
	 := make([]func(*frame) reflect.Value, )
	 := make([]reflect.SelectCase, +1)
	 := getExec(.tnext)

	for  := 0;  < ; ++ {
		 := .child[]
		if .kind == commClauseDefault {
			[].Dir = reflect.SelectDefault
			if len(.child) == 0 {
				[] = func(*frame) bltn { return  }
			} else {
				[] = getExec(.child[0].start)
			}
			continue
		}
		// The comm clause is in send or recv direction.
		switch  := .child[0]; {
		case len(.child) > 1:
			// The comm clause contains a channel operation and a clause body.
			[] = getExec(.child[1].start)
			[], [], [], [].Dir = clauseChanDir()
			[] = genValue([])
			if [] != nil {
				[] = genValue([])
			}
			if [] != nil {
				[] = genValue([])
			}
		case .kind == exprStmt && len(.child) == 1 && .child[0].action == aRecv:
			// The comm clause has an empty body clause after channel receive.
			[] = genValue(.child[0].child[0])
			[].Dir = reflect.SelectRecv
			[] = func(*frame) bltn { return  }
		case .kind == sendStmt:
			// The comm clause as an empty body clause after channel send.
			[] = genValue(.child[0])
			[].Dir = reflect.SelectSend
			[] = genValue(.child[1])
			[] = func(*frame) bltn { return  }
		}
	}

	.exec = func( *frame) bltn {
		.mutex.RLock()
		[] = .done
		.mutex.RUnlock()

		for  := range [:] {
			switch [].Dir {
			case reflect.SelectRecv:
				[].Chan = []()
			case reflect.SelectSend:
				[].Chan = []()
				[].Send = []()
			case reflect.SelectDefault:
				// Keep zero values for comm clause
			}
		}
		, ,  := reflect.Select()
		if  ==  {
			return nil
		}
		if [].Dir == reflect.SelectRecv && [] != nil {
			[]().Set()
			if [] != nil {
				[]().SetBool()
			}
		}
		return []
	}
}

// slice expression: array[low:high:max].
func slice( *node) {
	 := .findex
	 := .level
	 := getExec(.tnext)
	 := genValueArray(.child[0]) // array
	 := genValue(.child[1])      // low (if 2 or 3 args) or high (if 1 arg)

	switch len(.child) {
	case 2:
		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .Slice(int(vInt(())), .Len())
			return 
		}
	case 3:
		 := genValue(.child[2]) // max

		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .Slice(int(vInt(())), int(vInt(())))
			return 
		}
	case 4:
		 := genValue(.child[2])
		 := genValue(.child[3])

		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .Slice3(int(vInt(())), int(vInt(())), int(vInt(())))
			return 
		}
	}
}

// slice expression, no low value: array[:high:max].
func slice0( *node) {
	 := .findex
	 := .level
	 := getExec(.tnext)
	 := genValueArray(.child[0])

	switch len(.child) {
	case 1:
		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .Slice(0, .Len())
			return 
		}
	case 2:
		 := genValue(.child[1])
		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .Slice(0, int(vInt(())))
			return 
		}
	case 3:
		 := genValue(.child[1])
		 := genValue(.child[2])
		.exec = func( *frame) bltn {
			 := ()
			getFrame(, ).data[] = .Slice3(0, int(vInt(())), int(vInt(())))
			return 
		}
	}
}

func isNilChild( int) func( *node) {
	return func( *node) {
		var  func(*frame) reflect.Value
		 := .child[]
		 = genValue()
		 := .typ.concrete().TypeOf()
		 := .typ.TypeOf().Kind() == reflect.Interface
		 := getExec(.tnext)
		 := genValue()
		if .fnext == nil {
			if !isInterfaceSrc(.typ) {
				if  {
					.exec = func( *frame) bltn {
						().Set(reflect.ValueOf(().IsNil()).Convert())
						return 
					}
					return
				}
				.exec = func( *frame) bltn {
					().SetBool(().IsNil())
					return 
				}
				return
			}
			if  {
				.exec = func( *frame) bltn {
					 := ()
					var  bool
					if ,  := .Interface().(valueInterface);  {
						 = ( == valueInterface{} || .node.kind == basicLit && .node.typ.cat == nilT)
					} else {
						 = .IsNil()
					}
					().Set(reflect.ValueOf().Convert())
					return 
				}
				return
			}
			.exec = func( *frame) bltn {
				 := ()
				var  bool
				if ,  := .Interface().(valueInterface);  {
					 = ( == valueInterface{} || .node.kind == basicLit && .node.typ.cat == nilT)
				} else {
					 = .IsNil()
				}
				().SetBool()
				return 
			}
			return
		}

		 := getExec(.fnext)

		if !isInterfaceSrc(.typ) {
			.exec = func( *frame) bltn {
				if ().IsNil() {
					().SetBool(true)
					return 
				}
				().SetBool(false)
				return 
			}
			return
		}

		.exec = func( *frame) bltn {
			 := ()
			if ,  := .Interface().(valueInterface);  {
				if ( == valueInterface{} || .node.kind == basicLit && .node.typ.cat == nilT) {
					().SetBool(true)
					return 
				}
				().SetBool(false)
				return 
			}
			if .IsNil() {
				().SetBool(true)
				return 
			}
			().SetBool(false)
			return 
		}
	}
}

func isNotNil( *node) {
	var  func(*frame) reflect.Value
	 := .child[0]
	 = genValue()
	 := .typ.concrete().TypeOf()
	 := .typ.TypeOf().Kind() == reflect.Interface
	 := getExec(.tnext)
	 := genValue()

	if .fnext == nil {
		if isInterfaceSrc(.typ) && .typ.TypeOf() != valueInterfaceType {
			if  {
				.exec = func( *frame) bltn {
					().Set(reflect.ValueOf(!().IsNil()).Convert())
					return 
				}
				return
			}
			.exec = func( *frame) bltn {
				().SetBool(!().IsNil())
				return 
			}
			return
		}

		if  {
			.exec = func( *frame) bltn {
				 := ()
				var  bool
				if ,  := .Interface().(valueInterface);  {
					 = ( == valueInterface{} || .node.kind == basicLit && .node.typ.cat == nilT)
				} else {
					 = .IsNil()
				}
				().Set(reflect.ValueOf(!).Convert())
				return 
			}
			return
		}
		.exec = func( *frame) bltn {
			 := ()
			var  bool
			if ,  := .Interface().(valueInterface);  {
				 = ( == valueInterface{} || .node.kind == basicLit && .node.typ.cat == nilT)
			} else {
				 = .IsNil()
			}
			().SetBool(!)
			return 
		}
		return
	}

	 := getExec(.fnext)

	if isInterfaceSrc(.typ) && .typ.TypeOf() != valueInterfaceType {
		.exec = func( *frame) bltn {
			if ().IsNil() {
				().SetBool(false)
				return 
			}
			().SetBool(true)
			return 
		}
		return
	}

	.exec = func( *frame) bltn {
		 := ()
		if ,  := .Interface().(valueInterface);  {
			if ( == valueInterface{} || .node.kind == basicLit && .node.typ.cat == nilT) {
				().SetBool(false)
				return 
			}
			().SetBool(true)
			return 
		}
		if .IsNil() {
			().SetBool(false)
			return 
		}
		().SetBool(true)
		return 
	}
}

func complexConst( *node) {
	if ,  := .child[1].rval, .child[2].rval; .IsValid() && .IsValid() {
		.rval = reflect.ValueOf(complex(vFloat(), vFloat()))
		.gen = nop
	}
}

func imagConst( *node) {
	if  := .child[1].rval; .IsValid() {
		.rval = reflect.ValueOf(imag(.Complex()))
		.gen = nop
	}
}

func realConst( *node) {
	if  := .child[1].rval; .IsValid() {
		.rval = reflect.ValueOf(real(.Complex()))
		.gen = nop
	}
}