Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/mk2rbc/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 8 kB image not shown  

Quelle  variable.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mk2rbc

import (
 "fmt"
 "strings"
)

type variable interface {
 name() string
 emitGet(gctx *generationContext)
 emitSet(gctx *generationContext, asgn *assignmentNode)
 valueType() starlarkType
 setValueType(t starlarkType)
 defaultValueString() string
 isPreset() bool
}

type baseVariable struct {
 nam    string
 typ    starlarkType
 preset bool // true if it has been initialized at startup
}

func (v baseVariable) name() string {
 return v.nam
}

func (v baseVariable) valueType() starlarkType {
 return v.typ
}

func (v *baseVariable) setValueType(t starlarkType) {
 v.typ = t
}

func (v baseVariable) isPreset() bool {
 return v.preset
}

var defaultValuesByType = map[starlarkType]string{
 starlarkTypeUnknown: `""`,
 starlarkTypeList:    "[]",
 starlarkTypeString:  `""`,
 starlarkTypeInt:     "0",
 starlarkTypeBool:    "False",
 starlarkTypeVoid:    "None",
}

func (v baseVariable) defaultValueString() string {
 if v, ok := defaultValuesByType[v.valueType()]; ok {
  return v
 }
 panic(fmt.Errorf("%s has unknown type %q", v.name(), v.valueType()))
}

type productConfigVariable struct {
 baseVariable
}

func (pcv productConfigVariable) emitSet(gctx *generationContext, asgn *assignmentNode) {
 emitAssignment := func() {
  gctx.writef("cfg[%q] = ", pcv.nam)
  asgn.value.emitListVarCopy(gctx)
 }
 emitAppend := func() {
  gctx.writef("cfg[%q] += ", pcv.nam)
  value := asgn.value
  if pcv.valueType() == starlarkTypeString {
   gctx.writef(`" " + `)
   value = &toStringExpr{expr: value}
  }
  value.emit(gctx)
 }
 emitSetDefault := func() {
  if pcv.typ == starlarkTypeList {
   gctx.writef("%s(handle, %q)", cfnSetListDefault, pcv.name())
  } else {
   gctx.writef("cfg.setdefault(%q, %s)", pcv.name(), pcv.defaultValueString())
  }
  gctx.newLine()
 }

 // If we are not sure variable has been assigned before, emit setdefault
 needsSetDefault := !gctx.hasBeenAssigned(&pcv) && !pcv.isPreset() && asgn.isSelfReferential()

 switch asgn.flavor {
 case asgnSet:
  if needsSetDefault {
   emitSetDefault()
  }
  emitAssignment()
 case asgnAppend:
  if needsSetDefault {
   emitSetDefault()
  }
  emitAppend()
 case asgnMaybeSet:
  // In mk2rbc.go we never emit a maybeSet assignment for product config variables, because
  // they are set to empty strings before running product config.
  panic("Should never get here")
 default:
  panic("Unknown assignment flavor")
 }

 gctx.setHasBeenAssigned(&pcv)
}

func (pcv productConfigVariable) emitGet(gctx *generationContext) {
 if gctx.hasBeenAssigned(&pcv) || pcv.isPreset() {
  gctx.writef("cfg[%q]", pcv.nam)
 } else {
  gctx.writef("cfg.get(%q, %s)", pcv.nam, pcv.defaultValueString())
 }
}

type otherGlobalVariable struct {
 baseVariable
}

func (scv otherGlobalVariable) emitSet(gctx *generationContext, asgn *assignmentNode) {
 emitAssignment := func() {
  gctx.writef("g[%q] = ", scv.nam)
  asgn.value.emitListVarCopy(gctx)
 }

 emitAppend := func() {
  gctx.writef("g[%q] += ", scv.nam)
  value := asgn.value
  if scv.valueType() == starlarkTypeString {
   gctx.writef(`" " + `)
   value = &toStringExpr{expr: value}
  }
  value.emit(gctx)
 }

 // If we are not sure variable has been assigned before, emit setdefault
 needsSetDefault := !gctx.hasBeenAssigned(&scv) && !scv.isPreset() && asgn.isSelfReferential()

 switch asgn.flavor {
 case asgnSet:
  if needsSetDefault {
   gctx.writef("g.setdefault(%q, %s)", scv.name(), scv.defaultValueString())
   gctx.newLine()
  }
  emitAssignment()
 case asgnAppend:
  if needsSetDefault {
   gctx.writef("g.setdefault(%q, %s)", scv.name(), scv.defaultValueString())
   gctx.newLine()
  }
  emitAppend()
 case asgnMaybeSet:
  gctx.writef("if g.get(%q) == None:", scv.nam)
  gctx.indentLevel++
  gctx.newLine()
  if needsSetDefault {
   gctx.writef("g.setdefault(%q, %s)", scv.name(), scv.defaultValueString())
   gctx.newLine()
  }
  emitAssignment()
  gctx.indentLevel--
 }

 gctx.setHasBeenAssigned(&scv)
}

func (scv otherGlobalVariable) emitGet(gctx *generationContext) {
 if gctx.hasBeenAssigned(&scv) || scv.isPreset() {
  gctx.writef("g[%q]", scv.nam)
 } else {
  gctx.writef("g.get(%q, %s)", scv.nam, scv.defaultValueString())
 }
}

