Remove starlarkExpr.Eval()

It was only used to substitute variable references to
predefined variables with the predefined value, which
is an easy condition to directly parse into instead
of having a separate evalutation pass.

Bug: 201700692
Test: go test
Change-Id: I543d20a1d6435bfabd9faa90ffb09af3084ed28c
This commit is contained in:
Cole Faust
2021-12-14 12:46:32 -08:00
parent a6628d24c4
commit fc43868a5f
2 changed files with 54 additions and 239 deletions

View File

@@ -16,18 +16,13 @@ package mk2rbc
import (
"fmt"
"strconv"
"strings"
)
// Represents an expression in the Starlark code. An expression has
// a type, and it can be evaluated.
// Represents an expression in the Starlark code. An expression has a type.
type starlarkExpr interface {
starlarkNode
typ() starlarkType
// Try to substitute variable values. Return substitution result
// and whether it is the same as the original expression.
eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool)
// Emit the code to copy the expression, otherwise we will end up
// with source and target pointing to the same list.
emitListVarCopy(gctx *generationContext)
@@ -50,12 +45,6 @@ type stringLiteralExpr struct {
literal string
}
func (s *stringLiteralExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
res = s
same = true
return
}
func (s *stringLiteralExpr) emit(gctx *generationContext) {
gctx.writef("%q", s.literal)
}
@@ -81,12 +70,6 @@ type intLiteralExpr struct {
literal int
}
func (s *intLiteralExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
res = s
same = true
return
}
func (s *intLiteralExpr) emit(gctx *generationContext) {
gctx.writef("%d", s.literal)
}
@@ -112,10 +95,6 @@ type boolLiteralExpr struct {
literal bool
}
func (b *boolLiteralExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
return b, true
}
func (b *boolLiteralExpr) emit(gctx *generationContext) {
if b.literal {
gctx.write("True")
@@ -148,6 +127,35 @@ type interpolateExpr struct {
args []starlarkExpr
}
func NewInterpolateExpr(parts []starlarkExpr) starlarkExpr {
result := &interpolateExpr{}
needString := true
for _, part := range parts {
if needString {
if strLit, ok := part.(*stringLiteralExpr); ok {
result.chunks = append(result.chunks, strLit.literal)
} else {
result.chunks = append(result.chunks, "")
}
needString = false
} else {
if strLit, ok := part.(*stringLiteralExpr); ok {
result.chunks[len(result.chunks)-1] += strLit.literal
} else {
result.args = append(result.args, part)
needString = true
}
}
}
if len(result.chunks) == len(result.args) {
result.chunks = append(result.chunks, "")
}
if len(result.args) == 0 {
return &stringLiteralExpr{literal: strings.Join(result.chunks, "")}
}
return result
}
func (xi *interpolateExpr) emit(gctx *generationContext) {
if len(xi.chunks) != len(xi.args)+1 {
panic(fmt.Errorf("malformed interpolateExpr: #chunks(%d) != #args(%d)+1",
@@ -181,37 +189,6 @@ func (xi *interpolateExpr) emit(gctx *generationContext) {
}
}
func (xi *interpolateExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
same = true
newChunks := []string{xi.chunks[0]}
var newArgs []starlarkExpr
for i, arg := range xi.args {
newArg, sameArg := arg.eval(valueMap)
same = same && sameArg
switch x := newArg.(type) {
case *stringLiteralExpr:
newChunks[len(newChunks)-1] += x.literal + xi.chunks[i+1]
same = false
continue
case *intLiteralExpr:
newChunks[len(newChunks)-1] += strconv.Itoa(x.literal) + xi.chunks[i+1]
same = false
continue
default:
newChunks = append(newChunks, xi.chunks[i+1])
newArgs = append(newArgs, newArg)
}
}
if same {
res = xi
} else if len(newChunks) == 1 {
res = &stringLiteralExpr{newChunks[0]}
} else {
res = &interpolateExpr{chunks: newChunks, args: newArgs}
}
return
}
func (_ *interpolateExpr) typ() starlarkType {
return starlarkTypeString
}
@@ -238,14 +215,11 @@ type variableRefExpr struct {
isDefined bool
}
func (v *variableRefExpr) eval(map[string]starlarkExpr) (res starlarkExpr, same bool) {
predefined, ok := v.ref.(*predefinedVariable)
if same = !ok; same {
res = v
} else {
res = predefined.value
func NewVariableRefExpr(ref variable, isDefined bool) starlarkExpr {
if predefined, ok := ref.(*predefinedVariable); ok {
return predefined.value
}
return
return &variableRefExpr{ref, isDefined}
}
func (v *variableRefExpr) emit(gctx *generationContext) {
@@ -275,15 +249,6 @@ type toStringExpr struct {
expr starlarkExpr
}
func (s *toStringExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
if x, same := s.expr.eval(valueMap); same {
res = s
} else {
res = &toStringExpr{expr: x}
}
return
}
func (s *toStringExpr) emit(ctx *generationContext) {
switch s.expr.typ() {
case starlarkTypeString, starlarkTypeUnknown:
@@ -329,15 +294,6 @@ type notExpr struct {
expr starlarkExpr
}
func (n *notExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
if x, same := n.expr.eval(valueMap); same {
res = n
} else {
res = &notExpr{expr: x}
}
return
}
func (n *notExpr) emit(ctx *generationContext) {
ctx.write("not ")
n.expr.emit(ctx)
@@ -365,17 +321,6 @@ type eqExpr struct {
isEq bool // if false, it's !=
}
func (eq *eqExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
xLeft, sameLeft := eq.left.eval(valueMap)
xRight, sameRight := eq.right.eval(valueMap)
if same = sameLeft && sameRight; same {
res = eq
} else {
res = &eqExpr{left: xLeft, right: xRight, isEq: eq.isEq}
}
return
}
func (eq *eqExpr) emit(gctx *generationContext) {
var stringOperand string
var otherOperand starlarkExpr
@@ -444,13 +389,6 @@ type variableDefinedExpr struct {
v variable
}
func (v *variableDefinedExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
res = v
same = true
return
}
func (v *variableDefinedExpr) emit(gctx *generationContext) {
if v.v != nil {
v.v.emitDefined(gctx)
@@ -476,22 +414,6 @@ type listExpr struct {
items []starlarkExpr
}
func (l *listExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
newItems := make([]starlarkExpr, len(l.items))
same = true
for i, item := range l.items {
var sameItem bool
newItems[i], sameItem = item.eval(valueMap)
same = same && sameItem
}
if same {
res = l
} else {
res = &listExpr{newItems}
}
return
}
func (l *listExpr) emit(gctx *generationContext) {
if !gctx.inAssignment || len(l.items) < 2 {
gctx.write("[")
@@ -578,22 +500,6 @@ func (c *concatExpr) emit(gctx *generationContext) {
gctx.indentLevel -= 2
}
func (c *concatExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
same = true
xConcat := &concatExpr{items: make([]starlarkExpr, len(c.items))}
for i, item := range c.items {
var sameItem bool
xConcat.items[i], sameItem = item.eval(valueMap)
same = same && sameItem
}
if same {
res = c
} else {
res = xConcat
}
return
}
func (_ *concatExpr) typ() starlarkType {
return starlarkTypeList
}
@@ -622,19 +528,6 @@ type inExpr struct {
isNot bool
}
func (i *inExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
x := &inExpr{isNot: i.isNot}
var sameExpr, sameList bool
x.expr, sameExpr = i.expr.eval(valueMap)
x.list, sameList = i.list.eval(valueMap)
if same = sameExpr && sameList; same {
res = i
} else {
res = x
}
return
}
func (i *inExpr) emit(gctx *generationContext) {
i.expr.emit(gctx)
if i.isNot {
@@ -679,17 +572,6 @@ func (ix *indexExpr) typ() starlarkType {
return starlarkTypeString
}
func (ix *indexExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
newArray, isSameArray := ix.array.eval(valueMap)
newIndex, isSameIndex := ix.index.eval(valueMap)
if same = isSameArray && isSameIndex; same {
res = ix
} else {
res = &indexExpr{newArray, newIndex}
}
return
}
func (ix *indexExpr) emitListVarCopy(gctx *generationContext) {
ix.emit(gctx)
}
@@ -711,27 +593,6 @@ type callExpr struct {
returnType starlarkType
}
func (cx *callExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
newCallExpr := &callExpr{name: cx.name, args: make([]starlarkExpr, len(cx.args)),
returnType: cx.returnType}
if cx.object != nil {
newCallExpr.object, same = cx.object.eval(valueMap)
} else {
same = true
}
for i, args := range cx.args {
var s bool
newCallExpr.args[i], s = args.eval(valueMap)
same = same && s
}
if same {
res = cx
} else {
res = newCallExpr
}
return
}
func (cx *callExpr) emit(gctx *generationContext) {
sep := ""
if cx.object != nil {
@@ -793,22 +654,6 @@ type ifExpr struct {
ifFalse starlarkExpr
}
func (i *ifExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
cond, condSame := i.condition.eval(valueMap)
t, tSame := i.ifTrue.eval(valueMap)
f, fSame := i.ifFalse.eval(valueMap)
same = condSame && tSame && fSame
if same {
return i, same
} else {
return &ifExpr{
condition: cond,
ifTrue: t,
ifFalse: f,
}, same
}
}
func (i *ifExpr) emit(gctx *generationContext) {
gctx.write("(")
i.ifTrue.emit(gctx)
@@ -851,10 +696,6 @@ type identifierExpr struct {
name string
}
func (i *identifierExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
return i, true
}
func (i *identifierExpr) emit(gctx *generationContext) {
gctx.write(i.name)
}
@@ -881,21 +722,6 @@ type foreachExpr struct {
action starlarkExpr
}
func (f *foreachExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same bool) {
list, listSame := f.list.eval(valueMap)
action, actionSame := f.action.eval(valueMap)
same = listSame && actionSame
if same {
return f, same
} else {
return &foreachExpr{
varName: f.varName,
list: list,
action: action,
}, same
}
}
func (f *foreachExpr) emit(gctx *generationContext) {
gctx.write("[")
f.action.emit(gctx)
@@ -927,12 +753,6 @@ type badExpr struct {
message string
}
func (b *badExpr) eval(_ map[string]starlarkExpr) (res starlarkExpr, same bool) {
res = b
same = true
return
}
func (b *badExpr) emit(gctx *generationContext) {
gctx.emitConversionError(b.errorLocation, b.message)
}