@abaplint/transpiler 2.13.95 → 2.13.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/build/src/chunk.js +2 -1
  2. package/build/src/db/schema_generation/pg_database_schema.js +3 -0
  3. package/build/src/db/schema_generation/snowflake_database_schema.js +3 -0
  4. package/build/src/db/schema_generation/sqlite_database_schema.js +3 -0
  5. package/build/src/expressions/reduce_body.js +12 -16
  6. package/build/src/expressions/source.d.ts +3 -1
  7. package/build/src/expressions/source.js +29 -5
  8. package/build/src/expressions/sql_cond.d.ts +1 -0
  9. package/build/src/expressions/sql_cond.js +15 -3
  10. package/build/src/expressions/value_body.js +25 -22
  11. package/build/src/statements/_dataset.d.ts +17 -0
  12. package/build/src/statements/_dataset.js +82 -0
  13. package/build/src/statements/_selection.d.ts +18 -0
  14. package/build/src/statements/_selection.js +82 -0
  15. package/build/src/statements/assign.js +9 -8
  16. package/build/src/statements/call.js +3 -3
  17. package/build/src/statements/call_function.js +10 -3
  18. package/build/src/statements/close_dataset.d.ts +1 -1
  19. package/build/src/statements/close_dataset.js +40 -2
  20. package/build/src/statements/create_data.js +1 -1
  21. package/build/src/statements/delete_dataset.d.ts +1 -1
  22. package/build/src/statements/delete_dataset.js +40 -2
  23. package/build/src/statements/generate_subroutine.d.ts +3 -1
  24. package/build/src/statements/generate_subroutine.js +72 -2
  25. package/build/src/statements/get_dataset.d.ts +1 -1
  26. package/build/src/statements/get_dataset.js +14 -2
  27. package/build/src/statements/loop.d.ts +1 -0
  28. package/build/src/statements/loop.js +12 -0
  29. package/build/src/statements/move.d.ts +2 -0
  30. package/build/src/statements/move.js +70 -1
  31. package/build/src/statements/open_dataset.d.ts +1 -1
  32. package/build/src/statements/open_dataset.js +32 -2
  33. package/build/src/statements/parameter.d.ts +2 -1
  34. package/build/src/statements/parameter.js +68 -2
  35. package/build/src/statements/perform.js +13 -1
  36. package/build/src/statements/read_dataset.d.ts +1 -1
  37. package/build/src/statements/read_dataset.js +16 -2
  38. package/build/src/statements/select.js +78 -13
  39. package/build/src/statements/select_option.d.ts +1 -1
  40. package/build/src/statements/select_option.js +63 -2
  41. package/build/src/statements/set_dataset.d.ts +1 -1
  42. package/build/src/statements/set_dataset.js +10 -2
  43. package/build/src/statements/sort.d.ts +2 -0
  44. package/build/src/statements/sort.js +33 -4
  45. package/build/src/statements/transfer.d.ts +1 -1
  46. package/build/src/statements/transfer.js +14 -2
  47. package/build/src/structures/class_definition.js +10 -9
  48. package/package.json +2 -2
@@ -1,10 +1,48 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.CloseDatasetTranspiler = void 0;
37
+ const abaplint = __importStar(require("@abaplint/core"));
4
38
  const chunk_1 = require("../chunk");
5
39
  class CloseDatasetTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("CloseDataset, not supported, transpiler");`);
40
+ transpile(node, traversal) {
41
+ const name = traversal.traverse(node.findDirectExpression(abaplint.Expressions.Source)).getCode();
42
+ return new chunk_1.Chunk()
43
+ .append("await abap.statements.closeDataset(", node, traversal)
44
+ .appendString(name)
45
+ .append(");", node.getLastToken(), traversal);
8
46
  }
9
47
  }
10
48
  exports.CloseDatasetTranspiler = CloseDatasetTranspiler;
@@ -83,7 +83,7 @@ class CreateDataTranspiler {
83
83
  }
84
84
  const handle = node.findExpressionAfterToken("HANDLE");
85
85
  if (handle) {
86
- const so = traversal.traverse(node.findDirectExpression(abaplint.Expressions.Source));
86
+ const so = traversal.traverse(handle);
87
87
  const lookup = traversal.lookupClassOrInterface("KERNEL_CREATE_DATA_HANDLE", node.getFirstToken());
88
88
  const call = `await ${lookup}.call({handle: ${so.getCode()}, dref: ${target.getCode()}});`;
89
89
  return new chunk_1.Chunk().append(`if (${lookup} === undefined) throw new Error("CreateData, kernel class missing");\n${call}`, node, traversal);
@@ -3,5 +3,5 @@ import { IStatementTranspiler } from "./_statement_transpiler";
3
3
  import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class DeleteDatasetTranspiler implements IStatementTranspiler {
6
- transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
6
+ transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
7
  }
@@ -1,10 +1,48 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.DeleteDatasetTranspiler = void 0;
37
+ const abaplint = __importStar(require("@abaplint/core"));
4
38
  const chunk_1 = require("../chunk");
5
39
  class DeleteDatasetTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("DeleteDataset, not supported, transpiler");`);