type localVariable struct {
 baseVariable
}

func (lv localVariable) String() string {
 return "_" + lv.nam
}

func (lv localVariable) emitSet(gctx *generationContext, asgn *assignmentNode) {
 switch asgn.flavor {
 case asgnSet, asgnMaybeSet:
  gctx.writef("%s = ", lv)
  asgn.value.emitListVarCopy(gctx)
 case asgnAppend:
  gctx.writef("%s += ", lv)
  value := asgn.value
  if lv.valueType() == starlarkTypeString {
   gctx.writef(`" " + `)
   value = &toStringExpr{expr: value}
  }
  value.emit(gctx)
 }
}

func (lv localVariable) emitGet(gctx *generationContext) {
 gctx.writef("%s", lv)
}

type predefinedVariable struct {
 baseVariable
 value starlarkExpr
}

func (pv predefinedVariable) emitGet(gctx *generationContext) {
 pv.value.emit(gctx)
}

func (pv predefinedVariable) emitSet(gctx *generationContext, asgn *assignmentNode) {
 if expectedValue, ok1 := maybeString(pv.value); ok1 {
  actualValue, ok2 := maybeString(asgn.value)
  if ok2 {
   if actualValue == expectedValue {
    return
   }
   gctx.emitConversionError(asgn.location,
    fmt.Sprintf("cannot set predefined variable %s to %q, its value should be %q",
     pv.name(), actualValue, expectedValue))
   gctx.starScript.hasErrors = true
   return
  }
 }
 panic(fmt.Errorf("cannot set predefined variable %s to %q", pv.name(), asgn.mkValue.Dump()))
}

var localProductConfigVariables = map[string]string{
 "LOCAL_AUDIO_PRODUCT_PACKAGE":         "PRODUCT_PACKAGES",
 "LOCAL_AUDIO_PRODUCT_COPY_FILES":      "PRODUCT_COPY_FILES",
 "LOCAL_AUDIO_DEVICE_PACKAGE_OVERLAYS": "DEVICE_PACKAGE_OVERLAYS",
 "LOCAL_DUMPSTATE_PRODUCT_PACKAGE":     "PRODUCT_PACKAGES",
 "LOCAL_GATEKEEPER_PRODUCT_PACKAGE":    "PRODUCT_PACKAGES",
 "LOCAL_HEALTH_PRODUCT_PACKAGE":        "PRODUCT_PACKAGES",
 "LOCAL_SENSOR_PRODUCT_PACKAGE":        "PRODUCT_PACKAGES",
 "LOCAL_KEYMASTER_PRODUCT_PACKAGE":     "PRODUCT_PACKAGES",
 "LOCAL_KEYMINT_PRODUCT_PACKAGE":       "PRODUCT_PACKAGES",
}

var presetVariables = map[string]bool{
 "BUILD_ID":                  true,
 "HOST_ARCH":                 true,
 "HOST_OS":                   true,
 "HOST_BUILD_TYPE":           true,
 "OUT_DIR":                   true,
 "PLATFORM_VERSION_CODENAME": true,
 "PLATFORM_VERSION":          true,
 "TARGET_ARCH":               true,
 "TARGET_ARCH_VARIANT":       true,
 "TARGET_BUILD_TYPE":         true,
 "TARGET_BUILD_VARIANT":      true,
 "TARGET_PRODUCT":            true,
}

// addVariable returns a variable with a given name. A variable is
// added if it does not exist yet.
func (ctx *parseContext) addVariable(name string) variable {
 // Get the hintType before potentially changing the variable name
 var hintType starlarkType
 var ok bool
 if hintType, ok = ctx.typeHints[name]; !ok {
  hintType = starlarkTypeUnknown
 }
 // Heuristics: if variable's name is all lowercase, consider it local
 // string variable.
 isLocalVariable := name == strings.ToLower(name)
 // Local variables can't have special characters in them, because they
 // will be used as starlark identifiers
 if isLocalVariable {
  name = strings.ReplaceAll(strings.TrimSpace(name), "-", "_")
 }
 v, found := ctx.variables[name]
 if !found {
  if vi, found := KnownVariables[name]; found {
   _, preset := presetVariables[name]
   switch vi.class {
   case VarClassConfig:
    v = &productConfigVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}}
   case VarClassSoong:
    v = &otherGlobalVariable{baseVariable{nam: name, typ: vi.valueType, preset: preset}}
   }
  } else if isLocalVariable {
   v = &localVariable{baseVariable{nam: name, typ: hintType}}
  } else {
   vt := hintType
   // Heuristics: local variables that contribute to corresponding config variables
   if cfgVarName, found := localProductConfigVariables[name]; found && vt == starlarkTypeUnknown {
    vi, found2 := KnownVariables[cfgVarName]
    if !found2 {
     panic(fmt.Errorf("unknown config variable %s for %s", cfgVarName, name))
    }
    vt = vi.valueType
   }
   if strings.HasSuffix(name, "_LIST") && vt == starlarkTypeUnknown {
    // Heuristics: Variables with "_LIST" suffix are lists
    vt = starlarkTypeList
   }
   v = &otherGlobalVariable{baseVariable{nam: name, typ: vt}}
  }
  ctx.variables[name] = v
 }
 return v
}

[Dauer der Verarbeitung: 0.2 Sekunden, vorverarbeitet 2026-06-28]