funcity 0.6.0 → 0.7.0
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/dist/index.cjs +186 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +186 -58
- package/dist/index.mjs.map +1 -1
- package/dist/node.cjs +2 -2
- package/dist/node.d.ts +2 -2
- package/dist/node.mjs +2 -2
- package/dist/parser.d.ts +2 -2
- package/dist/parser.d.ts.map +1 -1
- package/dist/reducer.d.ts +2 -2
- package/dist/reducer.d.ts.map +1 -1
- package/dist/scripting.d.ts +2 -2
- package/dist/tokenizer.d.ts +2 -2
- package/dist/tokenizer.d.ts.map +1 -1
- package/dist/types.d.ts +68 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -2
- package/dist/variables/fetch-variables.d.ts +2 -2
- package/dist/variables/nodejs-variables.d.ts +2 -2
- package/dist/variables/object-variables.d.ts +23 -0
- package/dist/variables/object-variables.d.ts.map +1 -0
- package/dist/variables/standard-variables.d.ts +3 -4
- package/dist/variables/standard-variables.d.ts.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* name: funcity
|
|
3
|
-
* version: 0.
|
|
3
|
+
* version: 0.7.0
|
|
4
4
|
* description: A functional language interpreter with text processing
|
|
5
5
|
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
6
6
|
* license: MIT
|
|
7
7
|
* repository.url: https://github.com/kekyo/funcity
|
|
8
|
-
* git.commit.hash:
|
|
8
|
+
* git.commit.hash: fc92f38c817d11189397d8e458b1d25db727f766
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
"use strict";
|
|
@@ -139,11 +139,10 @@ const tokenizeNumber = (context) => {
|
|
|
139
139
|
}
|
|
140
140
|
};
|
|
141
141
|
const firstVariableChars = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
142
|
-
const variableChars = "_
|
|
142
|
+
const variableChars = "_-?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
143
143
|
const tokenizeIdentity = (context) => {
|
|
144
144
|
const start = context.cursor.location("start");
|
|
145
145
|
let index = 1;
|
|
146
|
-
let lastCh = "";
|
|
147
146
|
while (true) {
|
|
148
147
|
if (context.cursor.eot()) {
|
|
149
148
|
break;
|
|
@@ -152,11 +151,14 @@ const tokenizeIdentity = (context) => {
|
|
|
152
151
|
if (variableChars.indexOf(ch) < 0) {
|
|
153
152
|
break;
|
|
154
153
|
}
|
|
155
|
-
if (
|
|
156
|
-
index
|
|
154
|
+
if (ch === "?") {
|
|
155
|
+
const next = context.cursor.getChar(index + 1);
|
|
156
|
+
if (next === ".") {
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
index++;
|
|
157
160
|
break;
|
|
158
161
|
}
|
|
159
|
-
lastCh = ch;
|
|
160
162
|
index++;
|
|
161
163
|
}
|
|
162
164
|
return {
|
|
@@ -256,6 +258,24 @@ const tokenizeCodeTokens = (context, stopOnClose, finalizeUnknownOnEot) => {
|
|
|
256
258
|
range: { start: location, end: location }
|
|
257
259
|
});
|
|
258
260
|
context.cursor.skip(1);
|
|
261
|
+
} else if (ch === "?" && context.cursor.getChar(1) === ".") {
|
|
262
|
+
finalizeUnknown();
|
|
263
|
+
const start = context.cursor.location("start");
|
|
264
|
+
context.cursor.skip(2);
|
|
265
|
+
tokens.push({
|
|
266
|
+
kind: "dot",
|
|
267
|
+
optional: true,
|
|
268
|
+
range: { start, end: context.cursor.location("end") }
|
|
269
|
+
});
|
|
270
|
+
} else if (ch === ".") {
|
|
271
|
+
finalizeUnknown();
|
|
272
|
+
const location = context.cursor.location("start");
|
|
273
|
+
tokens.push({
|
|
274
|
+
kind: "dot",
|
|
275
|
+
optional: false,
|
|
276
|
+
range: { start: location, end: location }
|
|
277
|
+
});
|
|
278
|
+
context.cursor.skip(1);
|
|
259
279
|
} else if (firstVariableChars.indexOf(ch) >= 0) {
|
|
260
280
|
finalizeUnknown();
|
|
261
281
|
tokens.push(tokenizeIdentity(context));
|
|
@@ -686,6 +706,52 @@ const combineIntoScopeMultipleExpressions = (expressionList, ...outerRanges) =>
|
|
|
686
706
|
}
|
|
687
707
|
}
|
|
688
708
|
};
|
|
709
|
+
const parseDotChain = (cursor, logs, baseNode) => {
|
|
710
|
+
const segments = [];
|
|
711
|
+
const ranges = [baseNode.range];
|
|
712
|
+
while (true) {
|
|
713
|
+
const dotToken = cursor.peekToken();
|
|
714
|
+
if (!dotToken || dotToken.kind !== "dot") {
|
|
715
|
+
break;
|
|
716
|
+
}
|
|
717
|
+
const actualDotToken = cursor.takeToken();
|
|
718
|
+
ranges.push(actualDotToken.range);
|
|
719
|
+
const nextToken = cursor.peekToken();
|
|
720
|
+
if (!nextToken) {
|
|
721
|
+
logs.push({
|
|
722
|
+
type: "error",
|
|
723
|
+
description: "Could not find member identity after dot",
|
|
724
|
+
range: actualDotToken.range
|
|
725
|
+
});
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
if (nextToken.kind !== "identity") {
|
|
729
|
+
logs.push({
|
|
730
|
+
type: "error",
|
|
731
|
+
description: "Required member identity after dot",
|
|
732
|
+
range: widerRange(actualDotToken.range, nextToken.range)
|
|
733
|
+
});
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
const memberToken = cursor.takeToken();
|
|
737
|
+
segments.push({
|
|
738
|
+
name: memberToken.name,
|
|
739
|
+
optional: actualDotToken.optional,
|
|
740
|
+
range: memberToken.range,
|
|
741
|
+
operatorRange: actualDotToken.range
|
|
742
|
+
});
|
|
743
|
+
ranges.push(memberToken.range);
|
|
744
|
+
}
|
|
745
|
+
if (segments.length === 0) {
|
|
746
|
+
return baseNode;
|
|
747
|
+
}
|
|
748
|
+
return {
|
|
749
|
+
kind: "dot",
|
|
750
|
+
base: baseNode,
|
|
751
|
+
segments,
|
|
752
|
+
range: widerRange(...ranges)
|
|
753
|
+
};
|
|
754
|
+
};
|
|
689
755
|
const parsePartialExpression = (cursor, logs) => {
|
|
690
756
|
const token = cursor.peekToken();
|
|
691
757
|
if (!token) {
|
|
@@ -694,15 +760,24 @@ const parsePartialExpression = (cursor, logs) => {
|
|
|
694
760
|
switch (token.kind) {
|
|
695
761
|
case "number": {
|
|
696
762
|
const node = parseNumber(cursor);
|
|
697
|
-
return node;
|
|
763
|
+
return parseDotChain(cursor, logs, node);
|
|
698
764
|
}
|
|
699
765
|
case "string": {
|
|
700
766
|
const node = parseString(cursor);
|
|
701
|
-
return node;
|
|
767
|
+
return parseDotChain(cursor, logs, node);
|
|
702
768
|
}
|
|
703
769
|
case "identity": {
|
|
704
770
|
const node = parseIdentity(cursor);
|
|
705
|
-
return node;
|
|
771
|
+
return parseDotChain(cursor, logs, node);
|
|
772
|
+
}
|
|
773
|
+
case "dot": {
|
|
774
|
+
const dotToken = cursor.takeToken();
|
|
775
|
+
logs.push({
|
|
776
|
+
type: "error",
|
|
777
|
+
description: "Invalid dot at this location",
|
|
778
|
+
range: dotToken.range
|
|
779
|
+
});
|
|
780
|
+
return void 0;
|
|
706
781
|
}
|
|
707
782
|
case "open": {
|
|
708
783
|
cursor.skipToken();
|
|
@@ -747,7 +822,7 @@ const parsePartialExpression = (cursor, logs) => {
|
|
|
747
822
|
};
|
|
748
823
|
} else {
|
|
749
824
|
const node = combineIntoScopeMultipleExpressions(innerNodes, range);
|
|
750
|
-
return node;
|
|
825
|
+
return node ? parseDotChain(cursor, logs, node) : node;
|
|
751
826
|
}
|
|
752
827
|
}
|
|
753
828
|
// Bracket surrounding expression list `[ ... ]` (Iterable list)
|
|
@@ -758,7 +833,7 @@ const parsePartialExpression = (cursor, logs) => {
|
|
|
758
833
|
if (!closeToken) {
|
|
759
834
|
range = widerRange(
|
|
760
835
|
token.range,
|
|
761
|
-
...itemNodes.map((
|
|
836
|
+
...itemNodes.map((node2) => node2.range)
|
|
762
837
|
);
|
|
763
838
|
logs.push({
|
|
764
839
|
type: "error",
|
|
@@ -769,7 +844,7 @@ const parsePartialExpression = (cursor, logs) => {
|
|
|
769
844
|
cursor.skipToken();
|
|
770
845
|
range = widerRange(
|
|
771
846
|
token.range,
|
|
772
|
-
...itemNodes.map((
|
|
847
|
+
...itemNodes.map((node2) => node2.range),
|
|
773
848
|
closeToken.range
|
|
774
849
|
);
|
|
775
850
|
if (closeToken.kind !== "close" || closeToken.symbol !== "]") {
|
|
@@ -780,11 +855,12 @@ const parsePartialExpression = (cursor, logs) => {
|
|
|
780
855
|
});
|
|
781
856
|
}
|
|
782
857
|
}
|
|
783
|
-
|
|
858
|
+
const node = {
|
|
784
859
|
kind: "list",
|
|
785
860
|
items: itemNodes,
|
|
786
861
|
range
|
|
787
862
|
};
|
|
863
|
+
return parseDotChain(cursor, logs, node);
|
|
788
864
|
}
|
|
789
865
|
default: {
|
|
790
866
|
logs.push({
|
|
@@ -1417,33 +1493,54 @@ const deconstructConditionalCombine = (name) => {
|
|
|
1417
1493
|
canIgnore: false
|
|
1418
1494
|
};
|
|
1419
1495
|
};
|
|
1420
|
-
const
|
|
1421
|
-
const
|
|
1422
|
-
const
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
if (!result0.isFound) {
|
|
1426
|
-
if (!n0r.canIgnore) {
|
|
1496
|
+
const resolveVariable = (context, name, signal) => {
|
|
1497
|
+
const result = deconstructConditionalCombine(name.name);
|
|
1498
|
+
const valueResult = context.getValue(result.name, signal);
|
|
1499
|
+
if (!valueResult.isFound) {
|
|
1500
|
+
if (!result.canIgnore) {
|
|
1427
1501
|
throwError({
|
|
1428
|
-
description: `variable is not bound: ${
|
|
1502
|
+
description: `variable is not bound: ${result.name}`,
|
|
1429
1503
|
range: name.range
|
|
1430
1504
|
});
|
|
1431
1505
|
}
|
|
1432
1506
|
return void 0;
|
|
1433
1507
|
}
|
|
1434
|
-
|
|
1508
|
+
return valueResult.value;
|
|
1509
|
+
};
|
|
1510
|
+
const resolveDotNode = async (context, node, signal) => {
|
|
1511
|
+
var _a, _b;
|
|
1512
|
+
signal == null ? void 0 : signal.throwIfAborted();
|
|
1513
|
+
const firstSegmentOptional = (_b = (_a = node.segments[0]) == null ? void 0 : _a.optional) != null ? _b : false;
|
|
1514
|
+
let value;
|
|
1515
|
+
if (node.base.kind === "variable") {
|
|
1516
|
+
const baseResult = deconstructConditionalCombine(node.base.name);
|
|
1517
|
+
const valueResult = context.getValue(baseResult.name, signal);
|
|
1518
|
+
if (!valueResult.isFound) {
|
|
1519
|
+
if (!baseResult.canIgnore && !firstSegmentOptional) {
|
|
1520
|
+
throwError({
|
|
1521
|
+
description: `variable is not bound: ${baseResult.name}`,
|
|
1522
|
+
range: node.base.range
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
return void 0;
|
|
1526
|
+
}
|
|
1527
|
+
value = valueResult.value;
|
|
1528
|
+
} else {
|
|
1529
|
+
value = await reduceExpressionNode(context, node.base, signal);
|
|
1530
|
+
}
|
|
1435
1531
|
let parent;
|
|
1436
|
-
for (const
|
|
1437
|
-
const
|
|
1438
|
-
|
|
1439
|
-
|
|
1532
|
+
for (const segment of node.segments) {
|
|
1533
|
+
const result = deconstructConditionalCombine(segment.name);
|
|
1534
|
+
const isOptional = segment.optional || result.canIgnore;
|
|
1535
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
1536
|
+
const record = value;
|
|
1440
1537
|
parent = value;
|
|
1441
|
-
value =
|
|
1538
|
+
value = record[result.name];
|
|
1442
1539
|
} else {
|
|
1443
|
-
if (!
|
|
1540
|
+
if (!isOptional) {
|
|
1444
1541
|
throwError({
|
|
1445
|
-
description: `variable is not bound: ${
|
|
1446
|
-
range:
|
|
1542
|
+
description: `variable is not bound: ${result.name}`,
|
|
1543
|
+
range: segment.range
|
|
1447
1544
|
});
|
|
1448
1545
|
}
|
|
1449
1546
|
return void 0;
|
|
@@ -1464,16 +1561,20 @@ const applyFunction = async (context, node, signal) => {
|
|
|
1464
1561
|
});
|
|
1465
1562
|
return void 0;
|
|
1466
1563
|
}
|
|
1467
|
-
const
|
|
1564
|
+
const isSpecial = isFunCityFunction(func);
|
|
1565
|
+
const args = isSpecial ? node.args : await Promise.all(
|
|
1468
1566
|
node.args.map(async (argNode) => {
|
|
1469
1567
|
const arg = await reduceExpressionNode(context, argNode, signal);
|
|
1470
1568
|
return arg;
|
|
1471
1569
|
})
|
|
1472
1570
|
);
|
|
1473
|
-
const
|
|
1571
|
+
const shouldConstruct = !isSpecial && context.isConstructable(func);
|
|
1474
1572
|
try {
|
|
1475
|
-
|
|
1476
|
-
|
|
1573
|
+
if (shouldConstruct) {
|
|
1574
|
+
return Reflect.construct(func, args);
|
|
1575
|
+
}
|
|
1576
|
+
const thisProxy = context.createFunctionContext(node, signal);
|
|
1577
|
+
return await func.call(thisProxy, ...args);
|
|
1477
1578
|
} catch (e) {
|
|
1478
1579
|
if (e instanceof FunCityReducerError) {
|
|
1479
1580
|
throw e;
|
|
@@ -1495,7 +1596,10 @@ const reduceExpressionNode = async (context, node, signal) => {
|
|
|
1495
1596
|
return node.value;
|
|
1496
1597
|
}
|
|
1497
1598
|
case "variable": {
|
|
1498
|
-
return
|
|
1599
|
+
return resolveVariable(context, node, signal);
|
|
1600
|
+
}
|
|
1601
|
+
case "dot": {
|
|
1602
|
+
return await resolveDotNode(context, node, signal);
|
|
1499
1603
|
}
|
|
1500
1604
|
case "apply": {
|
|
1501
1605
|
return await applyFunction(context, node, signal);
|
|
@@ -1606,7 +1710,6 @@ const createScopedReducerContext = (parent, signal) => {
|
|
|
1606
1710
|
}
|
|
1607
1711
|
thisVars.set(name, value);
|
|
1608
1712
|
};
|
|
1609
|
-
const getBoundFunction = parent.getBoundFunction;
|
|
1610
1713
|
const createFunctionContext = (thisNode, signal2) => {
|
|
1611
1714
|
return {
|
|
1612
1715
|
thisNode,
|
|
@@ -1614,6 +1717,7 @@ const createScopedReducerContext = (parent, signal) => {
|
|
|
1614
1717
|
getValue: (name) => getValue(name, signal2),
|
|
1615
1718
|
setValue: (name, value) => setValue(name, value, signal2),
|
|
1616
1719
|
appendWarning: parent.appendWarning,
|
|
1720
|
+
getBoundFunction: parent.getBoundFunction,
|
|
1617
1721
|
newScope: () => createScopedReducerContext(thisContext, signal2),
|
|
1618
1722
|
convertToString: parent.convertToString,
|
|
1619
1723
|
reduce: (node) => reduceExpressionNode(thisContext, node, signal2)
|
|
@@ -1622,10 +1726,11 @@ const createScopedReducerContext = (parent, signal) => {
|
|
|
1622
1726
|
thisContext = {
|
|
1623
1727
|
getValue,
|
|
1624
1728
|
setValue,
|
|
1625
|
-
getBoundFunction,
|
|
1729
|
+
getBoundFunction: parent.getBoundFunction,
|
|
1626
1730
|
appendWarning: parent.appendWarning,
|
|
1627
1731
|
newScope: (signal2) => createScopedReducerContext(thisContext, signal2),
|
|
1628
1732
|
convertToString: parent.convertToString,
|
|
1733
|
+
isConstructable: parent.isConstructable,
|
|
1629
1734
|
createFunctionContext
|
|
1630
1735
|
};
|
|
1631
1736
|
return thisContext;
|
|
@@ -1633,24 +1738,22 @@ const createScopedReducerContext = (parent, signal) => {
|
|
|
1633
1738
|
const createReducerContext = (variables, warningLogs) => {
|
|
1634
1739
|
let thisVars;
|
|
1635
1740
|
let thisContext;
|
|
1636
|
-
const
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
return bound;
|
|
1651
|
-
};
|
|
1741
|
+
const boundFunctionCache = /* @__PURE__ */ new WeakMap();
|
|
1742
|
+
const getBoundFunction = (owner, fn) => {
|
|
1743
|
+
let ownerCache = boundFunctionCache.get(owner);
|
|
1744
|
+
if (!ownerCache) {
|
|
1745
|
+
ownerCache = /* @__PURE__ */ new WeakMap();
|
|
1746
|
+
boundFunctionCache.set(owner, ownerCache);
|
|
1747
|
+
}
|
|
1748
|
+
const cached = ownerCache.get(fn);
|
|
1749
|
+
if (cached) {
|
|
1750
|
+
return cached;
|
|
1751
|
+
}
|
|
1752
|
+
const bound = fn.bind(owner);
|
|
1753
|
+
ownerCache.set(fn, bound);
|
|
1754
|
+
return bound;
|
|
1652
1755
|
};
|
|
1653
|
-
const
|
|
1756
|
+
const constructorCache = /* @__PURE__ */ new WeakMap();
|
|
1654
1757
|
const getValue = (name, signal) => {
|
|
1655
1758
|
signal == null ? void 0 : signal.throwIfAborted();
|
|
1656
1759
|
if (thisVars == null ? void 0 : thisVars.has(name)) {
|
|
@@ -1671,6 +1774,20 @@ const createReducerContext = (variables, warningLogs) => {
|
|
|
1671
1774
|
const appendWarning = (warning) => {
|
|
1672
1775
|
warningLogs.push(warning);
|
|
1673
1776
|
};
|
|
1777
|
+
const isConstructable = (fn) => {
|
|
1778
|
+
if (constructorCache.has(fn)) {
|
|
1779
|
+
return constructorCache.get(fn);
|
|
1780
|
+
}
|
|
1781
|
+
let result = false;
|
|
1782
|
+
try {
|
|
1783
|
+
Reflect.construct(Object, [], fn);
|
|
1784
|
+
result = true;
|
|
1785
|
+
} catch (e) {
|
|
1786
|
+
result = false;
|
|
1787
|
+
}
|
|
1788
|
+
constructorCache.set(fn, result);
|
|
1789
|
+
return result;
|
|
1790
|
+
};
|
|
1674
1791
|
const getFuncId = internalCreateFunctionIdGenerator();
|
|
1675
1792
|
const convertToString2 = (v) => {
|
|
1676
1793
|
return internalConvertToString(v, getFuncId);
|
|
@@ -1682,6 +1799,7 @@ const createReducerContext = (variables, warningLogs) => {
|
|
|
1682
1799
|
getValue: (name) => getValue(name, signal),
|
|
1683
1800
|
setValue: (name, value) => setValue(name, value, signal),
|
|
1684
1801
|
appendWarning,
|
|
1802
|
+
getBoundFunction,
|
|
1685
1803
|
newScope: () => createScopedReducerContext(thisContext, signal),
|
|
1686
1804
|
convertToString: convertToString2,
|
|
1687
1805
|
reduce: (node) => reduceExpressionNode(thisContext, node, signal)
|
|
@@ -1694,6 +1812,7 @@ const createReducerContext = (variables, warningLogs) => {
|
|
|
1694
1812
|
appendWarning,
|
|
1695
1813
|
newScope: (signal) => createScopedReducerContext(thisContext, signal),
|
|
1696
1814
|
convertToString: convertToString2,
|
|
1815
|
+
isConstructable,
|
|
1697
1816
|
createFunctionContext
|
|
1698
1817
|
};
|
|
1699
1818
|
return thisContext;
|
|
@@ -1905,7 +2024,7 @@ const _ge = async (arg0, arg1) => {
|
|
|
1905
2024
|
return r;
|
|
1906
2025
|
};
|
|
1907
2026
|
const _now = async () => {
|
|
1908
|
-
return Date
|
|
2027
|
+
return /* @__PURE__ */ new Date();
|
|
1909
2028
|
};
|
|
1910
2029
|
const concatInner = (args) => {
|
|
1911
2030
|
let v = "";
|
|
@@ -2268,8 +2387,7 @@ const standardVariables = Object.freeze({
|
|
|
2268
2387
|
regex: _regex,
|
|
2269
2388
|
bind: _bind,
|
|
2270
2389
|
url: _url,
|
|
2271
|
-
delay: _delay
|
|
2272
|
-
math: Math
|
|
2390
|
+
delay: _delay
|
|
2273
2391
|
});
|
|
2274
2392
|
const buildCandidateVariables = (...variablesList) => {
|
|
2275
2393
|
return combineVariables(standardVariables, ...variablesList);
|
|
@@ -2335,6 +2453,15 @@ const runScriptOnceToText = async (script, props, signal) => {
|
|
|
2335
2453
|
const text = resultList.map((result) => reducerContext.convertToString(result)).join("");
|
|
2336
2454
|
return text;
|
|
2337
2455
|
};
|
|
2456
|
+
const objectVariables = Object.freeze({
|
|
2457
|
+
Object,
|
|
2458
|
+
Array,
|
|
2459
|
+
String,
|
|
2460
|
+
Number,
|
|
2461
|
+
Function,
|
|
2462
|
+
Math,
|
|
2463
|
+
Date
|
|
2464
|
+
});
|
|
2338
2465
|
const getFetch = () => {
|
|
2339
2466
|
const fetchFn = globalThis.fetch;
|
|
2340
2467
|
if (!fetchFn) {
|
|
@@ -2393,6 +2520,7 @@ exports.fetchVariables = fetchVariables;
|
|
|
2393
2520
|
exports.isConditionalTrue = isConditionalTrue;
|
|
2394
2521
|
exports.isFunCityFunction = isFunCityFunction;
|
|
2395
2522
|
exports.makeFunCityFunction = makeFunCityFunction;
|
|
2523
|
+
exports.objectVariables = objectVariables;
|
|
2396
2524
|
exports.outputErrors = outputErrors;
|
|
2397
2525
|
exports.parseBlock = parseBlock;
|
|
2398
2526
|
exports.parseExpression = parseExpression;
|