40
+ transpile(node, traversal) {
41
+ const name = traversal.traverse(node.findDirectExpression(abaplint.Expressions.Source)).getCode();
42
+ return new chunk_1.Chunk()
43
+ .append("await abap.statements.deleteDataset(", node, traversal)
44
+ .appendString(name)
45
+ .append(");", node.getLastToken(), traversal);
8
46
  }
9
47
  }
10
48
  exports.DeleteDatasetTranspiler = DeleteDatasetTranspiler;
@@ -3,5 +3,7 @@ import { IStatementTranspiler } from "./_statement_transpiler";
3
3
  import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class GenerateSubroutineTranspiler implements IStatementTranspiler {
6
- transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
6
+ transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
+ /** the expression directly after the addition keyword, MESSAGE does not match MESSAGE-ID */
8
+ private findAddition;
7
9
  }
@@ -1,10 +1,80 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.GenerateSubroutineTranspiler = void 0;
37
+ const abaplint = __importStar(require("@abaplint/core"));
4
38
  const chunk_1 = require("../chunk");
39
+ // GENERATE SUBROUTINE POOL cannot be supported, there is no compiler at runtime.
40
+ // The statement is refused without an exception: sy-subrc = 8 (documented as "other
41
+ // generation error"), NAME initial, MESSAGE filled, LINE 0 and WORD initial. This is
42
+ // a refusal of its own, not what a system answers; the other additions are left untouched.
5
43
  class GenerateSubroutineTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("GenerateSubroutine, not supported, transpiler");`);
44
+ transpile(node, traversal) {
45
+ const ret = new chunk_1.Chunk();
46
+ const name = this.findAddition(node, "NAME");
47
+ if (name) {
48
+ ret.appendString(traversal.traverse(name).getCode() + ".clear();\n");
49
+ }
50
+ const message = this.findAddition(node, "MESSAGE");
51
+ if (message) {
52
+ ret.appendString(traversal.traverse(message).getCode() + `.set("GENERATE SUBROUTINE POOL is not supported");\n`);
53
+ }
54
+ const line = this.findAddition(node, "LINE");
55
+ if (line) {
56
+ ret.appendString(traversal.traverse(line).getCode() + ".set(0);\n");
57
+ }
58
+ const word = this.findAddition(node, "WORD");
59
+ if (word) {
60
+ ret.appendString(traversal.traverse(word).getCode() + ".clear();\n");
61
+ }
62
+ ret.append("abap.builtin.sy.get().subrc.set(8);", node, traversal);
63
+ return ret;
64
+ }
65
+ /** the expression directly after the addition keyword, MESSAGE does not match MESSAGE-ID */
66
+ findAddition(node, keyword) {
67
+ const children = node.getChildren();
68
+ for (let i = 0; i < children.length - 1; i++) {
69
+ const child = children[i];
70
+ const next = children[i + 1];
71
+ if (child instanceof abaplint.Nodes.TokenNode
72
+ && child.getFirstToken().getStr().toUpperCase() === keyword
73
+ && next instanceof abaplint.Nodes.ExpressionNode) {
74
+ return next;
75
+ }
76
+ }
77
+ return undefined;
8
78
  }
9
79
  }
10
80
  exports.GenerateSubroutineTranspiler = GenerateSubroutineTranspiler;
@@ -3,5 +3,5 @@ import { IStatementTranspiler } from "./_statement_transpiler";
3
3
  import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class GetDatasetTranspiler implements IStatementTranspiler {
6
- transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
6
+ transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
7
  }
@@ -2,9 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GetDatasetTranspiler = void 0;
4
4
  const chunk_1 = require("../chunk");
5
+ const _dataset_1 = require("./_dataset");
5
6
  class GetDatasetTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("GetDataset, not supported, transpiler");`);
