package interp

import (
	
	
)

const (
	notInFrame  = -1 // value of node.findex for literal values (not in frame)
	globalFrame = -1 // value of node.level for global symbols
)

func valueGenerator( *node,  int) func(*frame) reflect.Value {
	switch .level {
	case globalFrame:
		return func( *frame) reflect.Value { return valueOf(.root.data, ) }
	case 0:
		return func( *frame) reflect.Value { return valueOf(.data, ) }
	case 1:
		return func( *frame) reflect.Value { return valueOf(.anc.data, ) }
	case 2:
		return func( *frame) reflect.Value { return valueOf(.anc.anc.data, ) }
	default:
		return func( *frame) reflect.Value {
			for  := .level;  > 0; -- {
				 = .anc
			}
			return valueOf(.data, )
		}
	}
}

// valueOf safely recovers the ith element of data. This is necessary
// because a cancellation prior to any evaluation result may leave
// the frame's data empty.
func valueOf( []reflect.Value,  int) reflect.Value {
	if  < 0 ||  >= len() {
		return reflect.Value{}
	}
	return []
}

func genValueRecv( *node) func(*frame) reflect.Value {
	var  func(*frame) reflect.Value
	if .recv.node == nil {
		 = func(*frame) reflect.Value { return .recv.val }
	} else {
		 = genValue(.recv.node)
	}
	 := .recv.index

	if len() == 0 {
		return 
	}

	return func( *frame) reflect.Value {
		 := ()
		for ,  := range  {
			if .Kind() == reflect.Ptr {
				 = .Elem()
			}
			// Note that we can't use reflect FieldByIndex method, as we may
			// traverse valueInterface wrappers to access the embedded receiver.
			 = .Field()
			,  := .Interface().(valueInterface)
			if  {
				 = .value
			}
		}
		return 
	}
}

func genValueAsFunctionWrapper( *node) func(*frame) reflect.Value {
	 := genValue()
	 := .typ.TypeOf()

	return func( *frame) reflect.Value {
		 := ()
		if .IsNil() {
			return reflect.New().Elem()
		}
		if .Kind() == reflect.Func {
			return 
		}
		,  := .Interface().(*node)
		if  && .rval.Kind() == reflect.Func {
			// The node value is already a callable func, no need to wrap it.
			return .rval
		}
		return genFunctionWrapper()()
	}
}

func genValueAs( *node,  reflect.Type) func(*frame) reflect.Value {
	 := genValue()

	return func( *frame) reflect.Value {
		 := ()
		switch .Kind() {
		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice, reflect.UnsafePointer:
			if .IsNil() {
				return reflect.New().Elem()
			}
		}
		return .Convert()
	}
}

func genValue( *node) func(*frame) reflect.Value {
	switch .kind {
	case basicLit:
		convertConstantValue()
		 := .rval
		if !.IsValid() {
			 = reflect.New(emptyInterfaceType).Elem()
		}
		return func( *frame) reflect.Value { return  }
	case funcDecl:
		var  reflect.Value
		if ,  := .val.(reflect.Value);  {
			 = 
		} else {
			 = reflect.ValueOf(.val)
		}
		return func( *frame) reflect.Value { return  }
	default:
		if .rval.IsValid() {
			convertConstantValue()
			 := .rval
			return func( *frame) reflect.Value { return  }
		}
		if .sym != nil {
			 := .sym.index
			if  < 0 &&  != .sym.node {
				return (.sym.node)
			}
			if .sym.global {
				return func( *frame) reflect.Value { return .root.data[] }
			}
			return valueGenerator(, )
		}
		if .findex == notInFrame {
			var  reflect.Value
			if ,  := .val.(reflect.Value);  {
				 = 
			} else {
				 = reflect.ValueOf(.val)
			}
			return func( *frame) reflect.Value { return  }
		}
		return valueGenerator(, .findex)
	}
}

func genDestValue( *itype,  *node) func(*frame) reflect.Value {
	convertLiteralValue(, .TypeOf())
	switch {
	case isInterfaceSrc() && (!isEmptyInterface() || len(.typ.method) > 0):
		return genValueInterface()
	case isNamedFuncSrc(.typ):
		return genFunctionWrapper()
	case isInterfaceBin():
		return genInterfaceWrapper(, .rtype)
	case .kind == basicLit && .val == nil:
		return func(*frame) reflect.Value { return reflect.New(.rtype).Elem() }
	case .typ.untyped && isComplex(.TypeOf()):
		return genValueComplex()
	case .typ.untyped && !.untyped:
		return genValueAs(, .TypeOf())
	}
	return genValue()
}

func genFuncValue( *node) func(*frame) reflect.Value {
	 := genValue()
	return func( *frame) reflect.Value {
		 := ()
		if ,  := .Interface().(*node);  {
			return genFunctionWrapper()()
		}
		return 
	}
}

