Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2daabfa authored by Cole Faust's avatar Cole Faust
Browse files

Add support for and/or in mk2rbc

Bug: 262303006
Test: go test
Change-Id: I04130648084775c0828e95cd18a82e348c3f09eb
parent 18ac53b4
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -77,6 +77,7 @@ var knownFunctions = map[string]interface {
	"add-to-product-copy-files-if-exists":  &simpleCallParser{name: baseName + ".copy_if_exists", returnType: starlarkTypeList},
	"addprefix":                            &simpleCallParser{name: baseName + ".addprefix", returnType: starlarkTypeList},
	"addsuffix":                            &simpleCallParser{name: baseName + ".addsuffix", returnType: starlarkTypeList},
	"and":                                  &andOrParser{isAnd: true},
	"copy-files":                           &simpleCallParser{name: baseName + ".copy_files", returnType: starlarkTypeList},
	"dir":                                  &simpleCallParser{name: baseName + ".dir", returnType: starlarkTypeString},
	"dist-for-goals":                       &simpleCallParser{name: baseName + ".mkdist_for_goals", returnType: starlarkTypeVoid, addGlobals: true},
@@ -105,6 +106,7 @@ var knownFunctions = map[string]interface {
	"math_gt":                              &mathComparisonCallParser{op: ">"},
	"math_lt":                              &mathComparisonCallParser{op: "<"},
	"my-dir":                               &myDirCallParser{},
	"or":                                   &andOrParser{isAnd: false},
	"patsubst":                             &substCallParser{fname: "patsubst"},
	"product-copy-files-by-pattern":        &simpleCallParser{name: baseName + ".product_copy_files_by_pattern", returnType: starlarkTypeList},
	"require-artifacts-in-path":            &simpleCallParser{name: baseName + ".require_artifacts_in_path", returnType: starlarkTypeVoid, addHandle: true},
@@ -1430,6 +1432,51 @@ func (p *myDirCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkp
	return &stringLiteralExpr{literal: filepath.Dir(ctx.script.mkFile)}
}

type andOrParser struct {
	isAnd bool
}

func (p *andOrParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
	if args.Empty() {
		return ctx.newBadExpr(node, "and/or function must have at least 1 argument")
	}
	op := "or"
	if p.isAnd {
		op = "and"
	}

	argsParsed := make([]starlarkExpr, 0)

	for _, arg := range args.Split(",") {
		arg.TrimLeftSpaces()
		arg.TrimRightSpaces()
		x := ctx.parseMakeString(node, arg)
		if xBad, ok := x.(*badExpr); ok {
			return xBad
		}
		argsParsed = append(argsParsed, x)
	}
	typ := starlarkTypeUnknown
	for _, arg := range argsParsed {
		if typ != arg.typ() && arg.typ() != starlarkTypeUnknown && typ != starlarkTypeUnknown {
			return ctx.newBadExpr(node, "Expected all arguments to $(or) or $(and) to have the same type, found %q and %q", typ.String(), arg.typ().String())
		}
		if arg.typ() != starlarkTypeUnknown {
			typ = arg.typ()
		}
	}
	result := argsParsed[0]
	for _, arg := range argsParsed[1:] {
		result = &binaryOpExpr{
			left:       result,
			right:      arg,
			op:         op,
			returnType: typ,
		}
	}
	return result
}

type isProductInListCallParser struct{}

func (p *isProductInListCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
+32 −0
Original line number Diff line number Diff line
@@ -1627,6 +1627,38 @@ def init(g, handle):
  g["MY_VAR_3"] = (cfg).get(g["MY_VAR_2"], (g).get(g["MY_VAR_2"], ""))
  g["MY_VAR_4"] = rblf.mk2rbc_error("product.mk:5", "cannot handle invoking foo")
  g["MY_VAR_5"] = rblf.mk2rbc_error("product.mk:6", "reference is too complex: $(MY_VAR_2) bar")
`,
	},
	{
		desc:   "Conditional functions",
		mkname: "product.mk",
		in: `
B := foo
X := $(or $(A))
X := $(or $(A),$(B))
X := $(or $(A),$(B),$(C))
X := $(and $(A))
X := $(and $(A),$(B))
X := $(and $(A),$(B),$(C))
X := $(or $(A),$(B)) Y

D := $(wildcard *.mk)
X := $(or $(B),$(D))
`,
		expected: `load("//build/make/core:product_config.rbc", "rblf")

def init(g, handle):
  cfg = rblf.cfg(handle)
  g["B"] = "foo"
  g["X"] = g.get("A", "")
  g["X"] = g.get("A", "") or g["B"]
  g["X"] = g.get("A", "") or g["B"] or g.get("C", "")
  g["X"] = g.get("A", "")
  g["X"] = g.get("A", "") and g["B"]
  g["X"] = g.get("A", "") and g["B"] and g.get("C", "")
  g["X"] = "%s Y" % g.get("A", "") or g["B"]
  g["D"] = rblf.expand_wildcard("*.mk")
  g["X"] = rblf.mk2rbc_error("product.mk:12", "Expected all arguments to $(or) or $(and) to have the same type, found \"string\" and \"list\"")
`,
	},
}
+21 −0
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@

package mk2rbc

import "fmt"

// Starlark expression types we use
type starlarkType int

@@ -31,6 +33,25 @@ const (
	starlarkTypeVoid    starlarkType = iota
)

func (t starlarkType) String() string {
	switch t {
	case starlarkTypeList:
		return "list"
	case starlarkTypeString:
		return "string"
	case starlarkTypeInt:
		return "int"
	case starlarkTypeBool:
		return "bool"
	case starlarkTypeVoid:
		return "void"
	case starlarkTypeUnknown:
		return "unknown"
	default:
		panic(fmt.Sprintf("Unknown starlark type %d", t))
	}
}

type hiddenArgType int

const (