-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathevalunaryexpr.go
More file actions
120 lines (104 loc) · 2.84 KB
/
evalunaryexpr.go
File metadata and controls
120 lines (104 loc) · 2.84 KB
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package eval
import (
"reflect"
"go/token"
)
func evalUnaryExpr(unary *UnaryExpr, env Env) ([]reflect.Value, error) {
if unary.IsConst() {
return []reflect.Value{unary.Const()}, nil
}
xx, err := EvalExpr(unary.X, env)
if err != nil {
return []reflect.Value{}, err
}
x := xx[0]
// handle & and <- first
if unary.Op == token.AND {
return []reflect.Value{x.Addr()}, nil
} else if unary.Op == token.ARROW {
// TODO[crc] use x.Recv in contexts where blocking is acceptable
v, ok := x.TryRecv()
if !v.IsValid() {
v = reflect.New(x.Type().Elem()).Elem()
}
// TODO[crc] also return ok once assignability context is implemented
return []reflect.Value{v, reflect.ValueOf(ok)}, nil
}
var r reflect.Value
switch x.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
r, err = evalUnaryIntExpr(x, unary.Op)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
r, err = evalUnaryUintExpr(x, unary.Op)
case reflect.Float32, reflect.Float64:
r, err = evalUnaryFloatExpr(x, unary.Op)
case reflect.Complex64, reflect.Complex128:
r, err = evalUnaryComplexExpr(x, unary.Op)
case reflect.Bool:
r, err = evalUnaryBoolExpr(x, unary.Op)
default:
panic("eval: impossible unary op " + unary.Op.String())
}
return []reflect.Value{r}, err
}
func evalUnaryIntExpr(x reflect.Value, op token.Token) (reflect.Value, error) {
var r int64
var err error
xx := x.Int()
switch op {
case token.ADD: r = +xx
case token.SUB: r = -xx
case token.XOR: r = ^xx
default:
panic("eval: impossible unary op " + op.String())
}
return reflect.ValueOf(r).Convert(x.Type()), err
}
func evalUnaryUintExpr(x reflect.Value, op token.Token) (reflect.Value, error) {
var err error
var r uint64
xx := x.Uint()
switch op {
case token.ADD: r = +xx
case token.SUB: r = -xx
case token.XOR: r = ^xx
default:
panic("eval: impossible unary op " + op.String())
}
return reflect.ValueOf(r).Convert(x.Type()), err
}
func evalUnaryFloatExpr(x reflect.Value, op token.Token) (reflect.Value, error) {
var err error
var r float64
xx := x.Float()
switch op {
case token.ADD: r = + xx
case token.SUB: r = - xx
default:
panic("eval: impossible unary op " + op.String())
}
return reflect.ValueOf(r).Convert(x.Type()), err
}
func evalUnaryComplexExpr(x reflect.Value, op token.Token) (reflect.Value, error) {
var err error
var r complex128
xx := x.Complex()
switch op {
case token.ADD: r = +xx
case token.SUB: r = -xx
default:
panic("eval: impossible unary op " + op.String())
}
return reflect.ValueOf(r).Convert(x.Type()), err
}
func evalUnaryBoolExpr(x reflect.Value, op token.Token) (reflect.Value, error) {
var err error
var r bool
xx := x.Bool()
switch op {
case token.NOT: r = !xx
default:
panic("eval: impossible unary op " + op.String())
}
return reflect.ValueOf(r).Convert(x.Type()), err
}