blob: dc16d1d2f7fa2f7cd0000e998e69f83d5a89e38b [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 -0800381type listExpr struct {
382 items []starlarkExpr
383}
384
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800385func (l *listExpr) emit(gctx *generationContext) {
386 if !gctx.inAssignment || len(l.items) < 2 {
387 gctx.write("[")
388 sep := ""
389 for _, item := range l.items {
390 gctx.write(sep)
391 item.emit(gctx)
392 sep = ", "
393 }
394 gctx.write("]")
395 return
396 }
397
398 gctx.write("[")
399 gctx.indentLevel += 2
400
401 for _, item := range l.items {
402 gctx.newLine()
403 item.emit(gctx)
404 gctx.write(",")
405 }
406 gctx.indentLevel -= 2
407 gctx.newLine()
408 gctx.write("]")
409}
410
411func (_ *listExpr) typ() starlarkType {
412 return starlarkTypeList
413}
414
415func (l *listExpr) emitListVarCopy(gctx *generationContext) {
416 l.emit(gctx)
417}
418
Cole Faustb0d32ab2021-12-09 14:00:59 -0800419func (l *listExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
420 itemsCopy := make([]starlarkExpr, len(l.items))
421 for i, item := range l.items {
422 itemsCopy[i] = item.transform(transformer)
423 }
424 l.items = itemsCopy
425 if replacement := transformer(l); replacement != nil {
426 return replacement
427 } else {
428 return l
429 }
430}
431
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800432func newStringListExpr(items []string) *listExpr {
433 v := listExpr{}
434 for _, item := range items {
435 v.items = append(v.items, &stringLiteralExpr{item})
436 }
437 return &v
438}
439
Sasha Smundak422b6142021-11-11 18:31:59 -0800440// concatExpr generates expr1 + expr2 + ... + exprN in Starlark.
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800441type concatExpr struct {
442 items []starlarkExpr
443}
444
445func (c *concatExpr) emit(gctx *generationContext) {
446 if len(c.items) == 1 {
447 c.items[0].emit(gctx)
448 return
449 }
450
451 if !gctx.inAssignment {
452 c.items[0].emit(gctx)
453 for _, item := range c.items[1:] {
454 gctx.write(" + ")
455 item.emit(gctx)
456 }
457 return
458 }
459 gctx.write("(")
460 c.items[0].emit(gctx)
461 gctx.indentLevel += 2
462 for _, item := range c.items[1:] {
463 gctx.write(" +")
464 gctx.newLine()
465 item.emit(gctx)
466 }
467 gctx.write(")")
468 gctx.indentLevel -= 2
469}
470
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800471func (_ *concatExpr) typ() starlarkType {
472 return starlarkTypeList
473}
474
475func (c *concatExpr) emitListVarCopy(gctx *generationContext) {
476 c.emit(gctx)
477}
478
Cole Faustb0d32ab2021-12-09 14:00:59 -0800479func (c *concatExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
480 itemsCopy := make([]starlarkExpr, len(c.items))
481 for i, item := range c.items {
482 itemsCopy[i] = item.transform(transformer)
483 }
484 c.items = itemsCopy
485 if replacement := transformer(c); replacement != nil {
486 return replacement
487 } else {
488 return c
489 }
490}
491
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800492// inExpr generates <expr> [not] in <list>
493type inExpr struct {
494 expr starlarkExpr
495 list starlarkExpr
496 isNot bool
497}
498
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800499func (i *inExpr) emit(gctx *generationContext) {
500 i.expr.emit(gctx)
501 if i.isNot {
502 gctx.write(" not in ")
503 } else {
504 gctx.write(" in ")
505 }
506 i.list.emit(gctx)
507}
508
509func (_ *inExpr) typ() starlarkType {
510 return starlarkTypeBool
511}
512
513func (i *inExpr) emitListVarCopy(gctx *generationContext) {
514 i.emit(gctx)
515}
516
Cole Faustb0d32ab2021-12-09 14:00:59 -0800517func (i *inExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
518 i.expr = i.expr.transform(transformer)
519 i.list = i.list.transform(transformer)
520 if replacement := transformer(i); replacement != nil {
521 return replacement
522 } else {
523 return i
524 }
525}
526
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800527type indexExpr struct {
528 array starlarkExpr
529 index starlarkExpr
530}
531
Cole Faustb0d32ab2021-12-09 14:00:59 -0800532func (ix *indexExpr) emit(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800533 ix.array.emit(gctx)
534 gctx.write("[")
535 ix.index.emit(gctx)
536 gctx.write("]")
537}
538
Cole Faustb0d32ab2021-12-09 14:00:59 -0800539func (ix *indexExpr) typ() starlarkType {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800540 return starlarkTypeString
541}
542
Cole Faustb0d32ab2021-12-09 14:00:59 -0800543func (ix *indexExpr) emitListVarCopy(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800544 ix.emit(gctx)
545}
546
Cole Faustb0d32ab2021-12-09 14:00:59 -0800547func (ix *indexExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
548 ix.array = ix.array.transform(transformer)
549 ix.index = ix.index.transform(transformer)
550 if replacement := transformer(ix); replacement != nil {
551 return replacement
552 } else {
553 return ix
554 }
555}
556
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800557type callExpr struct {
558 object starlarkExpr // nil if static call
559 name string
560 args []starlarkExpr
561 returnType starlarkType
562}
563
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800564func (cx *callExpr) emit(gctx *generationContext) {
565 if cx.object != nil {
566 gctx.write("(")
567 cx.object.emit(gctx)
568 gctx.write(")")
569 gctx.write(".", cx.name, "(")
570 } else {
Cole Faust9ebf6e42021-12-13 14:08:34 -0800571 gctx.write(cx.name, "(")
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800572 }
Cole Faust9ebf6e42021-12-13 14:08:34 -0800573 sep := ""
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800574 for _, arg := range cx.args {
575 gctx.write(sep)
576 arg.emit(gctx)
577 sep = ", "
578 }
579 gctx.write(")")
580}
581
582func (cx *callExpr) typ() starlarkType {
583 return cx.returnType
584}
585
586func (cx *callExpr) emitListVarCopy(gctx *generationContext) {
587 cx.emit(gctx)
588}
589
Cole Faustb0d32ab2021-12-09 14:00:59 -0800590func (cx *callExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
591 if cx.object != nil {
592 cx.object = cx.object.transform(transformer)
593 }
594 argsCopy := make([]starlarkExpr, len(cx.args))
595 for i, arg := range cx.args {
596 argsCopy[i] = arg.transform(transformer)
597 }
Cole Faustb67aa082022-02-28 16:39:59 -0800598 cx.args = argsCopy
Cole Faustb0d32ab2021-12-09 14:00:59 -0800599 if replacement := transformer(cx); replacement != nil {
600 return replacement
601 } else {
602 return cx
603 }
604}
605
Cole Faust4eadba72021-12-07 11:54:52 -0800606type ifExpr struct {
607 condition starlarkExpr
608 ifTrue starlarkExpr
609 ifFalse starlarkExpr
610}
611
Cole Faust4eadba72021-12-07 11:54:52 -0800612func (i *ifExpr) emit(gctx *generationContext) {
613 gctx.write("(")
614 i.ifTrue.emit(gctx)
615 gctx.write(" if ")
616 i.condition.emit(gctx)
617 gctx.write(" else ")
618 i.ifFalse.emit(gctx)
619 gctx.write(")")
620}
621
622func (i *ifExpr) typ() starlarkType {
623 tType := i.ifTrue.typ()
624 fType := i.ifFalse.typ()
625 if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
626 panic("Conflicting types in if expression")
627 }
628 if tType != starlarkTypeUnknown {
629 return tType
630 } else {
631 return fType
632 }
633}
634
635func (i *ifExpr) emitListVarCopy(gctx *generationContext) {
636 i.emit(gctx)
637}
638
Cole Faustb0d32ab2021-12-09 14:00:59 -0800639func (i *ifExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
640 i.condition = i.condition.transform(transformer)
641 i.ifTrue = i.ifTrue.transform(transformer)
642 i.ifFalse = i.ifFalse.transform(transformer)
643 if replacement := transformer(i); replacement != nil {
644 return replacement
645 } else {
646 return i
647 }
648}
649
650type identifierExpr struct {
651 name string
652}
653
Cole Faustb0d32ab2021-12-09 14:00:59 -0800654func (i *identifierExpr) emit(gctx *generationContext) {
655 gctx.write(i.name)
656}
657
658func (i *identifierExpr) typ() starlarkType {
659 return starlarkTypeUnknown
660}
661
662func (i *identifierExpr) emitListVarCopy(gctx *generationContext) {
663 i.emit(gctx)
664}
665
666func (i *identifierExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
667 if replacement := transformer(i); replacement != nil {
668 return replacement
669 } else {
670 return i
671 }
672}
673
674type foreachExpr struct {
675 varName string
676 list starlarkExpr
677 action starlarkExpr
678}
679
Cole Faustb0d32ab2021-12-09 14:00:59 -0800680func (f *foreachExpr) emit(gctx *generationContext) {
681 gctx.write("[")
682 f.action.emit(gctx)
683 gctx.write(" for " + f.varName + " in ")
684 f.list.emit(gctx)
685 gctx.write("]")
686}
687
688func (f *foreachExpr) typ() starlarkType {
689 return starlarkTypeList
690}
691
692func (f *foreachExpr) emitListVarCopy(gctx *generationContext) {
693 f.emit(gctx)
694}
695
696func (f *foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
697 f.list = f.list.transform(transformer)
698 f.action = f.action.transform(transformer)
699 if replacement := transformer(f); replacement != nil {
700 return replacement
701 } else {
702 return f
703 }
704}
705
Cole Faustb1103e22022-01-06 15:22:05 -0800706type binaryOpExpr struct {
707 left, right starlarkExpr
708 op string
709 returnType starlarkType
710}
711
712func (b *binaryOpExpr) emit(gctx *generationContext) {
713 b.left.emit(gctx)
714 gctx.write(" " + b.op + " ")
715 b.right.emit(gctx)
716}
717
718func (b *binaryOpExpr) typ() starlarkType {
719 return b.returnType
720}
721
722func (b *binaryOpExpr) emitListVarCopy(gctx *generationContext) {
723 b.emit(gctx)
724}
725
726func (b *binaryOpExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
727 b.left = b.left.transform(transformer)
728 b.right = b.right.transform(transformer)
729 if replacement := transformer(b); replacement != nil {
730 return replacement
731 } else {
732 return b
733 }
734}
735
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800736type badExpr struct {
Sasha Smundak422b6142021-11-11 18:31:59 -0800737 errorLocation ErrorLocation
738 message string
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800739}
740
Sasha Smundak422b6142021-11-11 18:31:59 -0800741func (b *badExpr) emit(gctx *generationContext) {
742 gctx.emitConversionError(b.errorLocation, b.message)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800743}
744
745func (_ *badExpr) typ() starlarkType {
746 return starlarkTypeUnknown
747}
748
Sasha Smundak422b6142021-11-11 18:31:59 -0800749func (_ *badExpr) emitListVarCopy(_ *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800750 panic("implement me")
751}
752
Cole Faustb0d32ab2021-12-09 14:00:59 -0800753func (b *badExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
754 if replacement := transformer(b); replacement != nil {
755 return replacement
756 } else {
757 return b
758 }
759}
760
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800761func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
762 if xString, ok := expr.(*stringLiteralExpr); ok {
763 return newStringListExpr(strings.Fields(xString.literal))
764 }
765 return expr
766}
Sasha Smundak0554d762021-07-08 18:26:12 -0700767
768func isEmptyString(expr starlarkExpr) bool {
769 x, ok := expr.(*stringLiteralExpr)
770 return ok && x.literal == ""
771}