Skip to content

Commit 266eb57

Browse files
authored
semantic: simplify keySubst (#6459)
Simplify substitution for aggregates and keys by using walkExpr.
1 parent 17a8bab commit 266eb57

File tree

1 file changed

+70
-148
lines changed

1 file changed

+70
-148
lines changed

compiler/semantic/projection.go

Lines changed: 70 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -73,209 +73,131 @@ func (a aggfuncs) tmp() string {
7373
}
7474

7575
func (a *aggfuncs) subst(e sem.Expr) sem.Expr {
76-
switch e := e.(type) {
77-
case nil:
78-
return e
79-
case *sem.AggFunc:
80-
// swap in a temp column for each agg function found, which
81-
// will then be referred to by the containing expression.
82-
// The agg function is computed into the tmp value with
83-
// the generated aggregate operator.
84-
tmp := a.tmp()
85-
*a = append(*a, namedAgg{name: tmp, agg: e})
86-
return sem.NewThis(e, []string{"in", tmp})
87-
case *sem.ArrayExpr:
88-
e.Elems = a.substArrayElems(e.Elems)
89-
case *sem.BadExpr:
90-
case *sem.BinaryExpr:
91-
e.LHS = a.subst(e.LHS)
92-
e.RHS = a.subst(e.RHS)
93-
case *sem.CallExpr:
94-
for k, arg := range e.Args {
95-
e.Args[k] = a.subst(arg)
96-
}
97-
case *sem.CondExpr:
98-
e.Cond = a.subst(e.Cond)
99-
e.Then = a.subst(e.Then)
100-
e.Else = a.subst(e.Else)
101-
case *sem.DotExpr:
102-
e.LHS = a.subst(e.LHS)
103-
case *sem.IndexExpr:
104-
e.Expr = a.subst(e.Expr)
105-
e.Index = a.subst(e.Index)
106-
case *sem.IsNullExpr:
107-
e.Expr = a.subst(e.Expr)
108-
case *sem.LiteralExpr:
109-
case *sem.MapExpr:
110-
for _, ent := range e.Entries {
111-
ent.Key = a.subst(ent.Key)
112-
ent.Value = a.subst(ent.Value)
113-
}
114-
case *sem.RecordExpr:
115-
var elems []sem.RecordElem
116-
for _, elem := range e.Elems {
117-
switch elem := elem.(type) {
118-
case *sem.FieldElem:
119-
sub := a.subst(elem.Value)
120-
elems = append(elems, &sem.FieldElem{Node: elem, Name: elem.Name, Value: sub})
121-
case *sem.SpreadElem:
122-
elems = append(elems, &sem.SpreadElem{Node: elem, Expr: a.subst(elem.Expr)})
123-
default:
124-
panic(elem)
125-
}
76+
return exprWalk(e, func(e sem.Expr) (sem.Expr, bool) {
77+
switch e := e.(type) {
78+
case *sem.AggFunc:
79+
// swap in a temp column for each agg function found, which
80+
// will then be referred to by the containing expression.
81+
// The agg function is computed into the tmp value with
82+
// the generated aggregate operator.
83+
tmp := a.tmp()
84+
*a = append(*a, namedAgg{name: tmp, agg: e})
85+
return sem.NewThis(e, []string{"in", tmp}), true
86+
default:
87+
return e, false
12688
}
127-
e.Elems = elems
128-
case *sem.RegexpMatchExpr:
129-
e.Expr = a.subst(e.Expr)
130-
case *sem.RegexpSearchExpr:
131-
e.Expr = a.subst(e.Expr)
132-
case *sem.SearchTermExpr:
133-
e.Expr = a.subst(e.Expr)
134-
case *sem.SetExpr:
135-
e.Elems = a.substArrayElems(e.Elems)
136-
case *sem.SliceExpr:
137-
e.Expr = a.subst(e.Expr)
138-
e.From = a.subst(e.From)
139-
e.To = a.subst(e.To)
140-
case *sem.ThisExpr:
141-
case *sem.UnaryExpr:
142-
e.Operand = a.subst(e.Operand)
143-
}
144-
return e
89+
})
14590
}
14691

147-
func (a *aggfuncs) substArrayElems(elems []sem.ArrayElem) []sem.ArrayElem {
148-
var out []sem.ArrayElem
149-
for _, e := range elems {
92+
func keySubst(e sem.Expr, exprs []exprloc) (sem.Expr, bool) {
93+
ok := true
94+
e = exprWalk(e, func(e sem.Expr) (sem.Expr, bool) {
95+
if i := exprMatch(e, exprs); i >= 0 {
96+
return sem.NewThis(e, []string{"in", fmt.Sprintf("k%d", i)}), true
97+
}
15098
switch e := e.(type) {
151-
case *sem.SpreadElem:
152-
out = append(out, &sem.SpreadElem{Node: e, Expr: a.subst(e.Expr)})
153-
case *sem.ExprElem:
154-
out = append(out, &sem.ExprElem{Node: e, Expr: a.subst(e.Expr)})
155-
default:
99+
case *sem.ThisExpr:
100+
ok = false
101+
case *sem.AggFunc:
102+
// This should't happen.
156103
panic(e)
157104
}
158-
}
159-
return out
105+
return e, false
106+
})
107+
return e, ok
160108
}
161109

162-
func keySubst(e sem.Expr, exprs []exprloc) (sem.Expr, bool) {
163-
if i := exprMatch(e, exprs); i >= 0 {
164-
return sem.NewThis(e, []string{"in", fmt.Sprintf("k%d", i)}), true
110+
type exprVisitor func(e sem.Expr) (sem.Expr, bool)
111+
112+
func exprWalk(e sem.Expr, visit exprVisitor) sem.Expr {
113+
var stop bool
114+
if e, stop = visit(e); stop {
115+
return e
165116
}
166-
ok := true
167117
switch e := e.(type) {
168118
case nil:
169119
case *sem.AggFunc:
170-
// This shouldn't happen.
171-
panic(e)
120+
e.Expr = exprWalk(e, visit)
121+
e.Where = exprWalk(e, visit)
172122
case *sem.ArrayExpr:
173-
e.Elems, ok = keySubstArrayElems(e.Elems, exprs)
123+
e.Elems = exprWalkArrayElems(e.Elems, visit)
174124
case *sem.BadExpr:
175125
case *sem.BinaryExpr:
176-
if e.LHS, ok = keySubst(e.LHS, exprs); ok {
177-
e.RHS, ok = keySubst(e.RHS, exprs)
178-
}
126+
e.LHS = exprWalk(e.LHS, visit)
127+
e.RHS = exprWalk(e.RHS, visit)
179128
case *sem.CallExpr:
180-
var args []sem.Expr
129+
var out []sem.Expr
181130
for _, arg := range e.Args {
182-
if arg, ok = keySubst(arg, exprs); !ok {
183-
return nil, false
184-
}
185-
args = append(args, arg)
131+
out = append(out, exprWalk(arg, visit))
186132
}
187-
e.Args = args
133+
e.Args = out
188134
case *sem.CondExpr:
189-
var ok1, ok2, ok3 bool
190-
e.Cond, ok1 = keySubst(e.Cond, exprs)
191-
e.Then, ok2 = keySubst(e.Then, exprs)
192-
e.Else, ok3 = keySubst(e.Else, exprs)
193-
ok = ok1 && ok2 && ok3
135+
e.Cond = exprWalk(e.Cond, visit)
136+
e.Then = exprWalk(e.Then, visit)
137+
e.Else = exprWalk(e.Else, visit)
194138
case *sem.DotExpr:
195-
e.LHS, ok = keySubst(e.LHS, exprs)
139+
e.LHS = exprWalk(e.LHS, visit)
196140
case *sem.IndexExpr:
197-
if e.Expr, ok = keySubst(e.Expr, exprs); ok {
198-
e.Index, ok = keySubst(e.Index, exprs)
199-
}
141+
e.Expr = exprWalk(e.Expr, visit)
142+
e.Index = exprWalk(e.Index, visit)
200143
case *sem.IsNullExpr:
201-
e.Expr, ok = keySubst(e.Expr, exprs)
144+
e.Expr = exprWalk(e.Expr, visit)
202145
case *sem.LiteralExpr:
203146
case *sem.MapExpr:
204147
for _, ent := range e.Entries {
205-
if ent.Key, ok = keySubst(ent.Key, exprs); !ok {
206-
break
207-
}
208-
if ent.Value, ok = keySubst(ent.Value, exprs); !ok {
209-
break
210-
}
148+
ent.Key = exprWalk(ent.Key, visit)
149+
ent.Value = exprWalk(ent.Value, visit)
211150
}
212151
case *sem.RecordExpr:
213-
var elems []sem.RecordElem
152+
var out []sem.RecordElem
214153
for _, elem := range e.Elems {
215154
switch elem := elem.(type) {
216155
case *sem.FieldElem:
217-
e, ok := keySubst(elem.Value, exprs)
218-
if !ok {
219-
return nil, false
220-
}
221-
elems = append(elems, &sem.FieldElem{Node: elem, Name: elem.Name, Value: e})
156+
e := exprWalk(elem.Value, visit)
157+
out = append(out, &sem.FieldElem{Node: elem, Name: elem.Name, Value: e})
222158
case *sem.SpreadElem:
223-
e, ok := keySubst(elem.Expr, exprs)
224-
if !ok {
225-
return nil, false
226-
}
227-
elems = append(elems, &sem.SpreadElem{Node: elem, Expr: e})
159+
e := exprWalk(elem.Expr, visit)
160+
out = append(out, &sem.SpreadElem{Node: elem, Expr: e})
228161
default:
229162
panic(elem)
230163
}
231164
}
232-
e.Elems = elems
165+
e.Elems = out
233166
case *sem.RegexpMatchExpr:
234-
e.Expr, ok = keySubst(e.Expr, exprs)
167+
e.Expr = exprWalk(e.Expr, visit)
235168
case *sem.RegexpSearchExpr:
236-
e.Expr, ok = keySubst(e.Expr, exprs)
169+
e.Expr = exprWalk(e.Expr, visit)
237170
case *sem.SearchTermExpr:
238-
e.Expr, ok = keySubst(e.Expr, exprs)
171+
e.Expr = exprWalk(e.Expr, visit)
239172
case *sem.SetExpr:
240-
e.Elems, ok = keySubstArrayElems(e.Elems, exprs)
173+
e.Elems = exprWalkArrayElems(e.Elems, visit)
241174
case *sem.SliceExpr:
242-
var ok1, ok2, ok3 bool
243-
e.Expr, ok1 = keySubst(e.Expr, exprs)
244-
e.From, ok2 = keySubst(e.From, exprs)
245-
e.To, ok3 = keySubst(e.To, exprs)
246-
ok = ok1 && ok2 && ok3
175+
e.Expr = exprWalk(e.Expr, visit)
176+
e.From = exprWalk(e.From, visit)
177+
e.To = exprWalk(e.To, visit)
247178
case *sem.SubqueryExpr: // XXX This might need to be traversed?
248179
case *sem.ThisExpr:
249-
// If we've gotten here it means we have a portion of e that does
250-
// not exist in exprs so we are in an error state.
251-
return nil, false
252180
case *sem.UnaryExpr:
253-
e.Operand, ok = keySubst(e.Operand, exprs)
181+
e.Operand = exprWalk(e.Operand, visit)
254182
default:
255183
panic(e)
256184
}
257-
return e, ok
185+
return e
258186
}
259187

260-
func keySubstArrayElems(elems []sem.ArrayElem, exprs []exprloc) ([]sem.ArrayElem, bool) {
188+
func exprWalkArrayElems(elems []sem.ArrayElem, visit exprVisitor) []sem.ArrayElem {
261189
var out []sem.ArrayElem
262190
for _, elem := range elems {
263191
switch elem := elem.(type) {
264192
case *sem.SpreadElem:
265-
e, ok := keySubst(elem.Expr, exprs)
266-
if !ok {
267-
return nil, false
268-
}
269-
out = append(out, &sem.SpreadElem{Node: elem, Expr: e})
193+
e := exprWalk(elem.Expr, visit)
194+
out = append(out, &sem.SpreadElem{Node: elem.Node, Expr: e})
270195
case *sem.ExprElem:
271-
e, ok := keySubst(elem.Expr, exprs)
272-
if !ok {
273-
return nil, false
274-
}
275-
out = append(out, &sem.ExprElem{Node: elem, Expr: e})
196+
e := exprWalk(elem.Expr, visit)
197+
out = append(out, &sem.ExprElem{Node: elem.Node, Expr: e})
276198
default:
277199
panic(elem)
278200
}
279201
}
280-
return out, true
202+
return out
281203
}

0 commit comments

Comments
 (0)