7
+ transpile(node, traversal) {
8
+ const operands = new _dataset_1.DatasetOperands(node, traversal);
9
+ const options = [];
10
+ if (operands.after("POSITION") !== undefined) {
11
+ options.push("position: " + operands.after("POSITION"));
12
+ }
13
+ if (operands.after("ATTRIBUTES") !== undefined) {
14
+ options.push("attributes: " + operands.after("ATTRIBUTES"));
15
+ }
16
+ return new chunk_1.Chunk()
17
+ .append("await abap.statements.getDataset(", node, traversal)
18
+ .appendString(operands.first() + ", {" + options.join(", ") + "}")
19
+ .append(");", node.getLastToken(), traversal);
8
20
  }
9
21
  }
10
22
  exports.GetDatasetTranspiler = GetDatasetTranspiler;
@@ -15,4 +15,5 @@ export declare class LoopTranspiler implements IStatementTranspiler {
15
15
  getTarget(): string;
16
16
  private determineInto;
17
17
  transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
18
+ private hasHeaderLine;
18
19
  }
@@ -94,6 +94,10 @@ class LoopTranspiler {
94
94
  targetNode = assigning;
95
95
  target = traversal.traverse(assigning).getCode() + ".assign(" + this.unique + ");";
96
96
  }
97
+ else if (!node.concatTokens().toUpperCase().includes(" TRANSPORTING NO FIELDS") && this.hasHeaderLine(loopSource, traversal)) {
98
+ // LOOP AT itab. without a target: the row goes into the header line of the table
99
+ target = source + ".getHeader().set(" + this.unique + ");";
100
+ }
97
101
  }
98
102
  const extra = [];
99
103
  const fromNode = node.findExpressionAfterToken("FROM");
@@ -188,6 +192,14 @@ class LoopTranspiler {
188
192
  }
189
193
  return ret;
190
194
  }
195
+ hasHeaderLine(loopSource, traversal) {
196
+ if (loopSource === undefined || /^[\w\/]+$/.test(loopSource.concatTokens()) === false) {
197
+ return false;
198
+ }
199
+ const token = loopSource.getFirstToken();
200
+ const type = traversal.findCurrentScopeByToken(token)?.findVariable(loopSource.concatTokens())?.getType();
201
+ return type instanceof abaplint.BasicTypes.TableType && type.isWithHeader();
202
+ }
191
203
  }
192
204
  exports.LoopTranspiler = LoopTranspiler;
193
205
  //# sourceMappingURL=loop.js.map
@@ -4,4 +4,6 @@ import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class MoveTranspiler implements IStatementTranspiler {
6
6
  transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
+ private isInt8Calculation;
8
+ private integerOperands;
7
9
  }
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.MoveTranspiler = void 0;
37
37
  const abaplint = __importStar(require("@abaplint/core"));
38
38
  const chunk_1 = require("../chunk");
