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

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

Convert math functions

Converts the following functions from build/make/common/math.mk:
 - math_max
 - math_min
 - math_gt_or_eq
 - math_gt
 - math_lt

Fixes: 213497955
Test: go test
Change-Id: I8c4e8fee321f03b813428fa10038fa8f06188cef
parent fe306aba
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -728,6 +728,36 @@ func (f *foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr
	}
}

type binaryOpExpr struct {
	left, right starlarkExpr
	op          string
	returnType  starlarkType
}

func (b *binaryOpExpr) emit(gctx *generationContext) {
	b.left.emit(gctx)
	gctx.write(" " + b.op + " ")
	b.right.emit(gctx)
}

func (b *binaryOpExpr) typ() starlarkType {
	return b.returnType
}

func (b *binaryOpExpr) emitListVarCopy(gctx *generationContext) {
	b.emit(gctx)
}

func (b *binaryOpExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
	b.left = b.left.transform(transformer)
	b.right = b.right.transform(transformer)
	if replacement := transformer(b); replacement != nil {
		return replacement
	} else {
		return b
	}
}

type badExpr struct {
	errorLocation ErrorLocation
	message       string
+91 −0
Original line number Diff line number Diff line
@@ -100,6 +100,11 @@ var knownFunctions = map[string]interface {
	"is-vendor-board-qcom":                &isVendorBoardQcomCallParser{},
	"lastword":                            &firstOrLastwordCallParser{isLastWord: true},
	"notdir":                              &simpleCallParser{name: baseName + ".notdir", returnType: starlarkTypeString, addGlobals: false},
	"math_max":                            &mathMaxOrMinCallParser{function: "max"},
	"math_min":                            &mathMaxOrMinCallParser{function: "min"},
	"math_gt_or_eq":                       &mathComparisonCallParser{op: ">="},
	"math_gt":                             &mathComparisonCallParser{op: ">"},
	"math_lt":                             &mathComparisonCallParser{op: "<"},
	"my-dir":                              &myDirCallParser{},
	"patsubst":                            &substCallParser{fname: "patsubst"},
	"product-copy-files-by-pattern":       &simpleCallParser{name: baseName + ".product_copy_files_by_pattern", returnType: starlarkTypeList, addGlobals: false},
@@ -1064,6 +1069,23 @@ func (ctx *parseContext) parseCompare(cond *mkparser.Directive) starlarkExpr {
		case *eqExpr:
			typedExpr.isEq = !typedExpr.isEq
			return typedExpr
		case *binaryOpExpr:
			switch typedExpr.op {
			case ">":
				typedExpr.op = "<="
				return typedExpr
			case "<":
				typedExpr.op = ">="
				return typedExpr
			case ">=":
				typedExpr.op = "<"
				return typedExpr
			case "<=":
				typedExpr.op = ">"
				return typedExpr
			default:
				return &notExpr{expr: expr}
			}
		default:
			return &notExpr{expr: expr}
		}
@@ -1086,6 +1108,13 @@ func (ctx *parseContext) parseCompare(cond *mkparser.Directive) starlarkExpr {
				return otherOperand
			}
		}
		if intOperand, err := strconv.Atoi(strings.TrimSpace(stringOperand)); err == nil && otherOperand.typ() == starlarkTypeInt {
			return &eqExpr{
				left:  otherOperand,
				right: &intLiteralExpr{literal: intOperand},
				isEq:  isEq,
			}
		}
	}

	return &eqExpr{left: xLeft, right: xRight, isEq: isEq}
@@ -1621,6 +1650,68 @@ func (p *firstOrLastwordCallParser) parse(ctx *parseContext, node mkparser.Node,
	return &indexExpr{&callExpr{object: arg, name: "split", returnType: starlarkTypeList}, index}
}

