blob: 7cd4899ab8358b1571c3c43ca56459e1caa32007 [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
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800122// interpolateExpr represents Starlark's interpolation operator <string> % list
123// we break <string> into a list of chunks, i.e., "first%second%third" % (X, Y)
124// will have chunks = ["first", "second", "third"] and args = [X, Y]
125type interpolateExpr struct {
126 chunks []string // string chunks, separated by '%'
127 args []starlarkExpr
128}
129
Cole Faustfc438682021-12-14 12:46:32 -0800130func NewInterpolateExpr(parts []starlarkExpr) starlarkExpr {
131 result := &interpolateExpr{}
132 needString := true
133 for _, part := range parts {
134 if needString {
135 if strLit, ok := part.(*stringLiteralExpr); ok {
136 result.chunks = append(result.chunks, strLit.literal)
137 } else {
138 result.chunks = append(result.chunks, "")
139 }
140 needString = false
141 } else {
142 if strLit, ok := part.(*stringLiteralExpr); ok {
143 result.chunks[len(result.chunks)-1] += strLit.literal
144 } else {
145 result.args = append(result.args, part)
146 needString = true
147 }
148 }
149 }
150 if len(result.chunks) == len(result.args) {
151 result.chunks = append(result.chunks, "")
152 }
153 if len(result.args) == 0 {
154 return &stringLiteralExpr{literal: strings.Join(result.chunks, "")}
155 }
156 return result
157}
158
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800159func (xi *interpolateExpr) emit(gctx *generationContext) {
160 if len(xi.chunks) != len(xi.args)+1 {
161 panic(fmt.Errorf("malformed interpolateExpr: #chunks(%d) != #args(%d)+1",
162 len(xi.chunks), len(xi.args)))
163 }
164 // Generate format as join of chunks, but first escape '%' in them
165 format := strings.ReplaceAll(xi.chunks[0], "%", "%%")
166 for _, chunk := range xi.chunks[1:] {
167 format += "%s" + strings.ReplaceAll(chunk, "%", "%%")
168 }
169 gctx.writef("%q %% ", format)
Sasha Smundak422b6142021-11-11 18:31:59 -0800170 emitArg := func(arg starlarkExpr) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800171 if arg.typ() == starlarkTypeList {
172 gctx.write(`" ".join(`)
173 arg.emit(gctx)
174 gctx.write(`)`)
175 } else {
176 arg.emit(gctx)
177 }
178 }
179 if len(xi.args) == 1 {
Sasha Smundak422b6142021-11-11 18:31:59 -0800180 emitArg(xi.args[0])
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800181 } else {
182 sep := "("
183 for _, arg := range xi.args {
184 gctx.write(sep)
Sasha Smundak422b6142021-11-11 18:31:59 -0800185 emitArg(arg)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800186 sep = ", "
187 }
188 gctx.write(")")
189 }
190}
191
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800192func (_ *interpolateExpr) typ() starlarkType {
193 return starlarkTypeString
194}
195
196func (xi *interpolateExpr) emitListVarCopy(gctx *generationContext) {
197 xi.emit(gctx)
198}
199
Cole Faustb0d32ab2021-12-09 14:00:59 -0800200func (xi *interpolateExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
201 argsCopy := make([]starlarkExpr, len(xi.args))
202 for i, arg := range xi.args {
203 argsCopy[i] = arg.transform(transformer)
204 }
205 xi.args = argsCopy
206 if replacement := transformer(xi); replacement != nil {
207 return replacement
208 } else {
209 return xi
210 }
211}
212
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800213type variableRefExpr struct {
214 ref variable
215 isDefined bool
216}
217
Cole Faustfc438682021-12-14 12:46:32 -0800218func NewVariableRefExpr(ref variable, isDefined bool) starlarkExpr {
219 if predefined, ok := ref.(*predefinedVariable); ok {
220 return predefined.value
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800221 }
Cole Faustfc438682021-12-14 12:46:32 -0800222 return &variableRefExpr{ref, isDefined}
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800223}
224
225func (v *variableRefExpr) emit(gctx *generationContext) {
226 v.ref.emitGet(gctx, v.isDefined)
227}
228
229func (v *variableRefExpr) typ() starlarkType {
230 return v.ref.valueType()
231}
232
233func (v *variableRefExpr) emitListVarCopy(gctx *generationContext) {
234 v.emit(gctx)
235 if v.typ() == starlarkTypeList {
236 gctx.write("[:]") // this will copy the list
237 }
238}
239
Cole Faustb0d32ab2021-12-09 14:00:59 -0800240func (v *variableRefExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
241 if replacement := transformer(v); replacement != nil {
242 return replacement
243 } else {
244 return v
245 }
246}
247
Cole Faustf8320212021-11-10 15:05:07 -0800248type toStringExpr struct {
249 expr starlarkExpr
250}
251
Cole Faustf8320212021-11-10 15:05:07 -0800252func (s *toStringExpr) emit(ctx *generationContext) {
253 switch s.expr.typ() {
254 case starlarkTypeString, starlarkTypeUnknown:
255 // Assume unknown types are strings already.
256 s.expr.emit(ctx)
257 case starlarkTypeList:
258 ctx.write(`" ".join(`)
259 s.expr.emit(ctx)
260 ctx.write(")")
261 case starlarkTypeInt:
262 ctx.write(`("%d" % (`)
263 s.expr.emit(ctx)
264 ctx.write("))")
265 case starlarkTypeBool:
Cole Faustf1f44d32021-11-16 14:52:12 -0800266 ctx.write(`("true" if (`)
Cole Faustf8320212021-11-10 15:05:07 -0800267 s.expr.emit(ctx)
Cole Faustf1f44d32021-11-16 14:52:12 -0800268 ctx.write(`) else "")`)
Cole Faustf8320212021-11-10 15:05:07 -0800269 case starlarkTypeVoid:
270 ctx.write(`""`)
271 default:
272 panic("Unknown starlark type!")
273 }
274}
275
276func (s *toStringExpr) typ() starlarkType {
277 return starlarkTypeString
278}
279
280func (s *toStringExpr) emitListVarCopy(gctx *generationContext) {
281 s.emit(gctx)
282}
283
Cole Faustb0d32ab2021-12-09 14:00:59 -0800284func (s *toStringExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
285 s.expr = s.expr.transform(transformer)
286 if replacement := transformer(s); replacement != nil {
287 return replacement
288 } else {
289 return s
290 }
291}
292
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800293type notExpr struct {
294 expr starlarkExpr
295}
296
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800297func (n *notExpr) emit(ctx *generationContext) {
298 ctx.write("not ")
299 n.expr.emit(ctx)
300}
301
302func (_ *notExpr) typ() starlarkType {
303 return starlarkTypeBool
304}
305
306func (n *notExpr) emitListVarCopy(gctx *generationContext) {
307 n.emit(gctx)
308}
309
Cole Faustb0d32ab2021-12-09 14:00:59 -0800310func (n *notExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
311 n.expr = n.expr.transform(transformer)
312 if replacement := transformer(n); replacement != nil {
313 return replacement
314 } else {
315 return n
316 }
317}
318
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800319type eqExpr struct {
320 left, right starlarkExpr
321 isEq bool // if false, it's !=
322}
323
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800324func (eq *eqExpr) emit(gctx *generationContext) {
Cole Faustf1f44d32021-11-16 14:52:12 -0800325 var stringOperand string
326 var otherOperand starlarkExpr
327 if s, ok := maybeString(eq.left); ok {
328 stringOperand = s
329 otherOperand = eq.right
330 } else if s, ok := maybeString(eq.right); ok {
331 stringOperand = s
332 otherOperand = eq.left
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800333 }
334
Cole Faustf1f44d32021-11-16 14:52:12 -0800335 // If we've identified one of the operands as being a string literal, check
336 // for some special cases we can do to simplify the resulting expression.
337 if otherOperand != nil {
338 if stringOperand == "" {
339 if eq.isEq {
340 gctx.write("not ")
341 }
342 otherOperand.emit(gctx)
343 return
344 }
345 if stringOperand == "true" && otherOperand.typ() == starlarkTypeBool {
346 if !eq.isEq {
347 gctx.write("not ")
348 }
349 otherOperand.emit(gctx)
350 return
351 }
Sasha Smundak0554d762021-07-08 18:26:12 -0700352 }
Cole Faustf8320212021-11-10 15:05:07 -0800353
354 if eq.left.typ() != eq.right.typ() {
355 eq.left = &toStringExpr{expr: eq.left}
356 eq.right = &toStringExpr{expr: eq.right}
357 }
358
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800359 // General case
360 eq.left.emit(gctx)
361 if eq.isEq {
362 gctx.write(" == ")
363 } else {
364 gctx.write(" != ")
365 }
366 eq.right.emit(gctx)
367}
368
369func (_ *eqExpr) typ() starlarkType {
370 return starlarkTypeBool
371}
372
373func (eq *eqExpr) emitListVarCopy(gctx *generationContext) {
374 eq.emit(gctx)
375}
376
Cole Faustb0d32ab2021-12-09 14:00:59 -0800377func (eq *eqExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
378 eq.left = eq.left.transform(transformer)
379 eq.right = eq.right.transform(transformer)
380 if replacement := transformer(eq); replacement != nil {
381 return replacement
382 } else {
383 return eq
384 }
385}
386
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800387// variableDefinedExpr corresponds to Make's ifdef VAR
388type variableDefinedExpr struct {
389 v variable
390}
391
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800392func (v *variableDefinedExpr) emit(gctx *generationContext) {
393 if v.v != nil {
394 v.v.emitDefined(gctx)
395 return
396 }
397 gctx.writef("%s(%q)", cfnWarning, "TODO(VAR)")
398}
399
400func (_ *variableDefinedExpr) typ() starlarkType {
401 return starlarkTypeBool
402}
403
404func (v *variableDefinedExpr) emitListVarCopy(gctx *generationContext) {
405 v.emit(gctx)
406}
407
Cole Faustb0d32ab2021-12-09 14:00:59 -0800408func (v *variableDefinedExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
409 // TODO: VariableDefinedExpr isn't really an expression?
410 return v
411}
412
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800413type listExpr struct {
414 items []starlarkExpr
415}
416
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800417func (l *listExpr) emit(gctx *generationContext) {
418 if !gctx.inAssignment || len(l.items) < 2 {
419 gctx.write("[")
420 sep := ""
421 for _, item := range l.items {
422 gctx.write(sep)
423 item.emit(gctx)
424 sep = ", "
425 }
426 gctx.write("]")
427 return
428 }
429
430 gctx.write("[")
431 gctx.indentLevel += 2
432
433 for _, item := range l.items {
434 gctx.newLine()
435 item.emit(gctx)
436 gctx.write(",")
437 }
438 gctx.indentLevel -= 2
439 gctx.newLine()
440 gctx.write("]")
441}
442
443func (_ *listExpr) typ() starlarkType {
444 return starlarkTypeList
445}
446
447func (l *listExpr) emitListVarCopy(gctx *generationContext) {
448 l.emit(gctx)
449}
450
Cole Faustb0d32ab2021-12-09 14:00:59 -0800451func (l *listExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
452 itemsCopy := make([]starlarkExpr, len(l.items))
453 for i, item := range l.items {
454 itemsCopy[i] = item.transform(transformer)
455 }
456 l.items = itemsCopy
457 if replacement := transformer(l); replacement != nil {
458 return replacement
459 } else {
460 return l
461 }
462}
463
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800464func newStringListExpr(items []string) *listExpr {
465 v := listExpr{}
466 for _, item := range items {
467 v.items = append(v.items, &stringLiteralExpr{item})
468 }
469 return &v
470}
471
Sasha Smundak422b6142021-11-11 18:31:59 -0800472// concatExpr generates expr1 + expr2 + ... + exprN in Starlark.
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800473type concatExpr struct {
474 items []starlarkExpr
475}
476
477func (c *concatExpr) emit(gctx *generationContext) {
478 if len(c.items) == 1 {
479 c.items[0].emit(gctx)
480 return
481 }
482
483 if !gctx.inAssignment {
484 c.items[0].emit(gctx)
485 for _, item := range c.items[1:] {
486 gctx.write(" + ")
487 item.emit(gctx)
488 }
489 return
490 }
491 gctx.write("(")
492 c.items[0].emit(gctx)
493 gctx.indentLevel += 2
494 for _, item := range c.items[1:] {
495 gctx.write(" +")
496 gctx.newLine()
497 item.emit(gctx)
498 }
499 gctx.write(")")
500 gctx.indentLevel -= 2
501}
502
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800503func (_ *concatExpr) typ() starlarkType {
504 return starlarkTypeList
505}
506
507func (c *concatExpr) emitListVarCopy(gctx *generationContext) {
508 c.emit(gctx)
509}
510
Cole Faustb0d32ab2021-12-09 14:00:59 -0800511func (c *concatExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
512 itemsCopy := make([]starlarkExpr, len(c.items))
513 for i, item := range c.items {
514 itemsCopy[i] = item.transform(transformer)
515 }
516 c.items = itemsCopy
517 if replacement := transformer(c); replacement != nil {
518 return replacement
519 } else {
520 return c
521 }
522}
523
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800524// inExpr generates <expr> [not] in <list>
525type inExpr struct {
526 expr starlarkExpr
527 list starlarkExpr
528 isNot bool
529}
530
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800531func (i *inExpr) emit(gctx *generationContext) {
532 i.expr.emit(gctx)
533 if i.isNot {
534 gctx.write(" not in ")
535 } else {
536 gctx.write(" in ")
537 }
538 i.list.emit(gctx)
539}
540
541func (_ *inExpr) typ() starlarkType {
542 return starlarkTypeBool
543}
544
545func (i *inExpr) emitListVarCopy(gctx *generationContext) {
546 i.emit(gctx)
547}
548
Cole Faustb0d32ab2021-12-09 14:00:59 -0800549func (i *inExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
550 i.expr = i.expr.transform(transformer)
551 i.list = i.list.transform(transformer)
552 if replacement := transformer(i); replacement != nil {
553 return replacement
554 } else {
555 return i
556 }
557}
558
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800559type indexExpr struct {
560 array starlarkExpr
561 index starlarkExpr
562}
563
Cole Faustb0d32ab2021-12-09 14:00:59 -0800564func (ix *indexExpr) emit(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800565 ix.array.emit(gctx)
566 gctx.write("[")
567 ix.index.emit(gctx)
568 gctx.write("]")
569}
570
Cole Faustb0d32ab2021-12-09 14:00:59 -0800571func (ix *indexExpr) typ() starlarkType {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800572 return starlarkTypeString
573}
574
Cole Faustb0d32ab2021-12-09 14:00:59 -0800575func (ix *indexExpr) emitListVarCopy(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800576 ix.emit(gctx)
577}
578
Cole Faustb0d32ab2021-12-09 14:00:59 -0800579func (ix *indexExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
580 ix.array = ix.array.transform(transformer)
581 ix.index = ix.index.transform(transformer)
582 if replacement := transformer(ix); replacement != nil {
583 return replacement
584 } else {
585 return ix
586 }
587}
588
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800589type callExpr struct {
590 object starlarkExpr // nil if static call
591 name string
592 args []starlarkExpr
593 returnType starlarkType
594}
595
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800596func (cx *callExpr) emit(gctx *generationContext) {
Sasha Smundak3deb9682021-07-26 18:42:25 -0700597 sep := ""
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800598 if cx.object != nil {
599 gctx.write("(")
600 cx.object.emit(gctx)
601 gctx.write(")")
602 gctx.write(".", cx.name, "(")
603 } else {
604 kf, found := knownFunctions[cx.name]
605 if !found {
606 panic(fmt.Errorf("callExpr with unknown function %q", cx.name))
607 }
608 if kf.runtimeName[0] == '!' {
609 panic(fmt.Errorf("callExpr for %q should not be there", cx.name))
610 }
611 gctx.write(kf.runtimeName, "(")
Sasha Smundak3deb9682021-07-26 18:42:25 -0700612 if kf.hiddenArg == hiddenArgGlobal {
613 gctx.write("g")
614 sep = ", "
615 } else if kf.hiddenArg == hiddenArgConfig {
616 gctx.write("cfg")
617 sep = ", "
618 }
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800619 }
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800620 for _, arg := range cx.args {
621 gctx.write(sep)
622 arg.emit(gctx)
623 sep = ", "
624 }
625 gctx.write(")")
626}
627
628func (cx *callExpr) typ() starlarkType {
629 return cx.returnType
630}
631
632func (cx *callExpr) emitListVarCopy(gctx *generationContext) {
633 cx.emit(gctx)
634}
635
Cole Faustb0d32ab2021-12-09 14:00:59 -0800636func (cx *callExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
637 if cx.object != nil {
638 cx.object = cx.object.transform(transformer)
639 }
640 argsCopy := make([]starlarkExpr, len(cx.args))
641 for i, arg := range cx.args {
642 argsCopy[i] = arg.transform(transformer)
643 }
644 if replacement := transformer(cx); replacement != nil {
645 return replacement
646 } else {
647 return cx
648 }
649}
650
Cole Faust4eadba72021-12-07 11:54:52 -0800651type ifExpr struct {
652 condition starlarkExpr
653 ifTrue starlarkExpr
654 ifFalse starlarkExpr
655}
656
Cole Faust4eadba72021-12-07 11:54:52 -0800657func (i *ifExpr) emit(gctx *generationContext) {
658 gctx.write("(")
659 i.ifTrue.emit(gctx)
660 gctx.write(" if ")
661 i.condition.emit(gctx)
662 gctx.write(" else ")
663 i.ifFalse.emit(gctx)
664 gctx.write(")")
665}
666
667func (i *ifExpr) typ() starlarkType {
668 tType := i.ifTrue.typ()
669 fType := i.ifFalse.typ()
670 if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
671 panic("Conflicting types in if expression")
672 }
673 if tType != starlarkTypeUnknown {
674 return tType
675 } else {
676 return fType
677 }
678}
679
680func (i *ifExpr) emitListVarCopy(gctx *generationContext) {
681 i.emit(gctx)
682}
683
Cole Faustb0d32ab2021-12-09 14:00:59 -0800684func (i *ifExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
685 i.condition = i.condition.transform(transformer)
686 i.ifTrue = i.ifTrue.transform(transformer)
687 i.ifFalse = i.ifFalse.transform(transformer)
688 if replacement := transformer(i); replacement != nil {
689 return replacement
690 } else {
691 return i
692 }
693}
694
695type identifierExpr struct {
696 name string
697}
698
Cole Faustb0d32ab2021-12-09 14:00:59 -0800699func (i *identifierExpr) emit(gctx *generationContext) {
700 gctx.write(i.name)
701}
702
703func (i *identifierExpr) typ() starlarkType {
704 return starlarkTypeUnknown
705}
706
707func (i *identifierExpr) emitListVarCopy(gctx *generationContext) {
708 i.emit(gctx)
709}
710
711func (i *identifierExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
712 if replacement := transformer(i); replacement != nil {
713 return replacement
714 } else {
715 return i
716 }
717}
718
719type foreachExpr struct {
720 varName string
721 list starlarkExpr
722 action starlarkExpr
723}
724
Cole Faustb0d32ab2021-12-09 14:00:59 -0800725func (f *foreachExpr) emit(gctx *generationContext) {
726 gctx.write("[")
727 f.action.emit(gctx)
728 gctx.write(" for " + f.varName + " in ")
729 f.list.emit(gctx)
730 gctx.write("]")
731}
732
733func (f *foreachExpr) typ() starlarkType {
734 return starlarkTypeList
735}
736
737func (f *foreachExpr) emitListVarCopy(gctx *generationContext) {
738 f.emit(gctx)
739}
740
741func (f *foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
742 f.list = f.list.transform(transformer)
743 f.action = f.action.transform(transformer)
744 if replacement := transformer(f); replacement != nil {
745 return replacement
746 } else {
747 return f
748 }
749}
750
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800751type badExpr struct {
Sasha Smundak422b6142021-11-11 18:31:59 -0800752 errorLocation ErrorLocation
753 message string
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800754}
755
Sasha Smundak422b6142021-11-11 18:31:59 -0800756func (b *badExpr) emit(gctx *generationContext) {
757 gctx.emitConversionError(b.errorLocation, b.message)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800758}
759
760func (_ *badExpr) typ() starlarkType {
761 return starlarkTypeUnknown
762}
763
Sasha Smundak422b6142021-11-11 18:31:59 -0800764func (_ *badExpr) emitListVarCopy(_ *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800765 panic("implement me")
766}
767
Cole Faustb0d32ab2021-12-09 14:00:59 -0800768func (b *badExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
769 if replacement := transformer(b); replacement != nil {
770 return replacement
771 } else {
772 return b
773 }
774}
775
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800776func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
777 if xString, ok := expr.(*stringLiteralExpr); ok {
778 return newStringListExpr(strings.Fields(xString.literal))
779 }
780 return expr
781}
Sasha Smundak0554d762021-07-08 18:26:12 -0700782
783func isEmptyString(expr starlarkExpr) bool {
784 x, ok := expr.(*stringLiteralExpr)
785 return ok && x.literal == ""
786}