39
+ const source_1 = require("../expressions/source");
39
40
  class MoveTranspiler {
40
41
  transpile(node, traversal) {
41
42
  const sourceExpression = node.findDirectExpression(abaplint.Expressions.Source);
@@ -55,7 +56,9 @@ class MoveTranspiler {
55
56
  ret.appendString(target + `.set(abap.alphaIn(${tSource.getCode()}, ${target}, ${target}));`);
56
57
  return ret;
57
58
  }
58
- let source = traversal.traverse(sourceExpression);
59
+ let source = this.isInt8Calculation(node, sourceExpression, targetExpressions.length, traversal)
60
+ ? new source_1.SourceTranspiler(false, true).transpile(sourceExpression, traversal)
61
+ : traversal.traverse(sourceExpression);
59
62
  const second = node.getChildren()[1]?.concatTokens();
60
63
  switch (second) {
61
64
  case "?=":
@@ -117,6 +120,72 @@ class MoveTranspiler {
117
120
  }
118
121
  return ret;
119
122
  }
123
+ // The calculation type of an arithmetic expression comes from its operands and the target
124
+ // field, the type with the largest range wins. With operands of type i or int8 it is int8
125
+ // when the target or an operand is int8: i * i into int8 is exact up to 2^62, and "/"
126
+ // rounds. The runtime decides by the operands alone and does not know the target, so here
127
+ // the operands are converted to int8 before the calculation. Only for an i or int8 target
128
+ // and operands whose type is known to be i or int8, and not for **, which counts as f
129
+ isInt8Calculation(node, source, targets, traversal) {
130
+ if (source === undefined
131
+ || targets !== 1
132
+ || source.findFirstExpression(abaplint.Expressions.ArithOperator) === undefined) {
133
+ return false;
134
+ }
135
+ const scope = traversal.findCurrentScopeByToken(node.getFirstToken());
136
+ const target = traversal.determineType(node, scope);
137
+ const found = { int8: target instanceof abaplint.BasicTypes.Integer8Type };
138
+ if (found.int8 === false && !(target instanceof abaplint.BasicTypes.IntegerType)) {
139
+ return false;
140
+ }
141
+ return this.integerOperands(source, scope, found) && found.int8;
142
+ }
143
+ integerOperands(node, scope, found) {
144
+ for (const c of node.getChildren()) {
145
+ if (c instanceof abaplint.Nodes.TokenNode) {
146
+ if (["(", ")", "-", "+"].includes(c.getFirstToken().getStr()) === false) {
147
+ return false;
148
+ }
149
+ }
150
+ else if (c.get() instanceof abaplint.Expressions.Source) {
151
+ if (this.integerOperands(c, scope, found) === false) {
152
+ return false;
153
+ }
154
+ }
155
+ else if (c.get() instanceof abaplint.Expressions.ArithOperator) {
156
+ if (["+", "-", "*", "/", "DIV", "MOD"].includes(c.concatTokens().toUpperCase()) === false) {
157
+ return false;
158
+ }
159
+ }
160
+ else if (c.get() instanceof abaplint.Expressions.Constant) {
161
+ const integer = c.findDirectExpression(abaplint.Expressions.Integer);
162
+ if (integer === undefined) {
163
+ return false;
164
+ }
165
+ else if (Math.abs(parseInt(integer.concatTokens().replace(/ /g, ""), 10)) > 2147483647) {
166
+ // the transpiler makes an int8 of a literal outside the range of i
167
+ found.int8 = true;
168
+ }
169
+ }
170
+ else if (c.get() instanceof abaplint.Expressions.FieldChain) {
171
+ const children = c.getChildren();
172
+ if (children.length !== 1) {
173
+ return false;
174
+ }
175
+ const type = scope?.findVariable(children[0].concatTokens())?.getType();
176
+ if (!(type instanceof abaplint.BasicTypes.IntegerType) && !(type instanceof abaplint.BasicTypes.Integer8Type)) {
177
+ return false;
178
+ }
179
+ if (type instanceof abaplint.BasicTypes.Integer8Type) {
180
+ found.int8 = true;
181
+ }
182
+ }
183
+ else {
184
+ return false;
185
+ }
186
+ }
187
+ return true;
188
+ }
120
189
  }
121
190
  exports.MoveTranspiler = MoveTranspiler;
122
191
  //# sourceMappingURL=move.js.map
@@ -3,5 +3,5 @@ import { IStatementTranspiler } from "./_statement_transpiler";
3
3
  import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class OpenDatasetTranspiler implements IStatementTranspiler {
6
- transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
6
+ transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
7
  }
@@ -2,9 +2,39 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.OpenDatasetTranspiler = void 0;
4
4
  const chunk_1 = require("../chunk");
5
+ const _dataset_1 = require("./_dataset");
5
6
  class OpenDatasetTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("OpenDataset, not supported, transpiler");`);
7
+ transpile(node, traversal) {
8
+ const operands = new _dataset_1.DatasetOperands(node, traversal);
9
+ const options = [];
10
+ const mode = ["INPUT", "OUTPUT", "APPENDING", "UPDATE"].find(m => operands.has("FOR " + m)) ?? "INPUT";
11
+ options.push(`mode: "${mode}"`);
12
+ options.push(`binary: ${operands.has("BINARY MODE")}`);
13
+ const encoding = ["DEFAULT", "UTF-8", "NON-UNICODE"].find(e => operands.has("ENCODING " + e));
14
+ if (encoding !== undefined) {
15
+ options.push(`encoding: "${encoding}"`);
16
+ }
17
+ if (operands.has("IN LEGACY")) {
18
+ options.push("legacy: true");
19
+ }
20
+ if (operands.after("MESSAGE") !== undefined) {
21
+ options.push("message: " + operands.after("MESSAGE"));
22
+ }
23
+ if (operands.after("AT POSITION") !== undefined) {
24
+ options.push("position: " + operands.after("AT POSITION"));
25
+ }
26
+ // accepted by the syntax, not implemented by the runtime: it refuses them
27
+ // by name rather than ignoring them
28
+ const unsupported = ["CODE PAGE", "TYPE", "FILTER", "REPLACEMENT CHARACTER", "WITH BYTE-ORDER MARK", "SKIPPING BYTE-ORDER MARK",
29
+ "WITH SMART LINEFEED", "WITH NATIVE LINEFEED", "WITH UNIX LINEFEED", "WITH WINDOWS LINEFEED", "IGNORING CONVERSION ERRORS"]
30
+ .filter(u => operands.has(u) || operands.after(u) !== undefined);
31
+ if (unsupported.length > 0) {
32
+ options.push("unsupported: " + JSON.stringify(unsupported));
33
+ }
34
+ return new chunk_1.Chunk()
35
+ .append("await abap.statements.openDataset(", node, traversal)
36
+ .appendString(operands.first() + ", {" + options.join(", ") + "}")
37
+ .append(");", node.getLastToken(), traversal);
8
38
  }
9
39
  }
10
40
  exports.OpenDatasetTranspiler = OpenDatasetTranspiler;
@@ -3,5 +3,6 @@ import { IStatementTranspiler } from "./_statement_transpiler";
3
3
  import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class ParameterTranspiler implements IStatementTranspiler {
6
- transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
6
+ transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
+ private isFirstOfUnsetRadioGroup;
7
8
  }
@@ -1,10 +1,76 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.ParameterTranspiler = void 0;
37
+ const abaplint = __importStar(require("@abaplint/core"));
4
38
  const chunk_1 = require("../chunk");
39
+ const transpile_types_1 = require("../transpile_types");
40
+ const _selection_1 = require("./_selection");
5
41
  class ParameterTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("Parameter, not supported, transpiler");`);
