Files
moxa/interp/value.go
Marc Vertes 6d21cefe75 fix: allow imported binary variables to be set (#85)
Change the way imported binary variables are imported, from
`reflect.ValueOf(val)` to `reflect.ValueOf(&val).Elem()`, to allow these
variables to be set from the interpreter.
Regenerate stdlib packages accordingly.
Ensure that binary value is forwarded if it exists.
Add tests.
2019-02-07 15:41:22 +01:00

158 lines
3.9 KiB
Go

package interp
import (
"reflect"
)
func valueGenerator(n *Node, i int) func(*Frame) reflect.Value {
switch n.level {
case 0:
return func(f *Frame) reflect.Value { return f.data[i] }
case 1:
return func(f *Frame) reflect.Value {
return f.anc.data[i]
}
case 2:
return func(f *Frame) reflect.Value { return f.anc.anc.data[i] }
default:
return func(f *Frame) reflect.Value {
for level := n.level; level > 0; level-- {
f = f.anc
}
return f.data[i]
}
}
}
func genValueRecv(n *Node) func(*Frame) reflect.Value {
v := genValue(n.recv.node)
fi := n.recv.index
if len(fi) == 0 {
return v
}
return func(f *Frame) reflect.Value {
r := v(f)
if r.Kind() == reflect.Ptr {
r = r.Elem()
}
return r.FieldByIndex(fi)
}
}
func genValue(n *Node) func(*Frame) reflect.Value {
switch n.kind {
case BasicLit, FuncDecl, SelectorSrc:
var v reflect.Value
if w, ok := n.val.(reflect.Value); ok {
v = w
} else {
v = reflect.ValueOf(n.val)
}
return func(f *Frame) reflect.Value { return v }
case Rvalue:
v := n.rval
return func(f *Frame) reflect.Value { return v }
default:
if n.rval.IsValid() {
v := n.rval
return func(f *Frame) reflect.Value { return v }
}
if n.sym != nil {
if n.sym.index < 0 {
return genValue(n.sym.node)
}
i := n.sym.index
if n.sym.global {
return func(f *Frame) reflect.Value {
return n.interp.Frame.data[i]
}
}
return valueGenerator(n, i)
}
if n.findex < 0 {
var v reflect.Value
if w, ok := n.val.(reflect.Value); ok {
v = w
} else {
v = reflect.ValueOf(n.val)
}
return func(f *Frame) reflect.Value { return v }
}
return valueGenerator(n, n.findex)
}
}
func genValueAddr(n *Node) func(*Frame) *reflect.Value {
return func(f *Frame) *reflect.Value {
for level := n.level; level > 0; level-- {
f = f.anc
}
return &f.data[n.findex]
}
}
func genValueInterface(n *Node) func(*Frame) reflect.Value {
value := genValue(n)
return func(f *Frame) reflect.Value {
return reflect.ValueOf(valueInterface{n, value(f)})
}
}
func genValueInterfaceValue(n *Node) func(*Frame) reflect.Value {
value := genValue(n)
return func(f *Frame) reflect.Value {
return value(f).Interface().(valueInterface).value
}
}
func genValueInt(n *Node) func(*Frame) int64 {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *Frame) int64 { return value(f).Int() }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return func(f *Frame) int64 { return int64(value(f).Uint()) }
case reflect.Float32, reflect.Float64:
return func(f *Frame) int64 { return int64(value(f).Float()) }
}
return nil
}
func genValueUint(n *Node) func(*Frame) uint64 {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *Frame) uint64 { return uint64(value(f).Int()) }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return func(f *Frame) uint64 { return value(f).Uint() }
case reflect.Float32, reflect.Float64:
return func(f *Frame) uint64 { return uint64(value(f).Float()) }
}
return nil
}
func genValueFloat(n *Node) func(*Frame) float64 {
value := genValue(n)
switch n.typ.TypeOf().Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return func(f *Frame) float64 { return float64(value(f).Int()) }
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return func(f *Frame) float64 { return float64(value(f).Uint()) }
case reflect.Float32, reflect.Float64:
return func(f *Frame) float64 { return value(f).Float() }
}
return nil
}
func genValueString(n *Node) func(*Frame) string {
value := genValue(n)
return func(f *Frame) string { return value(f).String() }
}