blob: e78f4927372b03c02a99e2722a8c26c4aff62053 [file] [log] [blame]
Sasha Smundakb051c4e2020-11-05 20:45:07 -08001// Copyright 2021 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package mk2rbc
16
17import (
18 "fmt"
Sasha Smundakb051c4e2020-11-05 20:45:07 -080019 "strings"
Sasha Smundakb051c4e2020-11-05 20:45:07 -080020)
21
Cole Faustfc438682021-12-14 12:46:32 -080022// Represents an expression in the Starlark code. An expression has a type.
Sasha Smundakb051c4e2020-11-05 20:45:07 -080023type starlarkExpr interface {
24 starlarkNode
25 typ() starlarkType
Sasha Smundakb051c4e2020-11-05 20:45:07 -080026 // Emit the code to copy the expression, otherwise we will end up
27 // with source and target pointing to the same list.
28 emitListVarCopy(gctx *generationContext)
Cole Faustb0d32ab2021-12-09 14:00:59 -080029 // Return the expression, calling the transformer func for
30 // every expression in the tree. If the transformer func returns non-nil,
31 // its result is used in place of the expression it was called with in the
32 // resulting expression. The resulting starlarkExpr will contain as many
33 // of the same objects from the original expression as possible.
34 transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr
Sasha Smundakb051c4e2020-11-05 20:45:07 -080035}
36
37func maybeString(expr starlarkExpr) (string, bool) {
38 if x, ok := expr.(*stringLiteralExpr); ok {
39 return x.literal, true
40 }
41 return "", false
42}
43
44type stringLiteralExpr struct {
45 literal string
46}
47
Sasha Smundakb051c4e2020-11-05 20:45:07 -080048func (s *stringLiteralExpr) emit(gctx *generationContext) {
49 gctx.writef("%q", s.literal)
50}
51
52func (_ *stringLiteralExpr) typ() starlarkType {
53 return starlarkTypeString
54}
55
56func (s *stringLiteralExpr) emitListVarCopy(gctx *generationContext) {
57 s.emit(gctx)
58}
59
Cole Faustb0d32ab2021-12-09 14:00:59 -080060func (s *stringLiteralExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
61 if replacement := transformer(s); replacement != nil {
62 return replacement
63 } else {
64 return s
65 }
66}
67
Sasha Smundakb051c4e2020-11-05 20:45:07 -080068// Integer literal
69type intLiteralExpr struct {
70 literal int
71}
72
Sasha Smundakb051c4e2020-11-05 20:45:07 -080073func (s *intLiteralExpr) emit(gctx *generationContext) {
74 gctx.writef("%d", s.literal)
75}
76
77func (_ *intLiteralExpr) typ() starlarkType {
78 return starlarkTypeInt
79}
80
81func (s *intLiteralExpr) emitListVarCopy(gctx *generationContext) {
82 s.emit(gctx)
83}
84
Cole Faustb0d32ab2021-12-09 14:00:59 -080085func (s *intLiteralExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
86 if replacement := transformer(s); replacement != nil {
87 return replacement
88 } else {
89 return s
90 }
91}
92
Cole Faust4eadba72021-12-07 11:54:52 -080093// Boolean literal
94type boolLiteralExpr struct {
95 literal bool
96}
97
Cole Faust4eadba72021-12-07 11:54:52 -080098func (b *boolLiteralExpr) emit(gctx *generationContext) {
99 if b.literal {
100 gctx.write("True")
101 } else {
102 gctx.write("False")
103 }
104}
105
106func (_ *boolLiteralExpr) typ() starlarkType {
107 return starlarkTypeBool
108}
109
110func (b *boolLiteralExpr) emitListVarCopy(gctx *generationContext) {
111 b.emit(gctx)
112}
113
Cole Faustb0d32ab2021-12-09 14:00:59 -0800114func (b *boolLiteralExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
115 if replacement := transformer(b); replacement != nil {
116 return replacement
117 } else {
118 return b
119 }
120}
121
Cole Faust9ebf6e42021-12-13 14:08:34 -0800122type globalsExpr struct {
123}
124
125func (g *globalsExpr) emit(gctx *generationContext) {
126 gctx.write("g")
127}
128
129func (g *globalsExpr) typ() starlarkType {
130 return starlarkTypeUnknown
131}
132
133func (g *globalsExpr) emitListVarCopy(gctx *generationContext) {
134 g.emit(gctx)
135}
136
137func (g *globalsExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
138 if replacement := transformer(g); replacement != nil {
139 return replacement
140 } else {
141 return g
142 }
143}
144
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800145// interpolateExpr represents Starlark's interpolation operator <string> % list
146// we break <string> into a list of chunks, i.e., "first%second%third" % (X, Y)
147// will have chunks = ["first", "second", "third"] and args = [X, Y]
148type interpolateExpr struct {
149 chunks []string // string chunks, separated by '%'
150 args []starlarkExpr
151}
152
Cole Faustfc438682021-12-14 12:46:32 -0800153func NewInterpolateExpr(parts []starlarkExpr) starlarkExpr {
154 result := &interpolateExpr{}
155 needString := true
156 for _, part := range parts {
157 if needString {
158 if strLit, ok := part.(*stringLiteralExpr); ok {
159 result.chunks = append(result.chunks, strLit.literal)
160 } else {
161 result.chunks = append(result.chunks, "")
162 }
163 needString = false
164 } else {
165 if strLit, ok := part.(*stringLiteralExpr); ok {
166 result.chunks[len(result.chunks)-1] += strLit.literal
167 } else {
168 result.args = append(result.args, part)
169 needString = true
170 }
171 }
172 }
173 if len(result.chunks) == len(result.args) {
174 result.chunks = append(result.chunks, "")
175 }
176 if len(result.args) == 0 {
177 return &stringLiteralExpr{literal: strings.Join(result.chunks, "")}
178 }
179 return result
180}
181
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800182func (xi *interpolateExpr) emit(gctx *generationContext) {
183 if len(xi.chunks) != len(xi.args)+1 {
184 panic(fmt.Errorf("malformed interpolateExpr: #chunks(%d) != #args(%d)+1",
185 len(xi.chunks), len(xi.args)))
186 }
187 // Generate format as join of chunks, but first escape '%' in them
188 format := strings.ReplaceAll(xi.chunks[0], "%", "%%")
189 for _, chunk := range xi.chunks[1:] {
190 format += "%s" + strings.ReplaceAll(chunk, "%", "%%")
191 }
192 gctx.writef("%q %% ", format)
Sasha Smundak422b6142021-11-11 18:31:59 -0800193 emitArg := func(arg starlarkExpr) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800194 if arg.typ() == starlarkTypeList {
195 gctx.write(`" ".join(`)
196 arg.emit(gctx)
197 gctx.write(`)`)
198 } else {
199 arg.emit(gctx)
200 }
201 }
202 if len(xi.args) == 1 {
Sasha Smundak422b6142021-11-11 18:31:59 -0800203 emitArg(xi.args[0])
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800204 } else {
205 sep := "("
206 for _, arg := range xi.args {
207 gctx.write(sep)
Sasha Smundak422b6142021-11-11 18:31:59 -0800208 emitArg(arg)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800209 sep = ", "
210 }
211 gctx.write(")")
212 }
213}
214
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800215func (_ *interpolateExpr) typ() starlarkType {
216 return starlarkTypeString
217}
218
219func (xi *interpolateExpr) emitListVarCopy(gctx *generationContext) {
220 xi.emit(gctx)
221}
222
Cole Faustb0d32ab2021-12-09 14:00:59 -0800223func (xi *interpolateExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
224 argsCopy := make([]starlarkExpr, len(xi.args))
225 for i, arg := range xi.args {
226 argsCopy[i] = arg.transform(transformer)
227 }
228 xi.args = argsCopy
229 if replacement := transformer(xi); replacement != nil {
230 return replacement
231 } else {
232 return xi
233 }
234}
235
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800236type variableRefExpr struct {
237 ref variable
238 isDefined bool
239}
240
Cole Faustfc438682021-12-14 12:46:32 -0800241func NewVariableRefExpr(ref variable, isDefined bool) starlarkExpr {
242 if predefined, ok := ref.(*predefinedVariable); ok {
243 return predefined.value
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800244 }
Cole Faustfc438682021-12-14 12:46:32 -0800245 return &variableRefExpr{ref, isDefined}
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800246}
247
248func (v *variableRefExpr) emit(gctx *generationContext) {
249 v.ref.emitGet(gctx, v.isDefined)
250}
251
252func (v *variableRefExpr) typ() starlarkType {
253 return v.ref.valueType()
254}
255
256func (v *variableRefExpr) emitListVarCopy(gctx *generationContext) {
257 v.emit(gctx)
258 if v.typ() == starlarkTypeList {
259 gctx.write("[:]") // this will copy the list
260 }
261}
262
Cole Faustb0d32ab2021-12-09 14:00:59 -0800263func (v *variableRefExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
264 if replacement := transformer(v); replacement != nil {
265 return replacement
266 } else {
267 return v
268 }
269}
270
Cole Faustf8320212021-11-10 15:05:07 -0800271type toStringExpr struct {
272 expr starlarkExpr
273}
274
Cole Faustf8320212021-11-10 15:05:07 -0800275func (s *toStringExpr) emit(ctx *generationContext) {
276 switch s.expr.typ() {
277 case starlarkTypeString, starlarkTypeUnknown:
278 // Assume unknown types are strings already.
279 s.expr.emit(ctx)
280 case starlarkTypeList:
281 ctx.write(`" ".join(`)
282 s.expr.emit(ctx)
283 ctx.write(")")
284 case starlarkTypeInt:
285 ctx.write(`("%d" % (`)
286 s.expr.emit(ctx)
287 ctx.write("))")
288 case starlarkTypeBool:
Cole Faustf1f44d32021-11-16 14:52:12 -0800289 ctx.write(`("true" if (`)
Cole Faustf8320212021-11-10 15:05:07 -0800290 s.expr.emit(ctx)
Cole Faustf1f44d32021-11-16 14:52:12 -0800291 ctx.write(`) else "")`)
Cole Faustf8320212021-11-10 15:05:07 -0800292 case starlarkTypeVoid:
293 ctx.write(`""`)
294 default:
295 panic("Unknown starlark type!")
296 }
297}
298
299func (s *toStringExpr) typ() starlarkType {
300 return starlarkTypeString
301}
302
303func (s *toStringExpr) emitListVarCopy(gctx *generationContext) {
304 s.emit(gctx)
305}
306
Cole Faustb0d32ab2021-12-09 14:00:59 -0800307func (s *toStringExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
308 s.expr = s.expr.transform(transformer)
309 if replacement := transformer(s); replacement != nil {
310 return replacement
311 } else {
312 return s
313 }
314}
315
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800316type notExpr struct {
317 expr starlarkExpr
318}
319
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800320func (n *notExpr) emit(ctx *generationContext) {
321 ctx.write("not ")
322 n.expr.emit(ctx)
323}
324
325func (_ *notExpr) typ() starlarkType {
326 return starlarkTypeBool
327}
328
329func (n *notExpr) emitListVarCopy(gctx *generationContext) {
330 n.emit(gctx)
331}
332
Cole Faustb0d32ab2021-12-09 14:00:59 -0800333func (n *notExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
334 n.expr = n.expr.transform(transformer)
335 if replacement := transformer(n); replacement != nil {
336 return replacement
337 } else {
338 return n
339 }
340}
341
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800342type eqExpr struct {
343 left, right starlarkExpr
344 isEq bool // if false, it's !=
345}
346
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800347func (eq *eqExpr) emit(gctx *generationContext) {
Cole Faustf8320212021-11-10 15:05:07 -0800348 if eq.left.typ() != eq.right.typ() {
349 eq.left = &toStringExpr{expr: eq.left}
350 eq.right = &toStringExpr{expr: eq.right}
351 }
352
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800353 // General case
354 eq.left.emit(gctx)
355 if eq.isEq {
356 gctx.write(" == ")
357 } else {
358 gctx.write(" != ")
359 }
360 eq.right.emit(gctx)
361}
362
363func (_ *eqExpr) typ() starlarkType {
364 return starlarkTypeBool
365}
366
367func (eq *eqExpr) emitListVarCopy(gctx *generationContext) {
368 eq.emit(gctx)
369}
370
Cole Faustb0d32ab2021-12-09 14:00:59 -0800371func (eq *eqExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
372 eq.left = eq.left.transform(transformer)
373 eq.right = eq.right.transform(transformer)
374 if replacement := transformer(eq); replacement != nil {
375 return replacement
376 } else {
377 return eq
378 }
379}
380
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800381// variableDefinedExpr corresponds to Make's ifdef VAR
382type variableDefinedExpr struct {
383 v variable
384}
385
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800386func (v *variableDefinedExpr) emit(gctx *generationContext) {
387 if v.v != nil {
388 v.v.emitDefined(gctx)
389 return
390 }
391 gctx.writef("%s(%q)", cfnWarning, "TODO(VAR)")
392}
393
394func (_ *variableDefinedExpr) typ() starlarkType {
395 return starlarkTypeBool
396}
397
398func (v *variableDefinedExpr) emitListVarCopy(gctx *generationContext) {
399 v.emit(gctx)
400}
401
Cole Faustb0d32ab2021-12-09 14:00:59 -0800402func (v *variableDefinedExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
403 // TODO: VariableDefinedExpr isn't really an expression?
404 return v
405}
406
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800407type listExpr struct {
408 items []starlarkExpr
409}
410
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800411func (l *listExpr) emit(gctx *generationContext) {
412 if !gctx.inAssignment || len(l.items) < 2 {
413 gctx.write("[")
414 sep := ""
415 for _, item := range l.items {
416 gctx.write(sep)
417 item.emit(gctx)
418 sep = ", "
419 }
420 gctx.write("]")
421 return
422 }
423
424 gctx.write("[")
425 gctx.indentLevel += 2
426
427 for _, item := range l.items {
428 gctx.newLine()
429 item.emit(gctx)
430 gctx.write(",")
431 }
432 gctx.indentLevel -= 2
433 gctx.newLine()
434 gctx.write("]")
435}
436
437func (_ *listExpr) typ() starlarkType {
438 return starlarkTypeList
439}
440
441func (l *listExpr) emitListVarCopy(gctx *generationContext) {
442 l.emit(gctx)
443}
444
Cole Faustb0d32ab2021-12-09 14:00:59 -0800445func (l *listExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
446 itemsCopy := make([]starlarkExpr, len(l.items))
447 for i, item := range l.items {
448 itemsCopy[i] = item.transform(transformer)
449 }
450 l.items = itemsCopy
451 if replacement := transformer(l); replacement != nil {
452 return replacement
453 } else {
454 return l
455 }
456}
457
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800458func newStringListExpr(items []string) *listExpr {
459 v := listExpr{}
460 for _, item := range items {
461 v.items = append(v.items, &stringLiteralExpr{item})
462 }
463 return &v
464}
465
Sasha Smundak422b6142021-11-11 18:31:59 -0800466// concatExpr generates expr1 + expr2 + ... + exprN in Starlark.
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800467type concatExpr struct {
468 items []starlarkExpr
469}
470
471func (c *concatExpr) emit(gctx *generationContext) {
472 if len(c.items) == 1 {
473 c.items[0].emit(gctx)
474 return
475 }
476
477 if !gctx.inAssignment {
478 c.items[0].emit(gctx)
479 for _, item := range c.items[1:] {
480 gctx.write(" + ")
481 item.emit(gctx)
482 }
483 return
484 }
485 gctx.write("(")
486 c.items[0].emit(gctx)
487 gctx.indentLevel += 2
488 for _, item := range c.items[1:] {
489 gctx.write(" +")
490 gctx.newLine()
491 item.emit(gctx)
492 }
493 gctx.write(")")
494 gctx.indentLevel -= 2
495}
496
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800497func (_ *concatExpr) typ() starlarkType {
498 return starlarkTypeList
499}
500
501func (c *concatExpr) emitListVarCopy(gctx *generationContext) {
502 c.emit(gctx)
503}
504
Cole Faustb0d32ab2021-12-09 14:00:59 -0800505func (c *concatExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
506 itemsCopy := make([]starlarkExpr, len(c.items))
507 for i, item := range c.items {
508 itemsCopy[i] = item.transform(transformer)
509 }
510 c.items = itemsCopy
511 if replacement := transformer(c); replacement != nil {
512 return replacement
513 } else {
514 return c
515 }
516}
517
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800518// inExpr generates <expr> [not] in <list>
519type inExpr struct {
520 expr starlarkExpr
521 list starlarkExpr
522 isNot bool
523}
524
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800525func (i *inExpr) emit(gctx *generationContext) {
526 i.expr.emit(gctx)
527 if i.isNot {
528 gctx.write(" not in ")
529 } else {
530 gctx.write(" in ")
531 }
532 i.list.emit(gctx)
533}
534
535func (_ *inExpr) typ() starlarkType {
536 return starlarkTypeBool
537}
538
539func (i *inExpr) emitListVarCopy(gctx *generationContext) {
540 i.emit(gctx)
541}
542
Cole Faustb0d32ab2021-12-09 14:00:59 -0800543func (i *inExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
544 i.expr = i.expr.transform(transformer)
545 i.list = i.list.transform(transformer)
546 if replacement := transformer(i); replacement != nil {
547 return replacement
548 } else {
549 return i
550 }
551}
552
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800553type indexExpr struct {
554 array starlarkExpr
555 index starlarkExpr
556}
557
Cole Faustb0d32ab2021-12-09 14:00:59 -0800558func (ix *indexExpr) emit(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800559 ix.array.emit(gctx)
560 gctx.write("[")
561 ix.index.emit(gctx)
562 gctx.write("]")
563}
564
Cole Faustb0d32ab2021-12-09 14:00:59 -0800565func (ix *indexExpr) typ() starlarkType {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800566 return starlarkTypeString
567}
568
Cole Faustb0d32ab2021-12-09 14:00:59 -0800569func (ix *indexExpr) emitListVarCopy(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800570 ix.emit(gctx)
571}
572
Cole Faustb0d32ab2021-12-09 14:00:59 -0800573func (ix *indexExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
574 ix.array = ix.array.transform(transformer)
575 ix.index = ix.index.transform(transformer)
576 if replacement := transformer(ix); replacement != nil {
577 return replacement
578 } else {
579 return ix
580 }
581}
582
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800583type callExpr struct {
584 object starlarkExpr // nil if static call
585 name string
586 args []starlarkExpr
587 returnType starlarkType
588}
589
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800590func (cx *callExpr) emit(gctx *generationContext) {
591 if cx.object != nil {
592 gctx.write("(")
593 cx.object.emit(gctx)
594 gctx.write(")")
595 gctx.write(".", cx.name, "(")
596 } else {
Cole Faust9ebf6e42021-12-13 14:08:34 -0800597 gctx.write(cx.name, "(")
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800598 }
Cole Faust9ebf6e42021-12-13 14:08:34 -0800599 sep := ""
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800600 for _, arg := range cx.args {
601 gctx.write(sep)
602 arg.emit(gctx)
603 sep = ", "
604 }
605 gctx.write(")")
606}
607
608func (cx *callExpr) typ() starlarkType {
609 return cx.returnType
610}
611
612func (cx *callExpr) emitListVarCopy(gctx *generationContext) {
613 cx.emit(gctx)
614}
615
Cole Faustb0d32ab2021-12-09 14:00:59 -0800616func (cx *callExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
617 if cx.object != nil {
618 cx.object = cx.object.transform(transformer)
619 }
620 argsCopy := make([]starlarkExpr, len(cx.args))
621 for i, arg := range cx.args {
622 argsCopy[i] = arg.transform(transformer)
623 }
624 if replacement := transformer(cx); replacement != nil {
625 return replacement
626 } else {
627 return cx
628 }
629}
630
Cole Faust4eadba72021-12-07 11:54:52 -0800631type ifExpr struct {
632 condition starlarkExpr
633 ifTrue starlarkExpr
634 ifFalse starlarkExpr
635}
636
Cole Faust4eadba72021-12-07 11:54:52 -0800637func (i *ifExpr) emit(gctx *generationContext) {
638 gctx.write("(")
639 i.ifTrue.emit(gctx)
640 gctx.write(" if ")
641 i.condition.emit(gctx)
642 gctx.write(" else ")
643 i.ifFalse.emit(gctx)
644 gctx.write(")")
645}
646
647func (i *ifExpr) typ() starlarkType {
648 tType := i.ifTrue.typ()
649 fType := i.ifFalse.typ()
650 if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
651 panic("Conflicting types in if expression")
652 }
653 if tType != starlarkTypeUnknown {
654 return tType
655 } else {
656 return fType
657 }
658}
659
660func (i *ifExpr) emitListVarCopy(gctx *generationContext) {
661 i.emit(gctx)
662}
663
Cole Faustb0d32ab2021-12-09 14:00:59 -0800664func (i *ifExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
665 i.condition = i.condition.transform(transformer)
666 i.ifTrue = i.ifTrue.transform(transformer)
667 i.ifFalse = i.ifFalse.transform(transformer)
668 if replacement := transformer(i); replacement != nil {
669 return replacement
670 } else {
671 return i
672 }
673}
674
675type identifierExpr struct {
676 name string
677}
678
Cole Faustb0d32ab2021-12-09 14:00:59 -0800679func (i *identifierExpr) emit(gctx *generationContext) {
680 gctx.write(i.name)
681}
682
683func (i *identifierExpr) typ() starlarkType {
684 return starlarkTypeUnknown
685}
686
687func (i *identifierExpr) emitListVarCopy(gctx *generationContext) {
688 i.emit(gctx)
689}
690
691func (i *identifierExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
692 if replacement := transformer(i); replacement != nil {
693 return replacement
694 } else {
695 return i
696 }
697}
698
699type foreachExpr struct {
700 varName string
701 list starlarkExpr
702 action starlarkExpr
703}
704
Cole Faustb0d32ab2021-12-09 14:00:59 -0800705func (f *foreachExpr) emit(gctx *generationContext) {
706 gctx.write("[")
707 f.action.emit(gctx)
708 gctx.write(" for " + f.varName + " in ")
709 f.list.emit(gctx)
710 gctx.write("]")
711}
712
713func (f *foreachExpr) typ() starlarkType {
714 return starlarkTypeList
715}
716
717func (f *foreachExpr) emitListVarCopy(gctx *generationContext) {
718 f.emit(gctx)
719}
720
721func (f *foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
722 f.list = f.list.transform(transformer)
723 f.action = f.action.transform(transformer)
724 if replacement := transformer(f); replacement != nil {
725 return replacement
726 } else {
727 return f
728 }
729}
730
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800731type badExpr struct {
Sasha Smundak422b6142021-11-11 18:31:59 -0800732 errorLocation ErrorLocation
733 message string
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800734}
735
Sasha Smundak422b6142021-11-11 18:31:59 -0800736func (b *badExpr) emit(gctx *generationContext) {
737 gctx.emitConversionError(b.errorLocation, b.message)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800738}
739
740func (_ *badExpr) typ() starlarkType {
741 return starlarkTypeUnknown
742}
743
Sasha Smundak422b6142021-11-11 18:31:59 -0800744func (_ *badExpr) emitListVarCopy(_ *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800745 panic("implement me")
746}
747
Cole Faustb0d32ab2021-12-09 14:00:59 -0800748func (b *badExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
749 if replacement := transformer(b); replacement != nil {
750 return replacement
751 } else {
752 return b
753 }
754}
755
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800756func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
757 if xString, ok := expr.(*stringLiteralExpr); ok {
758 return newStringListExpr(strings.Fields(xString.literal))
759 }
760 return expr
761}
Sasha Smundak0554d762021-07-08 18:26:12 -0700762
763func isEmptyString(expr starlarkExpr) bool {
764 x, ok := expr.(*stringLiteralExpr)
765 return ok && x.literal == ""
766}