blob: 92665207dfeb5bf9fa7bd8c5746dd9338eb1d520 [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 {
Cole Faustf0632662022-04-07 13:59:24 -0700235 ref variable
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800236}
237
Cole Faustf0632662022-04-07 13:59:24 -0700238func NewVariableRefExpr(ref variable) starlarkExpr {
Cole Faustfc438682021-12-14 12:46:32 -0800239 if predefined, ok := ref.(*predefinedVariable); ok {
240 return predefined.value
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800241 }
Cole Faustf0632662022-04-07 13:59:24 -0700242 return &variableRefExpr{ref}
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800243}
244
245func (v *variableRefExpr) emit(gctx *generationContext) {
Cole Faustf0632662022-04-07 13:59:24 -0700246 v.ref.emitGet(gctx)
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800247}
248
249func (v *variableRefExpr) typ() starlarkType {
250 return v.ref.valueType()
251}
252
253func (v *variableRefExpr) emitListVarCopy(gctx *generationContext) {
254 v.emit(gctx)
255 if v.typ() == starlarkTypeList {
256 gctx.write("[:]") // this will copy the list
257 }
258}
259
Cole Faustb0d32ab2021-12-09 14:00:59 -0800260func (v *variableRefExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
261 if replacement := transformer(v); replacement != nil {
262 return replacement
263 } else {
264 return v
265 }
266}
267
Cole Faustf8320212021-11-10 15:05:07 -0800268type toStringExpr struct {
269 expr starlarkExpr
270}
271
Cole Faustf8320212021-11-10 15:05:07 -0800272func (s *toStringExpr) emit(ctx *generationContext) {
273 switch s.expr.typ() {
274 case starlarkTypeString, starlarkTypeUnknown:
275 // Assume unknown types are strings already.
276 s.expr.emit(ctx)
277 case starlarkTypeList:
278 ctx.write(`" ".join(`)
279 s.expr.emit(ctx)
280 ctx.write(")")
281 case starlarkTypeInt:
282 ctx.write(`("%d" % (`)
283 s.expr.emit(ctx)
284 ctx.write("))")
285 case starlarkTypeBool:
Cole Faustf1f44d32021-11-16 14:52:12 -0800286 ctx.write(`("true" if (`)
Cole Faustf8320212021-11-10 15:05:07 -0800287 s.expr.emit(ctx)
Cole Faustf1f44d32021-11-16 14:52:12 -0800288 ctx.write(`) else "")`)
Cole Faustf8320212021-11-10 15:05:07 -0800289 case starlarkTypeVoid:
290 ctx.write(`""`)
291 default:
292 panic("Unknown starlark type!")
293 }
294}
295
296func (s *toStringExpr) typ() starlarkType {
297 return starlarkTypeString
298}
299
300func (s *toStringExpr) emitListVarCopy(gctx *generationContext) {
301 s.emit(gctx)
302}
303
Cole Faustb0d32ab2021-12-09 14:00:59 -0800304func (s *toStringExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
305 s.expr = s.expr.transform(transformer)
306 if replacement := transformer(s); replacement != nil {
307 return replacement
308 } else {
309 return s
310 }
311}
312
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800313type notExpr struct {
314 expr starlarkExpr
315}
316
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800317func (n *notExpr) emit(ctx *generationContext) {
318 ctx.write("not ")
319 n.expr.emit(ctx)
320}
321
322func (_ *notExpr) typ() starlarkType {
323 return starlarkTypeBool
324}
325
326func (n *notExpr) emitListVarCopy(gctx *generationContext) {
327 n.emit(gctx)
328}
329
Cole Faustb0d32ab2021-12-09 14:00:59 -0800330func (n *notExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
331 n.expr = n.expr.transform(transformer)
332 if replacement := transformer(n); replacement != nil {
333 return replacement
334 } else {
335 return n
336 }
337}
338
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800339type eqExpr struct {
340 left, right starlarkExpr
341 isEq bool // if false, it's !=
342}
343
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800344func (eq *eqExpr) emit(gctx *generationContext) {
Cole Faustf8320212021-11-10 15:05:07 -0800345 if eq.left.typ() != eq.right.typ() {
346 eq.left = &toStringExpr{expr: eq.left}
347 eq.right = &toStringExpr{expr: eq.right}
348 }
349
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800350 // General case
351 eq.left.emit(gctx)
352 if eq.isEq {
353 gctx.write(" == ")
354 } else {
355 gctx.write(" != ")
356 }
357 eq.right.emit(gctx)
358}
359
360func (_ *eqExpr) typ() starlarkType {
361 return starlarkTypeBool
362}
363
364func (eq *eqExpr) emitListVarCopy(gctx *generationContext) {
365 eq.emit(gctx)
366}
367
Cole Faustb0d32ab2021-12-09 14:00:59 -0800368func (eq *eqExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
369 eq.left = eq.left.transform(transformer)
370 eq.right = eq.right.transform(transformer)
371 if replacement := transformer(eq); replacement != nil {
372 return replacement
373 } else {
374 return eq
375 }
376}
377
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800378type listExpr struct {
379 items []starlarkExpr
380}
381
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800382func (l *listExpr) emit(gctx *generationContext) {
383 if !gctx.inAssignment || len(l.items) < 2 {
384 gctx.write("[")
385 sep := ""
386 for _, item := range l.items {
387 gctx.write(sep)
388 item.emit(gctx)
389 sep = ", "
390 }
391 gctx.write("]")
392 return
393 }
394
395 gctx.write("[")
396 gctx.indentLevel += 2
397
398 for _, item := range l.items {
399 gctx.newLine()
400 item.emit(gctx)
401 gctx.write(",")
402 }
403 gctx.indentLevel -= 2
404 gctx.newLine()
405 gctx.write("]")
406}
407
408func (_ *listExpr) typ() starlarkType {
409 return starlarkTypeList
410}
411
412func (l *listExpr) emitListVarCopy(gctx *generationContext) {
413 l.emit(gctx)
414}
415
Cole Faustb0d32ab2021-12-09 14:00:59 -0800416func (l *listExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
417 itemsCopy := make([]starlarkExpr, len(l.items))
418 for i, item := range l.items {
419 itemsCopy[i] = item.transform(transformer)
420 }
421 l.items = itemsCopy
422 if replacement := transformer(l); replacement != nil {
423 return replacement
424 } else {
425 return l
426 }
427}
428
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800429func newStringListExpr(items []string) *listExpr {
430 v := listExpr{}
431 for _, item := range items {
432 v.items = append(v.items, &stringLiteralExpr{item})
433 }
434 return &v
435}
436
Sasha Smundak422b6142021-11-11 18:31:59 -0800437// concatExpr generates expr1 + expr2 + ... + exprN in Starlark.
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800438type concatExpr struct {
439 items []starlarkExpr
440}
441
442func (c *concatExpr) emit(gctx *generationContext) {
443 if len(c.items) == 1 {
444 c.items[0].emit(gctx)
445 return
446 }
447
448 if !gctx.inAssignment {
449 c.items[0].emit(gctx)
450 for _, item := range c.items[1:] {
451 gctx.write(" + ")
452 item.emit(gctx)
453 }
454 return
455 }
456 gctx.write("(")
457 c.items[0].emit(gctx)
458 gctx.indentLevel += 2
459 for _, item := range c.items[1:] {
460 gctx.write(" +")
461 gctx.newLine()
462 item.emit(gctx)
463 }
464 gctx.write(")")
465 gctx.indentLevel -= 2
466}
467
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800468func (_ *concatExpr) typ() starlarkType {
469 return starlarkTypeList
470}
471
472func (c *concatExpr) emitListVarCopy(gctx *generationContext) {
473 c.emit(gctx)
474}
475
Cole Faustb0d32ab2021-12-09 14:00:59 -0800476func (c *concatExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
477 itemsCopy := make([]starlarkExpr, len(c.items))
478 for i, item := range c.items {
479 itemsCopy[i] = item.transform(transformer)
480 }
481 c.items = itemsCopy
482 if replacement := transformer(c); replacement != nil {
483 return replacement
484 } else {
485 return c
486 }
487}
488
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800489// inExpr generates <expr> [not] in <list>
490type inExpr struct {
491 expr starlarkExpr
492 list starlarkExpr
493 isNot bool
494}
495
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800496func (i *inExpr) emit(gctx *generationContext) {
497 i.expr.emit(gctx)
498 if i.isNot {
499 gctx.write(" not in ")
500 } else {
501 gctx.write(" in ")
502 }
503 i.list.emit(gctx)
504}
505
506func (_ *inExpr) typ() starlarkType {
507 return starlarkTypeBool
508}
509
510func (i *inExpr) emitListVarCopy(gctx *generationContext) {
511 i.emit(gctx)
512}
513
Cole Faustb0d32ab2021-12-09 14:00:59 -0800514func (i *inExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
515 i.expr = i.expr.transform(transformer)
516 i.list = i.list.transform(transformer)
517 if replacement := transformer(i); replacement != nil {
518 return replacement
519 } else {
520 return i
521 }
522}
523
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800524type indexExpr struct {
525 array starlarkExpr
526 index starlarkExpr
527}
528
Cole Faustb0d32ab2021-12-09 14:00:59 -0800529func (ix *indexExpr) emit(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800530 ix.array.emit(gctx)
531 gctx.write("[")
532 ix.index.emit(gctx)
533 gctx.write("]")
534}
535
Cole Faustb0d32ab2021-12-09 14:00:59 -0800536func (ix *indexExpr) typ() starlarkType {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800537 return starlarkTypeString
538}
539
Cole Faustb0d32ab2021-12-09 14:00:59 -0800540func (ix *indexExpr) emitListVarCopy(gctx *generationContext) {
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800541 ix.emit(gctx)
542}
543
Cole Faustb0d32ab2021-12-09 14:00:59 -0800544func (ix *indexExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
545 ix.array = ix.array.transform(transformer)
546 ix.index = ix.index.transform(transformer)
547 if replacement := transformer(ix); replacement != nil {
548 return replacement
549 } else {
550 return ix
551 }
552}
553
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800554type callExpr struct {
555 object starlarkExpr // nil if static call
556 name string
557 args []starlarkExpr
558 returnType starlarkType
559}
560
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800561func (cx *callExpr) emit(gctx *generationContext) {
562 if cx.object != nil {
563 gctx.write("(")
564 cx.object.emit(gctx)
565 gctx.write(")")
566 gctx.write(".", cx.name, "(")
567 } else {
Cole Faust9ebf6e42021-12-13 14:08:34 -0800568 gctx.write(cx.name, "(")
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800569 }
Cole Faust9ebf6e42021-12-13 14:08:34 -0800570 sep := ""
Sasha Smundakb051c4e2020-11-05 20:45:07 -0800571 for _, arg := range cx.args {
572 gctx.write(sep)
573 arg.emit(gctx)
574 sep = ", "
575 }
576 gctx.write(")")
577}
578
579func (cx *callExpr) typ() starlarkType {
580 return cx.returnType
581}
582
583func (cx *callExpr) emitListVarCopy(gctx *generationContext) {
584 cx.emit(gctx)
585}
586
Cole Faustb0d32ab2021-12-09 14:00:59 -0800587func (cx *callExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
588 if cx.object != nil {
589 cx.object = cx.object.transform(transformer)
590 }
Cole Faustf035d402022-03-28 14:02:50 -0700591 for i := range cx.args {
592 cx.args[i] = cx.args[i].transform(transformer)
Cole Faustb0d32ab2021-12-09 14:00:59 -0800593 }
594 if replacement := transformer(cx); replacement != nil {
595 return replacement
596 } else {
597 return cx
598 }
599}
600
Cole Faust4eadba72021-12-07 11:54:52 -0800601type ifExpr struct {
602 condition starlarkExpr
603 ifTrue starlarkExpr
604 ifFalse starlarkExpr
605}
606
Cole Faust4eadba72021-12-07 11:54:52 -0800607func (i *ifExpr) emit(gctx *generationContext) {
608 gctx.write("(")
609 i.ifTrue.emit(gctx)
610 gctx.write(" if ")
611 i.condition.emit(gctx)
612 gctx.write(" else ")
613 i.ifFalse.emit(gctx)
614 gctx.write(")")
615}
616
617func (i *ifExpr) typ() starlarkType {
618 tType := i.ifTrue.typ()
619 fType := i.ifFalse.typ()
620 if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
621 panic("Conflicting types in if expression")
622 }
623 if tType != starlarkTypeUnknown {
624 return tType
625 } else {
626 return fType
627 }
628}
629
630func (i *ifExpr) emitListVarCopy(gctx *generationContext) {
631 i.emit(gctx)
632}
633
Cole Faustb0d32ab2021-12-09 14:00:59 -0800634func (i *ifExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
635 i.condition = i.condition.transform(transformer)
636 i.ifTrue = i.ifTrue.transform(transformer)
637 i.ifFalse = i.ifFalse.transform(transformer)
638 if replacement := transformer(i); replacement != nil {
639 return replacement
640 } else {
641 return i
642 }
643}
644
645type identifierExpr struct {
646 name string
647}
648
Cole Faustb0d32ab2021-12-09 14:00:59 -0800649func (i *identifierExpr) emit(gctx *generationContext) {
650 gctx.write(i.name)
651}
652
653func (i *identifierExpr) typ() starlarkType {
654 return starlarkTypeUnknown
655}
656
657func (i *identifierExpr) emitListVarCopy(gctx *generationContext) {
658 i.emit(gctx)
659}
660
661func (i *identifierExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
662 if replacement := transformer(i); replacement != nil {
663 return replacement
664 } else {
665 return i
666 }
667}
668
669type foreachExpr struct {
670 varName string
671 list starlarkExpr
672 action starlarkExpr
673}
674
Cole Faustb0d32ab2021-12-09 14:00:59 -0800675func (f *foreachExpr) emit(gctx *generationContext) {
676 gctx.write("[")
677 f.action.emit(gctx)
678 gctx.write(" for " + f.varName + " in ")
679 f.list.emit(gctx)
680 gctx.write("]")
681}
682
683func (f *foreachExpr) typ() starlarkType {
684 return starlarkTypeList
685}
686
687func (f *foreachExpr) emitListVarCopy(gctx *generationContext) {
688 f.emit(gctx)
689}
690
691func (f *foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
692 f.list = f.list.transform(transformer)
693 f.action = f.action.transform(transformer)
694 if replacement := transformer(f); replacement != nil {
695 return replacement
696 } else {
697 return f
698 }
699}
700
Cole Faustb1103e22022-01-06 15:22:05 -0800701type binaryOpExpr struct {
702 left, right starlarkExpr
703 op string
704 returnType starlarkType
705}
706
707func (b *binaryOpExpr) emit(gctx *generationContext) {
708 b.left.emit(gctx)
709 gctx.write(" " + b.op + " ")
710 b.right.emit(gctx)
711}
712
713func (b *binaryOpExpr) typ() starlarkType {
714 return b.returnType
715}
716
717func (b *binaryOpExpr) emitListVarCopy(gctx *generationContext) {
718 b.emit(gctx)
719}
720
721func (b *binaryOpExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
722 b.left = b.left.transform(transformer)
723 b.right = b.right.transform(transformer)
724 if replacement := transformer(b); replacement != nil {
725 return replacement
726 } else {
727 return b
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}
Cole Faustf035d402022-03-28 14:02:50 -0700767
768func negateExpr(expr starlarkExpr) starlarkExpr {
769 switch typedExpr := expr.(type) {
770 case *notExpr:
771 return typedExpr.expr
772 case *inExpr:
773 typedExpr.isNot = !typedExpr.isNot
774 return typedExpr
775 case *eqExpr:
776 typedExpr.isEq = !typedExpr.isEq
777 return typedExpr
778 case *binaryOpExpr:
779 switch typedExpr.op {
780 case ">":
781 typedExpr.op = "<="
782 return typedExpr
783 case "<":
784 typedExpr.op = ">="
785 return typedExpr
786 case ">=":
787 typedExpr.op = "<"
788 return typedExpr
789 case "<=":
790 typedExpr.op = ">"
791 return typedExpr
792 default:
793 return &notExpr{expr: expr}
794 }
795 default:
796 return &notExpr{expr: expr}
797 }
798}