Files
moxa/interp/value.go
Marc Vertes 5677e0501e fix: correct propagation of values during eval (#95)
Eval returns the value of the root node of AST, so ensure
that node values are propagated back to ExprStmt and BlockStmt,
which should be sufficient to handle evaluation of simple
statements.
2019-02-19 14:51:44 +01:00

158 lines
3.8 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:
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() }
}