funcity 0.2.0 → 0.4.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 +508 -311
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +508 -311
- package/dist/index.mjs.map +1 -1
- package/dist/parser.d.ts +10 -266
- package/dist/parser.d.ts.map +1 -1
- package/dist/reducer.d.ts +7 -81
- package/dist/reducer.d.ts.map +1 -1
- package/dist/scripting.d.ts +10 -108
- package/dist/scripting.d.ts.map +1 -1
- package/dist/standards.d.ts +10 -5
- package/dist/standards.d.ts.map +1 -1
- package/dist/tokenizer.d.ts +8 -120
- package/dist/tokenizer.d.ts.map +1 -1
- package/dist/types.d.ts +453 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils.d.ts +75 -0
- package/dist/utils.d.ts.map +1 -0
- package/images/funcity.120.png +0 -0
- package/package.json +13 -12
package/dist/index.cjs
CHANGED
|
@@ -1,19 +1,227 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const emptyLocation = {
|
|
4
|
+
line: 0,
|
|
5
|
+
column: 0
|
|
6
|
+
};
|
|
7
|
+
const emptyRange = {
|
|
8
|
+
start: emptyLocation,
|
|
9
|
+
end: emptyLocation
|
|
10
|
+
};
|
|
11
|
+
const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
|
|
12
|
+
const makeFunCityFunction = (f) => {
|
|
13
|
+
f[specialFunctionMarker] = true;
|
|
14
|
+
return f;
|
|
15
|
+
};
|
|
16
|
+
const isFunCityFunction = (f) => {
|
|
17
|
+
var _a;
|
|
18
|
+
return (_a = f[specialFunctionMarker]) != null ? _a : false;
|
|
19
|
+
};
|
|
20
|
+
const isConditionalTrue = (v) => {
|
|
21
|
+
if (v === void 0 || v === null) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
switch (typeof v) {
|
|
25
|
+
case "boolean":
|
|
26
|
+
return v;
|
|
27
|
+
case "number":
|
|
28
|
+
case "bigint":
|
|
29
|
+
return v !== 0;
|
|
30
|
+
default:
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const asIterable = (v) => {
|
|
35
|
+
if (typeof v[Symbol.iterator] === "function") {
|
|
36
|
+
return v;
|
|
37
|
+
} else {
|
|
38
|
+
return void 0;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const combineVariables = (...variablesList) => {
|
|
42
|
+
const variables = /* @__PURE__ */ new Map();
|
|
43
|
+
const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
|
|
44
|
+
const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
|
|
45
|
+
variablesList.forEach((vs) => {
|
|
46
|
+
if (vs["forEach"] !== void 0) {
|
|
47
|
+
appendVariables(vs);
|
|
48
|
+
} else {
|
|
49
|
+
appendRecord(vs);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return variables;
|
|
53
|
+
};
|
|
54
|
+
const fromError = (error) => {
|
|
55
|
+
var _a;
|
|
56
|
+
if (error.message) {
|
|
57
|
+
return error.message;
|
|
58
|
+
} else if (typeof error.toString === "function") {
|
|
59
|
+
return (_a = error.toString()) != null ? _a : "unknown";
|
|
60
|
+
} else {
|
|
61
|
+
return "unknown";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const widerRange = (...ranges) => {
|
|
65
|
+
let start = emptyRange.start;
|
|
66
|
+
let end = emptyRange.end;
|
|
67
|
+
for (const range of ranges) {
|
|
68
|
+
if (range.start.line >= 1 && range.start.column >= 1) {
|
|
69
|
+
if (start.line === 0 || start.column === 0) {
|
|
70
|
+
start = range.start;
|
|
71
|
+
} else if (range.start.line < start.line) {
|
|
72
|
+
start = range.start;
|
|
73
|
+
} else if (range.start.line === start.line && range.start.column < start.column) {
|
|
74
|
+
start = range.start;
|
|
75
|
+
}
|
|
76
|
+
if (end.line === 0 || end.column === 0) {
|
|
77
|
+
end = range.end;
|
|
78
|
+
} else if (range.end.line > end.line) {
|
|
79
|
+
end = range.end;
|
|
80
|
+
} else if (range.end.line === end.line && range.end.column > end.column) {
|
|
81
|
+
end = range.end;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { start, end };
|
|
86
|
+
};
|
|
87
|
+
const locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
|
|
88
|
+
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}`;
|
|
89
|
+
const printErrorString = (path, error) => {
|
|
90
|
+
switch (error.type) {
|
|
91
|
+
case "warning":
|
|
92
|
+
console.warn(
|
|
93
|
+
`${path}:${getLocationString(error.range)}: warning: ${error.description}`
|
|
94
|
+
);
|
|
95
|
+
break;
|
|
96
|
+
case "error":
|
|
97
|
+
console.error(
|
|
98
|
+
`${path}:${getLocationString(error.range)}: error: ${error.description}`
|
|
99
|
+
);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
104
|
+
const outputErrors = (path, errors) => {
|
|
105
|
+
let isError = false;
|
|
106
|
+
for (const error of errors) {
|
|
107
|
+
const result = printErrorString(path, error);
|
|
108
|
+
isError || (isError = result);
|
|
109
|
+
}
|
|
110
|
+
return isError;
|
|
111
|
+
};
|
|
112
|
+
const funcIds = /* @__PURE__ */ new WeakMap();
|
|
113
|
+
let nextId = 1;
|
|
114
|
+
const getFuncId = (fn) => {
|
|
115
|
+
const cached = funcIds.get(fn);
|
|
116
|
+
if (cached) {
|
|
117
|
+
return cached;
|
|
118
|
+
}
|
|
119
|
+
const id = nextId++;
|
|
120
|
+
funcIds.set(fn, id);
|
|
121
|
+
return id;
|
|
122
|
+
};
|
|
123
|
+
const convertToString = (v) => {
|
|
124
|
+
switch (v) {
|
|
125
|
+
case void 0:
|
|
126
|
+
return "(undefined)";
|
|
127
|
+
case null:
|
|
128
|
+
return "(null)";
|
|
129
|
+
default:
|
|
130
|
+
switch (typeof v) {
|
|
131
|
+
case "string":
|
|
132
|
+
return v;
|
|
133
|
+
case "boolean":
|
|
134
|
+
return v ? "true" : "false";
|
|
135
|
+
case "number":
|
|
136
|
+
case "bigint":
|
|
137
|
+
case "symbol":
|
|
138
|
+
return v.toString();
|
|
139
|
+
case "function":
|
|
140
|
+
if (v.name) {
|
|
141
|
+
return `fun<${v.name}:#${getFuncId(v)}>`;
|
|
142
|
+
} else {
|
|
143
|
+
return `fun<#${getFuncId(v)}>`;
|
|
144
|
+
}
|
|
145
|
+
default:
|
|
146
|
+
if (Array.isArray(v)) {
|
|
147
|
+
return JSON.stringify(v);
|
|
148
|
+
}
|
|
149
|
+
const iterable = asIterable(v);
|
|
150
|
+
if (iterable) {
|
|
151
|
+
const arr = Array.from(iterable);
|
|
152
|
+
return JSON.stringify(arr);
|
|
153
|
+
} else if (v instanceof Date) {
|
|
154
|
+
return v.toISOString();
|
|
155
|
+
} else if (v instanceof Error) {
|
|
156
|
+
return `${v.name}: ${v.message}`;
|
|
157
|
+
} else if (v instanceof URL) {
|
|
158
|
+
return v.origin;
|
|
159
|
+
} else {
|
|
160
|
+
return JSON.stringify(v);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const stringEscapeMap = {
|
|
166
|
+
f: "\f",
|
|
167
|
+
n: "\n",
|
|
168
|
+
r: "\r",
|
|
169
|
+
t: " ",
|
|
170
|
+
v: "\v",
|
|
171
|
+
"0": "\0",
|
|
172
|
+
"'": "'",
|
|
173
|
+
"\\": "\\"
|
|
174
|
+
};
|
|
3
175
|
const tokenizeString = (context) => {
|
|
4
176
|
const start = context.cursor.location("start");
|
|
5
177
|
context.cursor.skip(1);
|
|
6
|
-
let value =
|
|
7
|
-
|
|
178
|
+
let value = "";
|
|
179
|
+
let closed = false;
|
|
180
|
+
while (!context.cursor.eot()) {
|
|
181
|
+
const ch = context.cursor.getChar();
|
|
182
|
+
if (ch === "'") {
|
|
183
|
+
context.cursor.skip(1);
|
|
184
|
+
closed = true;
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
if (ch === "\\") {
|
|
188
|
+
const escapeStart = context.cursor.location("start");
|
|
189
|
+
context.cursor.skip(1);
|
|
190
|
+
if (context.cursor.eot()) {
|
|
191
|
+
context.errors.push({
|
|
192
|
+
type: "error",
|
|
193
|
+
description: "invalid escape sequence: \\\\",
|
|
194
|
+
range: { start: escapeStart, end: context.cursor.location("end") }
|
|
195
|
+
});
|
|
196
|
+
value += "\\";
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
const escape = context.cursor.getChar();
|
|
200
|
+
const mapped = stringEscapeMap[escape];
|
|
201
|
+
if (mapped !== void 0) {
|
|
202
|
+
value += mapped;
|
|
203
|
+
context.cursor.skip(1);
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
context.cursor.skip(1);
|
|
207
|
+
context.errors.push({
|
|
208
|
+
type: "error",
|
|
209
|
+
description: `invalid escape sequence: \\${escape}`,
|
|
210
|
+
range: { start: escapeStart, end: context.cursor.location("end") }
|
|
211
|
+
});
|
|
212
|
+
value += `\\${escape}`;
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
value += ch;
|
|
8
216
|
context.cursor.skip(1);
|
|
9
|
-
}
|
|
217
|
+
}
|
|
218
|
+
if (!closed) {
|
|
10
219
|
const location = context.cursor.location("start");
|
|
11
220
|
context.errors.push({
|
|
12
221
|
type: "error",
|
|
13
222
|
description: "string close quote is not found",
|
|
14
223
|
range: { start: location, end: location }
|
|
15
224
|
});
|
|
16
|
-
value = "";
|
|
17
225
|
}
|
|
18
226
|
return {
|
|
19
227
|
kind: "string",
|
|
@@ -94,16 +302,8 @@ const tokenizeIdentity = (context) => {
|
|
|
94
302
|
range: { start, end: context.cursor.location("end") }
|
|
95
303
|
};
|
|
96
304
|
};
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
context.cursor.skip(2);
|
|
100
|
-
const tokens = [
|
|
101
|
-
{
|
|
102
|
-
kind: "open",
|
|
103
|
-
symbol: "{{",
|
|
104
|
-
range: { start: openStart, end: context.cursor.location("end") }
|
|
105
|
-
}
|
|
106
|
-
];
|
|
305
|
+
const tokenizeCodeTokens = (context, stopOnClose, finalizeUnknownOnEot) => {
|
|
306
|
+
const tokens = [];
|
|
107
307
|
let unknownStartLocation;
|
|
108
308
|
const finalizeUnknown = () => {
|
|
109
309
|
if (unknownStartLocation) {
|
|
@@ -119,20 +319,21 @@ const tokenizeCodeBlock = (context) => {
|
|
|
119
319
|
}
|
|
120
320
|
};
|
|
121
321
|
while (!context.cursor.eot()) {
|
|
122
|
-
if (context.cursor.assert("}}")) {
|
|
322
|
+
if (stopOnClose && context.cursor.assert("}}")) {
|
|
123
323
|
finalizeUnknown();
|
|
124
|
-
|
|
125
|
-
context.cursor.skip(2);
|
|
126
|
-
tokens.push({
|
|
127
|
-
kind: "close",
|
|
128
|
-
symbol: "}}",
|
|
129
|
-
range: { start: location, end: context.cursor.location("end") }
|
|
130
|
-
});
|
|
131
|
-
return tokens;
|
|
324
|
+
return { tokens, closed: true };
|
|
132
325
|
}
|
|
133
326
|
const ch = context.cursor.getChar();
|
|
134
327
|
if (ch === "\\") {
|
|
135
328
|
const next = context.cursor.getChar(1);
|
|
329
|
+
if (next === "\n") {
|
|
330
|
+
context.cursor.skip(2);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (next === "\r" && context.cursor.getChar(2) === "\n") {
|
|
334
|
+
context.cursor.skip(3);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
136
337
|
if (next === "{" || next === "}") {
|
|
137
338
|
context.cursor.skip(2);
|
|
138
339
|
continue;
|
|
@@ -197,12 +398,41 @@ const tokenizeCodeBlock = (context) => {
|
|
|
197
398
|
} else if (ch === " ") {
|
|
198
399
|
finalizeUnknown();
|
|
199
400
|
context.cursor.skip(1);
|
|
200
|
-
} else
|
|
201
|
-
|
|
401
|
+
} else {
|
|
402
|
+
if (!unknownStartLocation) {
|
|
403
|
+
unknownStartLocation = context.cursor.location("start");
|
|
404
|
+
}
|
|
202
405
|
context.cursor.skip(1);
|
|
203
406
|
}
|
|
204
407
|
context.cursor.skipChars(" ");
|
|
205
408
|
}
|
|
409
|
+
if (finalizeUnknownOnEot) {
|
|
410
|
+
finalizeUnknown();
|
|
411
|
+
}
|
|
412
|
+
return { tokens, closed: false };
|
|
413
|
+
};
|
|
414
|
+
const tokenizeCodeBlock = (context) => {
|
|
415
|
+
const openStart = context.cursor.location("start");
|
|
416
|
+
context.cursor.skip(2);
|
|
417
|
+
const tokens = [
|
|
418
|
+
{
|
|
419
|
+
kind: "open",
|
|
420
|
+
symbol: "{{",
|
|
421
|
+
range: { start: openStart, end: context.cursor.location("end") }
|
|
422
|
+
}
|
|
423
|
+
];
|
|
424
|
+
const result = tokenizeCodeTokens(context, true, false);
|
|
425
|
+
tokens.push(...result.tokens);
|
|
426
|
+
if (result.closed) {
|
|
427
|
+
const location = context.cursor.location("start");
|
|
428
|
+
context.cursor.skip(2);
|
|
429
|
+
tokens.push({
|
|
430
|
+
kind: "close",
|
|
431
|
+
symbol: "}}",
|
|
432
|
+
range: { start: location, end: context.cursor.location("end") }
|
|
433
|
+
});
|
|
434
|
+
return tokens;
|
|
435
|
+
}
|
|
206
436
|
const causeLocation = context.cursor.location("start");
|
|
207
437
|
context.errors.push({
|
|
208
438
|
type: "error",
|
|
@@ -227,9 +457,12 @@ const createTokenizerCursor = (script) => {
|
|
|
227
457
|
const ch = script[currentIndex];
|
|
228
458
|
if (ch === "\r") {
|
|
229
459
|
rawColumn = 0;
|
|
230
|
-
} else if (ch === "\n" && lastch !== "\r") {
|
|
231
|
-
rawColumn = 0;
|
|
232
460
|
rawLine++;
|
|
461
|
+
} else if (ch === "\n") {
|
|
462
|
+
rawColumn = 0;
|
|
463
|
+
if (lastch !== "\r") {
|
|
464
|
+
rawLine++;
|
|
465
|
+
}
|
|
233
466
|
} else {
|
|
234
467
|
rawColumn++;
|
|
235
468
|
}
|
|
@@ -306,6 +539,14 @@ const createTokenizerCursor = (script) => {
|
|
|
306
539
|
location
|
|
307
540
|
};
|
|
308
541
|
};
|
|
542
|
+
const runCodeTokenizer = (script, errors) => {
|
|
543
|
+
const context = {
|
|
544
|
+
cursor: createTokenizerCursor(script),
|
|
545
|
+
errors
|
|
546
|
+
};
|
|
547
|
+
const result = tokenizeCodeTokens(context, false, true);
|
|
548
|
+
return result.tokens;
|
|
549
|
+
};
|
|
309
550
|
const runTokenizer = (script, errors) => {
|
|
310
551
|
const context = {
|
|
311
552
|
cursor: createTokenizerCursor(script),
|
|
@@ -350,115 +591,6 @@ const runTokenizer = (script, errors) => {
|
|
|
350
591
|
}
|
|
351
592
|
return tokens;
|
|
352
593
|
};
|
|
353
|
-
const emptyLocation = {
|
|
354
|
-
line: 0,
|
|
355
|
-
column: 0
|
|
356
|
-
};
|
|
357
|
-
const emptyRange = {
|
|
358
|
-
start: emptyLocation,
|
|
359
|
-
end: emptyLocation
|
|
360
|
-
};
|
|
361
|
-
const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
|
|
362
|
-
const makeSpecialFunction = (f) => {
|
|
363
|
-
f[specialFunctionMarker] = true;
|
|
364
|
-
return f;
|
|
365
|
-
};
|
|
366
|
-
const isSpecialFunction = (f) => {
|
|
367
|
-
var _a;
|
|
368
|
-
return (_a = f[specialFunctionMarker]) != null ? _a : false;
|
|
369
|
-
};
|
|
370
|
-
const isConditionalTrue = (v) => {
|
|
371
|
-
if (v === void 0 || v === null) {
|
|
372
|
-
return false;
|
|
373
|
-
}
|
|
374
|
-
switch (typeof v) {
|
|
375
|
-
case "boolean":
|
|
376
|
-
return v;
|
|
377
|
-
case "number":
|
|
378
|
-
case "bigint":
|
|
379
|
-
return v !== 0;
|
|
380
|
-
default:
|
|
381
|
-
return true;
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
const asIterable = (v) => {
|
|
385
|
-
if (typeof v[Symbol.iterator] === "function") {
|
|
386
|
-
return v;
|
|
387
|
-
} else {
|
|
388
|
-
return void 0;
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
const combineVariables = (...variablesList) => {
|
|
392
|
-
const variables = /* @__PURE__ */ new Map();
|
|
393
|
-
const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
|
|
394
|
-
const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
|
|
395
|
-
variablesList.forEach((vs) => {
|
|
396
|
-
if (vs["forEach"] !== void 0) {
|
|
397
|
-
appendVariables(vs);
|
|
398
|
-
} else {
|
|
399
|
-
appendRecord(vs);
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
return variables;
|
|
403
|
-
};
|
|
404
|
-
const fromError = (error) => {
|
|
405
|
-
var _a;
|
|
406
|
-
if (error.message) {
|
|
407
|
-
return error.message;
|
|
408
|
-
} else if (typeof error.toString === "function") {
|
|
409
|
-
return (_a = error.toString()) != null ? _a : "unknown";
|
|
410
|
-
} else {
|
|
411
|
-
return "unknown";
|
|
412
|
-
}
|
|
413
|
-
};
|
|
414
|
-
const widerRange = (...ranges) => {
|
|
415
|
-
let start = emptyRange.start;
|
|
416
|
-
let end = emptyRange.end;
|
|
417
|
-
for (const range of ranges) {
|
|
418
|
-
if (range.start.line >= 1 && range.start.column >= 1) {
|
|
419
|
-
if (start.line === 0 || start.column === 0) {
|
|
420
|
-
start = range.start;
|
|
421
|
-
} else if (range.start.line < start.line) {
|
|
422
|
-
start = range.start;
|
|
423
|
-
} else if (range.start.line === start.line && range.start.column < start.column) {
|
|
424
|
-
start = range.start;
|
|
425
|
-
}
|
|
426
|
-
if (end.line === 0 || end.column === 0) {
|
|
427
|
-
end = range.end;
|
|
428
|
-
} else if (range.end.line > end.line) {
|
|
429
|
-
end = range.end;
|
|
430
|
-
} else if (range.end.line === end.line && range.end.column > end.column) {
|
|
431
|
-
end = range.end;
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
return { start, end };
|
|
436
|
-
};
|
|
437
|
-
const locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
|
|
438
|
-
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}`;
|
|
439
|
-
const printErrorString = (path, error) => {
|
|
440
|
-
switch (error.type) {
|
|
441
|
-
case "warning":
|
|
442
|
-
console.warn(
|
|
443
|
-
`${path}:${getLocationString(error.range)}: warning: ${error.description}`
|
|
444
|
-
);
|
|
445
|
-
break;
|
|
446
|
-
case "error":
|
|
447
|
-
console.error(
|
|
448
|
-
`${path}:${getLocationString(error.range)}: error: ${error.description}`
|
|
449
|
-
);
|
|
450
|
-
return true;
|
|
451
|
-
}
|
|
452
|
-
return false;
|
|
453
|
-
};
|
|
454
|
-
const outputErrors = (path, errors) => {
|
|
455
|
-
let isError = false;
|
|
456
|
-
for (const error of errors) {
|
|
457
|
-
const result = printErrorString(path, error);
|
|
458
|
-
isError || (isError = result);
|
|
459
|
-
}
|
|
460
|
-
return isError;
|
|
461
|
-
};
|
|
462
594
|
const parseNumber = (cursor, _errors) => {
|
|
463
595
|
const token = cursor.takeToken();
|
|
464
596
|
return {
|
|
@@ -546,6 +678,9 @@ const parseLambdaExpression = (cursor, errors) => {
|
|
|
546
678
|
};
|
|
547
679
|
const parsePartialExpression = (cursor, errors) => {
|
|
548
680
|
const token = cursor.peekToken();
|
|
681
|
+
if (!token) {
|
|
682
|
+
return void 0;
|
|
683
|
+
}
|
|
549
684
|
switch (token.kind) {
|
|
550
685
|
case "number": {
|
|
551
686
|
const node = parseNumber(cursor);
|
|
@@ -930,14 +1065,15 @@ const extractParameterArguments = (namesNode, errors) => {
|
|
|
930
1065
|
}
|
|
931
1066
|
}
|
|
932
1067
|
};
|
|
933
|
-
const
|
|
1068
|
+
const parseBlockCore = (cursor, errors, mode) => {
|
|
934
1069
|
const rootState = {
|
|
935
1070
|
kind: "root",
|
|
936
1071
|
startRange: emptyRange,
|
|
937
1072
|
branch: createBranchState()
|
|
938
1073
|
};
|
|
939
1074
|
const statementStates = [rootState];
|
|
940
|
-
|
|
1075
|
+
const isCodeMode = mode === "code";
|
|
1076
|
+
let isInExpressionBlock = isCodeMode;
|
|
941
1077
|
while (true) {
|
|
942
1078
|
const token = drainEndOfLineAndPeek(cursor);
|
|
943
1079
|
if (!token) {
|
|
@@ -964,14 +1100,16 @@ const parseBlock = (cursor, errors) => {
|
|
|
964
1100
|
case "open": {
|
|
965
1101
|
if (token.symbol === "{{") {
|
|
966
1102
|
cursor.skipToken();
|
|
967
|
-
if (
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
1103
|
+
if (!isCodeMode) {
|
|
1104
|
+
if (isInExpressionBlock) {
|
|
1105
|
+
errors.push({
|
|
1106
|
+
type: "error",
|
|
1107
|
+
description: `Already opened expression block`,
|
|
1108
|
+
range: token.range
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
isInExpressionBlock = true;
|
|
973
1112
|
}
|
|
974
|
-
isInExpressionBlock = true;
|
|
975
1113
|
} else {
|
|
976
1114
|
const node = parseExpression(cursor, errors);
|
|
977
1115
|
if (node) {
|
|
@@ -982,6 +1120,10 @@ const parseBlock = (cursor, errors) => {
|
|
|
982
1120
|
}
|
|
983
1121
|
case "close": {
|
|
984
1122
|
cursor.skipToken();
|
|
1123
|
+
if (token.symbol === "}}" && isCodeMode) {
|
|
1124
|
+
flushCurrentBranch(statementStates);
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
985
1127
|
if (!isInExpressionBlock) {
|
|
986
1128
|
errors.push({
|
|
987
1129
|
type: "error",
|
|
@@ -990,6 +1132,14 @@ const parseBlock = (cursor, errors) => {
|
|
|
990
1132
|
});
|
|
991
1133
|
break;
|
|
992
1134
|
}
|
|
1135
|
+
if (isCodeMode) {
|
|
1136
|
+
errors.push({
|
|
1137
|
+
type: "error",
|
|
1138
|
+
description: `Mismatched close bracket`,
|
|
1139
|
+
range: token.range
|
|
1140
|
+
});
|
|
1141
|
+
break;
|
|
1142
|
+
}
|
|
993
1143
|
flushCurrentBranch(statementStates);
|
|
994
1144
|
isInExpressionBlock = false;
|
|
995
1145
|
break;
|
|
@@ -1199,38 +1349,6 @@ const parseBlock = (cursor, errors) => {
|
|
|
1199
1349
|
}
|
|
1200
1350
|
break;
|
|
1201
1351
|
}
|
|
1202
|
-
case "set": {
|
|
1203
|
-
cursor.skipToken();
|
|
1204
|
-
const args = parseStatementArguments(cursor, errors);
|
|
1205
|
-
if (args.length !== 2) {
|
|
1206
|
-
errors.push({
|
|
1207
|
-
type: "error",
|
|
1208
|
-
description: "Required `set` bind identity and expression",
|
|
1209
|
-
range: widerRange(
|
|
1210
|
-
token.range,
|
|
1211
|
-
...args.map((node) => node.range)
|
|
1212
|
-
)
|
|
1213
|
-
});
|
|
1214
|
-
break;
|
|
1215
|
-
}
|
|
1216
|
-
const bindNode = args[0];
|
|
1217
|
-
if (bindNode.kind !== "variable") {
|
|
1218
|
-
errors.push({
|
|
1219
|
-
type: "error",
|
|
1220
|
-
description: "Required `set` bind identity",
|
|
1221
|
-
range: bindNode.range
|
|
1222
|
-
});
|
|
1223
|
-
break;
|
|
1224
|
-
}
|
|
1225
|
-
const exprNode = args[1];
|
|
1226
|
-
pushNode(statementStates, {
|
|
1227
|
-
kind: "set",
|
|
1228
|
-
name: bindNode,
|
|
1229
|
-
expr: exprNode,
|
|
1230
|
-
range: widerRange(token.range, bindNode.range, exprNode.range)
|
|
1231
|
-
});
|
|
1232
|
-
break;
|
|
1233
|
-
}
|
|
1234
1352
|
default: {
|
|
1235
1353
|
const node = parseExpression(cursor, errors);
|
|
1236
1354
|
if (node) {
|
|
@@ -1268,6 +1386,9 @@ const parseBlock = (cursor, errors) => {
|
|
|
1268
1386
|
}
|
|
1269
1387
|
return rootState.branch.blocks;
|
|
1270
1388
|
};
|
|
1389
|
+
const parseBlock = (cursor, errors) => {
|
|
1390
|
+
return parseBlockCore(cursor, errors, "script");
|
|
1391
|
+
};
|
|
1271
1392
|
const createParserCursor = (tokens) => {
|
|
1272
1393
|
let index = 0;
|
|
1273
1394
|
const peekToken = () => {
|
|
@@ -1293,6 +1414,10 @@ const createParserCursor = (tokens) => {
|
|
|
1293
1414
|
skipToken
|
|
1294
1415
|
};
|
|
1295
1416
|
};
|
|
1417
|
+
const parseExpressions = (tokens, errors) => {
|
|
1418
|
+
const cursor = createParserCursor(tokens);
|
|
1419
|
+
return parseBlockCore(cursor, errors, "code");
|
|
1420
|
+
};
|
|
1296
1421
|
const runParser = (tokens, errors) => {
|
|
1297
1422
|
const cursor = createParserCursor(tokens);
|
|
1298
1423
|
const blockNodes = parseBlock(cursor, errors);
|
|
@@ -1373,6 +1498,7 @@ const fromLambda = (context, lambda) => {
|
|
|
1373
1498
|
};
|
|
1374
1499
|
};
|
|
1375
1500
|
const reduceExpressionNode = async (context, node) => {
|
|
1501
|
+
var _a;
|
|
1376
1502
|
switch (node.kind) {
|
|
1377
1503
|
case "number":
|
|
1378
1504
|
case "string": {
|
|
@@ -1382,6 +1508,7 @@ const reduceExpressionNode = async (context, node) => {
|
|
|
1382
1508
|
return traverseVariable(context, node);
|
|
1383
1509
|
}
|
|
1384
1510
|
case "apply": {
|
|
1511
|
+
(_a = context.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
1385
1512
|
const func = await reduceExpressionNode(context, node.func);
|
|
1386
1513
|
if (typeof func !== "function") {
|
|
1387
1514
|
context.appendError({
|
|
@@ -1391,28 +1518,26 @@ const reduceExpressionNode = async (context, node) => {
|
|
|
1391
1518
|
});
|
|
1392
1519
|
return void 0;
|
|
1393
1520
|
}
|
|
1521
|
+
const args = isFunCityFunction(func) ? node.args : await Promise.all(
|
|
1522
|
+
node.args.map(async (argNode) => {
|
|
1523
|
+
const arg = await reduceExpressionNode(context, argNode);
|
|
1524
|
+
return arg;
|
|
1525
|
+
})
|
|
1526
|
+
);
|
|
1394
1527
|
const thisProxy = context.createFunctionContext(node);
|
|
1395
|
-
|
|
1396
|
-
const value = await func.call(thisProxy, ...node.args);
|
|
1397
|
-
return value;
|
|
1398
|
-
} else {
|
|
1399
|
-
const args = await Promise.all(
|
|
1400
|
-
node.args.map(async (argNode) => {
|
|
1401
|
-
try {
|
|
1402
|
-
const arg = await reduceExpressionNode(context, argNode);
|
|
1403
|
-
return arg;
|
|
1404
|
-
} catch (e) {
|
|
1405
|
-
context.appendError({
|
|
1406
|
-
type: "error",
|
|
1407
|
-
description: fromError(e),
|
|
1408
|
-
range: argNode.range
|
|
1409
|
-
});
|
|
1410
|
-
return void 0;
|
|
1411
|
-
}
|
|
1412
|
-
})
|
|
1413
|
-
);
|
|
1528
|
+
try {
|
|
1414
1529
|
const value = await func.call(thisProxy, ...args);
|
|
1415
1530
|
return value;
|
|
1531
|
+
} catch (e) {
|
|
1532
|
+
if (e instanceof Error && e.name === "AbortError") {
|
|
1533
|
+
throw e;
|
|
1534
|
+
}
|
|
1535
|
+
context.appendError({
|
|
1536
|
+
type: "error",
|
|
1537
|
+
description: fromError(e),
|
|
1538
|
+
range: node.range
|
|
1539
|
+
});
|
|
1540
|
+
return void 0;
|
|
1416
1541
|
}
|
|
1417
1542
|
}
|
|
1418
1543
|
case "lambda": {
|
|
@@ -1424,11 +1549,6 @@ const reduceExpressionNode = async (context, node) => {
|
|
|
1424
1549
|
);
|
|
1425
1550
|
return results;
|
|
1426
1551
|
}
|
|
1427
|
-
case "set": {
|
|
1428
|
-
const expr = await reduceExpressionNode(context, node.expr);
|
|
1429
|
-
context.setValue(node.name.name, expr);
|
|
1430
|
-
return void 0;
|
|
1431
|
-
}
|
|
1432
1552
|
case "scope": {
|
|
1433
1553
|
if (node.nodes.length === 0) {
|
|
1434
1554
|
return [];
|
|
@@ -1510,32 +1630,76 @@ const reduceNode = async (context, node) => {
|
|
|
1510
1630
|
}
|
|
1511
1631
|
}
|
|
1512
1632
|
};
|
|
1513
|
-
const
|
|
1514
|
-
let
|
|
1515
|
-
let
|
|
1516
|
-
|
|
1633
|
+
const createScopedReducerContext = (parent) => {
|
|
1634
|
+
let thisVars;
|
|
1635
|
+
let thisContext;
|
|
1636
|
+
const getValue = (name) => {
|
|
1637
|
+
var _a;
|
|
1638
|
+
(_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
1639
|
+
if (thisVars == null ? void 0 : thisVars.has(name)) {
|
|
1640
|
+
return { value: thisVars.get(name), isFound: true };
|
|
1641
|
+
} else {
|
|
1642
|
+
return parent.getValue(name);
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
const setValue = (name, value) => {
|
|
1646
|
+
var _a;
|
|
1647
|
+
(_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
1648
|
+
if (!thisVars) {
|
|
1649
|
+
thisVars = /* @__PURE__ */ new Map();
|
|
1650
|
+
}
|
|
1651
|
+
thisVars.set(name, value);
|
|
1652
|
+
};
|
|
1653
|
+
const createFunctionContext = (thisNode) => {
|
|
1654
|
+
const newContext = {
|
|
1655
|
+
thisNode,
|
|
1656
|
+
abortSignal: parent.abortSignal,
|
|
1657
|
+
getValue,
|
|
1658
|
+
setValue,
|
|
1659
|
+
isFailed: parent.isFailed,
|
|
1660
|
+
appendError: parent.appendError,
|
|
1661
|
+
reduce: (node) => {
|
|
1662
|
+
var _a;
|
|
1663
|
+
(_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
1664
|
+
return reduceExpressionNode(thisContext, node);
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
return newContext;
|
|
1668
|
+
};
|
|
1669
|
+
thisContext = {
|
|
1670
|
+
abortSignal: parent.abortSignal,
|
|
1671
|
+
getValue,
|
|
1672
|
+
setValue,
|
|
1673
|
+
isFailed: parent.isFailed,
|
|
1674
|
+
appendError: parent.appendError,
|
|
1675
|
+
newScope: () => {
|
|
1676
|
+
var _a;
|
|
1677
|
+
(_a = parent.abortSignal) == null ? void 0 : _a.throwIfAborted();
|
|
1678
|
+
return createScopedReducerContext(thisContext);
|
|
1679
|
+
},
|
|
1680
|
+
createFunctionContext
|
|
1681
|
+
};
|
|
1682
|
+
return thisContext;
|
|
1683
|
+
};
|
|
1684
|
+
const createReducerContext = (variables, errors, signal) => {
|
|
1685
|
+
let thisVars;
|
|
1686
|
+
let thisContext;
|
|
1517
1687
|
const getValue = (name) => {
|
|
1518
|
-
|
|
1519
|
-
|
|
1688
|
+
signal == null ? void 0 : signal.throwIfAborted();
|
|
1689
|
+
if (thisVars == null ? void 0 : thisVars.has(name)) {
|
|
1690
|
+
return { value: thisVars.get(name), isFound: true };
|
|
1691
|
+
} else if (variables.has(name)) {
|
|
1692
|
+
return { value: variables.get(name), isFound: true };
|
|
1520
1693
|
} else {
|
|
1521
1694
|
return { value: void 0, isFound: false };
|
|
1522
1695
|
}
|
|
1523
1696
|
};
|
|
1524
1697
|
const setValue = (name, value) => {
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
}
|
|
1529
|
-
mvs.set(name, value);
|
|
1530
|
-
if (variablesProxy !== void 0) {
|
|
1531
|
-
Object.defineProperty(variablesProxy, name, {
|
|
1532
|
-
get() {
|
|
1533
|
-
return vs.get(name);
|
|
1534
|
-
},
|
|
1535
|
-
configurable: true,
|
|
1536
|
-
enumerable: true
|
|
1537
|
-
});
|
|
1698
|
+
signal == null ? void 0 : signal.throwIfAborted();
|
|
1699
|
+
if (!thisVars) {
|
|
1700
|
+
thisVars = /* @__PURE__ */ new Map();
|
|
1538
1701
|
}
|
|
1702
|
+
thisVars.set(name, value);
|
|
1539
1703
|
};
|
|
1540
1704
|
const appendError = (error) => {
|
|
1541
1705
|
errors.push(error);
|
|
@@ -1543,47 +1707,37 @@ const createReducerContext = (variables, errors) => {
|
|
|
1543
1707
|
const isFailed = () => {
|
|
1544
1708
|
return errors.some((error) => error.type === "error");
|
|
1545
1709
|
};
|
|
1546
|
-
const newScope = () => {
|
|
1547
|
-
const newContext = createReducerContext(vs, errors);
|
|
1548
|
-
return newContext;
|
|
1549
|
-
};
|
|
1550
|
-
let context;
|
|
1551
|
-
const reduceByProxy = (node) => reduceExpressionNode(context, node);
|
|
1552
|
-
const getVariablesFromProxy = () => {
|
|
1553
|
-
if (variablesProxy === void 0) {
|
|
1554
|
-
variablesProxy = {};
|
|
1555
|
-
for (const key of vs.keys()) {
|
|
1556
|
-
Object.defineProperty(variablesProxy, key, {
|
|
1557
|
-
get: () => vs.get(key),
|
|
1558
|
-
configurable: true,
|
|
1559
|
-
enumerable: true
|
|
1560
|
-
});
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
return variablesProxy;
|
|
1564
|
-
};
|
|
1565
1710
|
const createFunctionContext = (thisNode) => {
|
|
1566
|
-
|
|
1567
|
-
get variables() {
|
|
1568
|
-
return getVariablesFromProxy();
|
|
1569
|
-
},
|
|
1711
|
+
const newContext = {
|
|
1570
1712
|
thisNode,
|
|
1713
|
+
abortSignal: signal,
|
|
1714
|
+
getValue,
|
|
1715
|
+
setValue,
|
|
1716
|
+
isFailed,
|
|
1571
1717
|
appendError,
|
|
1572
|
-
reduce:
|
|
1718
|
+
reduce: (node) => {
|
|
1719
|
+
signal == null ? void 0 : signal.throwIfAborted();
|
|
1720
|
+
return reduceExpressionNode(thisContext, node);
|
|
1721
|
+
}
|
|
1573
1722
|
};
|
|
1723
|
+
return newContext;
|
|
1574
1724
|
};
|
|
1575
|
-
|
|
1725
|
+
thisContext = {
|
|
1726
|
+
abortSignal: signal,
|
|
1576
1727
|
getValue,
|
|
1577
1728
|
setValue,
|
|
1578
1729
|
appendError,
|
|
1579
1730
|
isFailed,
|
|
1580
|
-
newScope
|
|
1731
|
+
newScope: () => {
|
|
1732
|
+
signal == null ? void 0 : signal.throwIfAborted();
|
|
1733
|
+
return createScopedReducerContext(thisContext);
|
|
1734
|
+
},
|
|
1581
1735
|
createFunctionContext
|
|
1582
1736
|
};
|
|
1583
|
-
return
|
|
1737
|
+
return thisContext;
|
|
1584
1738
|
};
|
|
1585
|
-
async function runReducer(nodes, variables, errors) {
|
|
1586
|
-
const context = createReducerContext(variables, errors);
|
|
1739
|
+
async function runReducer(nodes, variables, errors, signal) {
|
|
1740
|
+
const context = createReducerContext(variables, errors, signal);
|
|
1587
1741
|
const resultList = [];
|
|
1588
1742
|
for (const node of nodes) {
|
|
1589
1743
|
const results = await reduceNode(context, node);
|
|
@@ -1595,7 +1749,15 @@ async function runReducer(nodes, variables, errors) {
|
|
|
1595
1749
|
}
|
|
1596
1750
|
return resultList;
|
|
1597
1751
|
}
|
|
1598
|
-
const _cond =
|
|
1752
|
+
const _cond = makeFunCityFunction(async function(arg0, arg1, arg2) {
|
|
1753
|
+
if (!arg0 || !arg1 || !arg2) {
|
|
1754
|
+
this.appendError({
|
|
1755
|
+
type: "error",
|
|
1756
|
+
description: "Required `cond` condition, true and false expressions",
|
|
1757
|
+
range: this.thisNode.range
|
|
1758
|
+
});
|
|
1759
|
+
return void 0;
|
|
1760
|
+
}
|
|
1599
1761
|
const cond = await this.reduce(arg0);
|
|
1600
1762
|
if (isConditionalTrue(cond)) {
|
|
1601
1763
|
return await this.reduce(arg1);
|
|
@@ -1603,6 +1765,27 @@ const _cond = makeSpecialFunction(async function(arg0, arg1, arg2) {
|
|
|
1603
1765
|
return await this.reduce(arg2);
|
|
1604
1766
|
}
|
|
1605
1767
|
});
|
|
1768
|
+
const _set = makeFunCityFunction(async function(arg0, arg1, ...rest) {
|
|
1769
|
+
if (!arg0 || !arg1 || rest.length !== 0) {
|
|
1770
|
+
this.appendError({
|
|
1771
|
+
type: "error",
|
|
1772
|
+
description: "Required `set` bind identity and expression",
|
|
1773
|
+
range: this.thisNode.range
|
|
1774
|
+
});
|
|
1775
|
+
return void 0;
|
|
1776
|
+
}
|
|
1777
|
+
if (arg0.kind !== "variable") {
|
|
1778
|
+
this.appendError({
|
|
1779
|
+
type: "error",
|
|
1780
|
+
description: "Required `set` bind identity",
|
|
1781
|
+
range: arg0.range
|
|
1782
|
+
});
|
|
1783
|
+
return void 0;
|
|
1784
|
+
}
|
|
1785
|
+
const value = await this.reduce(arg1);
|
|
1786
|
+
this.setValue(arg0.name, value);
|
|
1787
|
+
return void 0;
|
|
1788
|
+
});
|
|
1606
1789
|
const _typeof = async (arg0) => {
|
|
1607
1790
|
if (arg0 === null) {
|
|
1608
1791
|
return "null";
|
|
@@ -1616,54 +1799,33 @@ const _typeof = async (arg0) => {
|
|
|
1616
1799
|
return typeof arg0;
|
|
1617
1800
|
}
|
|
1618
1801
|
};
|
|
1619
|
-
const funcIds = /* @__PURE__ */ new WeakMap();
|
|
1620
|
-
let nextId = 1;
|
|
1621
|
-
const getFuncId = (fn) => {
|
|
1622
|
-
const cached = funcIds.get(fn);
|
|
1623
|
-
if (cached) return cached;
|
|
1624
|
-
const id = nextId++;
|
|
1625
|
-
funcIds.set(fn, id);
|
|
1626
|
-
return id;
|
|
1627
|
-
};
|
|
1628
1802
|
const _toString = async (...args) => {
|
|
1629
|
-
const results = args.map((arg0) =>
|
|
1630
|
-
switch (arg0) {
|
|
1631
|
-
case void 0:
|
|
1632
|
-
return "(undefined)";
|
|
1633
|
-
case null:
|
|
1634
|
-
return "(null)";
|
|
1635
|
-
default:
|
|
1636
|
-
switch (typeof arg0) {
|
|
1637
|
-
case "string":
|
|
1638
|
-
return arg0;
|
|
1639
|
-
case "boolean":
|
|
1640
|
-
return arg0 ? "true" : "false";
|
|
1641
|
-
case "number":
|
|
1642
|
-
case "bigint":
|
|
1643
|
-
case "symbol":
|
|
1644
|
-
return arg0.toString();
|
|
1645
|
-
case "function":
|
|
1646
|
-
if (arg0.name) {
|
|
1647
|
-
return `fun<${arg0.name}:#${getFuncId(arg0)}>`;
|
|
1648
|
-
} else {
|
|
1649
|
-
return `fun<#${getFuncId(arg0)}>`;
|
|
1650
|
-
}
|
|
1651
|
-
default:
|
|
1652
|
-
if (Array.isArray(arg0)) {
|
|
1653
|
-
return JSON.stringify(arg0);
|
|
1654
|
-
}
|
|
1655
|
-
const iterable = asIterable(arg0);
|
|
1656
|
-
if (iterable) {
|
|
1657
|
-
const arr = Array.from(iterable);
|
|
1658
|
-
return JSON.stringify(arr);
|
|
1659
|
-
} else {
|
|
1660
|
-
return JSON.stringify(arg0);
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
});
|
|
1803
|
+
const results = args.map((arg0) => convertToString(arg0));
|
|
1665
1804
|
return results.join(",");
|
|
1666
1805
|
};
|
|
1806
|
+
const _toBoolean = async (arg0) => {
|
|
1807
|
+
const r = isConditionalTrue(arg0);
|
|
1808
|
+
return r;
|
|
1809
|
+
};
|
|
1810
|
+
const _toNumber = async (arg0) => {
|
|
1811
|
+
const r = Number(arg0);
|
|
1812
|
+
return r;
|
|
1813
|
+
};
|
|
1814
|
+
const _toBigInt = async (arg0) => {
|
|
1815
|
+
switch (typeof arg0) {
|
|
1816
|
+
case "number":
|
|
1817
|
+
case "bigint":
|
|
1818
|
+
case "string":
|
|
1819
|
+
case "boolean": {
|
|
1820
|
+
const r = BigInt(arg0);
|
|
1821
|
+
return r;
|
|
1822
|
+
}
|
|
1823
|
+
default: {
|
|
1824
|
+
const r = BigInt(await _toString(arg0));
|
|
1825
|
+
return r;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
};
|
|
1667
1829
|
const _add = async (arg0, ...args) => {
|
|
1668
1830
|
const r = args.reduce((v0, v) => v0 + Number(v), Number(arg0));
|
|
1669
1831
|
return r;
|
|
@@ -1761,20 +1923,40 @@ const _length = async (arg0) => {
|
|
|
1761
1923
|
}
|
|
1762
1924
|
return 0;
|
|
1763
1925
|
};
|
|
1764
|
-
const _and = async (...args)
|
|
1926
|
+
const _and = makeFunCityFunction(async function(...args) {
|
|
1765
1927
|
if (args.length === 0) {
|
|
1766
|
-
|
|
1928
|
+
this.appendError({
|
|
1929
|
+
type: "error",
|
|
1930
|
+
description: "empty arguments",
|
|
1931
|
+
range: this.thisNode.range
|
|
1932
|
+
});
|
|
1933
|
+
return void 0;
|
|
1767
1934
|
}
|
|
1768
|
-
const
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1935
|
+
for (const arg of args) {
|
|
1936
|
+
const value = await this.reduce(arg);
|
|
1937
|
+
if (!isConditionalTrue(value)) {
|
|
1938
|
+
return false;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
return true;
|
|
1942
|
+
});
|
|
1943
|
+
const _or = makeFunCityFunction(async function(...args) {
|
|
1772
1944
|
if (args.length === 0) {
|
|
1773
|
-
|
|
1945
|
+
this.appendError({
|
|
1946
|
+
type: "error",
|
|
1947
|
+
description: "empty arguments",
|
|
1948
|
+
range: this.thisNode.range
|
|
1949
|
+
});
|
|
1950
|
+
return void 0;
|
|
1774
1951
|
}
|
|
1775
|
-
const
|
|
1776
|
-
|
|
1777
|
-
|
|
1952
|
+
for (const arg of args) {
|
|
1953
|
+
const value = await this.reduce(arg);
|
|
1954
|
+
if (isConditionalTrue(value)) {
|
|
1955
|
+
return true;
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
return false;
|
|
1959
|
+
});
|
|
1778
1960
|
const _not = async (arg0) => {
|
|
1779
1961
|
return !isConditionalTrue(arg0);
|
|
1780
1962
|
};
|
|
@@ -1936,13 +2118,24 @@ const _bind = async (arg0, ...args) => {
|
|
|
1936
2118
|
const predicate = arg0;
|
|
1937
2119
|
return predicate.bind(void 0, ...args);
|
|
1938
2120
|
};
|
|
2121
|
+
const _url = async (arg0, arg1) => {
|
|
2122
|
+
const url = new URL(
|
|
2123
|
+
convertToString(arg0),
|
|
2124
|
+
arg1 !== void 0 ? convertToString(arg1) : void 0
|
|
2125
|
+
);
|
|
2126
|
+
return url;
|
|
2127
|
+
};
|
|
1939
2128
|
const standardVariables = Object.freeze({
|
|
1940
2129
|
undefined: void 0,
|
|
1941
2130
|
null: null,
|
|
1942
2131
|
true: true,
|
|
1943
2132
|
false: false,
|
|
1944
2133
|
cond: _cond,
|
|
2134
|
+
set: _set,
|
|
1945
2135
|
toString: _toString,
|
|
2136
|
+
toBoolean: _toBoolean,
|
|
2137
|
+
toNumber: _toNumber,
|
|
2138
|
+
toBigInt: _toBigInt,
|
|
1946
2139
|
typeof: _typeof,
|
|
1947
2140
|
add: _add,
|
|
1948
2141
|
sub: _sub,
|
|
@@ -1974,34 +2167,38 @@ const standardVariables = Object.freeze({
|
|
|
1974
2167
|
match: _match,
|
|
1975
2168
|
replace: _replace,
|
|
1976
2169
|
regex: _regex,
|
|
1977
|
-
bind: _bind
|
|
2170
|
+
bind: _bind,
|
|
2171
|
+
url: _url
|
|
1978
2172
|
});
|
|
1979
2173
|
const buildCandidateVariables = (...variablesList) => {
|
|
1980
2174
|
return combineVariables(standardVariables, ...variablesList);
|
|
1981
2175
|
};
|
|
1982
|
-
const runScriptOnce = async (script, variables, errors = []) => {
|
|
2176
|
+
const runScriptOnce = async (script, variables, errors = [], signal) => {
|
|
1983
2177
|
const blocks = runTokenizer(script, errors);
|
|
1984
2178
|
const nodes = runParser(blocks, errors);
|
|
1985
|
-
const results = await runReducer(nodes, variables, errors);
|
|
1986
|
-
const text = results.join("");
|
|
2179
|
+
const results = await runReducer(nodes, variables, errors, signal);
|
|
2180
|
+
const text = results.map((result) => convertToString(result)).join("");
|
|
1987
2181
|
return text;
|
|
1988
2182
|
};
|
|
1989
2183
|
exports.asIterable = asIterable;
|
|
1990
2184
|
exports.buildCandidateVariables = buildCandidateVariables;
|
|
1991
2185
|
exports.combineVariables = combineVariables;
|
|
2186
|
+
exports.convertToString = convertToString;
|
|
1992
2187
|
exports.createParserCursor = createParserCursor;
|
|
1993
2188
|
exports.createReducerContext = createReducerContext;
|
|
1994
2189
|
exports.emptyLocation = emptyLocation;
|
|
1995
2190
|
exports.emptyRange = emptyRange;
|
|
1996
2191
|
exports.fromError = fromError;
|
|
1997
2192
|
exports.isConditionalTrue = isConditionalTrue;
|
|
1998
|
-
exports.
|
|
1999
|
-
exports.
|
|
2193
|
+
exports.isFunCityFunction = isFunCityFunction;
|
|
2194
|
+
exports.makeFunCityFunction = makeFunCityFunction;
|
|
2000
2195
|
exports.outputErrors = outputErrors;
|
|
2001
2196
|
exports.parseBlock = parseBlock;
|
|
2002
2197
|
exports.parseExpression = parseExpression;
|
|
2198
|
+
exports.parseExpressions = parseExpressions;
|
|
2003
2199
|
exports.reduceExpressionNode = reduceExpressionNode;
|
|
2004
2200
|
exports.reduceNode = reduceNode;
|
|
2201
|
+
exports.runCodeTokenizer = runCodeTokenizer;
|
|
2005
2202
|
exports.runParser = runParser;
|
|
2006
2203
|
exports.runReducer = runReducer;
|
|
2007
2204
|
exports.runScriptOnce = runScriptOnce;
|