Spracherkennung für: .go vermutete Sprache: Abap {ABAP[72] SPS[60] C[30]} [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"
)
// Represents an expression
in the Starlark
code. An expression has a
type.
type starlarkExpr
interface {
starlarkNode
typ() starlarkType
// Emit the
code to copy the expression, otherwise we will end up
// with source
and target pointing
to the same list.
emitListVarCopy(gctx
*generationContext)
// Return the expression, calling the transformer func
for
// every expression
in the tree.
If the transformer func returns non-nil,
// its result
is used
in place
of the expression it was called with
in the
// resulting expression. The resulting starlarkExpr will contain
as many
//
of the same objects
from the original expression
as possible.
transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr
}
func maybeString(expr starlarkExpr) (
string, bool) {
if x, ok := expr.(
*stringLiteralExpr); ok {
return x.literal, true
}
return
"", false
}
type stringLiteralExpr struct {
literal
string
}
func (s
*stringLiteralExpr) emit(gctx *generationContext) {
gctx.writef(
"%q", s.literal)
}
func (_
*stringLiteralExpr) typ() starlarkType {
return starlarkTypeString
}
func (s
*stringLiteralExpr) emitListVarCopy(gctx *generationContext) {
s.emit(gctx)
}
func (s
*stringLiteralExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(s); replacement != nil {
return replacement
}
else {
return s
}
}
// Integer literal
type intLiteralExpr struct {
literal int
}
func (s
*intLiteralExpr) emit(gctx *generationContext) {
gctx.writef(
"%d", s.literal)
}
func (_
*intLiteralExpr) typ() starlarkType {
return starlarkTypeInt
}
func (s
*intLiteralExpr) emitListVarCopy(gctx *generationContext) {
s.emit(gctx)
}
func (s
*intLiteralExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(s); replacement != nil {
return replacement
}
else {
return s
}
}
// Boolean literal
type boolLiteralExpr struct {
literal bool
}
func (b
*boolLiteralExpr) emit(gctx *generationContext) {
if b.literal {
gctx.
write(
"True")
}
else {
gctx.
write(
"False")
}
}
func (_
*boolLiteralExpr) typ() starlarkType {
return starlarkTypeBool
}
func (b
*boolLiteralExpr) emitListVarCopy(gctx *generationContext) {
b.emit(gctx)
}
func (b
*boolLiteralExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(b); replacement != nil {
return replacement
}
else {
return b
}
}
type globalsExpr struct {
}
func (g
*globalsExpr) emit(gctx *generationContext) {
gctx.
write(
"g")
}
func (g
*globalsExpr) typ() starlarkType {
return starlarkTypeUnknown
}
func (g
*globalsExpr) emitListVarCopy(gctx *generationContext) {
g.emit(gctx)
}
func (g
*globalsExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(g); replacement != nil {
return replacement
}
else {
return g
}
}
// interpolateExpr represents Starlark
's interpolation operator <string> % list
// we break <
string>
into a list
of chunks, i.e.,
"first%second%third" % (X, Y)
// will have chunks = [
"first",
"second",
"third"]
and args = [X, Y]
type interpolateExpr struct {
chunks []
string //
string chunks, separated
by '%'
args []starlarkExpr
}
func NewInterpolateExpr(parts []starlarkExpr) starlarkExpr {
result := &interpolateExpr{}
needString := true
for _, part := range parts {
if needString {
if strLit, ok := part.(
*stringLiteralExpr); ok {
result.chunks =
append(result.chunks, strLit.literal)
}
else {
result.chunks =
append(result.chunks,
"")
}
needString = false
}
else {
if strLit, ok := part.(
*stringLiteralExpr); ok {
result.chunks[len(result.chunks)-
1] += strLit.literal
}
else {
result.args =
append(result.args, part)
needString = true
}
}
}
if len(result.chunks) == len(result.args) {
result.chunks =
append(result.chunks,
"")
}
if len(result.args) ==
0 {
return &stringLiteralExpr{literal: strings.
Join(result.chunks,
"")}
}
return result
}
func (xi
*interpolateExpr) emit(gctx *generationContext) {
if len(xi.chunks) != len(xi.args)+
1 {
panic(fmt.Errorf(
"malformed interpolateExpr: #chunks(%d) != #args(%d)+1",
len(xi.chunks), len(xi.args)))
}
//
Generate format as join of chunks, but first escape
'%' in them
format := strings.ReplaceAll(xi.chunks[
0],
"%",
"%%")
for _, chunk := range xi.chunks[
1:] {
format +=
"%s" + strings.ReplaceAll(chunk,
"%",
"%%")
}
gctx.writef(
"%q %% ",
format)
emitArg := func(arg starlarkExpr) {
if arg.typ() == starlarkTypeList {
gctx.
write(`
" ".
join(`)
arg.emit(gctx)
gctx.
write(`)`)
}
else {
arg.emit(gctx)
}
}
if len(xi.args) ==
1 {
emitArg(xi.args[
0])
}
else {
sep :=
"("
for _, arg := range xi.args {
gctx.
write(sep)
emitArg(arg)
sep =
", "
}
gctx.
write(
")")
}
}
func (_
*interpolateExpr) typ() starlarkType {
return starlarkTypeString
}
func (xi
*interpolateExpr) emitListVarCopy(gctx *generationContext) {
xi.emit(gctx)
}
func (xi
*interpolateExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
for i := range xi.args {
xi.args[i] = xi.args[i].transform(transformer)
}
if replacement := transformer(xi); replacement != nil {
return replacement
}
else {
return xi
}
}
type variableRefExpr struct {
ref variable
}
func NewVariableRefExpr(ref variable) starlarkExpr {
if predefined, ok := ref.(
*predefinedVariable); ok {
return predefined.value
}
return &variableRefExpr{ref}
}
func (v
*variableRefExpr) emit(gctx *generationContext) {
v.ref.emitGet(gctx)
}
func (v
*variableRefExpr) typ() starlarkType {
return v.ref.valueType()
}
func (v
*variableRefExpr) emitListVarCopy(gctx *generationContext) {
v.emit(gctx)
if v.typ() == starlarkTypeList {
gctx.
write(
"[:]") // this will
copy the list
}
}
func (v
*variableRefExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(v); replacement != nil {
return replacement
}
else {
return v
}
}
type toStringExpr struct {
expr starlarkExpr
}
func (s
*toStringExpr) emit(ctx *generationContext) {
switch s.expr.typ() {
case starlarkTypeString, starlarkTypeUnknown:
// Assume unknown
types are strings already.
s.expr.emit(ctx)
case starlarkTypeList:
ctx.
write(`
" ".
join(`)
s.expr.emit(ctx)
ctx.
write(
")")
case starlarkTypeInt:
ctx.
write(`(
"%d" % (`)
s.expr.emit(ctx)
ctx.
write(
"))")
case starlarkTypeBool:
ctx.
write(`(
"true" if (`)
s.expr.emit(ctx)
ctx.
write(`)
else "")`)
case starlarkTypeVoid:
ctx.
write(`
""`)
default:
panic(
"Unknown starlark type!")
}
}
func (s
*toStringExpr) typ() starlarkType {
return starlarkTypeString
}
func (s
*toStringExpr) emitListVarCopy(gctx *generationContext) {
s.emit(gctx)
}
func (s
*toStringExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
s.expr = s.expr.transform(transformer)
if replacement := transformer(s); replacement != nil {
return replacement
}
else {
return s
}
}
type notExpr struct {
expr starlarkExpr
}
func (n
*notExpr) emit(ctx *generationContext) {
ctx.
write(
"not ")
n.expr.emit(ctx)
}
func (_
*notExpr) typ() starlarkType {
return starlarkTypeBool
}
func (n
*notExpr) emitListVarCopy(gctx *generationContext) {
n.emit(gctx)
}
func (n
*notExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
n.expr = n.expr.transform(transformer)
if replacement := transformer(n); replacement != nil {
return replacement
}
else {
return n
}
}
type eqExpr struct {
left, right starlarkExpr
isEq bool //
if false, it
's !=
}
func (
eq *eqExpr) emit(gctx *generationContext) {
if eq.left.typ() !=
eq.right.typ() {
eq.left = &toStringExpr{expr:
eq.left}
eq.right = &toStringExpr{expr:
eq.right}
}
// General
case
eq.left.emit(gctx)
if eq.isEq {
gctx.
write(
" == ")
}
else {
gctx.
write(
" != ")
}
eq.right.emit(gctx)
}
func (_
*eqExpr) typ() starlarkType {
return starlarkTypeBool
}
func (
eq *eqExpr) emitListVarCopy(gctx *generationContext) {
eq.emit(gctx)
}
func (
eq *eqExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
eq.left =
eq.left.transform(transformer)
eq.right =
eq.right.transform(transformer)
if replacement := transformer(
eq); replacement != nil {
return replacement
}
else {
return
eq
}
}
type listExpr struct {
items []starlarkExpr
}
func (l
*listExpr) emit(gctx *generationContext) {
if !gctx.inAssignment || len(l.items) <
2 {
gctx.
write(
"[")
sep :=
""
for _, item := range l.items {
gctx.
write(sep)
item.emit(gctx)
sep =
", "
}
gctx.
write(
"]")
return
}
gctx.
write(
"[")
gctx.indentLevel +=
2
for _, item := range l.items {
gctx.newLine()
item.emit(gctx)
gctx.
write(
",")
}
gctx.indentLevel -=
2
gctx.newLine()
gctx.
write(
"]")
}
func (_
*listExpr) typ() starlarkType {
return starlarkTypeList
}
func (l
*listExpr) emitListVarCopy(gctx *generationContext) {
l.emit(gctx)
}
func (l
*listExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
itemsCopy := make([]starlarkExpr, len(l.items))
for i, item := range l.items {
itemsCopy[i] = item.transform(transformer)
}
l.items = itemsCopy
if replacement := transformer(l); replacement != nil {
return replacement
}
else {
return l
}
}
func newStringListExpr(items []
string)
*listExpr {
v := listExpr{}
for _, item := range items {
v.items =
append(v.items, &stringLiteralExpr{item})
}
return &v
}
// concatExpr generates expr1 + expr2 + ... + exprN
in Starlark.
type concatExpr struct {
items []starlarkExpr
}
func (c
*concatExpr) emit(gctx *generationContext) {
if len(c.items) ==
1 {
c.items[
0].emit(gctx)
return
}
if !gctx.inAssignment {
c.items[
0].emit(gctx)
for _, item := range c.items[
1:] {
gctx.
write(
" + ")
item.emit(gctx)
}
return
}
gctx.
write(
"(")
c.items[
0].emit(gctx)
gctx.indentLevel +=
2
for _, item := range c.items[
1:] {
gctx.
write(
" +")
gctx.newLine()
item.emit(gctx)
}
gctx.
write(
")")
gctx.indentLevel -=
2
}
func (_
*concatExpr) typ() starlarkType {
return starlarkTypeList
}
func (c
*concatExpr) emitListVarCopy(gctx *generationContext) {
c.emit(gctx)
}
func (c
*concatExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
itemsCopy := make([]starlarkExpr, len(c.items))
for i, item := range c.items {
itemsCopy[i] = item.transform(transformer)
}
c.items = itemsCopy
if replacement := transformer(c); replacement != nil {
return replacement
}
else {
return c
}
}
// inExpr generates <expr> [not]
in <list>
type inExpr struct {
expr starlarkExpr
list starlarkExpr
isNot bool
}
func (i
*inExpr) emit(gctx *generationContext) {
i.expr.emit(gctx)
if i.isNot {
gctx.
write(
" not in ")
}
else {
gctx.
write(
" in ")
}
i.list.emit(gctx)
}
func (_
*inExpr) typ() starlarkType {
return starlarkTypeBool
}
func (i
*inExpr) emitListVarCopy(gctx *generationContext) {
i.emit(gctx)
}
func (i
*inExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
i.expr = i.expr.transform(transformer)
i.list = i.list.transform(transformer)
if replacement := transformer(i); replacement != nil {
return replacement
}
else {
return i
}
}
type indexExpr struct {
array starlarkExpr
index starlarkExpr
}
func (ix
*indexExpr) emit(gctx *generationContext) {
ix.array.emit(gctx)
gctx.
write(
"[")
ix.
index.emit(gctx)
gctx.
write(
"]")
}
func (ix
*indexExpr) typ() starlarkType {
return starlarkTypeString
}
func (ix
*indexExpr) emitListVarCopy(gctx *generationContext) {
ix.emit(gctx)
}
func (ix
*indexExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
ix.array = ix.array.transform(transformer)
ix.
index = ix.
index.transform(transformer)
if replacement := transformer(ix); replacement != nil {
return replacement
}
else {
return ix
}
}
type callExpr struct {
object starlarkExpr // nil
if static
call
name
string
args []starlarkExpr
returnType starlarkType
}
func (cx
*callExpr) emit(gctx *generationContext) {
if cx.
object != nil {
gctx.
write(
"(")
cx.
object.emit(gctx)
gctx.
write(
")")
gctx.
write(
".", cx.name,
"(")
}
else {
gctx.
write(cx.name,
"(")
}
sep :=
""
for _, arg := range cx.args {
gctx.
write(sep)
arg.emit(gctx)
sep =
", "
}
gctx.
write(
")")
}
func (cx
*callExpr) typ() starlarkType {
return cx.returnType
}
func (cx
*callExpr) emitListVarCopy(gctx *generationContext) {
cx.emit(gctx)
}
func (cx
*callExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if cx.
object != nil {
cx.
object = cx.
object.transform(transformer)
}
for i := range cx.args {
cx.args[i] = cx.args[i].transform(transformer)
}
if replacement := transformer(cx); replacement != nil {
return replacement
}
else {
return cx
}
}
type ifExpr struct {
condition starlarkExpr
ifTrue starlarkExpr
ifFalse starlarkExpr
}
func (i
*ifExpr) emit(gctx *generationContext) {
gctx.
write(
"(")
i.ifTrue.emit(gctx)
gctx.
write(
" if ")
i.condition.emit(gctx)
gctx.
write(
" else ")
i.ifFalse.emit(gctx)
gctx.
write(
")")
}
func (i
*ifExpr) typ() starlarkType {
tType := i.ifTrue.typ()
fType := i.ifFalse.typ()
if tType != fType && tType != starlarkTypeUnknown && fType != starlarkTypeUnknown {
panic(
"Conflicting types in if expression")
}
if tType != starlarkTypeUnknown {
return tType
}
else {
return fType
}
}
func (i
*ifExpr) emitListVarCopy(gctx *generationContext) {
i.emit(gctx)
}
func (i
*ifExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
i.condition = i.condition.transform(transformer)
i.ifTrue = i.ifTrue.transform(transformer)
i.ifFalse = i.ifFalse.transform(transformer)
if replacement := transformer(i); replacement != nil {
return replacement
}
else {
return i
}
}
type identifierExpr struct {
name
string
}
func (i
*identifierExpr) emit(gctx *generationContext) {
gctx.
write(i.name)
}
func (i
*identifierExpr) typ() starlarkType {
return starlarkTypeUnknown
}
func (i
*identifierExpr) emitListVarCopy(gctx *generationContext) {
i.emit(gctx)
}
func (i
*identifierExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(i); replacement != nil {
return replacement
}
else {
return i
}
}
type foreachExpr struct {
varName
string
list starlarkExpr
action starlarkExpr
}
func (f
*foreachExpr) emit(gctx *generationContext) {
gctx.
write(
"[")
f.action.emit(gctx)
gctx.
write(
" for " + f.varName +
" in ")
f.list.emit(gctx)
gctx.
write(
"]")
}
func (f
*foreachExpr) typ() starlarkType {
return starlarkTypeList
}
func (f
*foreachExpr) emitListVarCopy(gctx *generationContext) {
f.emit(gctx)
}
func (f
*foreachExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
f.list = f.list.transform(transformer)
f.action = f.action.transform(transformer)
if replacement := transformer(f); replacement != nil {
return replacement
}
else {
return f
}
}
type binaryOpExpr struct {
left, right starlarkExpr
op
string
returnType starlarkType
}
func (b
*binaryOpExpr) emit(gctx *generationContext) {
b.left.emit(gctx)
gctx.
write(
" " + b.op +
" ")
b.right.emit(gctx)
}
func (b
*binaryOpExpr) typ() starlarkType {
return b.returnType
}
func (b
*binaryOpExpr) emitListVarCopy(gctx *generationContext) {
b.emit(gctx)
}
func (b
*binaryOpExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
b.left = b.left.transform(transformer)
b.right = b.right.transform(transformer)
if replacement := transformer(b); replacement != nil {
return replacement
}
else {
return b
}
}
type badExpr struct {
errorLocation ErrorLocation
message string
}
func (b
*badExpr) emit(gctx *generationContext) {
gctx.emitConversionError(b.errorLocation, b.
message)
}
func (_
*badExpr) typ() starlarkType {
return starlarkTypeUnknown
}
func (b
*badExpr) emitListVarCopy(gctx *generationContext) {
b.emit(gctx)
}
func (b
*badExpr) transform(transformer func(expr starlarkExpr) starlarkExpr) starlarkExpr {
if replacement := transformer(b); replacement != nil {
return replacement
}
else {
return b
}
}
func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
if xString, ok := expr.(
*stringLiteralExpr); ok {
return newStringListExpr(strings.Fields(
xString.literal))
}
return expr
}
func isEmptyString(expr starlarkExpr) bool {
x, ok := expr.(
*stringLiteralExpr)
return ok && x.literal ==
""
}
func negateExpr(expr starlarkExpr) starlarkExpr {
switch typedExpr := expr.(
type) {
case *notExpr:
return typedExpr.expr
case *inExpr:
typedExpr.isNot = !typedExpr.isNot
return typedExpr
case *eqExpr:
typedExpr.isEq = !typedExpr.isEq
return typedExpr
case *binaryOpExpr:
switch typedExpr.op {
case ">":
typedExpr.op =
"<="
return typedExpr
case "<":
typedExpr.op =
">="
return typedExpr
case ">=":
typedExpr.op =
"<"
return typedExpr
case "<=":
typedExpr.op =
">"
return typedExpr
default:
return ¬Expr{expr: expr}
}
default:
return ¬Expr{expr: expr}
}
}