1
1
package optimizer
2
2
3
3
import (
4
+ "fmt"
4
5
"math"
5
6
"reflect"
6
7
7
8
. "github.com/antonmedv/expr/ast"
8
9
"github.com/antonmedv/expr/file"
9
10
)
10
11
12
+ var (
13
+ integerType = reflect .TypeOf (0 )
14
+ floatType = reflect .TypeOf (float64 (0 ))
15
+ stringType = reflect .TypeOf ("" )
16
+ )
17
+
11
18
type fold struct {
12
19
applied bool
13
20
err * file.Error
@@ -18,29 +25,36 @@ func (fold *fold) Visit(node *Node) {
18
25
fold .applied = true
19
26
Patch (node , newNode )
20
27
}
21
- // for IntegerNode the type may have been changed from int->float
22
- // preserve this information by setting the type after the Patch
23
- patchWithType := func (newNode Node , leafType reflect.Type ) {
28
+ patchWithType := func (newNode Node ) {
24
29
patch (newNode )
25
- newNode .SetType (leafType )
30
+ switch newNode .(type ) {
31
+ case * IntegerNode :
32
+ newNode .SetType (integerType )
33
+ case * FloatNode :
34
+ newNode .SetType (floatType )
35
+ case * StringNode :
36
+ newNode .SetType (stringType )
37
+ default :
38
+ panic (fmt .Sprintf ("unknown type %T" , newNode ))
39
+ }
26
40
}
27
41
28
42
switch n := (* node ).(type ) {
29
43
case * UnaryNode :
30
44
switch n .Operator {
31
45
case "-" :
32
46
if i , ok := n .Node .(* IntegerNode ); ok {
33
- patchWithType (& IntegerNode {Value : - i .Value }, n . Node . Type () )
47
+ patchWithType (& IntegerNode {Value : - i .Value })
34
48
}
35
49
if i , ok := n .Node .(* FloatNode ); ok {
36
- patchWithType (& FloatNode {Value : - i .Value }, n . Node . Type () )
50
+ patchWithType (& FloatNode {Value : - i .Value })
37
51
}
38
52
case "+" :
39
53
if i , ok := n .Node .(* IntegerNode ); ok {
40
- patchWithType (& IntegerNode {Value : i .Value }, n . Node . Type () )
54
+ patchWithType (& IntegerNode {Value : i .Value })
41
55
}
42
56
if i , ok := n .Node .(* FloatNode ); ok {
43
- patchWithType (& FloatNode {Value : i .Value }, n . Node . Type () )
57
+ patchWithType (& FloatNode {Value : i .Value })
44
58
}
45
59
case "!" , "not" :
46
60
if a := toBool (n .Node ); a != nil {
@@ -55,28 +69,28 @@ func (fold *fold) Visit(node *Node) {
55
69
a := toInteger (n .Left )
56
70
b := toInteger (n .Right )
57
71
if a != nil && b != nil {
58
- patchWithType (& IntegerNode {Value : a .Value + b .Value }, a . Type () )
72
+ patchWithType (& IntegerNode {Value : a .Value + b .Value })
59
73
}
60
74
}
61
75
{
62
76
a := toInteger (n .Left )
63
77
b := toFloat (n .Right )
64
78
if a != nil && b != nil {
65
- patchWithType (& FloatNode {Value : float64 (a .Value ) + b .Value }, a . Type () )
79
+ patchWithType (& FloatNode {Value : float64 (a .Value ) + b .Value })
66
80
}
67
81
}
68
82
{
69
83
a := toFloat (n .Left )
70
84
b := toInteger (n .Right )
71
85
if a != nil && b != nil {
72
- patchWithType (& FloatNode {Value : a .Value + float64 (b .Value )}, a . Type () )
86
+ patchWithType (& FloatNode {Value : a .Value + float64 (b .Value )})
73
87
}
74
88
}
75
89
{
76
90
a := toFloat (n .Left )
77
91
b := toFloat (n .Right )
78
92
if a != nil && b != nil {
79
- patchWithType (& FloatNode {Value : a .Value + b .Value }, a . Type () )
93
+ patchWithType (& FloatNode {Value : a .Value + b .Value })
80
94
}
81
95
}
82
96
{
@@ -91,86 +105,86 @@ func (fold *fold) Visit(node *Node) {
91
105
a := toInteger (n .Left )
92
106
b := toInteger (n .Right )
93
107
if a != nil && b != nil {
94
- patchWithType (& IntegerNode {Value : a .Value - b .Value }, a . Type () )
108
+ patchWithType (& IntegerNode {Value : a .Value - b .Value })
95
109
}
96
110
}
97
111
{
98
112
a := toInteger (n .Left )
99
113
b := toFloat (n .Right )
100
114
if a != nil && b != nil {
101
- patchWithType (& FloatNode {Value : float64 (a .Value ) - b .Value }, a . Type () )
115
+ patchWithType (& FloatNode {Value : float64 (a .Value ) - b .Value })
102
116
}
103
117
}
104
118
{
105
119
a := toFloat (n .Left )
106
120
b := toInteger (n .Right )
107
121
if a != nil && b != nil {
108
- patchWithType (& FloatNode {Value : a .Value - float64 (b .Value )}, a . Type () )
122
+ patchWithType (& FloatNode {Value : a .Value - float64 (b .Value )})
109
123
}
110
124
}
111
125
{
112
126
a := toFloat (n .Left )
113
127
b := toFloat (n .Right )
114
128
if a != nil && b != nil {
115
- patchWithType (& FloatNode {Value : a .Value - b .Value }, a . Type () )
129
+ patchWithType (& FloatNode {Value : a .Value - b .Value })
116
130
}
117
131
}
118
132
case "*" :
119
133
{
120
134
a := toInteger (n .Left )
121
135
b := toInteger (n .Right )
122
136
if a != nil && b != nil {
123
- patchWithType (& IntegerNode {Value : a .Value * b .Value }, a . Type () )
137
+ patchWithType (& IntegerNode {Value : a .Value * b .Value })
124
138
}
125
139
}
126
140
{
127
141
a := toInteger (n .Left )
128
142
b := toFloat (n .Right )
129
143
if a != nil && b != nil {
130
- patchWithType (& FloatNode {Value : float64 (a .Value ) * b .Value }, a . Type () )
144
+ patchWithType (& FloatNode {Value : float64 (a .Value ) * b .Value })
131
145
}
132
146
}
133
147
{
134
148
a := toFloat (n .Left )
135
149
b := toInteger (n .Right )
136
150
if a != nil && b != nil {
137
- patchWithType (& FloatNode {Value : a .Value * float64 (b .Value )}, a . Type () )
151
+ patchWithType (& FloatNode {Value : a .Value * float64 (b .Value )})
138
152
}
139
153
}
140
154
{
141
155
a := toFloat (n .Left )
142
156
b := toFloat (n .Right )
143
157
if a != nil && b != nil {
144
- patchWithType (& FloatNode {Value : a .Value * b .Value }, a . Type () )
158
+ patchWithType (& FloatNode {Value : a .Value * b .Value })
145
159
}
146
160
}
147
161
case "/" :
148
162
{
149
163
a := toInteger (n .Left )
150
164
b := toInteger (n .Right )
151
165
if a != nil && b != nil {
152
- patchWithType (& FloatNode {Value : float64 (a .Value ) / float64 (b .Value )}, a . Type () )
166
+ patchWithType (& FloatNode {Value : float64 (a .Value ) / float64 (b .Value )})
153
167
}
154
168
}
155
169
{
156
170
a := toInteger (n .Left )
157
171
b := toFloat (n .Right )
158
172
if a != nil && b != nil {
159
- patchWithType (& FloatNode {Value : float64 (a .Value ) / b .Value }, a . Type () )
173
+ patchWithType (& FloatNode {Value : float64 (a .Value ) / b .Value })
160
174
}
161
175
}
162
176
{
163
177
a := toFloat (n .Left )
164
178
b := toInteger (n .Right )
165
179
if a != nil && b != nil {
166
- patchWithType (& FloatNode {Value : a .Value / float64 (b .Value )}, a . Type () )
180
+ patchWithType (& FloatNode {Value : a .Value / float64 (b .Value )})
167
181
}
168
182
}
169
183
{
170
184
a := toFloat (n .Left )
171
185
b := toFloat (n .Right )
172
186
if a != nil && b != nil {
173
- patchWithType (& FloatNode {Value : a .Value / b .Value }, a . Type () )
187
+ patchWithType (& FloatNode {Value : a .Value / b .Value })
174
188
}
175
189
}
176
190
case "%" :
@@ -191,28 +205,28 @@ func (fold *fold) Visit(node *Node) {
191
205
a := toInteger (n .Left )
192
206
b := toInteger (n .Right )
193
207
if a != nil && b != nil {
194
- patchWithType (& FloatNode {Value : math .Pow (float64 (a .Value ), float64 (b .Value ))}, a . Type () )
208
+ patchWithType (& FloatNode {Value : math .Pow (float64 (a .Value ), float64 (b .Value ))})
195
209
}
196
210
}
197
211
{
198
212
a := toInteger (n .Left )
199
213
b := toFloat (n .Right )
200
214
if a != nil && b != nil {
201
- patchWithType (& FloatNode {Value : math .Pow (float64 (a .Value ), b .Value )}, a . Type () )
215
+ patchWithType (& FloatNode {Value : math .Pow (float64 (a .Value ), b .Value )})
202
216
}
203
217
}
204
218
{
205
219
a := toFloat (n .Left )
206
220
b := toInteger (n .Right )
207
221
if a != nil && b != nil {
208
- patchWithType (& FloatNode {Value : math .Pow (a .Value , float64 (b .Value ))}, a . Type () )
222
+ patchWithType (& FloatNode {Value : math .Pow (a .Value , float64 (b .Value ))})
209
223
}
210
224
}
211
225
{
212
226
a := toFloat (n .Left )
213
227
b := toFloat (n .Right )
214
228
if a != nil && b != nil {
215
- patchWithType (& FloatNode {Value : math .Pow (a .Value , b .Value )}, a . Type () )
229
+ patchWithType (& FloatNode {Value : math .Pow (a .Value , b .Value )})
216
230
}
217
231
}
218
232
case "and" , "&&" :
0 commit comments