...
1 package main
2
3 import (
4 "fmt"
5 "log"
6 )
7
8
9
10
11 type Expression interface {
12
13
14
15
16 Concrete() bool
17
18
19
20
21 Eval() int
22
23
24
25
26
27 Reduce(prefix string) string
28
29
30 String() string
31
32
33
34 Initialize(p *Protocol)
35 }
36
37
38
39 type Function struct {
40 Name string
41 Expr Expression
42 }
43
44 func (e *Function) Concrete() bool {
45 return false
46 }
47
48 func (e *Function) Eval() int {
49 log.Fatalf("Cannot evaluate a 'Function'. It is not concrete.")
50 panic("unreachable")
51 }
52
53 func (e *Function) Reduce(prefix string) string {
54 return fmt.Sprintf("%s(%s)", e.Name, e.Expr.Reduce(prefix))
55 }
56
57 func (e *Function) String() string {
58 return e.Reduce("")
59 }
60
61 func (e *Function) Initialize(p *Protocol) {
62 e.Expr.Initialize(p)
63 }
64
65
66
67 type BinaryOp struct {
68 Op string
69 Expr1 Expression
70 Expr2 Expression
71 }
72
73
74
75
76 func newBinaryOp(op string, expr1, expr2 Expression) Expression {
77 switch {
78 case expr1 != nil && expr2 != nil:
79 return &BinaryOp{
80 Op: op,
81 Expr1: expr1,
82 Expr2: expr2,
83 }
84 case expr1 != nil && expr2 == nil:
85 return expr1
86 case expr1 == nil && expr2 != nil:
87 return expr2
88 case expr1 == nil && expr2 == nil:
89 return nil
90 }
91 panic("unreachable")
92 }
93
94 func (e *BinaryOp) Concrete() bool {
95 return e.Expr1.Concrete() && e.Expr2.Concrete()
96 }
97
98 func (e *BinaryOp) Eval() int {
99 switch e.Op {
100 case "+":
101 return e.Expr1.Eval() + e.Expr2.Eval()
102 case "-":
103 return e.Expr1.Eval() - e.Expr2.Eval()
104 case "*":
105 return e.Expr1.Eval() * e.Expr2.Eval()
106 case "/":
107 return e.Expr1.Eval() / e.Expr2.Eval()
108 case "&":
109 return e.Expr1.Eval() & e.Expr2.Eval()
110 case "<<":
111 return int(uint(e.Expr1.Eval()) << uint(e.Expr2.Eval()))
112 }
113
114 log.Fatalf("Invalid binary operator '%s' for expression.", e.Op)
115 panic("unreachable")
116 }
117
118 func (e *BinaryOp) Reduce(prefix string) string {
119 if e.Concrete() {
120 return fmt.Sprintf("%d", e.Eval())
121 }
122
123
124
125 expr1, expr2 := e.Expr1, e.Expr2
126 switch expr1.(type) {
127 case *FieldRef:
128 expr1 = &Function{
129 Name: "int",
130 Expr: expr1,
131 }
132 }
133 switch expr2.(type) {
134 case *FieldRef:
135 expr2 = &Function{
136 Name: "int",
137 Expr: expr2,
138 }
139 }
140 return fmt.Sprintf("(%s %s %s)",
141 expr1.Reduce(prefix), e.Op, expr2.Reduce(prefix))
142 }
143
144 func (e *BinaryOp) String() string {
145 return e.Reduce("")
146 }
147
148 func (e *BinaryOp) Initialize(p *Protocol) {
149 e.Expr1.Initialize(p)
150 e.Expr2.Initialize(p)
151 }
152
153
154
155 type UnaryOp struct {
156 Op string
157 Expr Expression
158 }
159
160 func (e *UnaryOp) Concrete() bool {
161 return e.Expr.Concrete()
162 }
163
164 func (e *UnaryOp) Eval() int {
165 switch e.Op {
166 case "~":
167 return ^e.Expr.Eval()
168 }
169
170 log.Fatalf("Invalid unary operator '%s' for expression.", e.Op)
171 panic("unreachable")
172 }
173
174 func (e *UnaryOp) Reduce(prefix string) string {
175 if e.Concrete() {
176 return fmt.Sprintf("%d", e.Eval())
177 }
178 return fmt.Sprintf("(%s (%s))", e.Op, e.Expr.Reduce(prefix))
179 }
180
181 func (e *UnaryOp) String() string {
182 return e.Reduce("")
183 }
184
185 func (e *UnaryOp) Initialize(p *Protocol) {
186 e.Expr.Initialize(p)
187 }
188
189
190
191 type Padding struct {
192 Expr Expression
193 }
194
195 func (e *Padding) Concrete() bool {
196 return e.Expr.Concrete()
197 }
198
199 func (e *Padding) Eval() int {
200 return pad(e.Expr.Eval())
201 }
202
203 func (e *Padding) Reduce(prefix string) string {
204 if e.Concrete() {
205 return fmt.Sprintf("%d", e.Eval())
206 }
207 return fmt.Sprintf("xgb.Pad(%s)", e.Expr.Reduce(prefix))
208 }
209
210 func (e *Padding) String() string {
211 return e.Reduce("")
212 }
213
214 func (e *Padding) Initialize(p *Protocol) {
215 e.Expr.Initialize(p)
216 }
217
218
219
220 type PopCount struct {
221 Expr Expression
222 }
223
224 func (e *PopCount) Concrete() bool {
225 return e.Expr.Concrete()
226 }
227
228 func (e *PopCount) Eval() int {
229 return int(popCount(uint(e.Expr.Eval())))
230 }
231
232 func (e *PopCount) Reduce(prefix string) string {
233 if e.Concrete() {
234 return fmt.Sprintf("%d", e.Eval())
235 }
236 return fmt.Sprintf("xgb.PopCount(%s)", e.Expr.Reduce(prefix))
237 }
238
239 func (e *PopCount) String() string {
240 return e.Reduce("")
241 }
242
243 func (e *PopCount) Initialize(p *Protocol) {
244 e.Expr.Initialize(p)
245 }
246
247
248 type Value struct {
249 v int
250 }
251
252 func (e *Value) Concrete() bool {
253 return true
254 }
255
256 func (e *Value) Eval() int {
257 return e.v
258 }
259
260 func (e *Value) Reduce(prefix string) string {
261 return fmt.Sprintf("%d", e.v)
262 }
263
264 func (e *Value) String() string {
265 return e.Reduce("")
266 }
267
268 func (e *Value) Initialize(p *Protocol) {}
269
270
271 type Bit struct {
272 b int
273 }
274
275 func (e *Bit) Concrete() bool {
276 return true
277 }
278
279 func (e *Bit) Eval() int {
280 return int(1 << uint(e.b))
281 }
282
283 func (e *Bit) Reduce(prefix string) string {
284 return fmt.Sprintf("%d", e.Eval())
285 }
286
287 func (e *Bit) String() string {
288 return e.Reduce("")
289 }
290
291 func (e *Bit) Initialize(p *Protocol) {}
292
293
294
295 type FieldRef struct {
296 Name string
297 }
298
299 func (e *FieldRef) Concrete() bool {
300 return false
301 }
302
303 func (e *FieldRef) Eval() int {
304 log.Fatalf("Cannot evaluate a 'FieldRef'. It is not concrete.")
305 panic("unreachable")
306 }
307
308 func (e *FieldRef) Reduce(prefix string) string {
309 val := e.Name
310 if len(prefix) > 0 {
311 val = fmt.Sprintf("%s%s", prefix, val)
312 }
313 return val
314 }
315
316 func (e *FieldRef) String() string {
317 return e.Reduce("")
318 }
319
320 func (e *FieldRef) Initialize(p *Protocol) {
321 e.Name = SrcName(p, e.Name)
322 }
323
324
325
326
327 type EnumRef struct {
328 EnumKind Type
329 EnumItem string
330 }
331
332 func (e *EnumRef) Concrete() bool {
333 return false
334 }
335
336 func (e *EnumRef) Eval() int {
337 log.Fatalf("Cannot evaluate an 'EnumRef'. It is not concrete.")
338 panic("unreachable")
339 }
340
341 func (e *EnumRef) Reduce(prefix string) string {
342 return fmt.Sprintf("%s%s", e.EnumKind, e.EnumItem)
343 }
344
345 func (e *EnumRef) String() string {
346 return e.Reduce("")
347 }
348
349 func (e *EnumRef) Initialize(p *Protocol) {
350 e.EnumKind = e.EnumKind.(*Translation).RealType(p)
351 e.EnumItem = SrcName(p, e.EnumItem)
352 }
353
354
355
356 type SumOf struct {
357 Name string
358 }
359
360 func (e *SumOf) Concrete() bool {
361 return false
362 }
363
364 func (e *SumOf) Eval() int {
365 log.Fatalf("Cannot evaluate a 'SumOf'. It is not concrete.")
366 panic("unreachable")
367 }
368
369 func (e *SumOf) Reduce(prefix string) string {
370 if len(prefix) > 0 {
371 return fmt.Sprintf("sum(%s%s)", prefix, e.Name)
372 }
373 return fmt.Sprintf("sum(%s)", e.Name)
374 }
375
376 func (e *SumOf) String() string {
377 return e.Reduce("")
378 }
379
380 func (e *SumOf) Initialize(p *Protocol) {
381 e.Name = SrcName(p, e.Name)
382 }
383
View as plain text