@lango-project/lango-js 0.1.3 → 0.1.5
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/package.json +1 -1
- package/src/compiler.mjs +53 -34
package/package.json
CHANGED
package/src/compiler.mjs
CHANGED
|
@@ -557,6 +557,8 @@ class Parser {
|
|
|
557
557
|
} else if (/^global (\$?[A-Za-z_]\w*)$/.test(text)) {
|
|
558
558
|
const [, name] = /^global (\$?[A-Za-z_]\w*)$/.exec(text);
|
|
559
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) });
|
|
560
562
|
} else if (/^context ([A-Za-z_]\w*) = (.+)$/.test(text)) {
|
|
561
563
|
const [, name, value] = /^context ([A-Za-z_]\w*) = (.+)$/.exec(text);
|
|
562
564
|
body.push({ type: "contextSet", name, value: expr(value, line, this) });
|
|
@@ -944,9 +946,9 @@ class Parser {
|
|
|
944
946
|
name,
|
|
945
947
|
value: { type: "sql", text: sqlText, parts, parameters },
|
|
946
948
|
});
|
|
947
|
-
} 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)) {
|
|
948
950
|
const [, receiver, firstIndex, secondIndex, sourceValue] =
|
|
949
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] = (.+)$/.exec(text);
|
|
951
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] = (.+)$/.exec(text);
|
|
950
952
|
body.push({
|
|
951
953
|
type: "indexAssign",
|
|
952
954
|
receiver,
|
|
@@ -954,9 +956,9 @@ class Parser {
|
|
|
954
956
|
value: this.expression(sourceValue, line),
|
|
955
957
|
operator: null,
|
|
956
958
|
});
|
|
957
|
-
} 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)) {
|
|
958
960
|
const [, receiver, firstIndex, secondIndex, operator, sourceValue] =
|
|
959
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
961
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
960
962
|
body.push({
|
|
961
963
|
type: "indexAssign",
|
|
962
964
|
receiver,
|
|
@@ -964,9 +966,9 @@ class Parser {
|
|
|
964
966
|
value: this.expression(sourceValue, line),
|
|
965
967
|
operator,
|
|
966
968
|
});
|
|
967
|
-
} 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)) {
|
|
968
970
|
const [, receiver, firstIndex, secondIndex, suffix] =
|
|
969
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
971
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\]\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
970
972
|
body.push({
|
|
971
973
|
type: "indexAssign",
|
|
972
974
|
receiver,
|
|
@@ -974,9 +976,9 @@ class Parser {
|
|
|
974
976
|
value: { type: "raw", value: "1" },
|
|
975
977
|
operator: suffix === "++" ? "+" : "-",
|
|
976
978
|
});
|
|
977
|
-
} 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)) {
|
|
978
980
|
const [, receiver, sourceIndex, sourceValue] =
|
|
979
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] = (.+)$/.exec(text);
|
|
981
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] = (.+)$/.exec(text);
|
|
980
982
|
body.push({
|
|
981
983
|
type: "indexAssign",
|
|
982
984
|
receiver,
|
|
@@ -984,9 +986,9 @@ class Parser {
|
|
|
984
986
|
value: this.expression(sourceValue, line),
|
|
985
987
|
operator: null,
|
|
986
988
|
});
|
|
987
|
-
} 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)) {
|
|
988
990
|
const [, receiver, sourceIndex, operator, sourceValue] =
|
|
989
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
991
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\] (\+|-|\*|\/|%|\*\*)= (.+)$/.exec(text);
|
|
990
992
|
body.push({
|
|
991
993
|
type: "indexAssign",
|
|
992
994
|
receiver,
|
|
@@ -994,9 +996,9 @@ class Parser {
|
|
|
994
996
|
value: this.expression(sourceValue, line),
|
|
995
997
|
operator,
|
|
996
998
|
});
|
|
997
|
-
} 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)) {
|
|
998
1000
|
const [, receiver, sourceIndex, suffix] =
|
|
999
|
-
/^([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
1001
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)\[([^\]]+)\](\+\+|--)$/.exec(text);
|
|
1000
1002
|
body.push({
|
|
1001
1003
|
type: "indexAssign",
|
|
1002
1004
|
receiver,
|
|
@@ -1005,7 +1007,7 @@ class Parser {
|
|
|
1005
1007
|
operator: suffix === "++" ? "+" : "-",
|
|
1006
1008
|
});
|
|
1007
1009
|
} else {
|
|
1008
|
-
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);
|
|
1009
1011
|
if (!assignment)
|
|
1010
1012
|
this.fail(line, "LNG1106", `unsupported Faz 2 statement: ${text}`);
|
|
1011
1013
|
body.push({
|
|
@@ -1053,7 +1055,10 @@ class Parser {
|
|
|
1053
1055
|
const next = this.peek();
|
|
1054
1056
|
if (next === undefined || spaces(next) < indent)
|
|
1055
1057
|
this.fail(line, "LNG1262", "unterminated multi-line expression");
|
|
1056
|
-
|
|
1058
|
+
const continuation = this.line().text.trim();
|
|
1059
|
+
const startsField = /^(?:\$?[A-Za-z_][\w-]*|['"][^'"]+['"]): /.test(continuation);
|
|
1060
|
+
if (startsField && !/[{,]\s*$/.test(source)) source += ",";
|
|
1061
|
+
source += ` ${continuation}`;
|
|
1057
1062
|
depth = curlyDelimiterDepth(source);
|
|
1058
1063
|
}
|
|
1059
1064
|
return source;
|
|
@@ -1412,7 +1417,7 @@ function expr(source, line, parser) {
|
|
|
1412
1417
|
line: line.number,
|
|
1413
1418
|
};
|
|
1414
1419
|
const nestedIndex =
|
|
1415
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*(?:\?\.)?\[.+\])(\?\.)?\[(.+)\]$/.exec(
|
|
1420
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*(?:\?\.)?\[.+\])(\?\.)?\[(.+)\]$/.exec(
|
|
1416
1421
|
text,
|
|
1417
1422
|
);
|
|
1418
1423
|
if (nestedIndex)
|
|
@@ -1423,7 +1428,7 @@ function expr(source, line, parser) {
|
|
|
1423
1428
|
index: expr(nestedIndex[3], line, parser),
|
|
1424
1429
|
};
|
|
1425
1430
|
const computedIndex =
|
|
1426
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*)(\?\.)?\[([^\]]+)\]$/.exec(
|
|
1431
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*)(\?\.)?\[([^\]]+)\]$/.exec(
|
|
1427
1432
|
text,
|
|
1428
1433
|
);
|
|
1429
1434
|
if (
|
|
@@ -1437,7 +1442,7 @@ function expr(source, line, parser) {
|
|
|
1437
1442
|
index: expr(computedIndex[3], line, parser),
|
|
1438
1443
|
};
|
|
1439
1444
|
const indexedProperty =
|
|
1440
|
-
/^([A-Za-z_]\w*.*\])(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1445
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\])(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1441
1446
|
if (
|
|
1442
1447
|
indexedProperty &&
|
|
1443
1448
|
!/^[A-Za-z_]\w*\?\.\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\]$/.test(
|
|
@@ -1451,7 +1456,7 @@ function expr(source, line, parser) {
|
|
|
1451
1456
|
name: indexedProperty[3],
|
|
1452
1457
|
};
|
|
1453
1458
|
const indexedMethodCall =
|
|
1454
|
-
/^([A-Za-z_]\w*.*\])(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1459
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\])(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1455
1460
|
if (indexedMethodCall)
|
|
1456
1461
|
return {
|
|
1457
1462
|
type: "methodCall",
|
|
@@ -1464,7 +1469,7 @@ function expr(source, line, parser) {
|
|
|
1464
1469
|
line: line.number,
|
|
1465
1470
|
};
|
|
1466
1471
|
const nestedCallResultIndex =
|
|
1467
|
-
/^([A-Za-z_]\w*.*\)\?\.\[.+\])(\?\.)?\[(.+)\]$/.exec(text);
|
|
1472
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\)\?\.\[.+\])(\?\.)?\[(.+)\]$/.exec(text);
|
|
1468
1473
|
if (nestedCallResultIndex)
|
|
1469
1474
|
return {
|
|
1470
1475
|
type: "index",
|
|
@@ -1473,7 +1478,7 @@ function expr(source, line, parser) {
|
|
|
1473
1478
|
index: expr(nestedCallResultIndex[3], line, parser),
|
|
1474
1479
|
};
|
|
1475
1480
|
const callResultIndex =
|
|
1476
|
-
/^([A-Za-z_]\w*.*\))(\?\.)?\[(.+)\]$/.exec(text);
|
|
1481
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.)?\[(.+)\]$/.exec(text);
|
|
1477
1482
|
if (callResultIndex)
|
|
1478
1483
|
return {
|
|
1479
1484
|
type: "index",
|
|
@@ -1482,7 +1487,7 @@ function expr(source, line, parser) {
|
|
|
1482
1487
|
index: expr(callResultIndex[3], line, parser),
|
|
1483
1488
|
};
|
|
1484
1489
|
const callResultProperty =
|
|
1485
|
-
/^([A-Za-z_]\w*.*\))(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1490
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1486
1491
|
if (callResultProperty)
|
|
1487
1492
|
return {
|
|
1488
1493
|
type: "property",
|
|
@@ -1491,7 +1496,7 @@ function expr(source, line, parser) {
|
|
|
1491
1496
|
name: callResultProperty[3],
|
|
1492
1497
|
};
|
|
1493
1498
|
const callResultMethod =
|
|
1494
|
-
/^([A-Za-z_]\w*.*\))(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1499
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1495
1500
|
if (callResultMethod)
|
|
1496
1501
|
return {
|
|
1497
1502
|
type: "methodCall",
|
|
@@ -1515,7 +1520,7 @@ function expr(source, line, parser) {
|
|
|
1515
1520
|
line: line.number,
|
|
1516
1521
|
};
|
|
1517
1522
|
const methodCall =
|
|
1518
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*?)(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(
|
|
1523
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*?)(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(
|
|
1519
1524
|
text,
|
|
1520
1525
|
);
|
|
1521
1526
|
const namespaceMethodCall =
|
|
@@ -1569,15 +1574,15 @@ function expr(source, line, parser) {
|
|
|
1569
1574
|
return { type: "raw", value: text };
|
|
1570
1575
|
}
|
|
1571
1576
|
if (/^(true|false|null)$/.test(text)) return { type: "raw", value: text };
|
|
1572
|
-
if (
|
|
1577
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*(?:\.|\?\.)_[A-Za-z_]\w*$/.test(text))
|
|
1573
1578
|
parser.fail(
|
|
1574
1579
|
line,
|
|
1575
1580
|
"LNG1115",
|
|
1576
1581
|
"protected properties are not accessible outside a class",
|
|
1577
1582
|
);
|
|
1578
|
-
if (
|
|
1583
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)\$?[A-Za-z_]\w*|(?:\?\.)?\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\])+$/.test(text))
|
|
1579
1584
|
return { type: "raw", value: text };
|
|
1580
|
-
if (
|
|
1585
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\]$/.test(text))
|
|
1581
1586
|
return { type: "raw", value: text };
|
|
1582
1587
|
if (/^(?:\$[A-Za-z_]\w*|@{0,2}\$?[A-Za-z_]\w*)$/.test(text)) return { type: "raw", value: text };
|
|
1583
1588
|
parser.fail(line, "LNG1108", `unsupported Faz 2 expression: ${text}`);
|
|
@@ -3754,15 +3759,10 @@ function emitStatement(node, depth, declared, flags) {
|
|
|
3754
3759
|
}
|
|
3755
3760
|
if (node.type === "assign") {
|
|
3756
3761
|
const decimalBinding = node.name.startsWith("$") || /^@{1,2}\$/.test(node.name);
|
|
3757
|
-
const property = node.name.slice(node.name.startsWith("@@") ? 2 : 1);
|
|
3758
3762
|
const target = /^[A-Za-z_]\w*(?:\.\$?[A-Za-z_]\w*)+$/.test(node.name)
|
|
3759
|
-
? node.name
|
|
3760
|
-
: node.name.startsWith("@@")
|
|
3761
|
-
? `${flags.className}.${property}`
|
|
3763
|
+
? emitReceiverName(node.name, flags)
|
|
3762
3764
|
: node.name.startsWith("@")
|
|
3763
|
-
? flags
|
|
3764
|
-
? `this.${property}`
|
|
3765
|
-
: `this.#${property}`
|
|
3765
|
+
? emitReceiverName(node.name, flags)
|
|
3766
3766
|
: flags.className && node.name.startsWith("_")
|
|
3767
3767
|
? `this.${node.name}`
|
|
3768
3768
|
: node.name;
|
|
@@ -3789,7 +3789,7 @@ function emitStatement(node, depth, declared, flags) {
|
|
|
3789
3789
|
return `${pad}${prefix}${target} = ${decimalBinding && node.value.type !== "binary" && !decimalLiteral ? `__decimal(${decimalInput})` : value};\n`;
|
|
3790
3790
|
}
|
|
3791
3791
|
if (node.type === "indexAssign") {
|
|
3792
|
-
const target = `${node.receiver}${(node.indexes ?? [node.index]).map((index) => `[${emitExpr(index, flags)}]`).join("")}`;
|
|
3792
|
+
const target = `${emitReceiverName(node.receiver, flags)}${(node.indexes ?? [node.index]).map((index) => `[${emitExpr(index, flags)}]`).join("")}`;
|
|
3793
3793
|
const value = emitExpr(node.value, flags);
|
|
3794
3794
|
if (node.operator) flags.finite = true;
|
|
3795
3795
|
return `${pad}${target} = ${node.operator ? `__finite(${target} ${node.operator} ${value})` : value};\n`;
|
|
@@ -3967,6 +3967,18 @@ function emitBoundaryChecks(parameters, depth, flags) {
|
|
|
3967
3967
|
.join("");
|
|
3968
3968
|
}
|
|
3969
3969
|
function emitReceiverName(name, flags) {
|
|
3970
|
+
const member = /^(@{1,2})(\$?[A-Za-z_]\w*)(.*)$/.exec(name);
|
|
3971
|
+
if (member) {
|
|
3972
|
+
const [, scope, property, suffix] = member;
|
|
3973
|
+
const owner = scope === "@@" ? flags.className : "this";
|
|
3974
|
+
const visibility = scope === "@@" || flags.publicProperties?.has(property) ? "" : "#";
|
|
3975
|
+
return `${owner}.${visibility}${property}${suffix}`;
|
|
3976
|
+
}
|
|
3977
|
+
const base = /^([A-Za-z_]\w*)([.\[].*)$/.exec(name);
|
|
3978
|
+
if (base && flags.contextNames?.has(base[1])) {
|
|
3979
|
+
flags.context = true;
|
|
3980
|
+
return `__contextGet(${JSON.stringify(base[1])})${base[2]}`;
|
|
3981
|
+
}
|
|
3970
3982
|
if (!flags.contextNames?.has(name)) return name;
|
|
3971
3983
|
flags.context = true;
|
|
3972
3984
|
return `__contextGet(${JSON.stringify(name)})`;
|
|
@@ -3985,11 +3997,18 @@ function emitExpr(node, flags) {
|
|
|
3985
3997
|
flags.normalize = true;
|
|
3986
3998
|
return `__normalize(${value})`;
|
|
3987
3999
|
};
|
|
4000
|
+
if (node.type === "raw")
|
|
4001
|
+
if (/^@{1,2}\$?[A-Za-z_]\w*[.\[?]/.test(node.value))
|
|
4002
|
+
return normalize(emitReceiverName(node.value, flags));
|
|
3988
4003
|
if (node.type === "raw")
|
|
3989
4004
|
if (flags.contextNames?.has(node.value)) {
|
|
3990
4005
|
flags.context = true;
|
|
3991
4006
|
return `__contextGet(${JSON.stringify(node.value)})`;
|
|
3992
4007
|
}
|
|
4008
|
+
if (node.type === "raw")
|
|
4009
|
+
if (/^[A-Za-z_]\w*[.\[]/.test(node.value) && flags.contextNames?.has(node.value.split(/[.\[]/)[0])) {
|
|
4010
|
+
return normalize(emitReceiverName(node.value, flags));
|
|
4011
|
+
}
|
|
3993
4012
|
if (node.type === "raw")
|
|
3994
4013
|
if (/^DB\.(Active|RollbackOnly|Failed)$/.test(node.value)) {
|
|
3995
4014
|
flags.databaseEnum = true;
|