Add support for and/or in mk2rbc
Bug: 262303006
Test: go test
Change-Id: I04130648084775c0828e95cd18a82e348c3f09eb
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index aa48e63..8b8629b 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -77,6 +77,7 @@
"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 @@
"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 @@
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 {
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 31555d3..7e14e25 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1629,6 +1629,38 @@
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\"")
+`,
+ },
}
var known_variables = []struct {
diff --git a/mk2rbc/types.go b/mk2rbc/types.go
index 46c6aa9..ac32507 100644
--- a/mk2rbc/types.go
+++ b/mk2rbc/types.go
@@ -14,6 +14,8 @@
package mk2rbc
+import "fmt"
+
// Starlark expression types we use
type starlarkType int
@@ -31,6 +33,25 @@
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 (