Spracherkennung für: .go vermutete Sprache: Abap {ABAP[70] SPS[54] Algol[38]} [Methode: maximale Elemente, drei 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"
mkparser
"android/soong/androidmk/parser"
)
// A parsed node
for which starlark
code will be generated
//
by calling emit().
type starlarkNode
interface {
emit(ctx
*generationContext)
}
//
Types used
to keep processed makefile
data:
type commentNode struct {
text string
}
func (c
*commentNode) emit(gctx *generationContext) {
chunks := strings.
Split(c.
text,
"\\\n")
gctx.newLine()
gctx.
write(chunks[
0]) // It has
'#' at the beginning already.
for _, chunk := range chunks[
1:] {
gctx.newLine()
gctx.
write(
"#", chunk)
}
}
type moduleInfo struct {
path
string // Converted Starlark
file path
originalPath
string // Makefile
file path
moduleLocalName
string
optional bool
missing bool // a
module may not exist
if a
module that depends
on it
is loaded dynamically
}
func (im moduleInfo) entryName()
string {
return im.moduleLocalName +
"_init"
}
func (mi moduleInfo) name()
string {
return fmt.Sprintf(
"%q", MakePath2ModuleName(mi.originalPath))
}
type inheritedModule
interface {
name()
string
entryName()
string
emitSelect(gctx
*generationContext)
pathExpr() starlarkExpr
needsLoadCheck() bool
}
type inheritedStaticModule struct {
*moduleInfo
loadAlways bool
}
func (im inheritedStaticModule) emitSelect(_
*generationContext) {
}
func (im inheritedStaticModule) pathExpr() starlarkExpr {
return &stringLiteralExpr{im.path}
}
func (im inheritedStaticModule) needsLoadCheck() bool {
return im.missing
}
type inheritedDynamicModule struct {
path starlarkExpr
candidateModules []
*moduleInfo
loadAlways bool
location ErrorLocation
needsWarning bool
}
func (i inheritedDynamicModule) name()
string {
return
"_varmod"
}
func (i inheritedDynamicModule) entryName()
string {
return i.name() +
"_init"
}
func (i inheritedDynamicModule) emitSelect(gctx
*generationContext) {
if i.needsWarning {
gctx.newLine()
gctx.writef(
"%s.mkwarning(%q, %q)", baseName, i.location,
"Please avoid starting an include path with a variable. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
}
gctx.newLine()
gctx.writef(
"_entry = {")
gctx.indentLevel++
for _, mi := range i.candidateModules {
gctx.newLine()
gctx.writef(`
"%s": (%s, %s),`, mi.originalPath, mi.name(), mi.entryName())
}
gctx.indentLevel--
gctx.newLine()
gctx.
write(
"}.get(")
i.path.emit(gctx)
gctx.
write(
")")
gctx.newLine()
gctx.writef(
"(%s, %s) = _entry if _entry else (None, None)", i.name(), i.entryName())
}
func (i inheritedDynamicModule) pathExpr() starlarkExpr {
return i.path
}
func (i inheritedDynamicModule) needsLoadCheck() bool {
return true
}
type inheritNode struct {
module inheritedModule
loadAlways bool
}
func (inn
*inheritNode) emit(gctx *generationContext) {
// Unconditional
case:
// maybe
check that loaded
// rblf.inherit(handle, <
module>, module_init)
// Conditional
case:
//
if <
module>_init != None:
// same
as above
inn.
module.emitSelect(gctx)
name := inn.
module.name()
entry := inn.
module.entryName()
if inn.loadAlways {
gctx.emitLoadCheck(inn.
module)
gctx.newLine()
gctx.writef(
"%s(handle, %s, %s)", cfnInherit, name, entry)
return
}
gctx.newLine()
gctx.writef(
"if %s:", entry)
gctx.indentLevel++
gctx.newLine()
gctx.writef(
"%s(handle, %s, %s)", cfnInherit, name, entry)
gctx.indentLevel--
}
type includeNode struct {
module inheritedModule
loadAlways bool
}
func (inn
*includeNode) emit(gctx *generationContext) {
inn.
module.emitSelect(gctx)
entry := inn.
module.entryName()
if inn.loadAlways {
gctx.emitLoadCheck(inn.
module)
gctx.newLine()
gctx.writef(
"%s(g, handle)", entry)
return
}
gctx.newLine()
gctx.writef(
"if %s != None:", entry)
gctx.indentLevel++
gctx.newLine()
gctx.writef(
"%s(g, handle)", entry)
gctx.indentLevel--
}
type assignmentFlavor int
const (
// Assignment flavors
asgnSet assignmentFlavor = iota // :=
or =
asgnMaybeSet assignmentFlavor = iota // ?=
asgnAppend assignmentFlavor = iota // +=
)
type assignmentNode struct {
lhs variable
value starlarkExpr
mkValue
*mkparser.MakeString
flavor assignmentFlavor
location ErrorLocation
isTraced bool
}
func (asgn
*assignmentNode) emit(gctx *generationContext) {
gctx.newLine()
gctx.inAssignment = true
asgn.lhs.emitSet(gctx, asgn)
gctx.inAssignment = false
if asgn.isTraced {
gctx.newLine()
gctx.tracedCount++
gctx.writef(`
print(
"%s.%d: %s := ", `, gctx.starScript.mkFile, gctx.tracedCount, asgn.l
hs.name())
asgn.lhs.emitGet(gctx)
gctx.writef(")")
}
}
func (asgn *assignmentNode) isSelfReferential() bool {
if asgn.flavor == asgnAppend {
return true
}
isSelfReferential := false
asgn.value.transform(func(expr starlarkExpr) starlarkExpr {
if ref, ok := expr.(*variableRefExpr); ok && ref.ref.name() == asgn.lhs.name() {
isSelfReferential = true
}
return nil
})
return isSelfReferential
}
type exprNode struct {
expr starlarkExpr
}
func (exn *exprNode) emit(gctx *generationContext) {
gctx.newLine()
exn.expr.emit(gctx)
}
type ifNode struct {
isElif bool // true if this is 'elif' statement
expr starlarkExpr
}
func (in *ifNode) emit(gctx *generationContext) {
ifElif := "if "
if in.isElif {
ifElif = "elif "
}
gctx.newLine()
gctx.write(ifElif)
in.expr.emit(gctx)
gctx.write(":")
}
type elseNode struct{}
func (br *elseNode) emit(gctx *generationContext) {
gctx.newLine()
gctx.write("else:")
}
// switchCase represents as single if/elseif/else branch. All the necessary
// info about flavor (if/elseif/else) is supposed to be kept in `gate`.
type switchCase struct {
gate starlarkNode
nodes []starlarkNode
}
func (cb *switchCase) emit(gctx *generationContext) {
cb.gate.emit(gctx)
gctx.indentLevel++
gctx.pushVariableAssignments()
hasStatements := false
for _, node := range cb.nodes {
if _, ok := node.(*commentNode); !ok {
hasStatements = true
}
node.emit(gctx)
}
if !hasStatements {
gctx.emitPass()
}
gctx.indentLevel--
gctx.popVariableAssignments()
}
// A single complete if ... elseif ... else ... endif sequences
type switchNode struct {
ssCases []*switchCase
}
func (ssw *switchNode) emit(gctx *generationContext) {
for _, ssCase := range ssw.ssCases {
ssCase.emit(gctx)
}
}
type foreachNode struct {
varName string
list starlarkExpr
actions []starlarkNode
}
func (f *foreachNode) emit(gctx *generationContext) {
gctx.pushVariableAssignments()
gctx.newLine()
gctx.writef("for %s in ", f.varName)
f.list.emit(gctx)
gctx.write(":")
gctx.indentLevel++
hasStatements := false
for _, a := range f.actions {
if _, ok := a.(*commentNode); !ok {
hasStatements = true
}
a.emit(gctx)
}
if !hasStatements {
gctx.emitPass()
}
gctx.indentLevel--
gctx.popVariableAssignments()
}