1*333d2b36SAndroid Build Coastguard Worker// Copyright 2021 Google LLC 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage mk2rbc 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "strings" 20*333d2b36SAndroid Build Coastguard Worker) 21*333d2b36SAndroid Build Coastguard Worker 22*333d2b36SAndroid Build Coastguard Workertype variable interface { 23*333d2b36SAndroid Build Coastguard Worker name() string 24*333d2b36SAndroid Build Coastguard Worker emitGet(gctx *generationContext) 25*333d2b36SAndroid Build Coastguard Worker emitSet(gctx *generationContext, asgn *assignmentNode) 26*333d2b36SAndroid Build Coastguard Worker valueType() starlarkType 27*333d2b36SAndroid Build Coastguard Worker setValueType(t starlarkType) 28*333d2b36SAndroid Build Coastguard Worker defaultValueString() string 29*333d2b36SAndroid Build Coastguard Worker isPreset() bool 30*333d2b36SAndroid Build Coastguard Worker} 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workertype baseVariable struct { 33*333d2b36SAndroid Build Coastguard Worker nam string 34*333d2b36SAndroid Build Coastguard Worker typ starlarkType 35*333d2b36SAndroid Build Coastguard Worker preset bool // true if it has been initialized at startup 36*333d2b36SAndroid Build Coastguard Worker} 37*333d2b36SAndroid Build Coastguard Worker 38*333d2b36SAndroid Build Coastguard Workerfunc (v baseVariable) name() string { 39*333d2b36SAndroid Build Coastguard Worker return v.nam 40*333d2b36SAndroid Build Coastguard Worker} 41*333d2b36SAndroid Build Coastguard Worker 42*333d2b36SAndroid Build Coastguard Workerfunc (v baseVariable) valueType() starlarkType { 43*333d2b36SAndroid Build Coastguard Worker return v.typ 44*333d2b36SAndroid Build Coastguard Worker} 45*333d2b36SAndroid Build Coastguard Worker 46*333d2b36SAndroid Build Coastguard Workerfunc (v *baseVariable) setValueType(t starlarkType) { 47*333d2b36SAndroid Build Coastguard Worker v.typ = t 48*333d2b36SAndroid Build Coastguard Worker} 49*333d2b36SAndroid Build Coastguard Worker 50*333d2b36SAndroid Build Coastguard Workerfunc (v baseVariable) isPreset() bool { 51*333d2b36SAndroid Build Coastguard Worker return v.preset 52*333d2b36SAndroid Build Coastguard Worker} 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Workervar defaultValuesByType = map[starlarkType]string{ 55*333d2b36SAndroid Build Coastguard Worker starlarkTypeUnknown: `""`, 56*333d2b36SAndroid Build Coastguard Worker starlarkTypeList: "[]", 57*333d2b36SAndroid Build Coastguard Worker starlarkTypeString: `""`, 58*333d2b36SAndroid Build Coastguard Worker starlarkTypeInt: "0", 59*333d2b36SAndroid Build Coastguard Worker starlarkTypeBool: "False", 60*333d2b36SAndroid Build Coastguard Worker starlarkTypeVoid: "None", 61*333d2b36SAndroid Build Coastguard Worker} 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Workerfunc (v baseVariable) defaultValueString() string { 64*333d2b36SAndroid Build Coastguard Worker if v, ok := defaultValuesByType[v.valueType()]; ok { 65*333d2b36SAndroid Build Coastguard Worker return v 66*333d2b36SAndroid Build Coastguard Worker } 67*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("%s has unknown type %q", v.name(), v.valueType())) 68*333d2b36SAndroid Build Coastguard Worker} 69*333d2b36SAndroid Build Coastguard Worker 70*333d2b36SAndroid Build Coastguard Workertype productConfigVariable struct { 71*333d2b36SAndroid Build Coastguard Worker baseVariable 72*333d2b36SAndroid Build Coastguard Worker} 73*333d2b36SAndroid Build Coastguard Worker 74*333d2b36SAndroid Build Coastguard Workerfunc (pcv productConfigVariable) emitSet(gctx *generationContext, asgn *assignmentNode) { 75*333d2b36SAndroid Build Coastguard Worker emitAssignment := func() { 76*333d2b36SAndroid Build Coastguard Worker gctx.writef("cfg[%q] = ", pcv.nam) 77*333d2b36SAndroid Build Coastguard Worker asgn.value.emitListVarCopy(gctx) 78*333d2b36SAndroid Build Coastguard Worker } 79*333d2b36SAndroid Build Coastguard Worker emitAppend := func() { 80*333d2b36SAndroid Build Coastguard Worker gctx.writef("cfg[%q] += ", pcv.nam) 81*333d2b36SAndroid Build Coastguard Worker value := asgn.value 82*333d2b36SAndroid Build Coastguard Worker if pcv.valueType() == starlarkTypeString { 83*333d2b36SAndroid Build Coastguard Worker gctx.writef(`" " + `) 84*333d2b36SAndroid Build Coastguard Worker value = &toStringExpr{expr: value} 85*333d2b36SAndroid Build Coastguard Worker } 86*333d2b36SAndroid Build Coastguard Worker value.emit(gctx) 87*333d2b36SAndroid Build Coastguard Worker } 88*333d2b36SAndroid Build Coastguard Worker emitSetDefault := func() { 89*333d2b36SAndroid Build Coastguard Worker if pcv.typ == starlarkTypeList { 90*333d2b36SAndroid Build Coastguard Worker gctx.writef("%s(handle, %q)", cfnSetListDefault, pcv.name()) 91*333d2b36SAndroid Build Coastguard Worker } else { 92*333d2b36SAndroid Build Coastguard Worker gctx.writef("cfg.setdefault(%q, %s)", pcv.name(), pcv.defaultValueString()) 93*333d2b36SAndroid Build Coastguard Worker } 94*333d2b36SAndroid Build Coastguard Worker gctx.newLine() 95*333d2b36SAndroid Build Coastguard Worker } 96*333d2b36SAndroid Build Coastguard Worker 97*333d2b36SAndroid Build Coastguard Worker // If we are not sure variable has been assigned before, emit setdefault 98*333d2b36SAndroid Build Coastguard Worker needsSetDefault := !gctx.hasBeenAssigned(&pcv) && !pcv.isPreset() && asgn.isSelfReferential() 99*333d2b36SAndroid Build Coastguard Worker 100*333d2b36SAndroid Build Coastguard Worker switch asgn.flavor { 101*333d2b36SAndroid Build Coastguard Worker case asgnSet: 102*333d2b36SAndroid Build Coastguard Worker if needsSetDefault { 103*333d2b36SAndroid Build Coastguard Worker emitSetDefault() 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker emitAssignment() 106*333d2b36SAndroid Build Coastguard Worker case asgnAppend: 107*333d2b36SAndroid Build Coastguard Worker if needsSetDefault { 108*333d2b36SAndroid Build Coastguard Worker emitSetDefault() 109*333d2b36SAndroid Build Coastguard Worker } 110*333d2b36SAndroid Build Coastguard Worker emitAppend() 111*333d2b36SAndroid Build Coastguard Worker case asgnMaybeSet: 112*333d2b36SAndroid Build Coastguard Worker // In mk2rbc.go we never emit a maybeSet assignment for product config variables, because 113*333d2b36SAndroid Build Coastguard Worker // they are set to empty strings before running product config. 114*333d2b36SAndroid Build Coastguard Worker panic("Should never get here") 115*333d2b36SAndroid Build Coastguard Worker default: 116*333d2b36SAndroid Build Coastguard Worker panic("Unknown assignment flavor") 117*333d2b36SAndroid Build Coastguard Worker } 118*333d2b36SAndroid Build Coastguard Worker 119*333d2b36SAndroid Build Coastguard Worker gctx.setHasBeenAssigned(&pcv) 120*333d2b36SAndroid Build Coastguard Worker} 121*333d2b36SAndroid Build Coastguard Worker 122*333d2b36SAndroid Build Coastguard Workerfunc (pcv productConfigVariable) emitGet(gctx *generationContext) { 123*333d2b36SAndroid Build Coastguard Worker if gctx.hasBeenAssigned(&pcv) || pcv.isPreset() { 124*333d2b36SAndroid Build Coastguard Worker gctx.writef("cfg[%q]", pcv.nam) 125*333d2b36SAndroid Build Coastguard Worker } else { 126*333d2b36SAndroid Build Coastguard Worker gctx.writef("cfg.get(%q, %s)", pcv.nam, pcv.defaultValueString()) 127*333d2b36SAndroid Build Coastguard Worker } 128*333d2b36SAndroid Build Coastguard Worker} 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Workertype otherGlobalVariable struct { 131*333d2b36SAndroid Build Coastguard Worker baseVariable 132*333d2b36SAndroid Build Coastguard Worker} 133*333d2b36SAndroid Build Coastguard Worker 134*333d2b36SAndroid Build Coastguard Workerfunc (scv otherGlobalVariable) emitSet(gctx *generationContext, asgn *assignmentNode) { 135*333d2b36SAndroid Build Coastguard Worker emitAssignment := func() { 136*333d2b36SAndroid Build Coastguard Worker gctx.writef("g[%q] = ", scv.nam) 137*333d2b36SAndroid Build Coastguard Worker asgn.value.emitListVarCopy(gctx) 138*333d2b36SAndroid Build Coastguard Worker } 139*333d2b36SAndroid Build Coastguard Worker 140*333d2b36SAndroid Build Coastguard Worker emitAppend := func() { 141*333d2b36SAndroid Build Coastguard Worker gctx.writef("g[%q] += ", scv.nam) 142*333d2b36SAndroid Build Coastguard Worker value := asgn.value 143*333d2b36SAndroid Build Coastguard Worker if scv.valueType() == starlarkTypeString { 144*333d2b36SAndroid Build Coastguard Worker gctx.writef(`" " + `) 145*333d2b36SAndroid Build Coastguard Worker value = &toStringExpr{expr: value} 146*333d2b36SAndroid Build Coastguard Worker } 147*333d2b36SAndroid Build Coastguard Worker value.emit(gctx) 148*333d2b36SAndroid Build Coastguard Worker } 149*333d2b36SAndroid Build Coastguard Worker 150*333d2b36SAndroid Build Coastguard Worker // If we are not sure variable has been assigned before, emit setdefault 151*333d2b36SAndroid Build Coastguard Worker needsSetDefault := !gctx.hasBeenAssigned(&scv) && !scv.isPreset() && asgn.isSelfReferential() 152*333d2b36SAndroid Build Coastguard Worker 153*333d2b36SAndroid Build Coastguard Worker switch asgn.flavor { 154*333d2b36SAndroid Build Coastguard Worker case asgnSet: 155*333d2b36SAndroid Build Coastguard Worker if needsSetDefault { 156*333d2b36SAndroid Build Coastguard Worker gctx.writef("g.setdefault(%q, %s)", scv.name(), scv.defaultValueString()) 157*333d2b36SAndroid Build Coastguard Worker gctx.newLine() 158*333d2b36SAndroid Build Coastguard Worker } 159*333d2b36SAndroid Build Coastguard Worker emitAssignment() 160*333d2b36SAndroid Build Coastguard Worker case asgnAppend: 161*333d2b36SAndroid Build Coastguard Worker if needsSetDefault { 162*333d2b36SAndroid Build Coastguard Worker gctx.writef("g.setdefault(%q, %s)", scv.name(), scv.defaultValueString()) 163*333d2b36SAndroid Build Coastguard Worker gctx.newLine() 164*333d2b36SAndroid Build Coastguard Worker } 165*333d2b36SAndroid Build Coastguard Worker emitAppend() 166*333d2b36SAndroid Build Coastguard Worker case asgnMaybeSet: 167*333d2b36SAndroid Build Coastguard Worker gctx.writef("if g.get(%q) == None:", scv.nam) 168*333d2b36SAndroid Build Coastguard Worker gctx.indentLevel++ 169*333d2b36SAndroid Build Coastguard Worker gctx.newLine() 170*333d2b36SAndroid Build Coastguard Worker if needsSetDefault { 171*333d2b36SAndroid Build Coastguard Worker gctx.writef("g.setdefault(%q, %s)", scv.name(), scv.defaultValueString()) 172*333d2b36SAndroid Build Coastguard Worker gctx.newLine() 173*333d2b36SAndroid Build Coastguard Worker } 174*333d2b36SAndroid Build Coastguard Worker emitAssignment() 175*333d2b36SAndroid Build Coastguard Worker gctx.indentLevel-- 176*333d2b36SAndroid Build Coastguard Worker } 177*333d2b36SAndroid Build Coastguard Worker 178*333d2b36SAndroid Build Coastguard Worker gctx.setHasBeenAssigned(&scv) 179*333d2b36SAndroid Build Coastguard Worker} 180*333d2b36SAndroid Build Coastguard Worker 181*333d2b36SAndroid Build Coastguard Workerfunc (scv otherGlobalVariable) emitGet(gctx *generationContext) { 182*333d2b36SAndroid Build Coastguard Worker if gctx.hasBeenAssigned(&scv) || scv.isPreset() { 183*333d2b36SAndroid Build Coastguard Worker gctx.writef("g[%q]", scv.nam) 184*333d2b36SAndroid Build Coastguard Worker } else { 185*333d2b36SAndroid Build Coastguard Worker gctx.writef("g.get(%q, %s)", scv.nam, scv.defaultValueString()) 186*333d2b36SAndroid Build Coastguard Worker } 187*333d2b36SAndroid Build Coastguard Worker} 188*333d2b36SAndroid Build Coastguard Worker 189*333d2b36SAndroid Build Coastguard Workertype localVariable struct { 190*333d2b36SAndroid Build Coastguard Worker baseVariable 191*333d2b36SAndroid Build Coastguard Worker} 192*333d2b36SAndroid Build Coastguard Worker 193*333d2b36SAndroid Build Coastguard Workerfunc (lv localVariable) String() string { 194*333d2b36SAndroid Build Coastguard Worker return "_" + lv.nam 195*333d2b36SAndroid Build Coastguard Worker} 196*333d2b36SAndroid Build Coastguard Worker 197*333d2b36SAndroid Build Coastguard Workerfunc (lv localVariable) emitSet(gctx *generationContext, asgn *assignmentNode) { 198*333d2b36SAndroid Build Coastguard Worker switch asgn.flavor { 199*333d2b36SAndroid Build Coastguard Worker case asgnSet, asgnMaybeSet: 200*333d2b36SAndroid Build Coastguard Worker gctx.writef("%s = ", lv) 201*333d2b36SAndroid Build Coastguard Worker asgn.value.emitListVarCopy(gctx) 202*333d2b36SAndroid Build Coastguard Worker case asgnAppend: 203*333d2b36SAndroid Build Coastguard Worker gctx.writef("%s += ", lv) 204*333d2b36SAndroid Build Coastguard Worker value := asgn.value 205*333d2b36SAndroid Build Coastguard Worker if lv.valueType() == starlarkTypeString { 206*333d2b36SAndroid Build Coastguard Worker gctx.writef(`" " + `) 207*333d2b36SAndroid Build Coastguard Worker value = &toStringExpr{expr: value} 208*333d2b36SAndroid Build Coastguard Worker } 209*333d2b36SAndroid Build Coastguard Worker value.emit(gctx) 210*333d2b36SAndroid Build Coastguard Worker } 211*333d2b36SAndroid Build Coastguard Worker} 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Workerfunc (lv localVariable) emitGet(gctx *generationContext) { 214*333d2b36SAndroid Build Coastguard Worker gctx.writef("%s", lv) 215*333d2b36SAndroid Build Coastguard Worker} 216*333d2b36SAndroid Build Coastguard Worker 217*333d2b36SAndroid Build Coastguard Workertype predefinedVariable struct { 218*333d2b36SAndroid Build Coastguard Worker baseVariable 219*333d2b36SAndroid Build Coastguard Worker value starlarkExpr 220*333d2b36SAndroid Build Coastguard Worker} 221*333d2b36SAndroid Build Coastguard Worker 222*333d2b36SAndroid Build Coastguard Workerfunc (pv predefinedVariable) emitGet(gctx *generationContext) { 223*333d2b36SAndroid Build Coastguard Worker pv.value.emit(gctx) 224*333d2b36SAndroid Build Coastguard Worker} 225*333d2b36SAndroid Build Coastguard Worker 226*333d2b36SAndroid Build Coastguard Workerfunc (pv predefinedVariable) emitSet(gctx *generationContext, asgn *assignmentNode) { 227*333d2b36SAndroid Build Coastguard Worker if expectedValue, ok1 := maybeString(pv.value); ok1 { 228*333d2b36SAndroid Build Coastguard Worker actualValue, ok2 := maybeString(asgn.value) 229*333d2b36SAndroid Build Coastguard Worker if ok2 { 230*333d2b36SAndroid Build Coastguard Worker if actualValue == expectedValue { 231*333d2b36SAndroid Build Coastguard Worker return 232*333d2b36SAndroid Build Coastguard Worker } 233*333d2b36SAndroid Build Coastguard Worker gctx.emitConversionError(asgn.location, 234*333d2b36SAndroid Build Coastguard Worker fmt.Sprintf("cannot set predefined variable %s to %q, its value should be %q", 235*333d2b36SAndroid Build Coastguard Worker pv.name(), actualValue, expectedValue)) 236*333d2b36SAndroid Build Coastguard Worker gctx.starScript.hasErrors = true 237*333d2b36SAndroid Build Coastguard Worker return 238*333d2b36SAndroid Build Coastguard Worker } 239*333d2b36SAndroid Build Coastguard Worker } 240*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("cannot set predefined variable %s to %q", pv.name(), asgn.mkValue.Dump())) 241*333d2b36SAndroid Build Coastguard Worker} 242*333d2b36SAndroid Build Coastguard Worker 243*333d2b36SAndroid Build Coastguard Workervar localProductConfigVariables = map[string]string{ 244*333d2b36SAndroid Build Coastguard Worker "LOCAL_AUDIO_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 245*333d2b36SAndroid Build Coastguard Worker "LOCAL_AUDIO_PRODUCT_COPY_FILES": "PRODUCT_COPY_FILES", 246*333d2b36SAndroid Build Coastguard Worker "LOCAL_AUDIO_DEVICE_PACKAGE_OVERLAYS": "DEVICE_PACKAGE_OVERLAYS", 247*333d2b36SAndroid Build Coastguard Worker "LOCAL_DUMPSTATE_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 248*333d2b36SAndroid Build Coastguard Worker "LOCAL_GATEKEEPER_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 249*333d2b36SAndroid Build Coastguard Worker "LOCAL_HEALTH_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 250*333d2b36SAndroid Build Coastguard Worker "LOCAL_SENSOR_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 251*333d2b36SAndroid Build Coastguard Worker "LOCAL_KEYMASTER_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 252*333d2b36SAndroid Build Coastguard Worker "LOCAL_KEYMINT_PRODUCT_PACKAGE": "PRODUCT_PACKAGES", 253*333d2b36SAndroid Build Coastguard Worker} 254*333d2b36SAndroid Build Coastguard Worker 255*333d2b36SAndroid Build Coastguard Workervar presetVariables = map[string]bool{ 256*333d2b36SAndroid Build Coastguard Worker "BUILD_ID": true, 257*333d2b36SAndroid Build Coastguard Worker "HOST_ARCH": true, 258*333d2b36SAndroid Build Coastguard Worker "HOST_OS": true, 259*333d2b36SAndroid Build Coastguard Worker "HOST_BUILD_TYPE": true, 260*333d2b36SAndroid Build Coastguard Worker "OUT_DIR": true, 261*333d2b36SAndroid Build Coastguard Worker "PLATFORM_VERSION_CODENAME": true, 262*333d2b36SAndroid Build Coastguard Worker "PLATFORM_VERSION": true, 263*333d2b36SAndroid Build Coastguard Worker "TARGET_ARCH": true, 264*333d2b36SAndroid Build Coastguard Worker "TARGET_ARCH_VARIANT": true, 265*333d2b36SAndroid Build Coastguard Worker "TARGET_BUILD_TYPE": true, 266*333d2b36SAndroid Build Coastguard Worker "TARGET_BUILD_VARIANT": true, 267*333d2b36SAndroid Build Coastguard Worker "TARGET_PRODUCT": true, 268*333d2b36SAndroid Build Coastguard Worker} 269*333d2b36SAndroid Build Coastguard Worker 270*333d2b36SAndroid Build Coastguard Worker// addVariable returns a variable with a given name. A variable is 271*333d2b36SAndroid Build Coastguard Worker// added if it does not exist yet. 272*333d2b36SAndroid Build Coastguard Workerfunc (ctx *parseContext) addVariable(name string) variable { 273*333d2b36SAndroid Build Coastguard Worker // Get the hintType before potentially changing the variable name 274*333d2b36SAndroid Build Coastguard Worker var hintType starlarkType 275*333d2b36SAndroid Build Coastguard Worker var ok bool 276*333d2b36SAndroid Build Coastguard Worker if hintType, ok = ctx.typeHints[name]; !ok { 277*333d2b36SAndroid Build Coastguard Worker hintType = starlarkTypeUnknown 278*333d2b36SAndroid Build Coastguard Worker } 279*333d2b36SAndroid Build Coastguard Worker // Heuristics: if variable's name is all lowercase, consider it local 280*333d2b36SAndroid Build Coastguard Worker // string variable. 281*333d2b36SAndroid Build Coastguard Worker isLocalVariable := name == strings.ToLower(name) 282*333d2b36SAndroid Build Coastguard Worker // Local variables can't have special characters in them, because they 283*333d2b36SAndroid Build Coastguard Worker // will be used as starlark identifiers 284*333d2b36SAndroid Build Coastguard Worker if isLocalVariable { 285*333d2b36SAndroid Build Coastguard Worker name = strings.ReplaceAll(strings.TrimSpace(name), "-", "_") 286*333d2b36SAndroid Build Coastguard Worker } 287*333d2b36SAndroid Build Coastguard Worker v, found := ctx.variables[name] 288*333d2b36SAndroid Build Coastguard Worker if !found { 289*333d2b36SAndroid Build Coastguard Worker if vi, found := KnownVariables[name]; found { 290*333d2b36SAndroid Build Coastguard Worker _, preset := presetVariables[name] 291*333d2b36SAndroid Build Coastguard Worker switch vi.class { 292*333d2b36SAndroid Build Coastguard Worker case VarClassConfig: 293*333d2b36SAndroid Build Coastguard Worker v = &productConfigVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}} 294*333d2b36SAndroid Build Coastguard Worker case VarClassSoong: 295*333d2b36SAndroid Build Coastguard Worker v = &otherGlobalVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}} 296*333d2b36SAndroid Build Coastguard Worker } 297*333d2b36SAndroid Build Coastguard Worker } else if isLocalVariable { 298*333d2b36SAndroid Build Coastguard Worker v = &localVariable{baseVariable{nam: name, typ: hintType}} 299*333d2b36SAndroid Build Coastguard Worker } else { 300*333d2b36SAndroid Build Coastguard Worker vt := hintType 301*333d2b36SAndroid Build Coastguard Worker // Heuristics: local variables that contribute to corresponding config variables 302*333d2b36SAndroid Build Coastguard Worker if cfgVarName, found := localProductConfigVariables[name]; found && vt == starlarkTypeUnknown { 303*333d2b36SAndroid Build Coastguard Worker vi, found2 := KnownVariables[cfgVarName] 304*333d2b36SAndroid Build Coastguard Worker if !found2 { 305*333d2b36SAndroid Build Coastguard Worker panic(fmt.Errorf("unknown config variable %s for %s", cfgVarName, name)) 306*333d2b36SAndroid Build Coastguard Worker } 307*333d2b36SAndroid Build Coastguard Worker vt = vi.valueType 308*333d2b36SAndroid Build Coastguard Worker } 309*333d2b36SAndroid Build Coastguard Worker if strings.HasSuffix(name, "_LIST") && vt == starlarkTypeUnknown { 310*333d2b36SAndroid Build Coastguard Worker // Heuristics: Variables with "_LIST" suffix are lists 311*333d2b36SAndroid Build Coastguard Worker vt = starlarkTypeList 312*333d2b36SAndroid Build Coastguard Worker } 313*333d2b36SAndroid Build Coastguard Worker v = &otherGlobalVariable{baseVariable{nam: name, typ: vt}} 314*333d2b36SAndroid Build Coastguard Worker } 315*333d2b36SAndroid Build Coastguard Worker ctx.variables[name] = v 316*333d2b36SAndroid Build Coastguard Worker } 317*333d2b36SAndroid Build Coastguard Worker return v 318*333d2b36SAndroid Build Coastguard Worker} 319