1
1
package compiler
2
2
3
3
import (
4
- "crypto/md5 "
4
+ "crypto/sha1 "
5
5
"fmt"
6
6
"sort"
7
7
"strconv"
@@ -11,78 +11,78 @@ import (
11
11
"github.com/antonmedv/expr/file"
12
12
)
13
13
14
- func (c * compiler ) checkCommonSubExpr (node ast.Node ) {
14
+ func (c * compiler ) countCommonExpr (node ast.Node ) {
15
15
switch n := node .(type ) {
16
16
case * ast.NilNode :
17
- c .checkNilNode (n )
17
+ c .commonCommonNilNode (n )
18
18
case * ast.IdentifierNode :
19
- c .checkIdentifierNode (n )
19
+ c .countCommonIdentifierNode (n )
20
20
case * ast.IntegerNode :
21
- c .checkIntegerNode (n )
21
+ c .countCommonIntegerNode (n )
22
22
case * ast.FloatNode :
23
- c .checkFloatNode (n )
23
+ c .countCommonFloatNode (n )
24
24
case * ast.BoolNode :
25
- c .checkBoolNode (n )
25
+ c .countCommonBoolNode (n )
26
26
case * ast.StringNode :
27
- c .checkStringNode (n )
27
+ c .countCommonStringNode (n )
28
28
case * ast.ConstantNode :
29
- c .checkConstantNode (n )
29
+ c .countCommonConstantNode (n )
30
30
case * ast.UnaryNode :
31
- c .checkUnaryNode (n )
31
+ c .countCommonUnaryNode (n )
32
32
case * ast.BinaryNode :
33
- c .checkBinaryNode (n )
33
+ c .countCommonBinaryNode (n )
34
34
case * ast.ChainNode :
35
- c .checkChainNode (n )
35
+ c .countCommonChainNode (n )
36
36
case * ast.MemberNode :
37
- c .checkMemberNode (n )
37
+ c .countCommonMemberNode (n )
38
38
case * ast.SliceNode :
39
- c .checkSliceNode (n )
39
+ c .countCommonSliceNode (n )
40
40
case * ast.CallNode :
41
41
c .checkCallNode (n )
42
42
case * ast.BuiltinNode :
43
- c .checkBuiltinNode (n )
43
+ c .countCommonBuiltinNode (n )
44
44
case * ast.ClosureNode :
45
- c .checkClosureNode (n )
45
+ c .countCommonClosureNode (n )
46
46
case * ast.PointerNode :
47
- c .checkPointerNode (n )
47
+ c .countCommonPointerNode (n )
48
48
case * ast.ConditionalNode :
49
- c .checkConditionalNode (n )
49
+ c .countCommonConditionalNode (n )
50
50
case * ast.ArrayNode :
51
- c .checkArrayNode (n )
51
+ c .countCommonArrayNode (n )
52
52
case * ast.MapNode :
53
- c .checkMapNode (n )
53
+ c .countCommonMapNode (n )
54
54
case * ast.PairNode :
55
- c .checkPairNode (n )
55
+ c .countCommonPairNode (n )
56
56
default :
57
57
panic (fmt .Sprintf ("undefined node type (%T)" , node ))
58
58
}
59
59
}
60
60
61
- func (c * compiler ) checkNilNode (n * ast.NilNode ) {
61
+ func (c * compiler ) commonCommonNilNode (n * ast.NilNode ) {
62
62
n .SetSubExpr ("nil" )
63
63
}
64
64
65
- func (c * compiler ) checkIdentifierNode (n * ast.IdentifierNode ) {
65
+ func (c * compiler ) countCommonIdentifierNode (n * ast.IdentifierNode ) {
66
66
n .SetSubExpr (n .Value )
67
67
}
68
68
69
- func (c * compiler ) checkIntegerNode (n * ast.IntegerNode ) {
69
+ func (c * compiler ) countCommonIntegerNode (n * ast.IntegerNode ) {
70
70
n .SetSubExpr (strconv .FormatInt (int64 (n .Value ), 10 ))
71
71
}
72
72
73
- func (c * compiler ) checkFloatNode (n * ast.FloatNode ) {
73
+ func (c * compiler ) countCommonFloatNode (n * ast.FloatNode ) {
74
74
n .SetSubExpr (strconv .FormatFloat (n .Value , 'f' , 10 , 64 ))
75
75
}
76
76
77
- func (c * compiler ) checkBoolNode (n * ast.BoolNode ) {
77
+ func (c * compiler ) countCommonBoolNode (n * ast.BoolNode ) {
78
78
n .SetSubExpr (strconv .FormatBool (n .Value ))
79
79
}
80
80
81
- func (c * compiler ) checkStringNode (n * ast.StringNode ) {
81
+ func (c * compiler ) countCommonStringNode (n * ast.StringNode ) {
82
82
n .SetSubExpr (strconv .Quote (n .Value ))
83
83
}
84
84
85
- func (c * compiler ) checkConstantNode (n * ast.ConstantNode ) {
85
+ func (c * compiler ) countCommonConstantNode (n * ast.ConstantNode ) {
86
86
switch n .Value .(type ) {
87
87
case string :
88
88
n .SetSubExpr (strconv .Quote (n .Value .(string )))
@@ -115,8 +115,8 @@ func (c *compiler) checkConstantNode(n *ast.ConstantNode) {
115
115
}
116
116
}
117
117
118
- func (c * compiler ) checkUnaryNode (n * ast.UnaryNode ) {
119
- c .checkCommonSubExpr (n .Node )
118
+ func (c * compiler ) countCommonUnaryNode (n * ast.UnaryNode ) {
119
+ c .countCommonExpr (n .Node )
120
120
switch n .Operator {
121
121
case "+" :
122
122
n .SetSubExpr (n .Node .SubExpr ())
@@ -127,23 +127,27 @@ func (c *compiler) checkUnaryNode(n *ast.UnaryNode) {
127
127
}
128
128
}
129
129
130
- func (c * compiler ) checkBinaryNode (n * ast.BinaryNode ) {
131
- c .checkCommonSubExpr (n .Left )
132
- c .checkCommonSubExpr (n .Right )
130
+ func (c * compiler ) countCommonBinaryNode (n * ast.BinaryNode ) {
131
+ c .countCommonExpr (n .Left )
132
+ c .countCommonExpr (n .Right )
133
133
switch n .Operator {
134
134
case "==" , "!=" , "and" , "or" , "+" , "*" , "||" , "&&" : // right / left can be swap
135
135
ls := n .Left .SubExpr ()
136
136
rs := n .Right .SubExpr ()
137
137
if rs <= ls {
138
138
ls , rs = rs , ls
139
139
}
140
- if n .Operator == "and " {
141
- n .SetSubExpr (fmt .Sprintf ("%s && %s" , ls , rs ))
142
- } else if n .Operator == "or " {
143
- n .SetSubExpr (fmt .Sprintf ("%s || %s" , ls , rs ))
140
+ if n .Operator == "&& " {
141
+ n .SetSubExpr (fmt .Sprintf ("%s and %s" , ls , rs ))
142
+ } else if n .Operator == "|| " {
143
+ n .SetSubExpr (fmt .Sprintf ("%s or %s" , ls , rs ))
144
144
} else {
145
145
n .SetSubExpr (fmt .Sprintf ("%s %s %s" , ls , n .Operator , rs ))
146
146
}
147
+ case ">=" :
148
+ n .SetSubExpr (fmt .Sprintf ("%s < %s" , n .Right .SubExpr (), n .Left .SubExpr ()))
149
+ case "<=" :
150
+ n .SetSubExpr (fmt .Sprintf ("%s > %s" , n .Right .SubExpr (), n .Left .SubExpr ()))
147
151
case "**" , "^" :
148
152
n .SetSubExpr (fmt .Sprintf ("%s ** %s" , n .Left .SubExpr (), n .Right .SubExpr ()))
149
153
default :
@@ -157,75 +161,75 @@ func (c *compiler) checkBinaryNode(n *ast.BinaryNode) {
157
161
}
158
162
}
159
163
160
- func (c * compiler ) checkChainNode (n * ast.ChainNode ) {
161
- c .checkCommonSubExpr (n .Node )
164
+ func (c * compiler ) countCommonChainNode (n * ast.ChainNode ) {
165
+ c .countCommonExpr (n .Node )
162
166
}
163
167
164
- func (c * compiler ) checkMemberNode (n * ast.MemberNode ) {
165
- c .checkCommonSubExpr (n .Node )
166
- c .checkCommonSubExpr (n .Property )
168
+ func (c * compiler ) countCommonMemberNode (n * ast.MemberNode ) {
169
+ c .countCommonExpr (n .Node )
170
+ c .countCommonExpr (n .Property )
167
171
optional := ""
168
172
if n .Optional {
169
173
optional = "?"
170
174
}
171
175
n .SetSubExpr (fmt .Sprintf ("%s%s.%s" , n .Node .SubExpr (), optional , n .Property .SubExpr ()))
172
176
}
173
177
174
- func (c * compiler ) checkSliceNode (n * ast.SliceNode ) {
175
- c .checkCommonSubExpr (n .Node )
176
- c .checkCommonSubExpr (n .To )
177
- c .checkCommonSubExpr (n .From )
178
+ func (c * compiler ) countCommonSliceNode (n * ast.SliceNode ) {
179
+ c .countCommonExpr (n .Node )
180
+ c .countCommonExpr (n .To )
181
+ c .countCommonExpr (n .From )
178
182
n .SetSubExpr (fmt .Sprintf ("%s[%s:%s]" , n .Node .SubExpr (), n .From .SubExpr (), n .To .SubExpr ()))
179
183
}
180
184
181
185
func (c * compiler ) checkCallNode (n * ast.CallNode ) {
182
186
s := make ([]string , 0 )
183
187
for _ , arg := range n .Arguments {
184
- c .checkCommonSubExpr (arg )
188
+ c .countCommonExpr (arg )
185
189
s = append (s , arg .SubExpr ())
186
190
}
187
- c .checkCommonSubExpr (n .Callee )
191
+ c .countCommonExpr (n .Callee )
188
192
n .SetSubExpr (fmt .Sprintf ("%s(%s)" , n .Callee .SubExpr (), strings .Join (s , "," )))
189
193
}
190
194
191
- func (c * compiler ) checkBuiltinNode (n * ast.BuiltinNode ) {
195
+ func (c * compiler ) countCommonBuiltinNode (n * ast.BuiltinNode ) {
192
196
s := make ([]string , 0 )
193
197
for _ , arg := range n .Arguments {
194
- c .checkCommonSubExpr (arg )
198
+ c .countCommonExpr (arg )
195
199
s = append (s , arg .SubExpr ())
196
200
}
197
201
n .SetSubExpr (fmt .Sprintf ("%s(%s)" , n .Name , strings .Join (s , "," )))
198
202
}
199
203
200
- func (c * compiler ) checkClosureNode (n * ast.ClosureNode ) {
201
- c .checkCommonSubExpr (n .Node )
204
+ func (c * compiler ) countCommonClosureNode (n * ast.ClosureNode ) {
205
+ c .countCommonExpr (n .Node )
202
206
}
203
207
204
- func (c * compiler ) checkPointerNode (n * ast.PointerNode ) {
208
+ func (c * compiler ) countCommonPointerNode (n * ast.PointerNode ) {
205
209
// do nothing
206
210
}
207
211
208
- func (c * compiler ) checkConditionalNode (n * ast.ConditionalNode ) {
209
- c .checkCommonSubExpr (n .Cond )
210
- c .checkCommonSubExpr (n .Exp1 )
211
- c .checkCommonSubExpr (n .Exp2 )
212
+ func (c * compiler ) countCommonConditionalNode (n * ast.ConditionalNode ) {
213
+ c .countCommonExpr (n .Cond )
214
+ c .countCommonExpr (n .Exp1 )
215
+ c .countCommonExpr (n .Exp2 )
212
216
n .SetSubExpr (fmt .Sprintf ("%s ? %s : %s" , n .Cond .SubExpr (), n .Exp1 .SubExpr (), n .Exp2 .SubExpr ()))
213
217
}
214
218
215
- func (c * compiler ) checkArrayNode (n * ast.ArrayNode ) {
219
+ func (c * compiler ) countCommonArrayNode (n * ast.ArrayNode ) {
216
220
s := make ([]string , 0 )
217
221
for _ , node := range n .Nodes {
218
- c .checkCommonSubExpr (node )
222
+ c .countCommonExpr (node )
219
223
s = append (s , node .SubExpr ())
220
224
}
221
225
n .SetSubExpr (fmt .Sprintf ("[%s]" , strings .Join (s , "," )))
222
226
}
223
227
224
- func (c * compiler ) checkMapNode (n * ast.MapNode ) {
228
+ func (c * compiler ) countCommonMapNode (n * ast.MapNode ) {
225
229
pairs := make ([]* ast.PairNode , 0 )
226
230
for _ , p := range n .Pairs {
227
231
pair := p .(* ast.PairNode )
228
- c .checkPairNode (pair )
232
+ c .countCommonPairNode (pair )
229
233
pairs = append (pairs , pair )
230
234
}
231
235
sort .Slice (pairs , func (i , j int ) bool {
@@ -238,38 +242,38 @@ func (c *compiler) checkMapNode(n *ast.MapNode) {
238
242
n .SetSubExpr (fmt .Sprintf ("{%s}" , strings .Join (s , "," )))
239
243
}
240
244
241
- func (c * compiler ) checkPairNode (n * ast.PairNode ) {
242
- c .checkCommonSubExpr (n .Key )
243
- c .checkCommonSubExpr (n .Value )
245
+ func (c * compiler ) countCommonPairNode (n * ast.PairNode ) {
246
+ c .countCommonExpr (n .Key )
247
+ c .countCommonExpr (n .Value )
244
248
n .SetSubExpr (fmt .Sprintf ("%s:%s" , n .Key .SubExpr (), n .Value .SubExpr ()))
245
249
}
246
250
247
251
func (c * compiler ) emitSubExpr (subExpr string , loc file.Location ) {
248
- if subExpr == "" {
252
+ if c . exprRecords == nil || subExpr == "" {
249
253
return
250
254
}
251
- hash := fmt .Sprintf ("%x" , md5 .Sum ([]byte (subExpr )))
252
- if cs , ok := c .subExprCache [hash ]; ! ok {
253
- c .subExprCache [hash ] = & SubExprRecord {
254
- cnt : 1 ,
255
- }
255
+ hash := fmt .Sprintf ("%x" , sha1 .Sum ([]byte (subExpr )))
256
+ if cs , ok := c .exprRecords [hash ]; ! ok {
257
+ c .exprRecords [hash ] = & exprRecord {cnt : 1 }
256
258
} else {
257
259
if cs .cnt == 1 {
258
- c .subExprUniqId += 1
259
- cs .id = c .subExprUniqId
260
+ cs .id = c .commonExprInc
261
+ c .commonExpr [cs .id ] = subExpr
262
+ c .commonExprInc += 1
260
263
}
261
264
cs .cnt = cs .cnt + 1
262
265
}
263
266
}
264
267
265
- func (c * compiler ) checkNeedCSE (n ast.Node ) (bool , int ) {
266
- needCSE := false
267
- cseUniqId := 0
268
- hash := fmt .Sprintf ("%x" , md5 .Sum ([]byte (n .SubExpr ())))
269
- cs , ok := c .subExprCache [hash ]
270
- if ok && cs .cnt > 1 {
271
- needCSE = true
272
- cseUniqId = cs .id
268
+ func (c * compiler ) needCacheCommon (n ast.Node ) (bool , int ) {
269
+ needCacheCommon , exprUniqId := false , - 1
270
+ if c .exprRecords != nil {
271
+ hash := fmt .Sprintf ("%x" , sha1 .Sum ([]byte (n .SubExpr ())))
272
+ cs , ok := c .exprRecords [hash ]
273
+ if ok && cs .cnt > 1 {
274
+ needCacheCommon = true
275
+ exprUniqId = cs .id
276
+ }
273
277
}
274
- return needCSE , cseUniqId
278
+ return needCacheCommon , exprUniqId
275
279
}
0 commit comments