func genValueArray( *node) func(*frame) reflect.Value {
	 := genValue()
	// dereference array pointer, to support array operations on array pointer
	if .typ.TypeOf().Kind() == reflect.Ptr {
		return func( *frame) reflect.Value {
			return ().Elem()
		}
	}
	return 
}

func genValueRangeArray( *node) func(*frame) reflect.Value {
	 := genValue()

	switch {
	case .typ.TypeOf().Kind() == reflect.Ptr:
		// dereference array pointer, to support array operations on array pointer
		return func( *frame) reflect.Value {
			return ().Elem()
		}
	case .typ.val != nil && .typ.val.cat == interfaceT:
		if len(.typ.val.field) > 0 {
			return func( *frame) reflect.Value {
				 := ()
				 := []valueInterface{}
				for  := 0;  < .Len(); ++ {
					switch av := .Index().Interface().(type) {
					case []valueInterface:
						 = append(, ...)
					case valueInterface:
						 = append(, )
					default:
						panic(.cfgErrorf("invalid type %v", .Index().Type()))
					}
				}
				return reflect.ValueOf()
			}
		}
		// empty interface, do not wrap.
		fallthrough
	default:
		return func( *frame) reflect.Value {
			// This is necessary to prevent changes in the returned
			// reflect.Value being reflected back to the value used
			// for the range expression.
			return reflect.ValueOf(().Interface())
		}
	}
}

func genValueInterface( *node) func(*frame) reflect.Value {
	 := genValue()

	return func( *frame) reflect.Value {
		 := ()
		 := 

		for .IsValid() {
			// traverse interface indirections to find out concrete type
			,  := .Interface().(valueInterface)
			if ! {
				break
			}
			 = .value
			 = .node
		}

		// empty interface, do not wrap.
		if  != nil && isEmptyInterface(.typ) {
			return 
		}

		return reflect.ValueOf(valueInterface{, })
	}
}

func getConcreteValue( reflect.Value) reflect.Value {
	 := 
	for {
		,  := .Interface().(valueInterface)
		if ! {
			break
		}
		 = .value
	}
	if .NumMethod() > 0 {
		return 
	}
	if .Kind() != reflect.Struct {
		return 
	}
	// Search a concrete value in fields of an emulated interface.
	for  := .NumField() - 1;  >= 0; -- {
		 := .Field()
		if .Kind() == reflect.Interface {
			 = .Elem()
		}
		if .IsValid() {
			return 
		}
	}
	return 
}

func zeroInterfaceValue() reflect.Value {
	 := &node{kind: basicLit, typ: &itype{cat: nilT, untyped: true, str: "nil"}}
	 := reflect.New(emptyInterfaceType).Elem()
	return reflect.ValueOf(valueInterface{, })
}

func wantEmptyInterface( *node) bool {
	return isEmptyInterface(.typ) ||
		.anc.action == aAssign && .anc.typ.cat == interfaceT && len(.anc.typ.field) == 0 ||
		.anc.kind == returnStmt && .anc.val.(*node).typ.ret[0].cat == interfaceT && len(.anc.val.(*node).typ.ret[0].field) == 0
}

func genValueOutput( *node,  reflect.Type) func(*frame) reflect.Value {
	 := genValue()
	switch {
	case .anc.action == aAssign && .anc.typ.cat == interfaceT:
		if len(.anc.typ.field) == 0 {
			// empty interface, do not wrap
			return 
		}
		fallthrough
	case .anc.kind == returnStmt && .anc.val.(*node).typ.ret[0].cat == interfaceT:
		if ,  := .anc.val.(*node); ! || len(.typ.ret[0].field) == 0 {
			// empty interface, do not wrap
			return 
		}
		// The result of the builtin has to be returned as an interface type.
		// Wrap it in a valueInterface and return the dereferenced value.
		return func( *frame) reflect.Value {
			 := ()
			 := reflect.New().Elem()
			.Set(reflect.ValueOf(valueInterface{, }))
			return 
		}
	}
	return 
}

func getBinValue( func(*itype) reflect.Type,  func(*frame) reflect.Value,  *frame) reflect.Value {
	 := ()
	if  == nil {
		return 
	}
	,  := .Interface().(valueInterface)
	if ! || .node == nil {
		return 
	}
	if  := (.node.typ);  != nil {
		return genInterfaceWrapper(.node, )()
	}
	return 
}

func valueInterfaceValue( reflect.Value) reflect.Value {
	for {
		,  := .Interface().(valueInterface)
		if ! {
			break
		}
		 = .value
	}
	return 
}

func genValueInterfaceValue( *node) func(*frame) reflect.Value {
	 := genValue()

	return func( *frame) reflect.Value {
		 := ()
		if ,  := .Interface().(valueInterface);  && .node == nil {
			// Uninitialized interface value, set it to a correct zero value.
			.Set(zeroInterfaceValue())
			 = ()
		}
		return valueInterfaceValue()
	}
}

