@lango-project/lango-js 0.1.2 → 0.1.4
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.
- package/NOTICE +5 -0
- package/README.md +3 -1
- package/package.json +1 -1
- package/src/cli.mjs +8 -2
- package/src/compiler.mjs +198 -58
- package/src/runtime.mjs +92 -1
- package/src/template/package.json +4 -0
- package/src/vendor/xmldom/conventions.js +429 -0
- package/src/vendor/xmldom/dom-parser.js +591 -0
- package/src/vendor/xmldom/dom.js +3759 -0
- package/src/vendor/xmldom/entities.js +2171 -0
- package/src/vendor/xmldom/errors.js +205 -0
- package/src/vendor/xmldom/grammar.js +559 -0
- package/src/vendor/xmldom/index.js +41 -0
- package/src/vendor/xmldom/sax.js +983 -0
- package/src/vendor/xmldom.LICENSE.md +8 -0
package/src/compiler.mjs
CHANGED
|
@@ -32,7 +32,8 @@ export function formatDiagnostics(error) {
|
|
|
32
32
|
|
|
33
33
|
export async function buildFile(inputPath, outputPath, seen = new Set(), includeTests = false, profile = {}) {
|
|
34
34
|
const decimalProfile = validateDecimalProfile(profile);
|
|
35
|
-
|
|
35
|
+
const isEntryPoint = seen.size === 0;
|
|
36
|
+
if (isEntryPoint)
|
|
36
37
|
await validateModuleInitializerCycles(inputPath, outputPath);
|
|
37
38
|
if (seen.has(inputPath)) return;
|
|
38
39
|
seen.add(inputPath);
|
|
@@ -86,10 +87,19 @@ export async function buildFile(inputPath, outputPath, seen = new Set(), include
|
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
const compiled = compile(source, inputPath, imports, includeTests, decimalProfile);
|
|
89
|
-
|
|
90
|
+
let output = compiled.javascript.replace(
|
|
90
91
|
"//# sourceMappingURL=main.mjs.map",
|
|
91
92
|
`//# sourceMappingURL=${path.basename(outputPath)}.map`,
|
|
92
93
|
);
|
|
94
|
+
if (isEntryPoint && profile.executable) {
|
|
95
|
+
const main = compiled.program.functions.find((item) => item.name === "main" && item.exported);
|
|
96
|
+
if (!main)
|
|
97
|
+
throw new LangoError("LNG1265", 1, "an executable build requires export main(args)", inputPath);
|
|
98
|
+
output = output.replace(
|
|
99
|
+
`//# sourceMappingURL=${path.basename(outputPath)}.map`,
|
|
100
|
+
`const { configure } = await import("./.lango/runtime.mjs");\nconfigure({ output: (value) => console.log(value) });\nawait main(process.argv.slice(2));\n//# sourceMappingURL=${path.basename(outputPath)}.map`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
93
103
|
const directory = path.dirname(outputPath);
|
|
94
104
|
|
|
95
105
|
await mkdir(path.join(directory, ".lango"), { recursive: true });
|
|
@@ -111,6 +121,19 @@ export async function buildFile(inputPath, outputPath, seen = new Set(), include
|
|
|
111
121
|
await readFile(new URL("./vendor/bignumber.mjs", import.meta.url), "utf8"),
|
|
112
122
|
"utf8",
|
|
113
123
|
);
|
|
124
|
+
const xmlVendor = new URL("./vendor/xmldom/", import.meta.url);
|
|
125
|
+
await mkdir(path.join(directory, ".lango/xmldom"), { recursive: true });
|
|
126
|
+
for (const name of ["conventions.js", "dom-parser.js", "dom.js", "entities.js", "errors.js", "grammar.js", "index.js", "sax.js"])
|
|
127
|
+
await writeFile(
|
|
128
|
+
path.join(directory, ".lango/xmldom", name),
|
|
129
|
+
await readFile(new URL(name, xmlVendor), "utf8"),
|
|
130
|
+
"utf8",
|
|
131
|
+
);
|
|
132
|
+
await writeFile(
|
|
133
|
+
path.join(directory, ".lango/xmldom.LICENSE.md"),
|
|
134
|
+
await readFile(new URL("./vendor/xmldom.LICENSE.md", import.meta.url), "utf8"),
|
|
135
|
+
"utf8",
|
|
136
|
+
);
|
|
114
137
|
}
|
|
115
138
|
|
|
116
139
|
export function compile(source, sourceName = "<source>", imports = [], includeTests = false, profile = {}) {
|
|
@@ -243,7 +266,6 @@ class Parser {
|
|
|
243
266
|
const tests = [];
|
|
244
267
|
const jsImports = [];
|
|
245
268
|
let declarationSeen = false;
|
|
246
|
-
let exportedClassSeen = false;
|
|
247
269
|
this.blank();
|
|
248
270
|
while (this.i < this.lines.length) {
|
|
249
271
|
const line = this.line();
|
|
@@ -293,9 +315,6 @@ class Parser {
|
|
|
293
315
|
);
|
|
294
316
|
if (classHeader) {
|
|
295
317
|
declarationSeen = true;
|
|
296
|
-
if (classHeader[1] && exportedClassSeen)
|
|
297
|
-
this.fail(line, "LNG1114", "a file may export one class");
|
|
298
|
-
exportedClassSeen ||= Boolean(classHeader[1]);
|
|
299
318
|
const classNode = {
|
|
300
319
|
name: classHeader[2],
|
|
301
320
|
ancestor: classHeader[3] ?? null,
|
|
@@ -538,6 +557,8 @@ class Parser {
|
|
|
538
557
|
} else if (/^global (\$?[A-Za-z_]\w*)$/.test(text)) {
|
|
539
558
|
const [, name] = /^global (\$?[A-Za-z_]\w*)$/.exec(text);
|
|
540
559
|
body.push({ type: "globalDeclare", name, line: line.number });
|
|
560
|
+
} else if (/^@{1,2}\$?[A-Za-z_]\w*.*\(.*\)$/.test(text) && !text.includes(" = ")) {
|
|
561
|
+
body.push({ type: "expression", value: expr(text, line, this) });
|
|
541
562
|
} else if (/^context ([A-Za-z_]\w*) = (.+)$/.test(text)) {
|
|
542
563
|
const [, name, value] = /^context ([A-Za-z_]\w*) = (.+)$/.exec(text);
|
|
543
564
|
body.push({ type: "contextSet", name, value: expr(value, line, this) });
|
|
@@ -777,7 +798,7 @@ class Parser {
|
|
|
777
798
|
value: { type: "new", name: constructor, arguments: [closure], line: line.number },
|
|
778
799
|
});
|
|
779
800
|
}
|
|
780
|
-
else if (/^(.+)\.([A-Za-z_]\w*)\((.*), \(([^)]*)\)$/.test(text)) {
|
|
801
|
+
else if (!text.includes(" = ") && /^(.+)\.([A-Za-z_]\w*)\((.*), \(([^)]*)\)$/.test(text)) {
|
|
781
802
|
const [, receiver, name, argumentsText, parameters] =
|
|
782
803
|
/^(.+)\.([A-Za-z_]\w*)\((.*), \(([^)]*)\)$/.exec(text);
|
|
783
804
|
const closure = {
|
|
@@ -803,7 +824,34 @@ class Parser {
|
|
|
803
824
|
},
|
|
804
825
|
});
|
|
805
826
|
}
|
|
806
|
-
else if (/^(.+)\.([A-Za-z_]\w*)\(
|
|
827
|
+
else if (/^(\$?[A-Za-z_]\w*) = (.+)\.([A-Za-z_]\w*)\((?:(.*), )?\(([^)]*)\)$/.test(text)) {
|
|
828
|
+
const [, name, receiver, method, argumentsText, parameters] =
|
|
829
|
+
/^(\$?[A-Za-z_]\w*) = (.+)\.([A-Za-z_]\w*)\((?:(.*), )?\(([^)]*)\)$/.exec(text);
|
|
830
|
+
const closure = {
|
|
831
|
+
type: "closure",
|
|
832
|
+
parameters: this.parameters(parameters, line),
|
|
833
|
+
captures: this.captures(),
|
|
834
|
+
line: line.number,
|
|
835
|
+
body: this.block(indent + 4),
|
|
836
|
+
};
|
|
837
|
+
this.blank();
|
|
838
|
+
if (this.peek() !== `${" ".repeat(indent)})`)
|
|
839
|
+
this.fail(line, "LNG1266", "assigned method callback requires a closing parenthesis");
|
|
840
|
+
this.i += 1;
|
|
841
|
+
body.push({
|
|
842
|
+
type: "assign",
|
|
843
|
+
name,
|
|
844
|
+
value: {
|
|
845
|
+
type: "methodCall",
|
|
846
|
+
receiver,
|
|
847
|
+
optional: false,
|
|
848
|
+
name: method,
|
|
849
|
+
arguments: [...(argumentsText ? splitTopLevel(argumentsText).map((item) => expr(item, line, this)) : []), closure],
|
|
850
|
+
line: line.number,
|
|
851
|
+
},
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
else if (!text.includes(" = ") && /^(.+)\.([A-Za-z_]\w*)\(\(([^)]*)\)$/.test(text)) {
|
|
807
855
|
const [, first, name, parameters] = /^(.+)\.([A-Za-z_]\w*)\(\(([^)]*)\)$/.exec(text);
|
|
808
856
|
const steps = [];
|
|
809
857
|
let step = { name, parameters: this.parameters(parameters, line), captures: this.captures(), line: line.number, body: this.block(indent + 4) };
|
|
@@ -898,9 +946,9 @@ class Parser {
|
|
|
898
946
|
name,
|
|
899
947
|
value: { type: "sql", text: sqlText, parts, parameters },
|
|
900
948
|
});
|
|
901
|
-
} else if (/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] = (.+)$/.test(text)) {
|
|
949
|
+
} else if (/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] = (.+)$/.test(text)) {
|
|
902
950
|
const [, receiver, firstIndex, secondIndex, sourceValue] =
|
|
903
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] = (.+)$/.exec(text);
|
|
951
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] = (.+)$/.exec(text);
|
|
904
952
|
body.push({
|
|
905
953
|
type: "indexAssign",
|
|
906
954
|
receiver,
|
|
@@ -908,9 +956,9 @@ class Parser {
|
|
|
908
956
|
value: this.expression(sourceValue, line),
|
|
909
957
|
operator: null,
|
|
910
958
|
});
|
|
911
|
-
} else if (/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.test(text)) {
|
|
959
|
+
} else if (/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.test(text)) {
|
|
912
960
|
const [, receiver, firstIndex, secondIndex, operator, sourceValue] =
|
|
913
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
961
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
914
962
|
body.push({
|
|
915
963
|
type: "indexAssign",
|
|
916
964
|
receiver,
|
|
@@ -918,9 +966,9 @@ class Parser {
|
|
|
918
966
|
value: this.expression(sourceValue, line),
|
|
919
967
|
operator,
|
|
920
968
|
});
|
|
921
|
-
} else if (/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\](\+\+|--)$/.test(text)) {
|
|
969
|
+
} else if (/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\](\+\+|--)$/.test(text)) {
|
|
922
970
|
const [, receiver, firstIndex, secondIndex, suffix] =
|
|
923
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
971
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
924
972
|
body.push({
|
|
925
973
|
type: "indexAssign",
|
|
926
974
|
receiver,
|
|
@@ -928,9 +976,9 @@ class Parser {
|
|
|
928
976
|
value: { type: "raw", value: "1" },
|
|
929
977
|
operator: suffix === "++" ? "+" : "-",
|
|
930
978
|
});
|
|
931
|
-
} else if (/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] = (.+)$/.test(text)) {
|
|
979
|
+
} else if (/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] = (.+)$/.test(text)) {
|
|
932
980
|
const [, receiver, sourceIndex, sourceValue] =
|
|
933
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] = (.+)$/.exec(text);
|
|
981
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] = (.+)$/.exec(text);
|
|
934
982
|
body.push({
|
|
935
983
|
type: "indexAssign",
|
|
936
984
|
receiver,
|
|
@@ -938,9 +986,9 @@ class Parser {
|
|
|
938
986
|
value: this.expression(sourceValue, line),
|
|
939
987
|
operator: null,
|
|
940
988
|
});
|
|
941
|
-
} else if (/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.test(text)) {
|
|
989
|
+
} else if (/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.test(text)) {
|
|
942
990
|
const [, receiver, sourceIndex, operator, sourceValue] =
|
|
943
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
991
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
944
992
|
body.push({
|
|
945
993
|
type: "indexAssign",
|
|
946
994
|
receiver,
|
|
@@ -948,9 +996,9 @@ class Parser {
|
|
|
948
996
|
value: this.expression(sourceValue, line),
|
|
949
997
|
operator,
|
|
950
998
|
});
|
|
951
|
-
} else if (/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\](\+\+|--)$/.test(text)) {
|
|
999
|
+
} else if (/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\](\+\+|--)$/.test(text)) {
|
|
952
1000
|
const [, receiver, sourceIndex, suffix] =
|
|
953
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
1001
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
954
1002
|
body.push({
|
|
955
1003
|
type: "indexAssign",
|
|
956
1004
|
receiver,
|
|
@@ -959,7 +1007,7 @@ class Parser {
|
|
|
959
1007
|
operator: suffix === "++" ? "+" : "-",
|
|
960
1008
|
});
|
|
961
1009
|
} else {
|
|
962
|
-
const assignment = /^(\$[A-Za-z_]\w*|@{0,2}\$?[A-Za-z_]\w
|
|
1010
|
+
const assignment = /^(\$[A-Za-z_]\w*|@{0,2}\$?[A-Za-z_]\w*(?:\.\$?[A-Za-z_]\w*)*) = (.+)$/.exec(text);
|
|
963
1011
|
if (!assignment)
|
|
964
1012
|
this.fail(line, "LNG1106", `unsupported Faz 2 statement: ${text}`);
|
|
965
1013
|
body.push({
|
|
@@ -1288,10 +1336,18 @@ function expr(source, line, parser) {
|
|
|
1288
1336
|
}),
|
|
1289
1337
|
};
|
|
1290
1338
|
}
|
|
1339
|
+
if (text.startsWith("not "))
|
|
1340
|
+
return {
|
|
1341
|
+
type: "unary",
|
|
1342
|
+
operator: "not",
|
|
1343
|
+
value: expr(text.slice(4), line, parser),
|
|
1344
|
+
};
|
|
1291
1345
|
for (const operators of [
|
|
1292
1346
|
["??"],
|
|
1293
|
-
["or"
|
|
1294
|
-
["and"
|
|
1347
|
+
["or"],
|
|
1348
|
+
["and"],
|
|
1349
|
+
["||"],
|
|
1350
|
+
["&&"],
|
|
1295
1351
|
["==", "!="],
|
|
1296
1352
|
[">=", "<=", ">", "<", "not in", "in"],
|
|
1297
1353
|
["+", "-"],
|
|
@@ -1314,12 +1370,6 @@ function expr(source, line, parser) {
|
|
|
1314
1370
|
left: expr(text.slice(0, exponent.index), line, parser),
|
|
1315
1371
|
right: expr(text.slice(exponent.index + exponent.operator.length + 2), line, parser),
|
|
1316
1372
|
};
|
|
1317
|
-
if (text.startsWith("not "))
|
|
1318
|
-
return {
|
|
1319
|
-
type: "unary",
|
|
1320
|
-
operator: "not",
|
|
1321
|
-
value: expr(text.slice(4), line, parser),
|
|
1322
|
-
};
|
|
1323
1373
|
if (/^-[^\s]/.test(text))
|
|
1324
1374
|
return {
|
|
1325
1375
|
type: "unary",
|
|
@@ -1364,7 +1414,7 @@ function expr(source, line, parser) {
|
|
|
1364
1414
|
line: line.number,
|
|
1365
1415
|
};
|
|
1366
1416
|
const nestedIndex =
|
|
1367
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*(?:\?\.)?\[.+\])(\?\.)?\[(.+)\]$/.exec(
|
|
1417
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*(?:\?\.)?\[.+\])(\?\.)?\[(.+)\]$/.exec(
|
|
1368
1418
|
text,
|
|
1369
1419
|
);
|
|
1370
1420
|
if (nestedIndex)
|
|
@@ -1375,7 +1425,7 @@ function expr(source, line, parser) {
|
|
|
1375
1425
|
index: expr(nestedIndex[3], line, parser),
|
|
1376
1426
|
};
|
|
1377
1427
|
const computedIndex =
|
|
1378
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*)(\?\.)?\[([^\]]+)\]$/.exec(
|
|
1428
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*)(\?\.)?\[([^\]]+)\]$/.exec(
|
|
1379
1429
|
text,
|
|
1380
1430
|
);
|
|
1381
1431
|
if (
|
|
@@ -1389,7 +1439,7 @@ function expr(source, line, parser) {
|
|
|
1389
1439
|
index: expr(computedIndex[3], line, parser),
|
|
1390
1440
|
};
|
|
1391
1441
|
const indexedProperty =
|
|
1392
|
-
/^([A-Za-z_]\w*.*\])(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1442
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\])(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1393
1443
|
if (
|
|
1394
1444
|
indexedProperty &&
|
|
1395
1445
|
!/^[A-Za-z_]\w*\?\.\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\]$/.test(
|
|
@@ -1403,7 +1453,7 @@ function expr(source, line, parser) {
|
|
|
1403
1453
|
name: indexedProperty[3],
|
|
1404
1454
|
};
|
|
1405
1455
|
const indexedMethodCall =
|
|
1406
|
-
/^([A-Za-z_]\w*.*\])(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1456
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\])(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1407
1457
|
if (indexedMethodCall)
|
|
1408
1458
|
return {
|
|
1409
1459
|
type: "methodCall",
|
|
@@ -1416,7 +1466,7 @@ function expr(source, line, parser) {
|
|
|
1416
1466
|
line: line.number,
|
|
1417
1467
|
};
|
|
1418
1468
|
const nestedCallResultIndex =
|
|
1419
|
-
/^([A-Za-z_]\w*.*\)\?\.\[.+\])(\?\.)?\[(.+)\]$/.exec(text);
|
|
1469
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\)\?\.\[.+\])(\?\.)?\[(.+)\]$/.exec(text);
|
|
1420
1470
|
if (nestedCallResultIndex)
|
|
1421
1471
|
return {
|
|
1422
1472
|
type: "index",
|
|
@@ -1425,7 +1475,7 @@ function expr(source, line, parser) {
|
|
|
1425
1475
|
index: expr(nestedCallResultIndex[3], line, parser),
|
|
1426
1476
|
};
|
|
1427
1477
|
const callResultIndex =
|
|
1428
|
-
/^([A-Za-z_]\w*.*\))(\?\.)?\[(.+)\]$/.exec(text);
|
|
1478
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.)?\[(.+)\]$/.exec(text);
|
|
1429
1479
|
if (callResultIndex)
|
|
1430
1480
|
return {
|
|
1431
1481
|
type: "index",
|
|
@@ -1434,7 +1484,7 @@ function expr(source, line, parser) {
|
|
|
1434
1484
|
index: expr(callResultIndex[3], line, parser),
|
|
1435
1485
|
};
|
|
1436
1486
|
const callResultProperty =
|
|
1437
|
-
/^([A-Za-z_]\w*.*\))(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1487
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1438
1488
|
if (callResultProperty)
|
|
1439
1489
|
return {
|
|
1440
1490
|
type: "property",
|
|
@@ -1443,7 +1493,7 @@ function expr(source, line, parser) {
|
|
|
1443
1493
|
name: callResultProperty[3],
|
|
1444
1494
|
};
|
|
1445
1495
|
const callResultMethod =
|
|
1446
|
-
/^([A-Za-z_]\w*.*\))(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1496
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1447
1497
|
if (callResultMethod)
|
|
1448
1498
|
return {
|
|
1449
1499
|
type: "methodCall",
|
|
@@ -1455,8 +1505,19 @@ function expr(source, line, parser) {
|
|
|
1455
1505
|
: [],
|
|
1456
1506
|
line: line.number,
|
|
1457
1507
|
};
|
|
1508
|
+
const indexedCall = /^(.+)\[(.+)\]\((.*)\)$/.exec(text);
|
|
1509
|
+
if (indexedCall)
|
|
1510
|
+
return {
|
|
1511
|
+
type: "indexedCall",
|
|
1512
|
+
receiver: expr(indexedCall[1], line, parser),
|
|
1513
|
+
index: expr(indexedCall[2], line, parser),
|
|
1514
|
+
arguments: indexedCall[3]
|
|
1515
|
+
? splitTopLevel(indexedCall[3]).map((item) => expr(item, line, parser))
|
|
1516
|
+
: [],
|
|
1517
|
+
line: line.number,
|
|
1518
|
+
};
|
|
1458
1519
|
const methodCall =
|
|
1459
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*?)(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(
|
|
1520
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*?)(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(
|
|
1460
1521
|
text,
|
|
1461
1522
|
);
|
|
1462
1523
|
const namespaceMethodCall =
|
|
@@ -1510,15 +1571,15 @@ function expr(source, line, parser) {
|
|
|
1510
1571
|
return { type: "raw", value: text };
|
|
1511
1572
|
}
|
|
1512
1573
|
if (/^(true|false|null)$/.test(text)) return { type: "raw", value: text };
|
|
1513
|
-
if (
|
|
1574
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*(?:\.|\?\.)_[A-Za-z_]\w*$/.test(text))
|
|
1514
1575
|
parser.fail(
|
|
1515
1576
|
line,
|
|
1516
1577
|
"LNG1115",
|
|
1517
1578
|
"protected properties are not accessible outside a class",
|
|
1518
1579
|
);
|
|
1519
|
-
if (
|
|
1580
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)\$?[A-Za-z_]\w*|(?:\?\.)?\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\])+$/.test(text))
|
|
1520
1581
|
return { type: "raw", value: text };
|
|
1521
|
-
if (
|
|
1582
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\]$/.test(text))
|
|
1522
1583
|
return { type: "raw", value: text };
|
|
1523
1584
|
if (/^(?:\$[A-Za-z_]\w*|@{0,2}\$?[A-Za-z_]\w*)$/.test(text)) return { type: "raw", value: text };
|
|
1524
1585
|
parser.fail(line, "LNG1108", `unsupported Faz 2 expression: ${text}`);
|
|
@@ -1760,6 +1821,8 @@ function validate(program, imports = []) {
|
|
|
1760
1821
|
["is_array", 1],
|
|
1761
1822
|
["range", [1, 2, 3]],
|
|
1762
1823
|
["to_js_number", 1],
|
|
1824
|
+
["import_module", 1],
|
|
1825
|
+
["xml2obj", 1],
|
|
1763
1826
|
["start_trans", 0], ["commit_trans", 0], ["rollback_trans", 0], ["trans_state", 0],
|
|
1764
1827
|
]);
|
|
1765
1828
|
const hostFunctions = new Set(["fetch"]);
|
|
@@ -2508,6 +2571,15 @@ function validate(program, imports = []) {
|
|
|
2508
2571
|
return names;
|
|
2509
2572
|
};
|
|
2510
2573
|
|
|
2574
|
+
const contextBindings = (body, names = new Set()) => {
|
|
2575
|
+
for (const node of body) {
|
|
2576
|
+
if (node.type === "contextDeclare" || node.type === "contextSet") names.add(node.name);
|
|
2577
|
+
if (node.type !== "closureAssign")
|
|
2578
|
+
nestedBodies(node).forEach((child) => contextBindings(child, names));
|
|
2579
|
+
}
|
|
2580
|
+
return names;
|
|
2581
|
+
};
|
|
2582
|
+
|
|
2511
2583
|
const globalDeclarations = (body, names = new Set()) => {
|
|
2512
2584
|
for (const node of body) {
|
|
2513
2585
|
if (node.type === "globalDeclare") names.add(node.name);
|
|
@@ -2563,9 +2635,14 @@ function validate(program, imports = []) {
|
|
|
2563
2635
|
outerBindings,
|
|
2564
2636
|
classScope = null,
|
|
2565
2637
|
inheritedExpiredCatchBindings = new Set(),
|
|
2638
|
+
outerContextBindings = new Set(),
|
|
2566
2639
|
) => {
|
|
2567
2640
|
const available = new Set(outerBindings);
|
|
2568
2641
|
const expiredCatchBindings = new Set(inheritedExpiredCatchBindings);
|
|
2642
|
+
const availableContexts = new Set([
|
|
2643
|
+
...outerContextBindings,
|
|
2644
|
+
...contextBindings(body),
|
|
2645
|
+
]);
|
|
2569
2646
|
for (const node of body) {
|
|
2570
2647
|
const references = new Set();
|
|
2571
2648
|
[node.value, node.condition, node.collection, node.arguments, node.tests].forEach((value) => {
|
|
@@ -2585,6 +2662,7 @@ function validate(program, imports = []) {
|
|
|
2585
2662
|
new Set(available),
|
|
2586
2663
|
classScope,
|
|
2587
2664
|
expiredCatchBindings,
|
|
2665
|
+
availableContexts,
|
|
2588
2666
|
);
|
|
2589
2667
|
const right = node.elseBody
|
|
2590
2668
|
? validateClosures(
|
|
@@ -2592,6 +2670,7 @@ function validate(program, imports = []) {
|
|
|
2592
2670
|
new Set(available),
|
|
2593
2671
|
classScope,
|
|
2594
2672
|
expiredCatchBindings,
|
|
2673
|
+
availableContexts,
|
|
2595
2674
|
)
|
|
2596
2675
|
: available;
|
|
2597
2676
|
const exits = [];
|
|
@@ -2610,6 +2689,7 @@ function validate(program, imports = []) {
|
|
|
2610
2689
|
new Set(available),
|
|
2611
2690
|
classScope,
|
|
2612
2691
|
expiredCatchBindings,
|
|
2692
|
+
availableContexts,
|
|
2613
2693
|
),
|
|
2614
2694
|
);
|
|
2615
2695
|
if (!node.elseBody || reachesEnd(node.elseBody))
|
|
@@ -2620,6 +2700,7 @@ function validate(program, imports = []) {
|
|
|
2620
2700
|
new Set(available),
|
|
2621
2701
|
classScope,
|
|
2622
2702
|
expiredCatchBindings,
|
|
2703
|
+
availableContexts,
|
|
2623
2704
|
)
|
|
2624
2705
|
: new Set(available),
|
|
2625
2706
|
);
|
|
@@ -2635,6 +2716,7 @@ function validate(program, imports = []) {
|
|
|
2635
2716
|
new Set(available),
|
|
2636
2717
|
classScope,
|
|
2637
2718
|
expiredCatchBindings,
|
|
2719
|
+
availableContexts,
|
|
2638
2720
|
);
|
|
2639
2721
|
if (reachesEnd(node.tryBody)) exits.push(tryExit);
|
|
2640
2722
|
if (node.catchBody) {
|
|
@@ -2645,6 +2727,7 @@ function validate(program, imports = []) {
|
|
|
2645
2727
|
new Set(
|
|
2646
2728
|
[...expiredCatchBindings].filter((name) => name !== node.catchName),
|
|
2647
2729
|
),
|
|
2730
|
+
availableContexts,
|
|
2648
2731
|
);
|
|
2649
2732
|
if (reachesEnd(node.catchBody)) exits.push(catchExit);
|
|
2650
2733
|
}
|
|
@@ -2658,6 +2741,7 @@ function validate(program, imports = []) {
|
|
|
2658
2741
|
certain,
|
|
2659
2742
|
classScope,
|
|
2660
2743
|
new Set([...expiredCatchBindings, node.catchName].filter(Boolean)),
|
|
2744
|
+
availableContexts,
|
|
2661
2745
|
)
|
|
2662
2746
|
: certain;
|
|
2663
2747
|
if (!node.finallyBody || reachesEnd(node.finallyBody))
|
|
@@ -2671,6 +2755,7 @@ function validate(program, imports = []) {
|
|
|
2671
2755
|
new Set([...available, node.item]),
|
|
2672
2756
|
classScope,
|
|
2673
2757
|
expiredCatchBindings,
|
|
2758
|
+
availableContexts,
|
|
2674
2759
|
);
|
|
2675
2760
|
continue;
|
|
2676
2761
|
}
|
|
@@ -2680,6 +2765,7 @@ function validate(program, imports = []) {
|
|
|
2680
2765
|
new Set([...available, node.key, node.value]),
|
|
2681
2766
|
classScope,
|
|
2682
2767
|
expiredCatchBindings,
|
|
2768
|
+
availableContexts,
|
|
2683
2769
|
);
|
|
2684
2770
|
continue;
|
|
2685
2771
|
}
|
|
@@ -2695,6 +2781,7 @@ function validate(program, imports = []) {
|
|
|
2695
2781
|
new Set(available),
|
|
2696
2782
|
classScope,
|
|
2697
2783
|
expiredCatchBindings,
|
|
2784
|
+
availableContexts,
|
|
2698
2785
|
);
|
|
2699
2786
|
continue;
|
|
2700
2787
|
}
|
|
@@ -2726,9 +2813,14 @@ function validate(program, imports = []) {
|
|
|
2726
2813
|
(name) =>
|
|
2727
2814
|
!localBindings.has(name) &&
|
|
2728
2815
|
!contextNames.has(name) &&
|
|
2729
|
-
!globalNames.has(name)
|
|
2816
|
+
!globalNames.has(name) &&
|
|
2817
|
+
!standardFunctions.has(name) &&
|
|
2818
|
+
!hostFunctions.has(name),
|
|
2730
2819
|
);
|
|
2731
2820
|
const captures = new Set(closure.captures);
|
|
2821
|
+
const contextCaptures = new Set(
|
|
2822
|
+
closure.captures.filter((name) => availableContexts.has(name)),
|
|
2823
|
+
);
|
|
2732
2824
|
for (const name of needed)
|
|
2733
2825
|
if (!captures.has(name))
|
|
2734
2826
|
throw new LangoError(
|
|
@@ -2737,7 +2829,7 @@ function validate(program, imports = []) {
|
|
|
2737
2829
|
`MissingCapture: ${name}; add capture ${name}`,
|
|
2738
2830
|
);
|
|
2739
2831
|
for (const name of captures) {
|
|
2740
|
-
if (!needed.includes(name))
|
|
2832
|
+
if (!needed.includes(name) && !contextCaptures.has(name))
|
|
2741
2833
|
throw new LangoError(
|
|
2742
2834
|
"LNG1211",
|
|
2743
2835
|
closure.line,
|
|
@@ -2745,7 +2837,7 @@ function validate(program, imports = []) {
|
|
|
2745
2837
|
);
|
|
2746
2838
|
const protectedMember = Boolean(classScope && name.startsWith("_"));
|
|
2747
2839
|
const propertyCapture = name.startsWith("@") || protectedMember;
|
|
2748
|
-
if (!propertyCapture && !available.has(name))
|
|
2840
|
+
if (!propertyCapture && !contextCaptures.has(name) && !available.has(name))
|
|
2749
2841
|
throw new LangoError(
|
|
2750
2842
|
"LNG1212",
|
|
2751
2843
|
closure.line,
|
|
@@ -2778,6 +2870,7 @@ function validate(program, imports = []) {
|
|
|
2778
2870
|
new Set([...available, ...localBindings]),
|
|
2779
2871
|
classScope,
|
|
2780
2872
|
expiredCatchBindings,
|
|
2873
|
+
new Set([...availableContexts, ...contextCaptures]),
|
|
2781
2874
|
);
|
|
2782
2875
|
if (node.type === "closureAssign" || node.type === "assign") available.add(node.name);
|
|
2783
2876
|
continue;
|
|
@@ -3327,6 +3420,7 @@ function emit(program, moduleImports = [], includeTests = false) {
|
|
|
3327
3420
|
flags.print && "println as __println",
|
|
3328
3421
|
flags.translate && "translate as __translate",
|
|
3329
3422
|
flags.xml && "xmlEscape as __xmlEscape",
|
|
3423
|
+
flags.xmlObject && "xml2obj as __xml2obj",
|
|
3330
3424
|
flags.context && "contextGet as __contextGet",
|
|
3331
3425
|
flags.context && "contextSet as __contextSet",
|
|
3332
3426
|
flags.context && "contextRestore as __contextRestore",
|
|
@@ -3356,6 +3450,7 @@ function emit(program, moduleImports = [], includeTests = false) {
|
|
|
3356
3450
|
flags.finite && "finite as __finite",
|
|
3357
3451
|
flags.number && "requireNumber as __requireNumber",
|
|
3358
3452
|
flags.call && "call as __call",
|
|
3453
|
+
flags.callMethod && "callMethod as __callMethod",
|
|
3359
3454
|
flags.boundary && "boundary as __boundary",
|
|
3360
3455
|
flags.database && "startTrans as __startTrans",
|
|
3361
3456
|
flags.database && "commitTrans as __commitTrans",
|
|
@@ -3661,20 +3756,15 @@ function emitStatement(node, depth, declared, flags) {
|
|
|
3661
3756
|
}
|
|
3662
3757
|
if (node.type === "assign") {
|
|
3663
3758
|
const decimalBinding = node.name.startsWith("$") || /^@{1,2}\$/.test(node.name);
|
|
3664
|
-
const
|
|
3665
|
-
|
|
3666
|
-
? node.name
|
|
3667
|
-
: node.name.startsWith("@@")
|
|
3668
|
-
? `${flags.className}.${property}`
|
|
3759
|
+
const target = /^[A-Za-z_]\w*(?:\.\$?[A-Za-z_]\w*)+$/.test(node.name)
|
|
3760
|
+
? emitReceiverName(node.name, flags)
|
|
3669
3761
|
: node.name.startsWith("@")
|
|
3670
|
-
? flags
|
|
3671
|
-
? `this.${property}`
|
|
3672
|
-
: `this.#${property}`
|
|
3762
|
+
? emitReceiverName(node.name, flags)
|
|
3673
3763
|
: flags.className && node.name.startsWith("_")
|
|
3674
3764
|
? `this.${node.name}`
|
|
3675
3765
|
: node.name;
|
|
3676
3766
|
const prefix =
|
|
3677
|
-
/^[A-Za-z_]\w
|
|
3767
|
+
/^[A-Za-z_]\w*(?:\.\$?[A-Za-z_]\w*)+$/.test(node.name)
|
|
3678
3768
|
? ""
|
|
3679
3769
|
: node.name.startsWith("@") ||
|
|
3680
3770
|
(flags.className && node.name.startsWith("_")) ||
|
|
@@ -3696,7 +3786,7 @@ function emitStatement(node, depth, declared, flags) {
|
|
|
3696
3786
|
return `${pad}${prefix}${target} = ${decimalBinding && node.value.type !== "binary" && !decimalLiteral ? `__decimal(${decimalInput})` : value};\n`;
|
|
3697
3787
|
}
|
|
3698
3788
|
if (node.type === "indexAssign") {
|
|
3699
|
-
const target = `${node.receiver}${(node.indexes ?? [node.index]).map((index) => `[${emitExpr(index, flags)}]`).join("")}`;
|
|
3789
|
+
const target = `${emitReceiverName(node.receiver, flags)}${(node.indexes ?? [node.index]).map((index) => `[${emitExpr(index, flags)}]`).join("")}`;
|
|
3700
3790
|
const value = emitExpr(node.value, flags);
|
|
3701
3791
|
if (node.operator) flags.finite = true;
|
|
3702
3792
|
return `${pad}${target} = ${node.operator ? `__finite(${target} ${node.operator} ${value})` : value};\n`;
|
|
@@ -3808,7 +3898,11 @@ function emitClosure(node, depth, flags) {
|
|
|
3808
3898
|
const priorContextNames = flags.contextNames;
|
|
3809
3899
|
const priorGlobalNames = flags.globalNames;
|
|
3810
3900
|
const priorArrayBindings = flags.arrayBindings;
|
|
3811
|
-
const
|
|
3901
|
+
const contextCaptures = node.captures.filter((name) => priorContextNames?.has(name));
|
|
3902
|
+
const contextNames = new Set([
|
|
3903
|
+
...collectContextNames(node.body),
|
|
3904
|
+
...contextCaptures,
|
|
3905
|
+
]);
|
|
3812
3906
|
flags.contextNames = contextNames;
|
|
3813
3907
|
flags.globalNames = collectGlobalNames(node.body);
|
|
3814
3908
|
flags.arrayBindings = new Set();
|
|
@@ -3836,7 +3930,16 @@ function emitClosure(node, depth, flags) {
|
|
|
3836
3930
|
if (!contextNames.size)
|
|
3837
3931
|
return wrap(`(${parameters}) => {\n${boundary}${body}${pad} return null;\n${pad}}`);
|
|
3838
3932
|
flags.context = true;
|
|
3839
|
-
|
|
3933
|
+
const capturedParameters = contextCaptures.map((_, index) => `__capturedContext${index}`);
|
|
3934
|
+
const capturedValues = contextCaptures.map((name) => `__contextGet(${JSON.stringify(name)})`);
|
|
3935
|
+
const capturedSetup = contextCaptures
|
|
3936
|
+
.map((name, index) => `${pad} __contextScope.push(__contextSet(${JSON.stringify(name)}, __capturedContext${index}));\n`)
|
|
3937
|
+
.join("");
|
|
3938
|
+
const callback = `(${parameters}) => {\n${pad} const __contextScope = [];\n${pad} try {\n${capturedSetup}${boundary}${body}${pad} return null;\n${pad} } finally {\n${pad} __contextRestore(__contextScope);\n${pad} }\n${pad}}`;
|
|
3939
|
+
const wrappedCallback = contextCaptures.length
|
|
3940
|
+
? `((${capturedParameters.join(", ")}) => ${callback})(${capturedValues.join(", ")})`
|
|
3941
|
+
: callback;
|
|
3942
|
+
return wrap(wrappedCallback);
|
|
3840
3943
|
}
|
|
3841
3944
|
function emitArityGuard(parameters, actual, name, depth, flags) {
|
|
3842
3945
|
const positions = parameters
|
|
@@ -3860,6 +3963,24 @@ function emitBoundaryChecks(parameters, depth, flags) {
|
|
|
3860
3963
|
})
|
|
3861
3964
|
.join("");
|
|
3862
3965
|
}
|
|
3966
|
+
function emitReceiverName(name, flags) {
|
|
3967
|
+
const member = /^(@{1,2})(\$?[A-Za-z_]\w*)(.*)$/.exec(name);
|
|
3968
|
+
if (member) {
|
|
3969
|
+
const [, scope, property, suffix] = member;
|
|
3970
|
+
const owner = scope === "@@" ? flags.className : "this";
|
|
3971
|
+
const visibility = scope === "@@" || flags.publicProperties?.has(property) ? "" : "#";
|
|
3972
|
+
return `${owner}.${visibility}${property}${suffix}`;
|
|
3973
|
+
}
|
|
3974
|
+
const base = /^([A-Za-z_]\w*)([.\[].*)$/.exec(name);
|
|
3975
|
+
if (base && flags.contextNames?.has(base[1])) {
|
|
3976
|
+
flags.context = true;
|
|
3977
|
+
return `__contextGet(${JSON.stringify(base[1])})${base[2]}`;
|
|
3978
|
+
}
|
|
3979
|
+
if (!flags.contextNames?.has(name)) return name;
|
|
3980
|
+
flags.context = true;
|
|
3981
|
+
return `__contextGet(${JSON.stringify(name)})`;
|
|
3982
|
+
}
|
|
3983
|
+
|
|
3863
3984
|
function emitExpr(node, flags) {
|
|
3864
3985
|
const decimalRaw = (value) =>
|
|
3865
3986
|
value?.type === "raw" &&
|
|
@@ -3873,11 +3994,18 @@ function emitExpr(node, flags) {
|
|
|
3873
3994
|
flags.normalize = true;
|
|
3874
3995
|
return `__normalize(${value})`;
|
|
3875
3996
|
};
|
|
3997
|
+
if (node.type === "raw")
|
|
3998
|
+
if (/^@{1,2}\$?[A-Za-z_]\w*[.\[?]/.test(node.value))
|
|
3999
|
+
return normalize(emitReceiverName(node.value, flags));
|
|
3876
4000
|
if (node.type === "raw")
|
|
3877
4001
|
if (flags.contextNames?.has(node.value)) {
|
|
3878
4002
|
flags.context = true;
|
|
3879
4003
|
return `__contextGet(${JSON.stringify(node.value)})`;
|
|
3880
4004
|
}
|
|
4005
|
+
if (node.type === "raw")
|
|
4006
|
+
if (/^[A-Za-z_]\w*[.\[]/.test(node.value) && flags.contextNames?.has(node.value.split(/[.\[]/)[0])) {
|
|
4007
|
+
return normalize(emitReceiverName(node.value, flags));
|
|
4008
|
+
}
|
|
3881
4009
|
if (node.type === "raw")
|
|
3882
4010
|
if (/^DB\.(Active|RollbackOnly|Failed)$/.test(node.value)) {
|
|
3883
4011
|
flags.databaseEnum = true;
|
|
@@ -3935,7 +4063,7 @@ function emitExpr(node, flags) {
|
|
|
3935
4063
|
return `super.${node.name}(${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
3936
4064
|
if (node.type === "index")
|
|
3937
4065
|
return normalize(
|
|
3938
|
-
`${typeof node.receiver === "string" ? node.receiver : emitExpr(node.receiver, flags)}${node.optional ? "?." : ""}[${emitExpr(node.index, flags)}]`,
|
|
4066
|
+
`${typeof node.receiver === "string" ? emitReceiverName(node.receiver, flags) : emitExpr(node.receiver, flags)}${node.optional ? "?." : ""}[${emitExpr(node.index, flags)}]`,
|
|
3939
4067
|
);
|
|
3940
4068
|
if (node.type === "property")
|
|
3941
4069
|
return normalize(
|
|
@@ -3946,7 +4074,7 @@ function emitExpr(node, flags) {
|
|
|
3946
4074
|
const sourceReceiver = namespace
|
|
3947
4075
|
? node.receiver.replaceAll("/", ".")
|
|
3948
4076
|
: typeof node.receiver === "string"
|
|
3949
|
-
? node.receiver
|
|
4077
|
+
? emitReceiverName(node.receiver, flags)
|
|
3950
4078
|
: emitExpr(node.receiver, flags);
|
|
3951
4079
|
const type =
|
|
3952
4080
|
sourceReceiver === flags.className ||
|
|
@@ -4089,6 +4217,14 @@ function emitExpr(node, flags) {
|
|
|
4089
4217
|
flags.toJsNumber = true;
|
|
4090
4218
|
return `__toJsNumber(${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
4091
4219
|
}
|
|
4220
|
+
if (node.type === "call")
|
|
4221
|
+
if (node.name === "import_module")
|
|
4222
|
+
return `import(${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
4223
|
+
if (node.type === "call")
|
|
4224
|
+
if (node.name === "xml2obj") {
|
|
4225
|
+
flags.xmlObject = true;
|
|
4226
|
+
return `__xml2obj(${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
4227
|
+
}
|
|
4092
4228
|
if (node.type === "call")
|
|
4093
4229
|
if (node.name === "from_json" || node.name === "to_json") {
|
|
4094
4230
|
flags.json = true;
|
|
@@ -4128,6 +4264,10 @@ function emitExpr(node, flags) {
|
|
|
4128
4264
|
return `__call(${node.name}, ${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
4129
4265
|
} else
|
|
4130
4266
|
return `${node.name}(${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
4267
|
+
if (node.type === "indexedCall") {
|
|
4268
|
+
flags.callMethod = true;
|
|
4269
|
+
return `__callMethod(${emitExpr(node.receiver, flags)}, ${emitExpr(node.index, flags)}, ${node.arguments.map((item) => emitExpr(item, flags)).join(", ")})`;
|
|
4270
|
+
}
|
|
4131
4271
|
if (node.type === "string") return emitString(node.literal, flags);
|
|
4132
4272
|
if (node.type === "xml") {
|
|
4133
4273
|
flags.xml = true;
|