in rule/expr.go [221:298]
func extractPlatformStringsExprs(expr bzl.Expr) (platformStringsExprs, error) {
var ps platformStringsExprs
if expr == nil {
return ps, nil
}
// Break the expression into a sequence of expressions combined with +.
var parts []bzl.Expr
for {
binop, ok := expr.(*bzl.BinaryExpr)
if !ok {
parts = append(parts, expr)
break
}
parts = append(parts, binop.Y)
expr = binop.X
}
// Process each part. They may be in any order.
for _, part := range parts {
switch part := part.(type) {
case *bzl.ListExpr:
if ps.generic != nil {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: multiple list expressions")
}
ps.generic = part
case *bzl.CallExpr:
x, ok := part.X.(*bzl.Ident)
if !ok || x.Name != "select" || len(part.List) != 1 {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: callee other than select or wrong number of args")
}
arg, ok := part.List[0].(*bzl.DictExpr)
if !ok {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: select argument not dict")
}
var dict **bzl.DictExpr
for _, kv := range arg.List {
k, ok := kv.Key.(*bzl.StringExpr)
if !ok {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: dict keys are not all strings")
}
if k.Value == "//conditions:default" {
continue
}
key, err := label.Parse(k.Value)
if err != nil {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: dict key is not label: %q", k.Value)
}
if KnownOSSet[key.Name] {
dict = &ps.os
break
}
if KnownArchSet[key.Name] {
dict = &ps.arch
break
}
osArch := strings.Split(key.Name, "_")
if len(osArch) != 2 || !KnownOSSet[osArch[0]] || !KnownArchSet[osArch[1]] {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: dict key contains unknown platform: %q", k.Value)
}
dict = &ps.platform
break
}
if dict == nil {
// We could not identify the dict because it's empty or only contains
// //conditions:default. We'll call it the platform dict to avoid
// dropping it.
dict = &ps.platform
}
if *dict != nil {
return platformStringsExprs{}, fmt.Errorf("expression could not be matched: multiple selects that are either os-specific, arch-specific, or platform-specific")
}
*dict = arg
}
}
return ps, nil
}