From 3311debbb3f37e0dc5246ad22b9a2d9cccc3f27a Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Wed, 10 Apr 2024 14:57:34 -0700 Subject: [PATCH] Support multi-variable selects and typed selects This adds support for selecting on multiple variables at once, so that you can do AND/OR combindations of them. For example: select(( arch(), os(), ), { ("arm64", "linux"): ["libfoo64"], (default, "linux"): ["libfoo"], (default, "windows"): ["libfoowindows"], (default, default): ["libbar"], }) It also allows for select conditions to be boolean-typed. You can write literal true and false without quotes to select on them. Currently we don't have any boolean-typed variables though, so a fake one was added for testing. Bug: 323382414 Test: m nothing --no-skip-soong-tests Change-Id: Ibe586e7b21865b8734027848cc421594cbd1d8cc --- parser/ast.go | 64 +++++---- parser/parser.go | 258 ++++++++++++++++++++++++--------- parser/parser_test.go | 11 ++ parser/printer.go | 101 ++++++++----- parser/printer_test.go | 46 +++--- proptools/configurable.go | 294 ++++++++++++++++++++++++++++++++------ proptools/extend_test.go | 150 +++++++++++++------ proptools/unpack.go | 119 +++++++++------ proptools/unpack_test.go | 123 ++++++++++++---- 9 files changed, 846 insertions(+), 320 deletions(-) diff --git a/parser/ast.go b/parser/ast.go index 68f15ed..7aea5e0 100644 --- a/parser/ast.go +++ b/parser/ast.go @@ -571,37 +571,46 @@ func endPos(pos scanner.Position, n int) scanner.Position { return pos } -type SelectType int +type ConfigurableCondition struct { + position scanner.Position + FunctionName string + Args []String +} -const ( - SelectTypeUnconfigured SelectType = iota // Used for selects with only one branch, which is "default" - SelectTypeReleaseVariable - SelectTypeSoongConfigVariable - SelectTypeProductVariable - SelectTypeVariant -) - -func (s SelectType) String() string { - switch s { - case SelectTypeUnconfigured: - return "unconfigured" - case SelectTypeReleaseVariable: - return "release variable" - case SelectTypeSoongConfigVariable: - return "soong config variable" - case SelectTypeProductVariable: - return "product variable" - case SelectTypeVariant: - return "variant" - default: - panic("unreachable") +func (c *ConfigurableCondition) Equals(other ConfigurableCondition) bool { + if c.FunctionName != other.FunctionName { + return false } + if len(c.Args) != len(other.Args) { + return false + } + for i := range c.Args { + if c.Args[i] != other.Args[i] { + return false + } + } + return true +} + +func (c *ConfigurableCondition) String() string { + var sb strings.Builder + sb.WriteString(c.FunctionName) + sb.WriteRune('(') + for i, arg := range c.Args { + sb.WriteRune('"') + sb.WriteString(arg.Value) + sb.WriteRune('"') + if i < len(c.Args)-1 { + sb.WriteString(", ") + } + } + sb.WriteRune(')') + return sb.String() } type Select struct { KeywordPos scanner.Position // the keyword "select" - Typ SelectType - Condition String + Conditions []ConfigurableCondition LBracePos scanner.Position RBracePos scanner.Position Cases []*SelectCase // the case statements @@ -640,8 +649,7 @@ func (s *Select) Type() Type { } type SelectCase struct { - // TODO: Support int and bool typed cases - Pattern String + Patterns []Expression ColonPos scanner.Position Value Expression } @@ -656,7 +664,7 @@ func (c *SelectCase) String() string { return "