@lango-project/lango-js 0.1.3 → 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/package.json +1 -1
- package/src/compiler.mjs +49 -33
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({
|
|
@@ -1412,7 +1414,7 @@ function expr(source, line, parser) {
|
|
|
1412
1414
|
line: line.number,
|
|
1413
1415
|
};
|
|
1414
1416
|
const nestedIndex =
|
|
1415
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*(?:\?\.)?\[.+\])(\?\.)?\[(.+)\]$/.exec(
|
|
1417
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*(?:\?\.)?\[.+\])(\?\.)?\[(.+)\]$/.exec(
|
|
1416
1418
|
text,
|
|
1417
1419
|
);
|
|
1418
1420
|
if (nestedIndex)
|
|
@@ -1423,7 +1425,7 @@ function expr(source, line, parser) {
|
|
|
1423
1425
|
index: expr(nestedIndex[3], line, parser),
|
|
1424
1426
|
};
|
|
1425
1427
|
const computedIndex =
|
|
1426
|
-
/^([A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*)(\?\.)?\[([^\]]+)\]$/.exec(
|
|
1428
|
+
/^(@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w)*)(\?\.)?\[([^\]]+)\]$/.exec(
|
|
1427
1429
|
text,
|
|
1428
1430
|
);
|
|
1429
1431
|
if (
|
|
@@ -1437,7 +1439,7 @@ function expr(source, line, parser) {
|
|
|
1437
1439
|
index: expr(computedIndex[3], line, parser),
|
|
1438
1440
|
};
|
|
1439
1441
|
const indexedProperty =
|
|
1440
|
-
/^([A-Za-z_]\w*.*\])(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1442
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\])(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1441
1443
|
if (
|
|
1442
1444
|
indexedProperty &&
|
|
1443
1445
|
!/^[A-Za-z_]\w*\?\.\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\]$/.test(
|
|
@@ -1451,7 +1453,7 @@ function expr(source, line, parser) {
|
|
|
1451
1453
|
name: indexedProperty[3],
|
|
1452
1454
|
};
|
|
1453
1455
|
const indexedMethodCall =
|
|
1454
|
-
/^([A-Za-z_]\w*.*\])(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1456
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\])(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1455
1457
|
if (indexedMethodCall)
|
|
1456
1458
|
return {
|
|
1457
1459
|
type: "methodCall",
|
|
@@ -1464,7 +1466,7 @@ function expr(source, line, parser) {
|
|
|
1464
1466
|
line: line.number,
|
|
1465
1467
|
};
|
|
1466
1468
|
const nestedCallResultIndex =
|
|
1467
|
-
/^([A-Za-z_]\w*.*\)\?\.\[.+\])(\?\.)?\[(.+)\]$/.exec(text);
|
|
1469
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\)\?\.\[.+\])(\?\.)?\[(.+)\]$/.exec(text);
|
|
1468
1470
|
if (nestedCallResultIndex)
|
|
1469
1471
|
return {
|
|
1470
1472
|
type: "index",
|
|
@@ -1473,7 +1475,7 @@ function expr(source, line, parser) {
|
|
|
1473
1475
|
index: expr(nestedCallResultIndex[3], line, parser),
|
|
1474
1476
|
};
|
|
1475
1477
|
const callResultIndex =
|
|
1476
|
-
/^([A-Za-z_]\w*.*\))(\?\.)?\[(.+)\]$/.exec(text);
|
|
1478
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.)?\[(.+)\]$/.exec(text);
|
|
1477
1479
|
if (callResultIndex)
|
|
1478
1480
|
return {
|
|
1479
1481
|
type: "index",
|
|
@@ -1482,7 +1484,7 @@ function expr(source, line, parser) {
|
|
|
1482
1484
|
index: expr(callResultIndex[3], line, parser),
|
|
1483
1485
|
};
|
|
1484
1486
|
const callResultProperty =
|
|
1485
|
-
/^([A-Za-z_]\w*.*\))(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1487
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.|\.)(\$?[A-Za-z_]\w*)$/.exec(text);
|
|
1486
1488
|
if (callResultProperty)
|
|
1487
1489
|
return {
|
|
1488
1490
|
type: "property",
|
|
@@ -1491,7 +1493,7 @@ function expr(source, line, parser) {
|
|
|
1491
1493
|
name: callResultProperty[3],
|
|
1492
1494
|
};
|
|
1493
1495
|
const callResultMethod =
|
|
1494
|
-
/^([A-Za-z_]\w*.*\))(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1496
|
+
/^(@{0,2}\$?[A-Za-z_]\w*.*\))(\?\.|\.)([A-Za-z_]\w*)\((.*)\)$/.exec(text);
|
|
1495
1497
|
if (callResultMethod)
|
|
1496
1498
|
return {
|
|
1497
1499
|
type: "methodCall",
|
|
@@ -1515,7 +1517,7 @@ function expr(source, line, parser) {
|
|
|
1515
1517
|
line: line.number,
|
|
1516
1518
|
};
|
|
1517
1519
|
const methodCall =
|
|
1518
|
-
/^([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(
|
|
1519
1521
|
text,
|
|
1520
1522
|
);
|
|
1521
1523
|
const namespaceMethodCall =
|
|
@@ -1569,15 +1571,15 @@ function expr(source, line, parser) {
|
|
|
1569
1571
|
return { type: "raw", value: text };
|
|
1570
1572
|
}
|
|
1571
1573
|
if (/^(true|false|null)$/.test(text)) return { type: "raw", value: text };
|
|
1572
|
-
if (
|
|
1574
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)[A-Za-z_]\w*)*(?:\.|\?\.)_[A-Za-z_]\w*$/.test(text))
|
|
1573
1575
|
parser.fail(
|
|
1574
1576
|
line,
|
|
1575
1577
|
"LNG1115",
|
|
1576
1578
|
"protected properties are not accessible outside a class",
|
|
1577
1579
|
);
|
|
1578
|
-
if (
|
|
1580
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*(?:(?:\.|\?\.)\$?[A-Za-z_]\w*|(?:\?\.)?\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\])+$/.test(text))
|
|
1579
1581
|
return { type: "raw", value: text };
|
|
1580
|
-
if (
|
|
1582
|
+
if (/^@{0,2}\$?[A-Za-z_]\w*\[(?:\d+|[A-Za-z_]\w*|['"][^'"]*['"])\]$/.test(text))
|
|
1581
1583
|
return { type: "raw", value: text };
|
|
1582
1584
|
if (/^(?:\$[A-Za-z_]\w*|@{0,2}\$?[A-Za-z_]\w*)$/.test(text)) return { type: "raw", value: text };
|
|
1583
1585
|
parser.fail(line, "LNG1108", `unsupported Faz 2 expression: ${text}`);
|
|
@@ -3754,15 +3756,10 @@ function emitStatement(node, depth, declared, flags) {
|
|
|
3754
3756
|
}
|
|
3755
3757
|
if (node.type === "assign") {
|
|
3756
3758
|
const decimalBinding = node.name.startsWith("$") || /^@{1,2}\$/.test(node.name);
|
|
3757
|
-
const property = node.name.slice(node.name.startsWith("@@") ? 2 : 1);
|
|
3758
3759
|
const target = /^[A-Za-z_]\w*(?:\.\$?[A-Za-z_]\w*)+$/.test(node.name)
|
|
3759
|
-
? node.name
|
|
3760
|
-
: node.name.startsWith("@@")
|
|
3761
|
-
? `${flags.className}.${property}`
|
|
3760
|
+
? emitReceiverName(node.name, flags)
|
|
3762
3761
|
: node.name.startsWith("@")
|
|
3763
|
-
? flags
|
|
3764
|
-
? `this.${property}`
|
|
3765
|
-
: `this.#${property}`
|
|
3762
|
+
? emitReceiverName(node.name, flags)
|
|
3766
3763
|
: flags.className && node.name.startsWith("_")
|
|
3767
3764
|
? `this.${node.name}`
|
|
3768
3765
|
: node.name;
|
|
@@ -3789,7 +3786,7 @@ function emitStatement(node, depth, declared, flags) {
|
|
|
3789
3786
|
return `${pad}${prefix}${target} = ${decimalBinding && node.value.type !== "binary" && !decimalLiteral ? `__decimal(${decimalInput})` : value};\n`;
|
|
3790
3787
|
}
|
|
3791
3788
|
if (node.type === "indexAssign") {
|
|
3792
|
-
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("")}`;
|
|
3793
3790
|
const value = emitExpr(node.value, flags);
|
|
3794
3791
|
if (node.operator) flags.finite = true;
|
|
3795
3792
|
return `${pad}${target} = ${node.operator ? `__finite(${target} ${node.operator} ${value})` : value};\n`;
|
|
@@ -3967,6 +3964,18 @@ function emitBoundaryChecks(parameters, depth, flags) {
|
|
|
3967
3964
|
.join("");
|
|
3968
3965
|
}
|
|
3969
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
|
+
}
|
|
3970
3979
|
if (!flags.contextNames?.has(name)) return name;
|
|
3971
3980
|
flags.context = true;
|
|
3972
3981
|
return `__contextGet(${JSON.stringify(name)})`;
|
|
@@ -3985,11 +3994,18 @@ function emitExpr(node, flags) {
|
|
|
3985
3994
|
flags.normalize = true;
|
|
3986
3995
|
return `__normalize(${value})`;
|
|
3987
3996
|
};
|
|
3997
|
+
if (node.type === "raw")
|
|
3998
|
+
if (/^@{1,2}\$?[A-Za-z_]\w*[.\[?]/.test(node.value))
|
|
3999
|
+
return normalize(emitReceiverName(node.value, flags));
|
|
3988
4000
|
if (node.type === "raw")
|
|
3989
4001
|
if (flags.contextNames?.has(node.value)) {
|
|
3990
4002
|
flags.context = true;
|
|
3991
4003
|
return `__contextGet(${JSON.stringify(node.value)})`;
|
|
3992
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
|
+
}
|
|
3993
4009
|
if (node.type === "raw")
|
|
3994
4010
|
if (/^DB\.(Active|RollbackOnly|Failed)$/.test(node.value)) {
|
|
3995
4011
|
flags.databaseEnum = true;
|