/
lvalue.go
69 lines (57 loc) · 1.33 KB
/
lvalue.go
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
}