1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
package script
import (
"go/ast"
"reflect"
)
// left-hand value in (single) assign statement
type LValue interface {
Expr
SetValue(interface{}) // assigns a new value
}
func (w *World) compileLvalue(lhs ast.Node) LValue {
switch lhs := lhs.(type) {
default:
panic(err(lhs.Pos(), "cannot assign to", typ(lhs)))
case *ast.Ident:
if l, ok := w.resolve(lhs.Pos(), lhs.Name).(LValue); ok {
return l
} else {
panic(err(lhs.Pos(), "cannot assign to", lhs.Name))
}
}
}
type reflectLvalue struct {
elem reflect.Value
}
// general lvalue implementation using reflect.
// lhs must be settable, e.g. address of something:
// var x float64
// newReflectLValue(&x)
func newReflectLvalue(addr interface{}) LValue {
elem := reflect.ValueOf(addr).Elem()
if elem.Kind() == 0 {
panic("variable/constant needs to be passed as pointer to addressable value")
}
return &reflectLvalue{elem}
}
func (l *reflectLvalue) Eval() interface{} {
return l.elem.Interface()
}
func (l *reflectLvalue) Type() reflect.Type {
return l.elem.Type()
}
func (l *reflectLvalue) SetValue(rvalue interface{}) {
l.elem.Set(reflect.ValueOf(rvalue))
}
func (l *reflectLvalue) Child() []Expr {
return nil
}
func (l *reflectLvalue) Fix() Expr {
return NewConst(l)
}
type TVar struct {
LValue
}
func (t *TVar) Fix() Expr {
return t // only variable that's not fixed
}
|