UNPKG

@abaplint/transpiler

Version:
251 lines • 13.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SourceTranspiler = void 0; const core_1 = require("@abaplint/core"); const _1 = require("."); const chunk_1 = require("../chunk"); const constant_1 = require("./constant"); const corresponding_body_1 = require("./corresponding_body"); const filter_body_1 = require("./filter_body"); const reduce_body_1 = require("./reduce_body"); const transpile_types_1 = require("../transpile_types"); const value_body_1 = require("./value_body"); class SourceTranspiler { addGet; constructor(addGet = false) { this.addGet = addGet; } transpile(node, traversal, context) { let ret = new chunk_1.Chunk(); const post = new chunk_1.Chunk(); const children = node.getChildren(); // Pre-scan for unary prefix +/- tokens (WDashW / WPlusW) before any expression let prefixNegated = false; let startIdx = 0; while (startIdx < children.length) { const c = children[startIdx]; if (c instanceof core_1.Nodes.TokenNode) { const s = c.getFirstToken().getStr(); if (s === "-") { prefixNegated = !prefixNegated; startIdx++; } else if (s === "+") { startIdx++; } else { break; } } else { break; } } for (let i = startIdx; i < children.length; i++) { const c = children[i]; const isLast = i === children.length - 1; if (c instanceof core_1.Nodes.ExpressionNode) { if (c.get() instanceof core_1.Expressions.FieldChain) { ret.appendChunk(new _1.FieldChainTranspiler(this.addGet).transpile(c, traversal)); } else if (c.get() instanceof core_1.Expressions.Constant) { ret.appendChunk(new constant_1.ConstantTranspiler(this.addGet).transpile(c, traversal)); } else if (c.get() instanceof core_1.Expressions.StringTemplate) { ret.appendChunk(new _1.StringTemplateTranspiler().transpile(c, traversal, context)); } else if (c.get() instanceof core_1.Expressions.Cond) { ret.appendChunk(traversal.traverse(c)); } else if (c.get() instanceof core_1.Expressions.ArithOperator) { ret = new chunk_1.Chunk().appendChunk(traversal.traverse(c)).appendString("(").appendChunk(ret).appendString(","); post.appendString(")"); if (this.addGet) { post.append(".get()", c, traversal); } } else if (c.get() instanceof core_1.Expressions.MethodCallChain) { ret.appendChunk(traversal.traverse(c)); const code = ret.getCode(); if (code.includes("await")) { ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(")"); } if (this.addGet && isLast === true) { ret.append(".get()", c, traversal); } } else if (c.get() instanceof core_1.Expressions.Source) { ret.appendChunk(new SourceTranspiler(this.addGet).transpile(c, traversal)); } else if (c.get() instanceof core_1.Expressions.Arrow) { ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(").get()."); } else if (c.get() instanceof core_1.Expressions.AttributeChain) { ret.appendChunk(new _1.AttributeChainTranspiler().transpile(c, traversal)); } else if (c.get() instanceof core_1.Expressions.ComponentChain) { ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(").get()."); ret.appendChunk(new _1.ComponentChainTranspiler().transpile(c, traversal)); if (this.addGet && isLast === true) { ret.append(".get()", c, traversal); } } else if (c.get() instanceof core_1.Expressions.Dereference) { ret = new chunk_1.Chunk().appendString("(").appendChunk(ret).appendString(").dereference()"); } else if (c.get() instanceof core_1.Expressions.TextElement) { ret = new chunk_1.Chunk().appendString(`new abap.types.String().set("${c.concatTokens()}")`); } else if (c.get() instanceof core_1.Expressions.TypeNameOrInfer) { continue; } else if (c.get() instanceof core_1.Expressions.ConvBody) { const typ = node.findFirstExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in ConvBody"); } ret = new chunk_1.Chunk().appendString(new _1.TypeNameOrInfer().transpile(typ, traversal).getCode()); ret.appendString(".set("); // todo: handle LET const context = new _1.TypeNameOrInfer().findType(typ, traversal); ret.appendString(new SourceTranspiler().transpile(c.getFirstChild(), traversal, context).getCode()); ret.appendString(")"); } else if (c.get() instanceof core_1.Expressions.ValueBody) { continue; } else if (c.get() instanceof core_1.Expressions.CorrespondingBody) { continue; } else if (c.get() instanceof core_1.Expressions.CondBody) { continue; } else if (c.get() instanceof core_1.Expressions.ReduceBody) { continue; } else if (c.get() instanceof core_1.Expressions.SwitchBody) { continue; } else if (c.get() instanceof core_1.Expressions.FilterBody) { continue; } else { ret.appendString("SourceUnknown$" + c.get().constructor.name); } } else if (c instanceof core_1.Nodes.TokenNode && (c.getFirstToken().getStr() === "&&" || c.getFirstToken().getStr() === "&")) { ret = new chunk_1.Chunk().appendString("abap.operators.concat(").appendChunk(ret).appendString(","); post.appendString(")"); if (this.addGet) { post.append(".get()", c, traversal); } } else if (c instanceof core_1.Nodes.TokenNodeRegex && c.getFirstToken().getStr().toUpperCase() === "BOOLC") { ret.append("abap.builtin.boolc(", c, traversal); post.append(")", c, traversal); } else if (c instanceof core_1.Nodes.TokenNodeRegex && c.getFirstToken().getStr().toUpperCase() === "XSDBOOL") { ret.append("abap.builtin.xsdbool(", c, traversal); post.append(")", c, traversal); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "VALUE") { const typ = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in ValueBody"); } const valueBody = node.findDirectExpression(core_1.Expressions.ValueBody); if (valueBody) { ret.appendChunk(new value_body_1.ValueBodyTranspiler().transpile(typ, valueBody, traversal)); } else { const context = new _1.TypeNameOrInfer().findType(typ, traversal); ret.appendString(transpile_types_1.TranspileTypes.toType(context)); } } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "CORRESPONDING") { const typ = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in CorrespondingBody"); } const correspondingBody = node.findDirectExpression(core_1.Expressions.CorrespondingBody); if (correspondingBody === undefined) { throw new Error("CorrespondingBody not found"); } ret.appendChunk(new corresponding_body_1.CorrespondingBodyTranspiler().transpile(typ, correspondingBody, traversal)); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "COND") { const typ = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in CondBody"); } const condBody = node.findDirectExpression(core_1.Expressions.CondBody); if (condBody === undefined) { throw new Error("CondBody not found"); } ret.appendChunk(new _1.CondBodyTranspiler().transpile(typ, condBody, traversal)); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "SWITCH") { const typ = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in SwitchBody"); } const switchBody = node.findDirectExpression(core_1.Expressions.SwitchBody); if (switchBody === undefined) { throw new Error("SwitchBody not found"); } ret.appendChunk(new _1.SwitchBodyTranspiler().transpile(typ, switchBody, traversal)); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "FILTER") { const typ = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in FilterBody"); } const filterBody = node.findDirectExpression(core_1.Expressions.FilterBody); if (filterBody === undefined) { throw new Error("FilterBody not found"); } ret.appendChunk(new filter_body_1.FilterBodyTranspiler().transpile(typ, filterBody, traversal)); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "REDUCE") { const typ = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (typ === undefined) { throw new Error("TypeNameOrInfer not found in ReduceBody"); } const reduceBody = node.findDirectExpression(core_1.Expressions.ReduceBody); if (reduceBody === undefined) { throw new Error("ReduceBody not found"); } ret.appendChunk(new reduce_body_1.ReduceBodyTranspiler().transpile(typ, reduceBody, traversal)); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "REF") { const infer = node.findDirectExpression(core_1.Expressions.TypeNameOrInfer); if (infer?.concatTokens() !== "#") { throw new Error("transpiler: REF # todo1"); } const scope = traversal.findCurrentScopeByToken(infer.getFirstToken()); const inferType = traversal.lookupInferred(infer, scope); if (inferType === undefined) { throw new Error("transpiler: REF # todo, lookupInferred, " + node.concatTokens()); } const typ = transpile_types_1.TranspileTypes.toType(inferType); if (typ.startsWith("new abap.types.DataReference(") === false) { throw new Error("transpiler: REF # unexpected type"); } ret.append(`abap.statements.getReference(${typ}, `, c, traversal); post.append(")", c, traversal); } else if (c instanceof core_1.Nodes.TokenNode && c.getFirstToken().getStr().toUpperCase() === "BIT") { // todo, this will not work in the general case ret.append("abap.operators.bitnot(", c, traversal); post.append(")", c, traversal); } } ret.appendChunk(post); if (prefixNegated) { ret = new chunk_1.Chunk().appendString("abap.operators.minus(0, ").appendChunk(ret).appendString(")"); } // console.dir("return: " + ret.getCode()); return ret; } } exports.SourceTranspiler = SourceTranspiler; //# sourceMappingURL=source.js.map