func vInt( reflect.Value) ( int64) {
	if  := vConstantValue();  != nil {
		, _ = constant.Int64Val(constant.ToInt())
		return 
	}
	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		 = .Int()
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		 = int64(.Uint())
	case reflect.Float32, reflect.Float64:
		 = int64(.Float())
	case reflect.Complex64, reflect.Complex128:
		 = int64(real(.Complex()))
	}
	return
}

func vUint( reflect.Value) ( uint64) {
	if  := vConstantValue();  != nil {
		, _ = constant.Uint64Val(constant.ToInt())
		return 
	}
	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		 = uint64(.Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		 = .Uint()
	case reflect.Float32, reflect.Float64:
		 = uint64(.Float())
	case reflect.Complex64, reflect.Complex128:
		 = uint64(real(.Complex()))
	}
	return
}

func vComplex( reflect.Value) ( complex128) {
	if  := vConstantValue();  != nil {
		 = constant.ToComplex()
		,  := constant.Float64Val(constant.Real())
		,  := constant.Float64Val(constant.Imag())
		return complex(, )
	}
	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		 = complex(float64(.Int()), 0)
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		 = complex(float64(.Uint()), 0)
	case reflect.Float32, reflect.Float64:
		 = complex(.Float(), 0)
	case reflect.Complex64, reflect.Complex128:
		 = .Complex()
	}
	return
}

func vFloat( reflect.Value) ( float64) {
	if  := vConstantValue();  != nil {
		, _ = constant.Float64Val(constant.ToFloat())
		return 
	}
	switch .Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		 = float64(.Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		 = float64(.Uint())
	case reflect.Float32, reflect.Float64:
		 = .Float()
	case reflect.Complex64, reflect.Complex128:
		 = real(.Complex())
	}
	return
}

func vString( reflect.Value) ( string) {
	if  := vConstantValue();  != nil {
		 = constant.StringVal()
		return 
	}
	return .String()
}

func vConstantValue( reflect.Value) ( constant.Value) {
	if .Type().Implements(constVal) {
		 = .Interface().(constant.Value)
	}
	return
}

func genValueInt( *node) func(*frame) (reflect.Value, int64) {
	 := genValue()

	switch .typ.TypeOf().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return func( *frame) (reflect.Value, int64) {  := (); return , .Int() }
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return func( *frame) (reflect.Value, int64) {  := (); return , int64(.Uint()) }
	case reflect.Float32, reflect.Float64:
		return func( *frame) (reflect.Value, int64) {  := (); return , int64(.Float()) }
	case reflect.Complex64, reflect.Complex128:
		if .typ.untyped && .rval.IsValid() && imag(.rval.Complex()) == 0 {
			return func( *frame) (reflect.Value, int64) {  := (); return , int64(real(.Complex())) }
		}
	}
	return nil
}

func genValueUint( *node) func(*frame) (reflect.Value, uint64) {
	 := genValue()

	switch .typ.TypeOf().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return func( *frame) (reflect.Value, uint64) {  := (); return , uint64(.Int()) }
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return func( *frame) (reflect.Value, uint64) {  := (); return , .Uint() }
	case reflect.Float32, reflect.Float64:
		return func( *frame) (reflect.Value, uint64) {  := (); return , uint64(.Float()) }
	case reflect.Complex64, reflect.Complex128:
		if .typ.untyped && .rval.IsValid() && imag(.rval.Complex()) == 0 {
			return func( *frame) (reflect.Value, uint64) {  := (); return , uint64(real(.Complex())) }
		}
	}
	return nil
}

func genValueFloat( *node) func(*frame) (reflect.Value, float64) {
	 := genValue()

	switch .typ.TypeOf().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return func( *frame) (reflect.Value, float64) {  := (); return , float64(.Int()) }
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return func( *frame) (reflect.Value, float64) {  := (); return , float64(.Uint()) }
	case reflect.Float32, reflect.Float64:
		return func( *frame) (reflect.Value, float64) {  := (); return , .Float() }
	case reflect.Complex64, reflect.Complex128:
		if .typ.untyped && .rval.IsValid() && imag(.rval.Complex()) == 0 {
			return func( *frame) (reflect.Value, float64) {  := (); return , real(.Complex()) }
		}
	}
	return nil
}

func genValueComplex( *node) func(*frame) reflect.Value {
	 := genComplex()
	return func( *frame) reflect.Value { return reflect.ValueOf(()) }
}

func genComplex( *node) func(*frame) complex128 {
	 := genValue()

	switch .typ.TypeOf().Kind() {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return func( *frame) complex128 { return complex(float64(().Int()), 0) }
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		return func( *frame) complex128 { return complex(float64(().Uint()), 0) }
	case reflect.Float32, reflect.Float64:
		return func( *frame) complex128 { return complex(().Float(), 0) }
	case reflect.Complex64, reflect.Complex128:
		return func( *frame) complex128 { return ().Complex() }
	}
	return nil
}

func genValueString( *node) func(*frame) (reflect.Value, string) {
	 := genValue()

	return func( *frame) (reflect.Value, string) {  := (); return , .String() }
}