blob: 54bb6d1244a98a5894d2ad3763f335933ee22063 [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 {
Cole Faustf035d402022-03-28 14:02:50 -0700224 for i := range xi.args {
225 xi.args[i] = xi.args[i].transform(transformer)
Cole Faustb0d32ab2021-12-09 14:00:59 -0800226 }
Cole Faustb0d32ab2021-12-09 14:00:59 -0800227 if replacement := transformer(xi); replacement != nil {
228 return replacement
229 } else {
230 return xi
231 }
232}
233
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800234type variableRefExpr struct {
235 ref variable
236 isDefined bool
237}
238
Cole Faustfc438682021-12-14 12:46:32 -0800239func NewVariableRefExpr(ref variable, isDefined bool) starlarkExpr {
240 if predefined, ok := ref.(*predefinedVariable); ok {
241 return predefined.value
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800242 }
Cole Faustfc438682021-12-14 12:46:32 -0800243 return &variableRefExpr{ref, isDefined}
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800244}
245
246func (v *variableRefExpr) emit(gctx *generationContext) {
247 v.ref.emitGet(gctx, v.isDefined)
248}
249
250func (v *variableRefExpr) typ() starlarkType {
251 return v.ref.valueType()
252}
253
254func (v *variableRefExpr) emitListVarCopy(gctx *generationContext) {
255 v.emit(gctx)
256 if v.typ() == starlarkTypeList {
257 gctx.write("[:]") // this will copy the list
258 }
259}
260
Cole Faustb0d32ab2021-12-09 14:00:59 -0800261func (v *variableRefExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
262 if replacement := transformer(v); replacement != nil {
263 return replacement
264 } else {
265 return v
266 }
267}
268
Cole Faustf8320212021-11-10 15:05:07 -0800269type toStringExpr struct {
270 expr starlarkExpr
271}
272
Cole Faustf8320212021-11-10 15:05:07 -0800273func (s *toStringExpr) emit(ctx *generationContext) {
274 switch s.expr.typ() {
275 case starlarkTypeString, starlarkTypeUnknown:
276 // Assume unknown types are strings already.
277 s.expr.emit(ctx)
278 case starlarkTypeList:
279 ctx.write(`" ".join(`)
280 s.expr.emit(ctx)
281 ctx.write(")")
282 case starlarkTypeInt:
283 ctx.write(`("%d" % (`)
284 s.expr.emit(ctx)
285 ctx.write("))")
286 case starlarkTypeBool:
Cole Faustf1f44d32021-11-16 14:52:12 -0800287 ctx.write(`("true" if (`)
Cole Faustf8320212021-11-10 15:05:07 -0800288 s.expr.emit(ctx)
Cole Faustf1f44d32021-11-16 14:52:12 -0800289 ctx.write(`) else "")`)
Cole Faustf8320212021-11-10 15:05:07 -0800290 case starlarkTypeVoid:
291 ctx.write(`""`)
292 default:
293 panic("Unknown starlark type!")
294 }
295}
296
297func (s *toStringExpr) typ() starlarkType {
298 return starlarkTypeString
299}
300
301func (s *toStringExpr) emitListVarCopy(gctx *generationContext) {
302 s.emit(gctx)
303}
304
Cole Faustb0d32ab2021-12-09 14:00:59 -0800305func (s *toStringExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
306 s.expr = s.expr.transform(transformer)
307 if replacement := transformer(s); replacement != nil {
308 return replacement
309 } else {
310 return s
311 }
312}
313
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800314type notExpr struct {
315 expr starlarkExpr
316}
317
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800318func (n *notExpr) emit(ctx *generationContext) {
319 ctx.write("not ")
320 n.expr.emit(ctx)
321}
322
323func (_ *notExpr) typ() starlarkType {
324 return starlarkTypeBool
325}
326
327func (n *notExpr) emitListVarCopy(gctx *generationContext) {
328 n.emit(gctx)
329}
330
Cole Faustb0d32ab2021-12-09 14:00:59 -0800331func (n *notExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
332 n.expr = n.expr.transform(transformer)
333 if replacement := transformer(n); replacement != nil {
334 return replacement
335 } else {
336 return n
337 }
338}
339
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800340type eqExpr struct {
341 left, right starlarkExpr
342 isEq bool // if false, it's !=
343}
344
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800345func (eq *eqExpr) emit(gctx *generationContext) {
Cole Faustf8320212021-11-10 15:05:07 -0800346 if eq.left.typ() != eq.right.typ() {
347 eq.left = &toStringExpr{expr: eq.left}
348 eq.right = &toStringExpr{expr: eq.right}
349 }
350
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800351 // General case
352 eq.left.emit(gctx)
353 if eq.isEq {
354 gctx.write(" == ")
355 } else {
356 gctx.write(" != ")
357 }
358 eq.right.emit(gctx)
359}
360
361func (_ *eqExpr) typ() starlarkType {
362 return starlarkTypeBool
363}
364
365func (eq *eqExpr) emitListVarCopy(gctx *generationContext) {
366 eq.emit(gctx)
367}
368
Cole Faustb0d32ab2021-12-09 14:00:59 -0800369func (eq *eqExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
370 eq.left = eq.left.transform(transformer)
371 eq.right = eq.right.transform(transformer)
372 if replacement := transformer(eq); replacement != nil {
373 return replacement
374 } else {
375 return eq
376 }
377}
378
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800379type listExpr struct {
380 items []starlarkExpr
381}
382
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800383func (l *listExpr) emit(gctx *generationContext) {
384 if !gctx.inAssignment || len(l.items) < 2 {
385 gctx.write("[")
386 sep := ""
387 for _, item := range l.items {
388 gctx.write(sep)
389 item.emit(gctx)
390 sep = ", "
391 }
392 gctx.write("]")
393 return
394 }
395
396 gctx.write("[")
397 gctx.indentLevel += 2
398
399 for _, item := range l.items {
400 gctx.newLine()
401 item.emit(gctx)
402 gctx.write(",")
403 }
404 gctx.indentLevel -= 2
405 gctx.newLine()
406 gctx.write("]")
407}
408
409func (_ *listExpr) typ() starlarkType {
410 return starlarkTypeList
411}
412
413func (l *listExpr) emitListVarCopy(gctx *generationContext) {
414 l.emit(gctx)
415}
416
Cole Faustb0d32ab2021-12-09 14:00:59 -0800417func (l *listExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
418 itemsCopy := make([]starlarkExpr, len(l.items))
419 for i, item := range l.items {
420 itemsCopy[i] = item.transform(transformer)
421 }
422 l.items = itemsCopy
423 if replacement := transformer(l); replacement != nil {
424 return replacement
425 } else {
426 return l
427 }
428}
429
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800430func newStringListExpr(items []string) *listExpr {
431 v := listExpr{}
432 for _, item := range items {
433 v.items = append(v.items, &stringLiteralExpr{item})
434 }
435 return &v
436}
437
Sasha Smundak422b6142021-11-11 18:31:59 -0800438// concatExpr generates expr1 + expr2 + ... + exprN in Starlark.
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800439type concatExpr struct {
440 items []starlarkExpr
441}
442
443func (c *concatExpr) emit(gctx *generationContext) {
444 if len(c.items) == 1 {
445 c.items[0].emit(gctx)
446 return
447 }
448
449 if !gctx.inAssignment {
450 c.items[0].emit(gctx)
451 for _, item := range c.items[1:] {
452 gctx.write(" + ")
453 item.emit(gctx)
454 }
455 return
456 }
457 gctx.write("(")
458 c.items[0].emit(gctx)
459 gctx.indentLevel += 2
460 for _, item := range c.items[1:] {
461 gctx.write(" +")
462 gctx.newLine()
463 item.emit(gctx)
464 }
465 gctx.write(")")
466 gctx.indentLevel -= 2
467}
468
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800469func (_ *concatExpr) typ() starlarkType {
470 return starlarkTypeList
471}
472
473func (c *concatExpr) emitListVarCopy(gctx *generationContext) {
474 c.emit(gctx)
475}
476
Cole Faustb0d32ab2021-12-09 14:00:59 -0800477func (c *concatExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
478 itemsCopy := make([]starlarkExpr, len(c.items))
479 for i, item := range c.items {
480 itemsCopy[i] = item.transform(transformer)
481 }
482 c.items = itemsCopy
483 if replacement := transformer(c); replacement != nil {
484 return replacement
485 } else {
486 return c
487 }
488}
489
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800490// inExpr generates <expr> [not] in <list>
491type inExpr struct {
492 expr starlarkExpr
493 list starlarkExpr
494 isNot bool
495}
496
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800497func (i *inExpr) emit(gctx *generationContext) {
498 i.expr.emit(gctx)
499 if i.isNot {
500 gctx.write(" not in ")
501 } else {
502 gctx.write(" in ")
503 }
504 i.list.emit(gctx)
505}
506
507func (_ *inExpr) typ() starlarkType {
508 return starlarkTypeBool
509}
510
511func (i *inExpr) emitListVarCopy(gctx *generationContext) {
512 i.emit(gctx)
513}
514
Cole Faustb0d32ab2021-12-09 14:00:59 -0800515func (i *inExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
516 i.expr = i.expr.transform(transformer)
517 i.list = i.list.transform(transformer)
518 if replacement := transformer(i); replacement != nil {
519 return replacement
520 } else {
521 return i
522 }
523}
524
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800525type indexExpr struct {
526 array starlarkExpr
527 index starlarkExpr
528}
529
Cole Faustb0d32ab2021-12-09 14:00:59 -0800530func (ix *indexExpr) emit(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800531 ix.array.emit(gctx)
532 gctx.write("[")
533 ix.index.emit(gctx)
534 gctx.write("]")
535}
536
Cole Faustb0d32ab2021-12-09 14:00:59 -0800537func (ix *indexExpr) typ() starlarkType {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800538 return starlarkTypeString
539}
540
Cole Faustb0d32ab2021-12-09 14:00:59 -0800541func (ix *indexExpr) emitListVarCopy(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800542 ix.emit(gctx)
543}
544
Cole Faustb0d32ab2021-12-09 14:00:59 -0800545func (ix *indexExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
546 ix.array = ix.array.transform(transformer)
547 ix.index = ix.index.transform(transformer)
548 if replacement := transformer(ix); replacement != nil {
549 return replacement
550 } else {
551 return ix
552 }
553}
554
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800555type callExpr struct {
556 object starlarkExpr // nil if static call
557 name string
558 args []starlarkExpr
559 returnType starlarkType
560}
561
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800562func (cx *callExpr) emit(gctx *generationContext) {
563 if cx.object != nil {
564 gctx.write("(")
565 cx.object.emit(gctx)
566 gctx.write(")")
567 gctx.write(".", cx.name, "(")
568 } else {
Cole Faust9ebf6e42021-12-13 14:08:34 -0800569 gctx.write(cx.name, "(")
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800570 }
Cole Faust9ebf6e42021-12-13 14:08:34 -0800571 sep := ""
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800572 for _, arg := range cx.args {
573 gctx.write(sep)
574 arg.emit(gctx)
575 sep = ", "
576 }
577 gctx.write(")")
578}
579
580func (cx *callExpr) typ() starlarkType {
581 return cx.returnType
582}
583
584func (cx *callExpr) emitListVarCopy(gctx *generationContext) {
585 cx.emit(gctx)
586}
587
Cole Faustb0d32ab2021-12-09 14:00:59 -0800588func (cx *callExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
589 if cx.object != nil {
590 cx.object = cx.object.transform(transformer)
591 }
Cole Faustf035d402022-03-28 14:02:50 -0700592 for i := range cx.args {
593 cx.args[i] = cx.args[i].transform(transformer)
Cole Faustb0d32ab2021-12-09 14:00:59 -0800594 }
595 if replacement := transformer(cx); replacement != nil {
596 return replacement
597 } else {
598 return cx
599 }
600}
601
Cole Faust4eadba72021-12-07 11:54:52 -0800602type ifExpr struct {
603 condition starlarkExpr
604 ifTrue starlarkExpr
605 ifFalse starlarkExpr
606}
607
Cole Faust4eadba72021-12-07 11:54:52 -0800608func (i *ifExpr) emit(gctx *generationContext) {
609 gctx.write("(")
610 i.ifTrue.emit(gctx)
611 gctx.write(" if ")
612 i.condition.emit(gctx)
613 gctx.write(" else ")
614 i.ifFalse.emit(gctx)
615 gctx.write(")")
616}
617
618func (i *ifExpr) typ() starlarkType {
619 tType := i.ifTrue.typ()
620 fType := i.ifFalse.typ()
621 if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
622 panic("Conflicting types in if expression")
623 }
624 if tType != starlarkTypeUnknown {
625 return tType
626 } else {
627 return fType
628 }
629}
630
631func (i *ifExpr) emitListVarCopy(gctx *generationContext) {
632 i.emit(gctx)
633}
634
Cole Faustb0d32ab2021-12-09 14:00:59 -0800635func (i *ifExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
636 i.condition = i.condition.transform(transformer)
637 i.ifTrue = i.ifTrue.transform(transformer)
638 i.ifFalse = i.ifFalse.transform(transformer)
639 if replacement := transformer(i); replacement != nil {
640 return replacement
641 } else {
642 return i
643 }
644}
645
646type identifierExpr struct {
647 name string
648}
649
Cole Faustb0d32ab2021-12-09 14:00:59 -0800650func (i *identifierExpr) emit(gctx *generationContext) {
651 gctx.write(i.name)
652}
653
654func (i *identifierExpr) typ() starlarkType {
655 return starlarkTypeUnknown
656}
657
658func (i *identifierExpr) emitListVarCopy(gctx *generationContext) {
659 i.emit(gctx)
660}
661
662func (i *identifierExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
663 if replacement := transformer(i); replacement != nil {
664 return replacement
665 } else {
666 return i
667 }
668}
669
670type foreachExpr struct {
671 varName string
672 list starlarkExpr
673 action starlarkExpr
674}
675
Cole Faustb0d32ab2021-12-09 14:00:59 -0800676func (f *foreachExpr) emit(gctx *generationContext) {
677 gctx.write("[")
678 f.action.emit(gctx)
679 gctx.write(" for " + f.varName + " in ")
680 f.list.emit(gctx)
681 gctx.write("]")
682}
683
684func (f *foreachExpr) typ() starlarkType {
685 return starlarkTypeList
686}
687
688func (f *foreachExpr) emitListVarCopy(gctx *generationContext) {
689 f.emit(gctx)
690}
691
692func (f *foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
693 f.list = f.list.transform(transformer)
694 f.action = f.action.transform(transformer)
695 if replacement := transformer(f); replacement != nil {
696 return replacement
697 } else {
698 return f
699 }
700}
701
Cole Faustb1103e22022-01-06 15:22:05 -0800702type binaryOpExpr struct {
703 left, right starlarkExpr
704 op string
705 returnType starlarkType
706}
707
708func (b *binaryOpExpr) emit(gctx *generationContext) {
709 b.left.emit(gctx)
710 gctx.write(" " + b.op + " ")
711 b.right.emit(gctx)
712}
713
714func (b *binaryOpExpr) typ() starlarkType {
715 return b.returnType
716}
717
718func (b *binaryOpExpr) emitListVarCopy(gctx *generationContext) {
719 b.emit(gctx)
720}
721
722func (b *binaryOpExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
723 b.left = b.left.transform(transformer)
724 b.right = b.right.transform(transformer)
725 if replacement := transformer(b); replacement != nil {
726 return replacement
727 } else {
728 return b
729 }
730}
731
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800732type badExpr struct {
Sasha Smundak422b6142021-11-11 18:31:59 -0800733 errorLocation ErrorLocation
734 message string
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800735}
736
Sasha Smundak422b6142021-11-11 18:31:59 -0800737func (b *badExpr) emit(gctx *generationContext) {
738 gctx.emitConversionError(b.errorLocation, b.message)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800739}
740
741func (_ *badExpr) typ() starlarkType {
742 return starlarkTypeUnknown
743}
744
Sasha Smundak422b6142021-11-11 18:31:59 -0800745func (_ *badExpr) emitListVarCopy(_ *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800746 panic("implement me")
747}
748
Cole Faustb0d32ab2021-12-09 14:00:59 -0800749func (b *badExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
750 if replacement := transformer(b); replacement != nil {
751 return replacement
752 } else {
753 return b
754 }
755}
756
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800757func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
758 if xString, ok := expr.(*stringLiteralExpr); ok {
759 return newStringListExpr(strings.Fields(xString.literal))
760 }
761 return expr
762}
Sasha Smundak0554d762021-07-08 18:26:12 -0700763
764func isEmptyString(expr starlarkExpr) bool {
765 x, ok := expr.(*stringLiteralExpr)
766 return ok && x.literal == ""
767}
Cole Faustf035d402022-03-28 14:02:50 -0700768
769func negateExpr(expr starlarkExpr) starlarkExpr {
770 switch typedExpr := expr.(type) {
771 case *notExpr:
772 return typedExpr.expr
773 case *inExpr:
774 typedExpr.isNot = !typedExpr.isNot
775 return typedExpr
776 case *eqExpr:
777 typedExpr.isEq = !typedExpr.isEq
778 return typedExpr
779 case *binaryOpExpr:
780 switch typedExpr.op {
781 case ">":
782 typedExpr.op = "<="
783 return typedExpr
784 case "<":
785 typedExpr.op = ">="
786 return typedExpr
787 case ">=":
788 typedExpr.op = "<"
789 return typedExpr
790 case "<=":
791 typedExpr.op = ">"
792 return typedExpr
793 default:
794 return &notExpr{expr: expr}
795 }
796 default:
797 return &notExpr{expr: expr}
798 }
799}