func parseIntegerArguments(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString, expectedArgs int) ([]starlarkExpr, error) {
	parsedArgs := make([]starlarkExpr, 0)
	for _, arg := range args.Split(",") {
		expr := ctx.parseMakeString(node, arg)
		if expr.typ() == starlarkTypeList {
			return nil, fmt.Errorf("argument to math argument has type list, which cannot be converted to int")
		}
		if s, ok := maybeString(expr); ok {
			intVal, err := strconv.Atoi(strings.TrimSpace(s))
			if err != nil {
				return nil, err
			}
			expr = &intLiteralExpr{literal: intVal}
		} else if expr.typ() != starlarkTypeInt {
			expr = &callExpr{
				name:       "int",
				args:       []starlarkExpr{expr},
				returnType: starlarkTypeInt,
			}
		}
		parsedArgs = append(parsedArgs, expr)
	}
	if len(parsedArgs) != expectedArgs {
		return nil, fmt.Errorf("function should have %d arguments", expectedArgs)
	}
	return parsedArgs, nil
}

type mathComparisonCallParser struct {
	op string
}

func (p *mathComparisonCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
	parsedArgs, err := parseIntegerArguments(ctx, node, args, 2)
	if err != nil {
		return ctx.newBadExpr(node, err.Error())
	}
	return &binaryOpExpr{
		left:       parsedArgs[0],
		right:      parsedArgs[1],
		op:         p.op,
		returnType: starlarkTypeBool,
	}
}

type mathMaxOrMinCallParser struct {
	function string
}

func (p *mathMaxOrMinCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
	parsedArgs, err := parseIntegerArguments(ctx, node, args, 2)
	if err != nil {
		return ctx.newBadExpr(node, err.Error())
	}
	return &callExpr{
		object:     nil,
		name:       p.function,
		args:       parsedArgs,
		returnType: starlarkTypeInt,
	}
}

func (ctx *parseContext) parseMakeString(node mkparser.Node, mk *mkparser.MakeString) starlarkExpr {
	if mk.Const() {
		return &stringLiteralExpr{mk.Dump()}
+57 −0
Original line number Diff line number Diff line
@@ -1239,6 +1239,63 @@ def init(g, handle):
  g["NATIVE_BRIDGE_PRODUCT_PACKAGES"] = "libnative_bridge_vdso.native_bridge      native_bridge_guest_app_process.native_bridge      native_bridge_guest_linker.native_bridge"
  g["NATIVE_BRIDGE_MODIFIED_GUEST_LIBS"] = "libaaudio      libamidi      libandroid      libandroid_runtime"
  g["NATIVE_BRIDGE_PRODUCT_PACKAGES"] += " " + " ".join(rblf.addsuffix(".native_bridge", g.get("NATIVE_BRIDGE_ORIG_GUEST_LIBS", "")))
`,
	},
	{
		desc:   "Math functions",
		mkname: "product.mk",
		in: `
# Test the math functions defined in build/make/common/math.mk
ifeq ($(call math_max,2,5),5)
endif
ifeq ($(call math_min,2,5),2)
endif
ifeq ($(call math_gt_or_eq,2,5),true)
endif
ifeq ($(call math_gt,2,5),true)
endif
ifeq ($(call math_lt,2,5),true)
endif
ifeq ($(call math_gt_or_eq,2,5),)
endif
ifeq ($(call math_gt,2,5),)
endif
ifeq ($(call math_lt,2,5),)
endif
ifeq ($(call math_gt_or_eq,$(MY_VAR), 5),true)
endif
ifeq ($(call math_gt_or_eq,$(MY_VAR),$(MY_OTHER_VAR)),true)
endif
ifeq ($(call math_gt_or_eq,100$(MY_VAR),10),true)
endif
`,
		expected: `# Test the math functions defined in build/make/common/math.mk
load("//build/make/core:product_config.rbc", "rblf")

def init(g, handle):
  cfg = rblf.cfg(handle)
  if max(2, 5) == 5:
    pass
  if min(2, 5) == 2:
    pass
  if 2 >= 5:
    pass
  if 2 > 5:
    pass
  if 2 < 5:
    pass
  if 2 < 5:
    pass
  if 2 <= 5:
    pass
  if 2 >= 5:
    pass
  if int(g.get("MY_VAR", "")) >= 5:
    pass
  if int(g.get("MY_VAR", "")) >= int(g.get("MY_OTHER_VAR", "")):
    pass
  if int("100%s" % g.get("MY_VAR", "")) >= 10:
    pass
`,
	},
}