funcity 0.2.0 → 0.3.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.mjs CHANGED
@@ -1,17 +1,225 @@
1
+ const emptyLocation = {
2
+ line: 0,
3
+ column: 0
4
+ };
5
+ const emptyRange = {
6
+ start: emptyLocation,
7
+ end: emptyLocation
8
+ };
9
+ const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
10
+ const makeFunCityFunction = (f) => {
11
+ f[specialFunctionMarker] = true;
12
+ return f;
13
+ };
14
+ const isFunCityFunction = (f) => {
15
+ var _a;
16
+ return (_a = f[specialFunctionMarker]) != null ? _a : false;
17
+ };
18
+ const isConditionalTrue = (v) => {
19
+ if (v === void 0 || v === null) {
20
+ return false;
21
+ }
22
+ switch (typeof v) {
23
+ case "boolean":
24
+ return v;
25
+ case "number":
26
+ case "bigint":
27
+ return v !== 0;
28
+ default:
29
+ return true;
30
+ }
31
+ };
32
+ const asIterable = (v) => {
33
+ if (typeof v[Symbol.iterator] === "function") {
34
+ return v;
35
+ } else {
36
+ return void 0;
37
+ }
38
+ };
39
+ const combineVariables = (...variablesList) => {
40
+ const variables = /* @__PURE__ */ new Map();
41
+ const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
42
+ const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
43
+ variablesList.forEach((vs) => {
44
+ if (vs["forEach"] !== void 0) {
45
+ appendVariables(vs);
46
+ } else {
47
+ appendRecord(vs);
48
+ }
49
+ });
50
+ return variables;
51
+ };
52
+ const fromError = (error) => {
53
+ var _a;
54
+ if (error.message) {
55
+ return error.message;
56
+ } else if (typeof error.toString === "function") {
57
+ return (_a = error.toString()) != null ? _a : "unknown";
58
+ } else {
59
+ return "unknown";
60
+ }
61
+ };
62
+ const widerRange = (...ranges) => {
63
+ let start = emptyRange.start;
64
+ let end = emptyRange.end;
65
+ for (const range of ranges) {
66
+ if (range.start.line >= 1 && range.start.column >= 1) {
67
+ if (start.line === 0 || start.column === 0) {
68
+ start = range.start;
69
+ } else if (range.start.line < start.line) {
70
+ start = range.start;
71
+ } else if (range.start.line === start.line && range.start.column < start.column) {
72
+ start = range.start;
73
+ }
74
+ if (end.line === 0 || end.column === 0) {
75
+ end = range.end;
76
+ } else if (range.end.line > end.line) {
77
+ end = range.end;
78
+ } else if (range.end.line === end.line && range.end.column > end.column) {
79
+ end = range.end;
80
+ }
81
+ }
82
+ }
83
+ return { start, end };
84
+ };
85
+ const locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
86
+ const getLocationString = (range) => locationEquals(range.start, range.end) ? `${range.start.line}:${range.start.column}` : `${range.start.line}:${range.start.column}:${range.end.line}:${range.end.column}`;
87
+ const printErrorString = (path, error) => {
88
+ switch (error.type) {
89
+ case "warning":
90
+ console.warn(
91
+ `${path}:${getLocationString(error.range)}: warning: ${error.description}`
92
+ );
93
+ break;
94
+ case "error":
95
+ console.error(
96
+ `${path}:${getLocationString(error.range)}: error: ${error.description}`
97
+ );
98
+ return true;
99
+ }
100
+ return false;
101
+ };
102
+ const outputErrors = (path, errors) => {
103
+ let isError = false;
104
+ for (const error of errors) {
105
+ const result = printErrorString(path, error);
106
+ isError || (isError = result);
107
+ }
108
+ return isError;
109
+ };
110
+ const funcIds = /* @__PURE__ */ new WeakMap();
111
+ let nextId = 1;
112
+ const getFuncId = (fn) => {
113
+ const cached = funcIds.get(fn);
114
+ if (cached) {
115
+ return cached;
116
+ }
117
+ const id = nextId++;
118
+ funcIds.set(fn, id);
119
+ return id;
120
+ };
121
+ const convertToString = (v) => {
122
+ switch (v) {
123
+ case void 0:
124
+ return "(undefined)";
125
+ case null:
126
+ return "(null)";
127
+ default:
128
+ switch (typeof v) {
129
+ case "string":
130
+ return v;
131
+ case "boolean":
132
+ return v ? "true" : "false";
133
+ case "number":
134
+ case "bigint":
135
+ case "symbol":
136
+ return v.toString();
137
+ case "function":
138
+ if (v.name) {
139
+ return `fun<${v.name}:#${getFuncId(v)}>`;
140
+ } else {
141
+ return `fun<#${getFuncId(v)}>`;
142
+ }
143
+ default:
144
+ if (Array.isArray(v)) {
145
+ return JSON.stringify(v);
146
+ }
147
+ const iterable = asIterable(v);
148
+ if (iterable) {
149
+ const arr = Array.from(iterable);
150
+ return JSON.stringify(arr);
151
+ } else if (v instanceof Date) {
152
+ return v.toISOString();
153
+ } else if (v instanceof Error) {
154
+ return `${v.name}: ${v.message}`;
155
+ } else if (v instanceof URL) {
156
+ return v.origin;
157
+ } else {
158
+ return JSON.stringify(v);
159
+ }
160
+ }
161
+ }
162
+ };
163
+ const stringEscapeMap = {
164
+ f: "\f",
165
+ n: "\n",
166
+ r: "\r",
167
+ t: " ",
168
+ v: "\v",
169
+ "0": "\0",
170
+ "'": "'",
171
+ "\\": "\\"
172
+ };
1
173
  const tokenizeString = (context) => {
2
174
  const start = context.cursor.location("start");
3
175
  context.cursor.skip(1);
4
- let value = context.cursor.getUntil("'");
5
- if (value !== void 0) {
176
+ let value = "";
177
+ let closed = false;
178
+ while (!context.cursor.eot()) {
179
+ const ch = context.cursor.getChar();
180
+ if (ch === "'") {
181
+ context.cursor.skip(1);
182
+ closed = true;
183
+ break;
184
+ }
185
+ if (ch === "\\") {
186
+ const escapeStart = context.cursor.location("start");
187
+ context.cursor.skip(1);
188
+ if (context.cursor.eot()) {
189
+ context.errors.push({
190
+ type: "error",
191
+ description: "invalid escape sequence: \\\\",
192
+ range: { start: escapeStart, end: context.cursor.location("end") }
193
+ });
194
+ value += "\\";
195
+ break;
196
+ }
197
+ const escape = context.cursor.getChar();
198
+ const mapped = stringEscapeMap[escape];
199
+ if (mapped !== void 0) {
200
+ value += mapped;
201
+ context.cursor.skip(1);
202
+ continue;
203
+ }
204
+ context.cursor.skip(1);
205
+ context.errors.push({
206
+ type: "error",
207
+ description: `invalid escape sequence: \\${escape}`,
208
+ range: { start: escapeStart, end: context.cursor.location("end") }
209
+ });
210
+ value += `\\${escape}`;
211
+ continue;
212
+ }
213
+ value += ch;
6
214
  context.cursor.skip(1);
7
- } else {
215
+ }
216
+ if (!closed) {
8
217
  const location = context.cursor.location("start");
9
218
  context.errors.push({
10
219
  type: "error",
11
220
  description: "string close quote is not found",
12
221
  range: { start: location, end: location }
13
222
  });
14
- value = "";
15
223
  }
16
224
  return {
17
225
  kind: "string",
@@ -348,115 +556,6 @@ const runTokenizer = (script, errors) => {
348
556
  }
349
557
  return tokens;
350
558
  };
351
- const emptyLocation = {
352
- line: 0,
353
- column: 0
354
- };
355
- const emptyRange = {
356
- start: emptyLocation,
357
- end: emptyLocation
358
- };
359
- const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
360
- const makeSpecialFunction = (f) => {
361
- f[specialFunctionMarker] = true;
362
- return f;
363
- };
364
- const isSpecialFunction = (f) => {
365
- var _a;
366
- return (_a = f[specialFunctionMarker]) != null ? _a : false;
367
- };
368
- const isConditionalTrue = (v) => {
369
- if (v === void 0 || v === null) {
370
- return false;
371
- }
372
- switch (typeof v) {
373
- case "boolean":
374
- return v;
375
- case "number":
376
- case "bigint":
377
- return v !== 0;
378
- default:
379
- return true;
380
- }
381
- };
382
- const asIterable = (v) => {
383
- if (typeof v[Symbol.iterator] === "function") {
384
- return v;
385
- } else {
386
- return void 0;
387
- }
388
- };
389
- const combineVariables = (...variablesList) => {
390
- const variables = /* @__PURE__ */ new Map();
391
- const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
392
- const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
393
- variablesList.forEach((vs) => {
394
- if (vs["forEach"] !== void 0) {
395
- appendVariables(vs);
396
- } else {
397
- appendRecord(vs);
398
- }
399
- });
400
- return variables;
401
- };
402
- const fromError = (error) => {
403
- var _a;
404
- if (error.message) {
405
- return error.message;
406
- } else if (typeof error.toString === "function") {
407
- return (_a = error.toString()) != null ? _a : "unknown";
408
- } else {
409
- return "unknown";
410
- }
411
- };
412
- const widerRange = (...ranges) => {
413
- let start = emptyRange.start;
414
- let end = emptyRange.end;
415
- for (const range of ranges) {
416
- if (range.start.line >= 1 && range.start.column >= 1) {
417
- if (start.line === 0 || start.column === 0) {
418
- start = range.start;
419
- } else if (range.start.line < start.line) {
420
- start = range.start;
421
- } else if (range.start.line === start.line && range.start.column < start.column) {
422
- start = range.start;
423
- }
424
- if (end.line === 0 || end.column === 0) {
425
- end = range.end;
426
- } else if (range.end.line > end.line) {
427
- end = range.end;
428
- } else if (range.end.line === end.line && range.end.column > end.column) {
429
- end = range.end;
430
- }
431
- }
432
- }
433
- return { start, end };
434
- };
435
- const locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
436
- const getLocationString = (range) => locationEquals(range.start, range.end) ? `${range.start.line}:${range.start.column}` : `${range.start.line}:${range.start.column}:${range.end.line}:${range.end.column}`;
437
- const printErrorString = (path, error) => {
438
- switch (error.type) {
439
- case "warning":
440
- console.warn(
441
- `${path}:${getLocationString(error.range)}: warning: ${error.description}`
442
- );
443
- break;
444
- case "error":
445
- console.error(
446
- `${path}:${getLocationString(error.range)}: error: ${error.description}`
447
- );
448
- return true;
449
- }
450
- return false;
451
- };
452
- const outputErrors = (path, errors) => {
453
- let isError = false;
454
- for (const error of errors) {
455
- const result = printErrorString(path, error);
456
- isError || (isError = result);
457
- }
458
- return isError;
459
- };
460
559
  const parseNumber = (cursor, _errors) => {
461
560
  const token = cursor.takeToken();
462
561
  return {
@@ -1197,38 +1296,6 @@ const parseBlock = (cursor, errors) => {
1197
1296
  }
1198
1297
  break;
1199
1298
  }
1200
- case "set": {
1201
- cursor.skipToken();
1202
- const args = parseStatementArguments(cursor, errors);
1203
- if (args.length !== 2) {
1204
- errors.push({
1205
- type: "error",
1206
- description: "Required `set` bind identity and expression",
1207
- range: widerRange(
1208
- token.range,
1209
- ...args.map((node) => node.range)
1210
- )
1211
- });
1212
- break;
1213
- }
1214
- const bindNode = args[0];
1215
- if (bindNode.kind !== "variable") {
1216
- errors.push({
1217
- type: "error",
1218
- description: "Required `set` bind identity",
1219
- range: bindNode.range
1220
- });
1221
- break;
1222
- }
1223
- const exprNode = args[1];
1224
- pushNode(statementStates, {
1225
- kind: "set",
1226
- name: bindNode,
1227
- expr: exprNode,
1228
- range: widerRange(token.range, bindNode.range, exprNode.range)
1229
- });
1230
- break;
1231
- }
1232
1299
  default: {
1233
1300
  const node = parseExpression(cursor, errors);
1234
1301
  if (node) {
@@ -1371,6 +1438,7 @@ const fromLambda = (context, lambda) => {
1371
1438
  };
1372
1439
  };
1373
1440
  const reduceExpressionNode = async (context, node) => {
1441
+ var _a;
1374
1442
  switch (node.kind) {
1375
1443
  case "number":
1376
1444
  case "string": {
@@ -1380,6 +1448,7 @@ const reduceExpressionNode = async (context, node) => {
1380
1448
  return traverseVariable(context, node);
1381
1449
  }
1382
1450
  case "apply": {
1451
+ (_a = context.abortSignal) == null ? void 0 : _a.throwIfAborted();
1383
1452
  const func = await reduceExpressionNode(context, node.func);
1384
1453
  if (typeof func !== "function") {
1385
1454
  context.appendError({
@@ -1389,28 +1458,26 @@ const reduceExpressionNode = async (context, node) => {
1389
1458
  });
1390
1459
  return void 0;
1391
1460
  }
1461
+ const args = isFunCityFunction(func) ? node.args : await Promise.all(
1462
+ node.args.map(async (argNode) => {
1463
+ const arg = await reduceExpressionNode(context, argNode);
1464
+ return arg;
1465
+ })
1466
+ );
1392
1467
  const thisProxy = context.createFunctionContext(node);
1393
- if (isSpecialFunction(func)) {
1394
- const value = await func.call(thisProxy, ...node.args);
1395
- return value;
1396
- } else {
1397
- const args = await Promise.all(
1398
- node.args.map(async (argNode) => {
1399
- try {
1400
- const arg = await reduceExpressionNode(context, argNode);
1401
- return arg;
1402
- } catch (e) {
1403
- context.appendError({
1404
- type: "error",
1405
- description: fromError(e),
1406
- range: argNode.range
1407
- });
1408
- return void 0;
1409
- }
1410
- })
1411
- );
1468
+ try {
1412
1469
  const value = await func.call(thisProxy, ...args);
1413
1470
  return value;
1471
+ } catch (e) {
1472
+ if (e instanceof Error && e.name === "AbortError") {
1473
+ throw e;
1474
+ }
1475
+ context.appendError({
1476
+ type: "error",
1477
+ description: fromError(e),
1478
+ range: node.range
1479
+ });
1480
+ return void 0;
1414
1481
  }
1415
1482
  }
1416
1483
  case "lambda": {
@@ -1422,11 +1489,6 @@ const reduceExpressionNode = async (context, node) => {
1422
1489
  );
1423
1490
  return results;
1424
1491
  }
1425
- case "set": {
1426
- const expr = await reduceExpressionNode(context, node.expr);
1427
- context.setValue(node.name.name, expr);
1428
- return void 0;
1429
- }
1430
1492
  case "scope": {
1431
1493
  if (node.nodes.length === 0) {
1432
1494
  return [];
@@ -1508,32 +1570,76 @@ const reduceNode = async (context, node) => {
1508
1570
  }
1509
1571
  }
1510
1572
  };
1511
- const createReducerContext = (variables, errors) => {
1512
- let vs = variables;
1513
- let mvs;
1514
- let variablesProxy;
1573
+ const createScopedReducerContext = (parent) => {
1574
+ let thisVars;
1575
+ let thisContext;
1576
+ const getValue = (name) => {
1577
+ var _a;
1578
+ (_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
1579
+ if (thisVars == null ? void 0 : thisVars.has(name)) {
1580
+ return { value: thisVars.get(name), isFound: true };
1581
+ } else {
1582
+ return parent.getValue(name);
1583
+ }
1584
+ };
1585
+ const setValue = (name, value) => {
1586
+ var _a;
1587
+ (_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
1588
+ if (!thisVars) {
1589
+ thisVars = /* @__PURE__ */ new Map();
1590
+ }
1591
+ thisVars.set(name, value);
1592
+ };
1593
+ const createFunctionContext = (thisNode) => {
1594
+ const newContext = {
1595
+ thisNode,
1596
+ abortSignal: parent.abortSignal,
1597
+ getValue,
1598
+ setValue,
1599
+ isFailed: parent.isFailed,
1600
+ appendError: parent.appendError,
1601
+ reduce: (node) => {
1602
+ var _a;
1603
+ (_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
1604
+ return reduceExpressionNode(thisContext, node);
1605
+ }
1606
+ };
1607
+ return newContext;
1608
+ };
1609
+ thisContext = {
1610
+ abortSignal: parent.abortSignal,
1611
+ getValue,
1612
+ setValue,
1613
+ isFailed: parent.isFailed,
1614
+ appendError: parent.appendError,
1615
+ newScope: () => {
1616
+ var _a;
1617
+ (_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
1618
+ return createScopedReducerContext(thisContext);
1619
+ },
1620
+ createFunctionContext
1621
+ };
1622
+ return thisContext;
1623
+ };
1624
+ const createReducerContext = (variables, errors, signal) => {
1625
+ let thisVars;
1626
+ let thisContext;
1515
1627
  const getValue = (name) => {
1516
- if (vs.has(name)) {
1517
- return { value: vs.get(name), isFound: true };
1628
+ signal == null ? void 0 : signal.throwIfAborted();
1629
+ if (thisVars == null ? void 0 : thisVars.has(name)) {
1630
+ return { value: thisVars.get(name), isFound: true };
1631
+ } else if (variables.has(name)) {
1632
+ return { value: variables.get(name), isFound: true };
1518
1633
  } else {
1519
1634
  return { value: void 0, isFound: false };
1520
1635
  }
1521
1636
  };
1522
1637
  const setValue = (name, value) => {
1523
- if (!mvs) {
1524
- mvs = new Map(vs);
1525
- vs = mvs;
1526
- }
1527
- mvs.set(name, value);
1528
- if (variablesProxy !== void 0) {
1529
- Object.defineProperty(variablesProxy, name, {
1530
- get() {
1531
- return vs.get(name);
1532
- },
1533
- configurable: true,
1534
- enumerable: true
1535
- });
1638
+ signal == null ? void 0 : signal.throwIfAborted();
1639
+ if (!thisVars) {
1640
+ thisVars = /* @__PURE__ */ new Map();
1536
1641
  }
1642
+ thisVars.set(name, value);
1537
1643
  };
1538
1644
  const appendError = (error) => {
1539
1645
  errors.push(error);
@@ -1541,47 +1647,37 @@ const createReducerContext = (variables, errors) => {
1541
1647
  const isFailed = () => {
1542
1648
  return errors.some((error) => error.type === "error");
1543
1649
  };
1544
- const newScope = () => {
1545
- const newContext = createReducerContext(vs, errors);
1546
- return newContext;
1547
- };
1548
- let context;
1549
- const reduceByProxy = (node) => reduceExpressionNode(context, node);
1550
- const getVariablesFromProxy = () => {
1551
- if (variablesProxy === void 0) {
1552
- variablesProxy = {};
1553
- for (const key of vs.keys()) {
1554
- Object.defineProperty(variablesProxy, key, {
1555
- get: () => vs.get(key),
1556
- configurable: true,
1557
- enumerable: true
1558
- });
1559
- }
1560
- }
1561
- return variablesProxy;
1562
- };
1563
1650
  const createFunctionContext = (thisNode) => {
1564
- return {
1565
- get variables() {
1566
- return getVariablesFromProxy();
1567
- },
1651
+ const newContext = {
1568
1652
  thisNode,
1653
+ abortSignal: signal,
1654
+ getValue,
1655
+ setValue,
1656
+ isFailed,
1569
1657
  appendError,
1570
- reduce: reduceByProxy
1658
+ reduce: (node) => {
1659
+ signal == null ? void 0 : signal.throwIfAborted();
1660
+ return reduceExpressionNode(thisContext, node);
1661
+ }
1571
1662
  };
1663
+ return newContext;
1572
1664
  };
1573
- context = {
1665
+ thisContext = {
1666
+ abortSignal: signal,
1574
1667
  getValue,
1575
1668
  setValue,
1576
1669
  appendError,
1577
1670
  isFailed,
1578
- newScope,
1671
+ newScope: () => {
1672
+ signal == null ? void 0 : signal.throwIfAborted();
1673
+ return createScopedReducerContext(thisContext);
1674
+ },
1579
1675
  createFunctionContext
1580
1676
  };
1581
- return context;
1677
+ return thisContext;
1582
1678
  };
1583
- async function runReducer(nodes, variables, errors) {
1584
- const context = createReducerContext(variables, errors);
1679
+ async function runReducer(nodes, variables, errors, signal) {
1680
+ const context = createReducerContext(variables, errors, signal);
1585
1681
  const resultList = [];
1586
1682
  for (const node of nodes) {
1587
1683
  const results = await reduceNode(context, node);
@@ -1593,7 +1689,15 @@ async function runReducer(nodes, variables, errors) {
1593
1689
  }
1594
1690
  return resultList;
1595
1691
  }
1596
- const _cond = makeSpecialFunction(async function(arg0, arg1, arg2) {
1692
+ const _cond = makeFunCityFunction(async function(arg0, arg1, arg2) {
1693
+ if (!arg0 || !arg1 || !arg2) {
1694
+ this.appendError({
1695
+ type: "error",
1696
+ description: "Required `cond` condition, true and false expressions",
1697
+ range: this.thisNode.range
1698
+ });
1699
+ return void 0;
1700
+ }
1597
1701
  const cond = await this.reduce(arg0);
1598
1702
  if (isConditionalTrue(cond)) {
1599
1703
  return await this.reduce(arg1);
@@ -1601,6 +1705,27 @@ const _cond = makeSpecialFunction(async function(arg0, arg1, arg2) {
1601
1705
  return await this.reduce(arg2);
1602
1706
  }
1603
1707
  });
1708
+ const _set = makeFunCityFunction(async function(arg0, arg1, ...rest) {
1709
+ if (!arg0 || !arg1 || rest.length !== 0) {
1710
+ this.appendError({
1711
+ type: "error",
1712
+ description: "Required `set` bind identity and expression",
1713
+ range: this.thisNode.range
1714
+ });
1715
+ return void 0;
1716
+ }
1717
+ if (arg0.kind !== "variable") {
1718
+ this.appendError({
1719
+ type: "error",
1720
+ description: "Required `set` bind identity",
1721
+ range: arg0.range
1722
+ });
1723
+ return void 0;
1724
+ }
1725
+ const value = await this.reduce(arg1);
1726
+ this.setValue(arg0.name, value);
1727
+ return void 0;
1728
+ });
1604
1729
  const _typeof = async (arg0) => {
1605
1730
  if (arg0 === null) {
1606
1731
  return "null";
@@ -1614,54 +1739,33 @@ const _typeof = async (arg0) => {
1614
1739
  return typeof arg0;
1615
1740
  }
1616
1741
  };
1617
- const funcIds = /* @__PURE__ */ new WeakMap();
1618
- let nextId = 1;
1619
- const getFuncId = (fn) => {
1620
- const cached = funcIds.get(fn);
1621
- if (cached) return cached;
1622
- const id = nextId++;
1623
- funcIds.set(fn, id);
1624
- return id;
1625
- };
1626
1742
  const _toString = async (...args) => {
1627
- const results = args.map((arg0) => {
1628
- switch (arg0) {
1629
- case void 0:
1630
- return "(undefined)";
1631
- case null:
1632
- return "(null)";
1633
- default:
1634
- switch (typeof arg0) {
1635
- case "string":
1636
- return arg0;
1637
- case "boolean":
1638
- return arg0 ? "true" : "false";
1639
- case "number":
1640
- case "bigint":
1641
- case "symbol":
1642
- return arg0.toString();
1643
- case "function":
1644
- if (arg0.name) {
1645
- return `fun<${arg0.name}:#${getFuncId(arg0)}>`;
1646
- } else {
1647
- return `fun<#${getFuncId(arg0)}>`;
1648
- }
1649
- default:
1650
- if (Array.isArray(arg0)) {
1651
- return JSON.stringify(arg0);
1652
- }
1653
- const iterable = asIterable(arg0);
1654
- if (iterable) {
1655
- const arr = Array.from(iterable);
1656
- return JSON.stringify(arr);
1657
- } else {
1658
- return JSON.stringify(arg0);
1659
- }
1660
- }
1661
- }
1662
- });
1743
+ const results = args.map((arg0) => convertToString(arg0));
1663
1744
  return results.join(",");
1664
1745
  };
1746
+ const _toBoolean = async (arg0) => {
1747
+ const r = isConditionalTrue(arg0);
1748
+ return r;
1749
+ };
1750
+ const _toNumber = async (arg0) => {
1751
+ const r = Number(arg0);
1752
+ return r;
1753
+ };
1754
+ const _toBigInt = async (arg0) => {
1755
+ switch (typeof arg0) {
1756
+ case "number":
1757
+ case "bigint":
1758
+ case "string":
1759
+ case "boolean": {
1760
+ const r = BigInt(arg0);
1761
+ return r;
1762
+ }
1763
+ default: {
1764
+ const r = BigInt(await _toString(arg0));
1765
+ return r;
1766
+ }
1767
+ }
1768
+ };
1665
1769
  const _add = async (arg0, ...args) => {
1666
1770
  const r = args.reduce((v0, v) => v0 + Number(v), Number(arg0));
1667
1771
  return r;
@@ -1759,20 +1863,40 @@ const _length = async (arg0) => {
1759
1863
  }
1760
1864
  return 0;
1761
1865
  };
1762
- const _and = async (...args) => {
1866
+ const _and = makeFunCityFunction(async function(...args) {
1763
1867
  if (args.length === 0) {
1764
- throw new Error("empty arguments");
1868
+ this.appendError({
1869
+ type: "error",
1870
+ description: "empty arguments",
1871
+ range: this.thisNode.range
1872
+ });
1873
+ return void 0;
1765
1874
  }
1766
- const r = args.reduce((v0, v) => v0 && isConditionalTrue(v), true);
1767
- return r;
1768
- };
1769
- const _or = async (...args) => {
1875
+ for (const arg of args) {
1876
+ const value = await this.reduce(arg);
1877
+ if (!isConditionalTrue(value)) {
1878
+ return false;
1879
+ }
1880
+ }
1881
+ return true;
1882
+ });
1883
+ const _or = makeFunCityFunction(async function(...args) {
1770
1884
  if (args.length === 0) {
1771
- throw new Error("empty arguments");
1885
+ this.appendError({
1886
+ type: "error",
1887
+ description: "empty arguments",
1888
+ range: this.thisNode.range
1889
+ });
1890
+ return void 0;
1772
1891
  }
1773
- const r = args.reduce((v0, v) => v0 || isConditionalTrue(v), false);
1774
- return r;
1775
- };
1892
+ for (const arg of args) {
1893
+ const value = await this.reduce(arg);
1894
+ if (isConditionalTrue(value)) {
1895
+ return true;
1896
+ }
1897
+ }
1898
+ return false;
1899
+ });
1776
1900
  const _not = async (arg0) => {
1777
1901
  return !isConditionalTrue(arg0);
1778
1902
  };
@@ -1934,13 +2058,24 @@ const _bind = async (arg0, ...args) => {
1934
2058
  const predicate = arg0;
1935
2059
  return predicate.bind(void 0, ...args);
1936
2060
  };
2061
+ const _url = async (arg0, arg1) => {
2062
+ const url = new URL(
2063
+ convertToString(arg0),
2064
+ arg1 !== void 0 ? convertToString(arg1) : void 0
2065
+ );
2066
+ return url;
2067
+ };
1937
2068
  const standardVariables = Object.freeze({
1938
2069
  undefined: void 0,
1939
2070
  null: null,
1940
2071
  true: true,
1941
2072
  false: false,
1942
2073
  cond: _cond,
2074
+ set: _set,
1943
2075
  toString: _toString,
2076
+ toBoolean: _toBoolean,
2077
+ toNumber: _toNumber,
2078
+ toBigInt: _toBigInt,
1944
2079
  typeof: _typeof,
1945
2080
  add: _add,
1946
2081
  sub: _sub,
@@ -1972,30 +2107,32 @@ const standardVariables = Object.freeze({
1972
2107
  match: _match,
1973
2108
  replace: _replace,
1974
2109
  regex: _regex,
1975
- bind: _bind
2110
+ bind: _bind,
2111
+ url: _url
1976
2112
  });
1977
2113
  const buildCandidateVariables = (...variablesList) => {
1978
2114
  return combineVariables(standardVariables, ...variablesList);
1979
2115
  };
1980
- const runScriptOnce = async (script, variables, errors = []) => {
2116
+ const runScriptOnce = async (script, variables, errors = [], signal) => {
1981
2117
  const blocks = runTokenizer(script, errors);
1982
2118
  const nodes = runParser(blocks, errors);
1983
- const results = await runReducer(nodes, variables, errors);
1984
- const text = results.join("");
2119
+ const results = await runReducer(nodes, variables, errors, signal);
2120
+ const text = results.map((result) => convertToString(result)).join("");
1985
2121
  return text;
1986
2122
  };
1987
2123
  export {
1988
2124
  asIterable,
1989
2125
  buildCandidateVariables,
1990
2126
  combineVariables,
2127
+ convertToString,
1991
2128
  createParserCursor,
1992
2129
  createReducerContext,
1993
2130
  emptyLocation,
1994
2131
  emptyRange,
1995
2132
  fromError,
1996
2133
  isConditionalTrue,
1997
- isSpecialFunction,
1998
- makeSpecialFunction,
2134
+ isFunCityFunction,
2135
+ makeFunCityFunction,
1999
2136
  outputErrors,
2000
2137
  parseBlock,
2001
2138
  parseExpression,