@abaplint/transpiler
Version:
251 lines • 13.6 kB
JavaScript
"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