42
+ transpile(node, traversal) {
43
+ const variable = _selection_1.SelectionDefault.variable(node, traversal);
44
+ // abaplint types "TYPE c LENGTH 3" and "TYPE p ... DECIMALS 2" of a parameter
45
+ // without the length and the decimals, a value would be cut silently
46
+ const tokens = node.getTokens().map(t => t.getStr().toUpperCase());
47
+ const sized = tokens.some((t, i) => (t === "LENGTH" && tokens[i - 1] !== "VISIBLE") || t === "DECIMALS");
48
+ if (variable === undefined || sized === true) {
49
+ return new chunk_1.Chunk(`throw new Error("Parameter, not supported, transpiler");`);
50
+ }
51
+ const { name, type } = variable;
52
+ const ret = new chunk_1.Chunk().appendString("let " + name + " = " + transpile_types_1.TranspileTypes.toType(type) + ";");
53
+ const operand = _selection_1.SelectionDefault.after(node, "DEFAULT");
54
+ if (operand) {
55
+ ret.appendString(_selection_1.SelectionDefault.set(node, name, type, operand, traversal));
56
+ }
57
+ else if (this.isFirstOfUnsetRadioGroup(node, traversal)) {
58
+ // a radio button group without DEFAULT 'X' starts with its first button chosen
59
+ ret.appendString("\n" + name + ".set('X');");
60
+ }
61
+ return ret;
62
+ }
63
+ isFirstOfUnsetRadioGroup(node, traversal) {
64
+ const group = node.findDirectExpression(abaplint.Expressions.RadioGroupName)?.concatTokens().toUpperCase();
65
+ if (group === undefined) {
66
+ return false;
67
+ }
68
+ const members = traversal.getFile().getStatements().filter(s => s.get() instanceof abaplint.Statements.Parameter
69
+ && s.findDirectExpression(abaplint.Expressions.RadioGroupName)?.concatTokens().toUpperCase() === group);
70
+ if (members.some(m => _selection_1.SelectionDefault.after(m, "DEFAULT") !== undefined)) {
71
+ return false;
72
+ }
73
+ return members[0].getStart().equals(node.getStart());
8
74
  }
9
75
  }
10
76
  exports.ParameterTranspiler = ParameterTranspiler;
@@ -44,16 +44,18 @@ class PerformTranspiler {
44
44
  return new chunk_1.Chunk(`throw new Error("PerformTranspiler FormName not found");`);
45
45
  }
46
46
  else if (node.concatTokens().toUpperCase().includes(" IN PROGRAM ")) {
47
- // todo: throw exception if not found?
48
47
  const expression = node.findExpressionAfterToken("PROGRAM");
49
48
  let ref = "";
49
+ let program = "";
50
50
  if (expression?.get() instanceof abaplint.Expressions.Dynamic) {
51
51
  const name = expression.getChildren()[1].concatTokens() + ".get().trimEnd()";
52
52
  ref = `abap.Forms['PROG-' + ${name} + '-${formName.concatTokens().toUpperCase()}']`;
53
+ program = `'PROG-' + ${name} + '-'`;
53
54
  }
54
55
  else {
55
56
  const progName = expression?.concatTokens().toUpperCase();
56
57
  ref = `abap.Forms['PROG-${progName}-${formName.concatTokens().toUpperCase()}']`;
58
+ program = `'PROG-${progName}-'`;
57
59
  }
58
60
  const params = [];
59
61
  // hacky hack
@@ -65,6 +67,16 @@ class PerformTranspiler {
65
67
  if (node.concatTokens().toUpperCase().includes(" IF FOUND")) {
66
68
  call = `if (${ref} !== undefined) { ${call} }`;
67
69
  }
70
+ else {
71
+ // the form is missing from a program whose forms are registered: CX_SY_DYN_CALL_ILLEGAL_FORM,
72
+ // no form of the program is registered: CX_SY_PROGRAM_NOT_FOUND
73
+ const raise = (name) => {
74
+ const cls = traversal.lookupClassOrInterface(`'${name}'`, node.getFirstToken(), true);
75
+ return `if (${cls} === undefined) { throw "${name} not found"; } else { throw await new ${cls}().constructor_(); }`;
76
+ };
77
+ const loaded = `Object.keys(abap.Forms).some(k => k.startsWith(${program}))`;
78
+ call = `if (${ref} === undefined) { if (${loaded}) { ${raise("CX_SY_DYN_CALL_ILLEGAL_FORM")} } else { ${raise("CX_SY_PROGRAM_NOT_FOUND")} } }\n` + call;
79
+ }
68
80
  return new chunk_1.Chunk(call);
69
81
  }
70
82
  else {
@@ -3,5 +3,5 @@ import { IStatementTranspiler } from "./_statement_transpiler";
3
3
  import { Traversal } from "../traversal";
4
4
  import { Chunk } from "../chunk";
5
5
  export declare class ReadDatasetTranspiler implements IStatementTranspiler {
6
- transpile(_node: abaplint.Nodes.StatementNode, _traversal: Traversal): Chunk;
6
+ transpile(node: abaplint.Nodes.StatementNode, traversal: Traversal): Chunk;
7
7
  }
@@ -2,9 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ReadDatasetTranspiler = void 0;
4
4
  const chunk_1 = require("../chunk");
5
+ const _dataset_1 = require("./_dataset");
5
6
  class ReadDatasetTranspiler {
6
- transpile(_node, _traversal) {
7
- return new chunk_1.Chunk(`throw new Error("ReadDataset, not supported, transpiler");`);
7
+ transpile(node, traversal) {
8
+ const operands = new _dataset_1.DatasetOperands(node, traversal);
9
+ const options = [];
10
+ if (operands.after("MAXIMUM LENGTH") !== undefined) {
11
+ options.push("maximumLength: " + operands.after("MAXIMUM LENGTH"));
12
+ }
13
+ // the obsolete LENGTH is ACTUAL LENGTH
14
+ const actual = operands.after("ACTUAL LENGTH") ?? operands.after("LENGTH", ["MAXIMUM", "ACTUAL"]);
15
+ if (actual !== undefined) {
16
+ options.push("actualLength: " + actual);
17
+ }
18
+ return new chunk_1.Chunk()
19
+ .append("await abap.statements.readDataset(", node, traversal)
20
+ .appendString(operands.first() + ", " + operands.after("INTO") + ", {" + options.join(", ") + "}")
21
+ .append(");", node.getLastToken(), traversal);
8
22
  }
9
23
  }
10
24
  exports.ReadDatasetTranspiler = ReadDatasetTranspiler;