funcity 1.3.0 → 1.5.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/compile-cache-D9XyNhoC.cjs +4869 -0
- package/dist/compile-cache-D9XyNhoC.cjs.map +1 -0
- package/dist/compile-cache-uzGiV-kt.js +4713 -0
- package/dist/compile-cache-uzGiV-kt.js.map +1 -0
- package/dist/index.cjs +155 -3374
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +129 -3379
- package/dist/index.mjs.map +1 -1
- package/dist/node.cjs +160 -147
- package/dist/node.cjs.map +1 -1
- package/dist/node.mjs +121 -127
- package/dist/node.mjs.map +1 -1
- package/dist/src/compile-cache.d.ts +61 -0
- package/dist/src/compile-cache.d.ts.map +1 -0
- package/dist/src/dcodegen.d.ts +131 -0
- package/dist/src/dcodegen.d.ts.map +1 -0
- package/dist/src/index.d.ts +22 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/node.d.ts +12 -0
- package/dist/src/node.d.ts.map +1 -0
- package/dist/src/parser.d.ts +46 -0
- package/dist/src/parser.d.ts.map +1 -0
- package/dist/src/reducer.d.ts +43 -0
- package/dist/src/reducer.d.ts.map +1 -0
- package/dist/src/scripting.d.ts +28 -0
- package/dist/src/scripting.d.ts.map +1 -0
- package/dist/src/tokenizer.d.ts +28 -0
- package/dist/src/tokenizer.d.ts.map +1 -0
- package/dist/src/types.d.ts +754 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/utils.d.ts +86 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/variables/fetch-variables.d.ts +26 -0
- package/dist/src/variables/fetch-variables.d.ts.map +1 -0
- package/dist/src/variables/nodejs-variables.d.ts +26 -0
- package/dist/src/variables/nodejs-variables.d.ts.map +1 -0
- package/dist/src/variables/object-variables.d.ts +37 -0
- package/dist/src/variables/object-variables.d.ts.map +1 -0
- package/dist/src/variables/standard-variables.d.ts +122 -0
- package/dist/src/variables/standard-variables.d.ts.map +1 -0
- package/package.json +12 -11
- package/dist/index.d.ts +0 -987
- package/dist/node.d.ts +0 -447
|
@@ -0,0 +1,4869 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* name: funcity
|
|
3
|
+
* version: 1.5.0
|
|
4
|
+
* description: A functional language interpreter with text processing
|
|
5
|
+
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
6
|
+
* license: MIT
|
|
7
|
+
* repository.url: https://github.com/kekyo/funcity
|
|
8
|
+
* git.commit.hash: e583c1a43f3a2b29f8bbbb7b7ad0cc199b0a0fca
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/*!
|
|
12
|
+
* name: funcity
|
|
13
|
+
* version: 1.5.0
|
|
14
|
+
* description: A functional language interpreter with text processing
|
|
15
|
+
* author: Kouji Matsui (@kekyo@mi.kekyo.net)
|
|
16
|
+
* license: MIT
|
|
17
|
+
* repository.url: https://github.com/kekyo/funcity
|
|
18
|
+
* git.commit.hash: e583c1a43f3a2b29f8bbbb7b7ad0cc199b0a0fca
|
|
19
|
+
*/
|
|
20
|
+
const require_node = require("./node.cjs");
|
|
21
|
+
//#region \0@oxc-project+runtime@0.121.0/helpers/typeof.js
|
|
22
|
+
function _typeof$1(o) {
|
|
23
|
+
"@babel/helpers - typeof";
|
|
24
|
+
return _typeof$1 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
25
|
+
return typeof o;
|
|
26
|
+
} : function(o) {
|
|
27
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
28
|
+
}, _typeof$1(o);
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region \0@oxc-project+runtime@0.121.0/helpers/toPrimitive.js
|
|
32
|
+
function toPrimitive(t, r) {
|
|
33
|
+
if ("object" != _typeof$1(t) || !t) return t;
|
|
34
|
+
var e = t[Symbol.toPrimitive];
|
|
35
|
+
if (void 0 !== e) {
|
|
36
|
+
var i = e.call(t, r || "default");
|
|
37
|
+
if ("object" != _typeof$1(i)) return i;
|
|
38
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
39
|
+
}
|
|
40
|
+
return ("string" === r ? String : Number)(t);
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region \0@oxc-project+runtime@0.121.0/helpers/toPropertyKey.js
|
|
44
|
+
function toPropertyKey(t) {
|
|
45
|
+
var i = toPrimitive(t, "string");
|
|
46
|
+
return "symbol" == _typeof$1(i) ? i : i + "";
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region \0@oxc-project+runtime@0.121.0/helpers/defineProperty.js
|
|
50
|
+
function _defineProperty(e, r, t) {
|
|
51
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
52
|
+
value: t,
|
|
53
|
+
enumerable: !0,
|
|
54
|
+
configurable: !0,
|
|
55
|
+
writable: !0
|
|
56
|
+
}) : e[r] = t, e;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/types.ts
|
|
60
|
+
/**
|
|
61
|
+
* Reducer running error.
|
|
62
|
+
*/
|
|
63
|
+
var FunCityReducerError = class FunCityReducerError extends Error {
|
|
64
|
+
constructor(info) {
|
|
65
|
+
super(info.description);
|
|
66
|
+
_defineProperty(
|
|
67
|
+
this,
|
|
68
|
+
/**
|
|
69
|
+
* Error information.
|
|
70
|
+
*/
|
|
71
|
+
"info",
|
|
72
|
+
void 0
|
|
73
|
+
);
|
|
74
|
+
this.name = "FunCityReducerError";
|
|
75
|
+
this.info = info;
|
|
76
|
+
Object.setPrototypeOf(this, FunCityReducerError.prototype);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/tokenizer.ts
|
|
81
|
+
var createRange = (context, start, end) => ({
|
|
82
|
+
sourceId: context.sourceId,
|
|
83
|
+
start,
|
|
84
|
+
end
|
|
85
|
+
});
|
|
86
|
+
/**
|
|
87
|
+
* Tokenize the string value.
|
|
88
|
+
* @param context Tokenizer context
|
|
89
|
+
* @returns String token
|
|
90
|
+
*/
|
|
91
|
+
var stringEscapeMap = {
|
|
92
|
+
f: "\f",
|
|
93
|
+
n: "\n",
|
|
94
|
+
r: "\r",
|
|
95
|
+
t: " ",
|
|
96
|
+
v: "\v",
|
|
97
|
+
"0": "\0",
|
|
98
|
+
"'": "'",
|
|
99
|
+
"\"": "\"",
|
|
100
|
+
"`": "`",
|
|
101
|
+
"{": "{",
|
|
102
|
+
"}": "}",
|
|
103
|
+
"\\": "\\"
|
|
104
|
+
};
|
|
105
|
+
var tokenizeString = (context, quoteSymbol) => {
|
|
106
|
+
const start = context.cursor.location("start");
|
|
107
|
+
context.cursor.skip(quoteSymbol.length);
|
|
108
|
+
let value = "";
|
|
109
|
+
let templateTokens;
|
|
110
|
+
let textStart;
|
|
111
|
+
const appendText = (text, startLocation) => {
|
|
112
|
+
if (value.length === 0) textStart = startLocation !== null && startLocation !== void 0 ? startLocation : context.cursor.location("start");
|
|
113
|
+
value += text;
|
|
114
|
+
};
|
|
115
|
+
const flushTextToken = () => {
|
|
116
|
+
if (!templateTokens || value.length === 0 || !textStart) return;
|
|
117
|
+
templateTokens.push({
|
|
118
|
+
kind: "text",
|
|
119
|
+
text: value,
|
|
120
|
+
range: createRange(context, textStart, context.cursor.location("end"))
|
|
121
|
+
});
|
|
122
|
+
value = "";
|
|
123
|
+
textStart = void 0;
|
|
124
|
+
};
|
|
125
|
+
let closed = false;
|
|
126
|
+
while (!context.cursor.eot()) {
|
|
127
|
+
if (context.cursor.assert(quoteSymbol)) {
|
|
128
|
+
if (templateTokens) flushTextToken();
|
|
129
|
+
context.cursor.skip(quoteSymbol.length);
|
|
130
|
+
closed = true;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
if (context.cursor.assert("{{")) {
|
|
134
|
+
if (!templateTokens) templateTokens = [];
|
|
135
|
+
flushTextToken();
|
|
136
|
+
const tokens = tokenizeCodeBlock(context);
|
|
137
|
+
templateTokens.push(...tokens);
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const ch = context.cursor.getChar();
|
|
141
|
+
if (ch === "\\") {
|
|
142
|
+
const escapeStart = context.cursor.location("start");
|
|
143
|
+
context.cursor.skip(1);
|
|
144
|
+
if (context.cursor.eot()) {
|
|
145
|
+
context.logs.push({
|
|
146
|
+
type: "error",
|
|
147
|
+
description: "invalid escape sequence: \\\\",
|
|
148
|
+
range: createRange(context, escapeStart, context.cursor.location("end"))
|
|
149
|
+
});
|
|
150
|
+
appendText("\\", escapeStart);
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
const escape = context.cursor.getChar();
|
|
154
|
+
const mapped = stringEscapeMap[escape];
|
|
155
|
+
if (mapped !== void 0) {
|
|
156
|
+
appendText(mapped, escapeStart);
|
|
157
|
+
context.cursor.skip(1);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
context.cursor.skip(1);
|
|
161
|
+
context.logs.push({
|
|
162
|
+
type: "error",
|
|
163
|
+
description: `invalid escape sequence: \\${escape}`,
|
|
164
|
+
range: createRange(context, escapeStart, context.cursor.location("end"))
|
|
165
|
+
});
|
|
166
|
+
appendText(`\\${escape}`, escapeStart);
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
appendText(ch);
|
|
170
|
+
context.cursor.skip(1);
|
|
171
|
+
}
|
|
172
|
+
if (!closed) {
|
|
173
|
+
const location = context.cursor.location("start");
|
|
174
|
+
context.logs.push({
|
|
175
|
+
type: "error",
|
|
176
|
+
description: "string close quote is not found",
|
|
177
|
+
range: createRange(context, location, location)
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (templateTokens) {
|
|
181
|
+
flushTextToken();
|
|
182
|
+
return {
|
|
183
|
+
kind: "template",
|
|
184
|
+
tokens: templateTokens,
|
|
185
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
kind: "string",
|
|
190
|
+
value,
|
|
191
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
var firstNumericChars = "0123456789-+";
|
|
195
|
+
var numericCharsWithDot = "0123456789.";
|
|
196
|
+
var numericChars = "0123456789";
|
|
197
|
+
/**
|
|
198
|
+
* Tokenize the number (numeric) value.
|
|
199
|
+
* @param context Tokenizer context
|
|
200
|
+
* @returns Number token
|
|
201
|
+
*/
|
|
202
|
+
var tokenizeNumber = (context) => {
|
|
203
|
+
const start = context.cursor.location("start");
|
|
204
|
+
let index = 1;
|
|
205
|
+
while (true) {
|
|
206
|
+
if (context.cursor.eot()) return {
|
|
207
|
+
kind: "number",
|
|
208
|
+
value: Number(context.cursor.getRangeAndSkip(index)),
|
|
209
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
210
|
+
};
|
|
211
|
+
const ch = context.cursor.getChar(index);
|
|
212
|
+
if (numericCharsWithDot.indexOf(ch) < 0) {
|
|
213
|
+
if (ch === ".") break;
|
|
214
|
+
return {
|
|
215
|
+
kind: "number",
|
|
216
|
+
value: Number(context.cursor.getRangeAndSkip(index)),
|
|
217
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
index++;
|
|
221
|
+
}
|
|
222
|
+
while (true) {
|
|
223
|
+
if (context.cursor.eot()) return {
|
|
224
|
+
kind: "number",
|
|
225
|
+
value: Number(context.cursor.getRangeAndSkip(index)),
|
|
226
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
227
|
+
};
|
|
228
|
+
const ch = context.cursor.getChar(index);
|
|
229
|
+
if (numericChars.indexOf(ch) < 0) return {
|
|
230
|
+
kind: "number",
|
|
231
|
+
value: Number(context.cursor.getRangeAndSkip(index)),
|
|
232
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
233
|
+
};
|
|
234
|
+
index++;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
var firstVariableChars = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
238
|
+
var variableChars = "_-?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
239
|
+
/**
|
|
240
|
+
* Tokenize the identity (variable name).
|
|
241
|
+
* @param context Tokenizer context
|
|
242
|
+
* @returns Identity token
|
|
243
|
+
*/
|
|
244
|
+
var tokenizeIdentity = (context) => {
|
|
245
|
+
const start = context.cursor.location("start");
|
|
246
|
+
let index = 1;
|
|
247
|
+
while (true) {
|
|
248
|
+
if (context.cursor.eot()) break;
|
|
249
|
+
const ch = context.cursor.getChar(index);
|
|
250
|
+
if (variableChars.indexOf(ch) < 0) break;
|
|
251
|
+
if (ch === "?") {
|
|
252
|
+
if (context.cursor.getChar(index + 1) === ".") break;
|
|
253
|
+
index++;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
index++;
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
kind: "identity",
|
|
260
|
+
name: context.cursor.getRangeAndSkip(index),
|
|
261
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
var tokenizeCodeTokens = (context, stopOnClose, finalizeUnknownOnEot, closeSymbol = "}}") => {
|
|
265
|
+
const tokens = [];
|
|
266
|
+
let unknownStartLocation;
|
|
267
|
+
const finalizeUnknown = () => {
|
|
268
|
+
if (unknownStartLocation) {
|
|
269
|
+
context.logs.push({
|
|
270
|
+
type: "warning",
|
|
271
|
+
description: "unknown words",
|
|
272
|
+
range: createRange(context, unknownStartLocation, context.cursor.location("end"))
|
|
273
|
+
});
|
|
274
|
+
unknownStartLocation = void 0;
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
while (!context.cursor.eot()) {
|
|
278
|
+
if (stopOnClose && context.cursor.assert(closeSymbol)) {
|
|
279
|
+
finalizeUnknown();
|
|
280
|
+
return {
|
|
281
|
+
tokens,
|
|
282
|
+
closed: true
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const ch = context.cursor.getChar();
|
|
286
|
+
if (ch === "\\") {
|
|
287
|
+
const next = context.cursor.getChar(1);
|
|
288
|
+
if (next === "\n") {
|
|
289
|
+
context.cursor.skip(2);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (next === "\r" && context.cursor.getChar(2) === "\n") {
|
|
293
|
+
context.cursor.skip(3);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (next === "{" || next === "}") {
|
|
297
|
+
context.cursor.skip(2);
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (ch === "/" && context.cursor.getChar(1) === "/") {
|
|
302
|
+
finalizeUnknown();
|
|
303
|
+
context.cursor.skip(2);
|
|
304
|
+
while (!context.cursor.eot()) {
|
|
305
|
+
const commentCh = context.cursor.getChar();
|
|
306
|
+
if (commentCh === "\n" || commentCh === "\r") break;
|
|
307
|
+
context.cursor.skip(1);
|
|
308
|
+
}
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
if (ch === "'" || ch === "\"" || ch === "`") {
|
|
312
|
+
finalizeUnknown();
|
|
313
|
+
let quoteCount = 1;
|
|
314
|
+
while (context.cursor.getChar(quoteCount) === ch) quoteCount++;
|
|
315
|
+
const quoteLength = quoteCount >= 3 ? quoteCount : 1;
|
|
316
|
+
tokens.push(tokenizeString(context, ch.repeat(quoteLength)));
|
|
317
|
+
} else if (firstNumericChars.indexOf(ch) >= 0) {
|
|
318
|
+
finalizeUnknown();
|
|
319
|
+
tokens.push(tokenizeNumber(context));
|
|
320
|
+
} else if (ch === "(") {
|
|
321
|
+
finalizeUnknown();
|
|
322
|
+
const location = context.cursor.location("start");
|
|
323
|
+
tokens.push({
|
|
324
|
+
kind: "open",
|
|
325
|
+
symbol: "(",
|
|
326
|
+
range: createRange(context, location, location)
|
|
327
|
+
});
|
|
328
|
+
context.cursor.skip(1);
|
|
329
|
+
} else if (ch === ")") {
|
|
330
|
+
finalizeUnknown();
|
|
331
|
+
const location = context.cursor.location("start");
|
|
332
|
+
tokens.push({
|
|
333
|
+
kind: "close",
|
|
334
|
+
symbol: ")",
|
|
335
|
+
range: createRange(context, location, location)
|
|
336
|
+
});
|
|
337
|
+
context.cursor.skip(1);
|
|
338
|
+
} else if (ch === "[") {
|
|
339
|
+
finalizeUnknown();
|
|
340
|
+
const location = context.cursor.location("start");
|
|
341
|
+
tokens.push({
|
|
342
|
+
kind: "open",
|
|
343
|
+
symbol: "[",
|
|
344
|
+
range: createRange(context, location, location)
|
|
345
|
+
});
|
|
346
|
+
context.cursor.skip(1);
|
|
347
|
+
} else if (ch === "]") {
|
|
348
|
+
finalizeUnknown();
|
|
349
|
+
const location = context.cursor.location("start");
|
|
350
|
+
tokens.push({
|
|
351
|
+
kind: "close",
|
|
352
|
+
symbol: "]",
|
|
353
|
+
range: createRange(context, location, location)
|
|
354
|
+
});
|
|
355
|
+
context.cursor.skip(1);
|
|
356
|
+
} else if (ch === "?" && context.cursor.getChar(1) === ".") {
|
|
357
|
+
finalizeUnknown();
|
|
358
|
+
const start = context.cursor.location("start");
|
|
359
|
+
context.cursor.skip(2);
|
|
360
|
+
tokens.push({
|
|
361
|
+
kind: "dot",
|
|
362
|
+
optional: true,
|
|
363
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
364
|
+
});
|
|
365
|
+
} else if (ch === ".") {
|
|
366
|
+
finalizeUnknown();
|
|
367
|
+
const location = context.cursor.location("start");
|
|
368
|
+
tokens.push({
|
|
369
|
+
kind: "dot",
|
|
370
|
+
optional: false,
|
|
371
|
+
range: createRange(context, location, location)
|
|
372
|
+
});
|
|
373
|
+
context.cursor.skip(1);
|
|
374
|
+
} else if (firstVariableChars.indexOf(ch) >= 0) {
|
|
375
|
+
finalizeUnknown();
|
|
376
|
+
tokens.push(tokenizeIdentity(context));
|
|
377
|
+
} else if (ch === "\n") {
|
|
378
|
+
finalizeUnknown();
|
|
379
|
+
const location = context.cursor.location("start");
|
|
380
|
+
tokens.push({
|
|
381
|
+
kind: "eol",
|
|
382
|
+
source: "newline",
|
|
383
|
+
range: createRange(context, location, location)
|
|
384
|
+
});
|
|
385
|
+
context.cursor.skip(1);
|
|
386
|
+
} else if (ch === ";") {
|
|
387
|
+
finalizeUnknown();
|
|
388
|
+
const location = context.cursor.location("start");
|
|
389
|
+
tokens.push({
|
|
390
|
+
kind: "eol",
|
|
391
|
+
source: "semicolon",
|
|
392
|
+
range: createRange(context, location, location)
|
|
393
|
+
});
|
|
394
|
+
context.cursor.skip(1);
|
|
395
|
+
} else if (ch === "\r") {
|
|
396
|
+
finalizeUnknown();
|
|
397
|
+
context.cursor.skip(1);
|
|
398
|
+
} else if (ch === " ") {
|
|
399
|
+
finalizeUnknown();
|
|
400
|
+
context.cursor.skip(1);
|
|
401
|
+
} else {
|
|
402
|
+
if (!unknownStartLocation) unknownStartLocation = context.cursor.location("start");
|
|
403
|
+
context.cursor.skip(1);
|
|
404
|
+
}
|
|
405
|
+
context.cursor.skipChars(" ");
|
|
406
|
+
}
|
|
407
|
+
if (finalizeUnknownOnEot) finalizeUnknown();
|
|
408
|
+
return {
|
|
409
|
+
tokens,
|
|
410
|
+
closed: false
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
/**
|
|
414
|
+
* Tokenize code block.
|
|
415
|
+
* @param context Tokenizer context
|
|
416
|
+
* @returns The token list
|
|
417
|
+
*/
|
|
418
|
+
var tokenizeCodeBlock = (context) => {
|
|
419
|
+
const openStart = context.cursor.location("start");
|
|
420
|
+
let openCount = 0;
|
|
421
|
+
while (context.cursor.getChar(openCount) === "{") openCount++;
|
|
422
|
+
const openSymbol = "{".repeat(openCount);
|
|
423
|
+
const closeSymbol = "}".repeat(openCount);
|
|
424
|
+
context.cursor.skip(openCount);
|
|
425
|
+
const tokens = [{
|
|
426
|
+
kind: "open",
|
|
427
|
+
symbol: openSymbol,
|
|
428
|
+
range: createRange(context, openStart, context.cursor.location("end"))
|
|
429
|
+
}];
|
|
430
|
+
const result = tokenizeCodeTokens(context, true, false, closeSymbol);
|
|
431
|
+
tokens.push(...result.tokens);
|
|
432
|
+
if (result.closed) {
|
|
433
|
+
const location = context.cursor.location("start");
|
|
434
|
+
context.cursor.skip(openCount);
|
|
435
|
+
tokens.push({
|
|
436
|
+
kind: "close",
|
|
437
|
+
symbol: closeSymbol,
|
|
438
|
+
range: createRange(context, location, context.cursor.location("end"))
|
|
439
|
+
});
|
|
440
|
+
return tokens;
|
|
441
|
+
}
|
|
442
|
+
const causeLocation = context.cursor.location("start");
|
|
443
|
+
context.logs.push({
|
|
444
|
+
type: "error",
|
|
445
|
+
description: `required code block closer: \`${closeSymbol}\``,
|
|
446
|
+
range: createRange(context, causeLocation, causeLocation)
|
|
447
|
+
});
|
|
448
|
+
return tokens;
|
|
449
|
+
};
|
|
450
|
+
/**
|
|
451
|
+
* Create a tonenizer cursor.
|
|
452
|
+
* @param script - Input script text
|
|
453
|
+
* @returns Tonenizer cursor
|
|
454
|
+
*/
|
|
455
|
+
var createTokenizerCursor = (script) => {
|
|
456
|
+
let currentIndex = 0;
|
|
457
|
+
let rawLine = 0;
|
|
458
|
+
let rawColumn = 0;
|
|
459
|
+
let lastLine = 0;
|
|
460
|
+
let lastColumn = 0;
|
|
461
|
+
const eot = () => currentIndex >= script.length;
|
|
462
|
+
const getChar = (index) => script[(index !== null && index !== void 0 ? index : 0) + currentIndex];
|
|
463
|
+
const skip = (length) => {
|
|
464
|
+
let lastch = "\0";
|
|
465
|
+
while (length > 0) {
|
|
466
|
+
lastColumn = rawColumn;
|
|
467
|
+
lastLine = rawLine;
|
|
468
|
+
const ch = script[currentIndex];
|
|
469
|
+
if (ch === "\r") {
|
|
470
|
+
rawColumn = 0;
|
|
471
|
+
rawLine++;
|
|
472
|
+
} else if (ch === "\n") {
|
|
473
|
+
rawColumn = 0;
|
|
474
|
+
if (lastch !== "\r") rawLine++;
|
|
475
|
+
} else rawColumn++;
|
|
476
|
+
currentIndex++;
|
|
477
|
+
length--;
|
|
478
|
+
lastch = ch;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
const skipChars = (ch) => {
|
|
482
|
+
while (!eot()) {
|
|
483
|
+
if (getChar() !== ch) return true;
|
|
484
|
+
skip(1);
|
|
485
|
+
}
|
|
486
|
+
return false;
|
|
487
|
+
};
|
|
488
|
+
const skipUntil = (word) => {
|
|
489
|
+
while (!eot()) {
|
|
490
|
+
if (script.indexOf(word, currentIndex) === currentIndex) {
|
|
491
|
+
skip(word.length);
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
skip(1);
|
|
495
|
+
}
|
|
496
|
+
return false;
|
|
497
|
+
};
|
|
498
|
+
const assert = (word) => {
|
|
499
|
+
if (script.length - currentIndex < word.length) return false;
|
|
500
|
+
if (script.substring(currentIndex, currentIndex + word.length) === word) return true;
|
|
501
|
+
return false;
|
|
502
|
+
};
|
|
503
|
+
const getRangeAndSkip = (length) => {
|
|
504
|
+
const result = script.substring(currentIndex, currentIndex + length);
|
|
505
|
+
skip(result.length);
|
|
506
|
+
return result;
|
|
507
|
+
};
|
|
508
|
+
const getUntil = (word) => {
|
|
509
|
+
if (currentIndex >= script.length) return;
|
|
510
|
+
const index = script.indexOf(word, currentIndex);
|
|
511
|
+
if (index >= 0) {
|
|
512
|
+
const result = script.substring(currentIndex, index);
|
|
513
|
+
skip(index - currentIndex);
|
|
514
|
+
return result;
|
|
515
|
+
} else {
|
|
516
|
+
const result = script.substring(currentIndex, script.length);
|
|
517
|
+
skip(script.length - currentIndex);
|
|
518
|
+
return result;
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
const location = (type) => type === "end" ? {
|
|
522
|
+
line: lastLine + 1,
|
|
523
|
+
column: lastColumn + 1
|
|
524
|
+
} : {
|
|
525
|
+
line: rawLine + 1,
|
|
526
|
+
column: rawColumn + 1
|
|
527
|
+
};
|
|
528
|
+
return {
|
|
529
|
+
eot,
|
|
530
|
+
getChar,
|
|
531
|
+
skip,
|
|
532
|
+
skipChars,
|
|
533
|
+
skipUntil,
|
|
534
|
+
assert,
|
|
535
|
+
getRangeAndSkip,
|
|
536
|
+
getUntil,
|
|
537
|
+
location
|
|
538
|
+
};
|
|
539
|
+
};
|
|
540
|
+
/**
|
|
541
|
+
* Run the tokenizer for code expressions only.
|
|
542
|
+
* @param script - Input script text
|
|
543
|
+
* @param logs - Will be stored detected warnings/logs into it
|
|
544
|
+
* @param sourceId - Source identifier (file path, URL, etc)
|
|
545
|
+
* @returns The token list
|
|
546
|
+
*/
|
|
547
|
+
var runCodeTokenizer = (script, logs, sourceId) => {
|
|
548
|
+
return tokenizeCodeTokens({
|
|
549
|
+
cursor: createTokenizerCursor(script),
|
|
550
|
+
sourceId,
|
|
551
|
+
logs
|
|
552
|
+
}, false, true).tokens;
|
|
553
|
+
};
|
|
554
|
+
/**
|
|
555
|
+
* Run the tokenizer.
|
|
556
|
+
* @param script - Input script text
|
|
557
|
+
* @param logs - Will be stored detected warnings/logs into it
|
|
558
|
+
* @param sourceId - Source identifier (file path, URL, etc)
|
|
559
|
+
* @returns The token list
|
|
560
|
+
*/
|
|
561
|
+
var runTokenizer = (script, logs, sourceId) => {
|
|
562
|
+
const context = {
|
|
563
|
+
cursor: createTokenizerCursor(script),
|
|
564
|
+
sourceId,
|
|
565
|
+
logs
|
|
566
|
+
};
|
|
567
|
+
const tokens = [];
|
|
568
|
+
const readTextBlock = () => {
|
|
569
|
+
if (context.cursor.eot()) return;
|
|
570
|
+
let text = "";
|
|
571
|
+
while (!context.cursor.eot()) {
|
|
572
|
+
if (context.cursor.assert("{{")) return text;
|
|
573
|
+
const ch = context.cursor.getChar();
|
|
574
|
+
if (ch === "\\") {
|
|
575
|
+
const next = context.cursor.getChar(1);
|
|
576
|
+
if (next === "{" || next === "}") {
|
|
577
|
+
text += next;
|
|
578
|
+
context.cursor.skip(2);
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
text += ch;
|
|
583
|
+
context.cursor.skip(1);
|
|
584
|
+
}
|
|
585
|
+
return text;
|
|
586
|
+
};
|
|
587
|
+
while (!context.cursor.eot()) {
|
|
588
|
+
const start = context.cursor.location("start");
|
|
589
|
+
const text = readTextBlock();
|
|
590
|
+
if (text) tokens.push({
|
|
591
|
+
kind: "text",
|
|
592
|
+
text,
|
|
593
|
+
range: createRange(context, start, context.cursor.location("end"))
|
|
594
|
+
});
|
|
595
|
+
else tokens.push(...tokenizeCodeBlock(context));
|
|
596
|
+
}
|
|
597
|
+
return tokens;
|
|
598
|
+
};
|
|
599
|
+
//#endregion
|
|
600
|
+
//#region src/utils.ts
|
|
601
|
+
/**
|
|
602
|
+
* Empty location with zeroed coordinates.
|
|
603
|
+
*/
|
|
604
|
+
var emptyLocation = {
|
|
605
|
+
line: 0,
|
|
606
|
+
column: 0
|
|
607
|
+
};
|
|
608
|
+
/**
|
|
609
|
+
* Empty range with zeroed coordinates.
|
|
610
|
+
*/
|
|
611
|
+
var emptyRange = {
|
|
612
|
+
sourceId: "unknown.fc",
|
|
613
|
+
start: emptyLocation,
|
|
614
|
+
end: emptyLocation
|
|
615
|
+
};
|
|
616
|
+
var specialFunctionMarker = Symbol("$$special$$");
|
|
617
|
+
/**
|
|
618
|
+
* Mark a function as a funcity special function.
|
|
619
|
+
* @param f - Target function.
|
|
620
|
+
* @returns The same function with a marker.
|
|
621
|
+
*/
|
|
622
|
+
var makeFunCityFunction = (f) => {
|
|
623
|
+
f[specialFunctionMarker] = true;
|
|
624
|
+
return f;
|
|
625
|
+
};
|
|
626
|
+
/**
|
|
627
|
+
* Check whether a function is marked as funcity special function.
|
|
628
|
+
* @param f - Target function.
|
|
629
|
+
* @returns True when marked.
|
|
630
|
+
*/
|
|
631
|
+
var isFunCityFunction = (f) => {
|
|
632
|
+
var _f$specialFunctionMar;
|
|
633
|
+
return (_f$specialFunctionMar = f[specialFunctionMarker]) !== null && _f$specialFunctionMar !== void 0 ? _f$specialFunctionMar : false;
|
|
634
|
+
};
|
|
635
|
+
/**
|
|
636
|
+
* Evaluate value with the interpreter's conditional semantics.
|
|
637
|
+
* @param v - Target value.
|
|
638
|
+
* @returns True when the value should be treated as truthy.
|
|
639
|
+
*/
|
|
640
|
+
var isConditionalTrue = (v) => {
|
|
641
|
+
if (v === void 0 || v === null) return false;
|
|
642
|
+
switch (typeof v) {
|
|
643
|
+
case "boolean": return v;
|
|
644
|
+
case "number":
|
|
645
|
+
case "bigint": return v !== 0;
|
|
646
|
+
default: return true;
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
/**
|
|
650
|
+
* Cast a value to iterable when it has a default iterator.
|
|
651
|
+
* @param v - Target value.
|
|
652
|
+
* @returns Iterable instance or undefined when not iterable.
|
|
653
|
+
*/
|
|
654
|
+
var asIterable = (v) => {
|
|
655
|
+
if (typeof v[Symbol.iterator] === "function") return v;
|
|
656
|
+
else return;
|
|
657
|
+
};
|
|
658
|
+
/**
|
|
659
|
+
* Combine variable maps or records into a single variable map.
|
|
660
|
+
* @param variablesList - Variable sources to merge.
|
|
661
|
+
* @returns Combined variable map.
|
|
662
|
+
*/
|
|
663
|
+
var combineVariables = (...variablesList) => {
|
|
664
|
+
const variables = /* @__PURE__ */ new Map();
|
|
665
|
+
const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
|
|
666
|
+
const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
|
|
667
|
+
variablesList.forEach((vs) => {
|
|
668
|
+
if (vs["forEach"] !== void 0) appendVariables(vs);
|
|
669
|
+
else appendRecord(vs);
|
|
670
|
+
});
|
|
671
|
+
return variables;
|
|
672
|
+
};
|
|
673
|
+
/**
|
|
674
|
+
* Convert an error object into a human-readable message.
|
|
675
|
+
* @param error - Error object.
|
|
676
|
+
* @returns Error message.
|
|
677
|
+
*/
|
|
678
|
+
var fromError = (error) => {
|
|
679
|
+
if (error.message) return error.message;
|
|
680
|
+
else if (typeof error.toString === "function") {
|
|
681
|
+
var _error$toString;
|
|
682
|
+
return (_error$toString = error.toString()) !== null && _error$toString !== void 0 ? _error$toString : "unknown";
|
|
683
|
+
} else return "unknown";
|
|
684
|
+
};
|
|
685
|
+
/**
|
|
686
|
+
* Check whether a value is promise-like.
|
|
687
|
+
* @param value - Target value.
|
|
688
|
+
* @returns True when the value has a `then` method.
|
|
689
|
+
*/
|
|
690
|
+
var isPromiseLike = (value) => {
|
|
691
|
+
if (value === null || value === void 0) return false;
|
|
692
|
+
return typeof value.then === "function";
|
|
693
|
+
};
|
|
694
|
+
var widerRange = (...args) => {
|
|
695
|
+
var _primarySourceId;
|
|
696
|
+
const lastArg = args[args.length - 1];
|
|
697
|
+
const logs = Array.isArray(lastArg) ? lastArg : void 0;
|
|
698
|
+
const ranges = Array.isArray(lastArg) ? args.slice(0, -1) : args;
|
|
699
|
+
let start = emptyRange.start;
|
|
700
|
+
let end = emptyRange.end;
|
|
701
|
+
let primarySourceId;
|
|
702
|
+
const sourceIds = /* @__PURE__ */ new Set();
|
|
703
|
+
for (const range of ranges) if (range.start.line >= 1 && range.start.column >= 1) {
|
|
704
|
+
if (!primarySourceId) primarySourceId = range.sourceId;
|
|
705
|
+
sourceIds.add(range.sourceId);
|
|
706
|
+
if (start.line === 0 || start.column === 0) start = range.start;
|
|
707
|
+
else if (range.start.line < start.line) start = range.start;
|
|
708
|
+
else if (range.start.line === start.line && range.start.column < start.column) start = range.start;
|
|
709
|
+
if (end.line === 0 || end.column === 0) end = range.end;
|
|
710
|
+
else if (range.end.line > end.line) end = range.end;
|
|
711
|
+
else if (range.end.line === end.line && range.end.column > end.column) end = range.end;
|
|
712
|
+
}
|
|
713
|
+
const combinedRange = {
|
|
714
|
+
sourceId: (_primarySourceId = primarySourceId) !== null && _primarySourceId !== void 0 ? _primarySourceId : emptyRange.sourceId,
|
|
715
|
+
start,
|
|
716
|
+
end
|
|
717
|
+
};
|
|
718
|
+
if (sourceIds.size >= 2 && logs) logs.push({
|
|
719
|
+
type: "error",
|
|
720
|
+
description: "Range sourceId mismatch",
|
|
721
|
+
range: combinedRange
|
|
722
|
+
});
|
|
723
|
+
return combinedRange;
|
|
724
|
+
};
|
|
725
|
+
var locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
|
|
726
|
+
var 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}`;
|
|
727
|
+
var printErrorString = (error, writer) => {
|
|
728
|
+
const sourceId = error.range.sourceId;
|
|
729
|
+
switch (error.type) {
|
|
730
|
+
case "warning":
|
|
731
|
+
writer.warn(`${sourceId}:${getLocationString(error.range)}: warning: ${error.description}`);
|
|
732
|
+
break;
|
|
733
|
+
case "error":
|
|
734
|
+
writer.error(`${sourceId}:${getLocationString(error.range)}: error: ${error.description}`);
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
return false;
|
|
738
|
+
};
|
|
739
|
+
/**
|
|
740
|
+
* Output error list and return whether any error-level entry exists.
|
|
741
|
+
* @param logs - Errors to output.
|
|
742
|
+
* @param writer - Writer interface.
|
|
743
|
+
* @returns True when an error-level entry exists.
|
|
744
|
+
*/
|
|
745
|
+
var outputErrors = (logs, writer) => {
|
|
746
|
+
const _writer = writer !== null && writer !== void 0 ? writer : console;
|
|
747
|
+
let isError = false;
|
|
748
|
+
for (const error of logs) {
|
|
749
|
+
const result = printErrorString(error, _writer);
|
|
750
|
+
isError || (isError = result);
|
|
751
|
+
}
|
|
752
|
+
return isError;
|
|
753
|
+
};
|
|
754
|
+
var iterToString = (iter, getFuncId) => {
|
|
755
|
+
const strs = [];
|
|
756
|
+
for (const item of iter) {
|
|
757
|
+
const str = internalConvertToString(item, getFuncId);
|
|
758
|
+
strs.push(str);
|
|
759
|
+
}
|
|
760
|
+
return `[${strs.join(" ")}]`;
|
|
761
|
+
};
|
|
762
|
+
var internalConvertToString = (v, getFuncId) => {
|
|
763
|
+
switch (v) {
|
|
764
|
+
case void 0: return "(undefined)";
|
|
765
|
+
case null: return "(null)";
|
|
766
|
+
default: switch (typeof v) {
|
|
767
|
+
case "string": return v;
|
|
768
|
+
case "boolean": return v ? "true" : "false";
|
|
769
|
+
case "number":
|
|
770
|
+
case "bigint":
|
|
771
|
+
case "symbol": return v.toString();
|
|
772
|
+
case "function": if (v.name) return `fun<${v.name}:#${getFuncId(v)}>`;
|
|
773
|
+
else return `fun<#${getFuncId(v)}>`;
|
|
774
|
+
default:
|
|
775
|
+
if (Array.isArray(v)) return iterToString(v, getFuncId);
|
|
776
|
+
const iterable = asIterable(v);
|
|
777
|
+
if (iterable) return iterToString(iterable, getFuncId);
|
|
778
|
+
else if (v instanceof Date) return v.toISOString();
|
|
779
|
+
else if (v instanceof Error) return `${v.name}: ${v.message}`;
|
|
780
|
+
else if (v instanceof URL) return v.origin;
|
|
781
|
+
else return JSON.stringify(v);
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
var internalCreateFunctionIdGenerator = () => {
|
|
786
|
+
const funcIds = /* @__PURE__ */ new WeakMap();
|
|
787
|
+
let nextId = 1;
|
|
788
|
+
const getFuncId = (fn) => {
|
|
789
|
+
const cached = funcIds.get(fn);
|
|
790
|
+
if (cached) return cached;
|
|
791
|
+
const id = nextId++;
|
|
792
|
+
funcIds.set(fn, id);
|
|
793
|
+
return id;
|
|
794
|
+
};
|
|
795
|
+
return getFuncId;
|
|
796
|
+
};
|
|
797
|
+
var getGlobalFuncId = internalCreateFunctionIdGenerator();
|
|
798
|
+
/**
|
|
799
|
+
* Convert to string.
|
|
800
|
+
* @param v Target instance
|
|
801
|
+
* @returns String
|
|
802
|
+
*/
|
|
803
|
+
var convertToString = (v) => internalConvertToString(v, getGlobalFuncId);
|
|
804
|
+
//#endregion
|
|
805
|
+
//#region src/parser.ts
|
|
806
|
+
var parseNumber = (cursor, _errors) => {
|
|
807
|
+
const token = cursor.takeToken();
|
|
808
|
+
return {
|
|
809
|
+
kind: "number",
|
|
810
|
+
value: token.value,
|
|
811
|
+
range: token.range
|
|
812
|
+
};
|
|
813
|
+
};
|
|
814
|
+
var parseString = (cursor, _errors) => {
|
|
815
|
+
const token = cursor.takeToken();
|
|
816
|
+
return {
|
|
817
|
+
kind: "string",
|
|
818
|
+
value: token.value,
|
|
819
|
+
range: token.range
|
|
820
|
+
};
|
|
821
|
+
};
|
|
822
|
+
var parseTemplate = (cursor, logs) => {
|
|
823
|
+
const token = cursor.takeToken();
|
|
824
|
+
return {
|
|
825
|
+
kind: "template",
|
|
826
|
+
blocks: parseBlockCore(createParserCursor(token.tokens), logs, "script"),
|
|
827
|
+
range: token.range
|
|
828
|
+
};
|
|
829
|
+
};
|
|
830
|
+
var parseIdentity = (cursor, _errors) => {
|
|
831
|
+
const token = cursor.takeToken();
|
|
832
|
+
return {
|
|
833
|
+
kind: "variable",
|
|
834
|
+
name: token.name,
|
|
835
|
+
range: token.range
|
|
836
|
+
};
|
|
837
|
+
};
|
|
838
|
+
var unitKind = "'()'";
|
|
839
|
+
var combineIntoScopeMultipleExpressions = (expressionList, logs, ...outerRanges) => {
|
|
840
|
+
switch (expressionList.length) {
|
|
841
|
+
case 0: return;
|
|
842
|
+
case 1: return expressionList[0];
|
|
843
|
+
default: return {
|
|
844
|
+
kind: "scope",
|
|
845
|
+
nodes: expressionList,
|
|
846
|
+
range: widerRange(...expressionList.map((node) => node.range), ...outerRanges, logs)
|
|
847
|
+
};
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
var parseDotChain = (cursor, logs, baseNode) => {
|
|
851
|
+
const segments = [];
|
|
852
|
+
const ranges = [baseNode.range];
|
|
853
|
+
while (true) {
|
|
854
|
+
const dotToken = cursor.peekToken();
|
|
855
|
+
if (!dotToken || dotToken.kind !== "dot") break;
|
|
856
|
+
const actualDotToken = cursor.takeToken();
|
|
857
|
+
ranges.push(actualDotToken.range);
|
|
858
|
+
const nextToken = cursor.peekToken();
|
|
859
|
+
if (!nextToken) {
|
|
860
|
+
logs.push({
|
|
861
|
+
type: "error",
|
|
862
|
+
description: "Could not find member identity after dot",
|
|
863
|
+
range: actualDotToken.range
|
|
864
|
+
});
|
|
865
|
+
break;
|
|
866
|
+
}
|
|
867
|
+
if (nextToken.kind !== "identity") {
|
|
868
|
+
logs.push({
|
|
869
|
+
type: "error",
|
|
870
|
+
description: "Required member identity after dot",
|
|
871
|
+
range: widerRange(actualDotToken.range, nextToken.range, logs)
|
|
872
|
+
});
|
|
873
|
+
break;
|
|
874
|
+
}
|
|
875
|
+
const memberToken = cursor.takeToken();
|
|
876
|
+
segments.push({
|
|
877
|
+
name: memberToken.name,
|
|
878
|
+
optional: actualDotToken.optional,
|
|
879
|
+
range: memberToken.range,
|
|
880
|
+
operatorRange: actualDotToken.range
|
|
881
|
+
});
|
|
882
|
+
ranges.push(memberToken.range);
|
|
883
|
+
}
|
|
884
|
+
if (segments.length === 0) return baseNode;
|
|
885
|
+
return {
|
|
886
|
+
kind: "dot",
|
|
887
|
+
base: baseNode,
|
|
888
|
+
segments,
|
|
889
|
+
range: widerRange(...ranges, logs)
|
|
890
|
+
};
|
|
891
|
+
};
|
|
892
|
+
var parsePartialExpression = (cursor, logs) => {
|
|
893
|
+
const token = cursor.peekToken();
|
|
894
|
+
if (!token) return;
|
|
895
|
+
switch (token.kind) {
|
|
896
|
+
case "number": return parseDotChain(cursor, logs, parseNumber(cursor, logs));
|
|
897
|
+
case "string": return parseDotChain(cursor, logs, parseString(cursor, logs));
|
|
898
|
+
case "template": return parseDotChain(cursor, logs, parseTemplate(cursor, logs));
|
|
899
|
+
case "identity": return parseDotChain(cursor, logs, parseIdentity(cursor, logs));
|
|
900
|
+
case "dot": {
|
|
901
|
+
const dotToken = cursor.takeToken();
|
|
902
|
+
logs.push({
|
|
903
|
+
type: "error",
|
|
904
|
+
description: "Invalid dot at this location",
|
|
905
|
+
range: dotToken.range
|
|
906
|
+
});
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
case "open":
|
|
910
|
+
cursor.skipToken();
|
|
911
|
+
switch (token.symbol) {
|
|
912
|
+
case "(": {
|
|
913
|
+
const innerNodes = parseMultipleApplicationExpressions(cursor, logs);
|
|
914
|
+
const closeToken = cursor.peekToken();
|
|
915
|
+
let range;
|
|
916
|
+
if (!closeToken) {
|
|
917
|
+
range = widerRange(token.range, ...innerNodes.map((node) => node.range), logs);
|
|
918
|
+
logs.push({
|
|
919
|
+
type: "error",
|
|
920
|
+
description: "Could not find close parenthesis",
|
|
921
|
+
range: widerRange(token.range, ...innerNodes.map((node) => node.range), logs)
|
|
922
|
+
});
|
|
923
|
+
} else {
|
|
924
|
+
cursor.skipToken();
|
|
925
|
+
range = widerRange(token.range, ...innerNodes.map((node) => node.range), closeToken.range, logs);
|
|
926
|
+
if (closeToken.kind !== "close" || closeToken.symbol !== ")") logs.push({
|
|
927
|
+
type: "error",
|
|
928
|
+
description: `Mismatched close parenthesis`,
|
|
929
|
+
range
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
if (innerNodes.length === 0) return {
|
|
933
|
+
kind: unitKind,
|
|
934
|
+
range
|
|
935
|
+
};
|
|
936
|
+
else {
|
|
937
|
+
const node = combineIntoScopeMultipleExpressions(innerNodes, logs, range);
|
|
938
|
+
return node ? parseDotChain(cursor, logs, node) : node;
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
case "[": {
|
|
942
|
+
const itemNodes = parseListExpression(cursor, logs);
|
|
943
|
+
const closeToken = cursor.peekToken();
|
|
944
|
+
let range;
|
|
945
|
+
if (!closeToken) {
|
|
946
|
+
range = widerRange(token.range, ...itemNodes.map((node) => node.range), logs);
|
|
947
|
+
logs.push({
|
|
948
|
+
type: "error",
|
|
949
|
+
description: "Could not find close bracket",
|
|
950
|
+
range
|
|
951
|
+
});
|
|
952
|
+
} else {
|
|
953
|
+
cursor.skipToken();
|
|
954
|
+
range = widerRange(token.range, ...itemNodes.map((node) => node.range), closeToken.range, logs);
|
|
955
|
+
if (closeToken.kind !== "close" || closeToken.symbol !== "]") logs.push({
|
|
956
|
+
type: "error",
|
|
957
|
+
description: `Mismatched close bracket`,
|
|
958
|
+
range
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
return parseDotChain(cursor, logs, {
|
|
962
|
+
kind: "list",
|
|
963
|
+
items: itemNodes,
|
|
964
|
+
range
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
default:
|
|
968
|
+
logs.push({
|
|
969
|
+
type: "error",
|
|
970
|
+
description: `Invalid open parenthesis/bracket`,
|
|
971
|
+
range: token.range
|
|
972
|
+
});
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
var normalizePartialUnitNode = (node, logs) => {
|
|
978
|
+
if (node.kind === unitKind) {
|
|
979
|
+
logs.push({
|
|
980
|
+
type: "error",
|
|
981
|
+
description: `Invalid ${unitKind} at this location`,
|
|
982
|
+
range: node.range
|
|
983
|
+
});
|
|
984
|
+
return {
|
|
985
|
+
kind: "variable",
|
|
986
|
+
name: "undefined",
|
|
987
|
+
range: node.range
|
|
988
|
+
};
|
|
989
|
+
} else return node;
|
|
990
|
+
};
|
|
991
|
+
var finalizeApplicationException = (partialNodes, logs) => {
|
|
992
|
+
if (partialNodes.length === 0) return;
|
|
993
|
+
if (partialNodes.length === 1) return normalizePartialUnitNode(partialNodes[0], logs);
|
|
994
|
+
const func = partialNodes[0];
|
|
995
|
+
if (func.kind === unitKind) {
|
|
996
|
+
logs.push({
|
|
997
|
+
type: "error",
|
|
998
|
+
description: `Invalid ${unitKind} at this location`,
|
|
999
|
+
range: func.range
|
|
1000
|
+
});
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
const arg0 = partialNodes[1];
|
|
1004
|
+
if (arg0.kind === unitKind) return {
|
|
1005
|
+
kind: "apply",
|
|
1006
|
+
func,
|
|
1007
|
+
args: [],
|
|
1008
|
+
range: widerRange(func.range, arg0.range, logs)
|
|
1009
|
+
};
|
|
1010
|
+
const args = partialNodes.slice(1).map((node) => normalizePartialUnitNode(node, logs));
|
|
1011
|
+
return {
|
|
1012
|
+
kind: "apply",
|
|
1013
|
+
func,
|
|
1014
|
+
args,
|
|
1015
|
+
range: widerRange(func.range, ...args.map((node) => node.range), logs)
|
|
1016
|
+
};
|
|
1017
|
+
};
|
|
1018
|
+
var parseMultipleApplicationExpressions = (cursor, logs) => {
|
|
1019
|
+
const expressionList = [];
|
|
1020
|
+
const partialNodes = [];
|
|
1021
|
+
while (true) {
|
|
1022
|
+
const token = cursor.peekToken();
|
|
1023
|
+
if (!token) break;
|
|
1024
|
+
switch (token.kind) {
|
|
1025
|
+
case "eol": {
|
|
1026
|
+
cursor.skipToken();
|
|
1027
|
+
const expr = finalizeApplicationException(partialNodes, logs);
|
|
1028
|
+
if (expr) expressionList.push(expr);
|
|
1029
|
+
partialNodes.length = 0;
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
const partialNode = parsePartialExpression(cursor, logs);
|
|
1034
|
+
if (!partialNode) break;
|
|
1035
|
+
partialNodes.push(partialNode);
|
|
1036
|
+
}
|
|
1037
|
+
const expr = finalizeApplicationException(partialNodes, logs);
|
|
1038
|
+
if (expr) expressionList.push(expr);
|
|
1039
|
+
return expressionList;
|
|
1040
|
+
};
|
|
1041
|
+
var parseListExpression = (cursor, logs) => {
|
|
1042
|
+
const itemNodes = [];
|
|
1043
|
+
while (true) {
|
|
1044
|
+
const token = cursor.peekToken();
|
|
1045
|
+
if (!token) break;
|
|
1046
|
+
switch (token.kind) {
|
|
1047
|
+
case "eol":
|
|
1048
|
+
cursor.skipToken();
|
|
1049
|
+
if (token.source === "semicolon") logs.push({
|
|
1050
|
+
type: "error",
|
|
1051
|
+
description: "Semicolon is not allowed in list expression",
|
|
1052
|
+
range: token.range
|
|
1053
|
+
});
|
|
1054
|
+
continue;
|
|
1055
|
+
}
|
|
1056
|
+
const partialNode = parsePartialExpression(cursor, logs);
|
|
1057
|
+
if (!partialNode) break;
|
|
1058
|
+
itemNodes.push(normalizePartialUnitNode(partialNode, logs));
|
|
1059
|
+
}
|
|
1060
|
+
return itemNodes;
|
|
1061
|
+
};
|
|
1062
|
+
var drainEndOfLineAndPeek = (cursor) => {
|
|
1063
|
+
let token = cursor.peekToken();
|
|
1064
|
+
while (token) {
|
|
1065
|
+
if (token.kind === "eol") cursor.skipToken();
|
|
1066
|
+
else break;
|
|
1067
|
+
token = cursor.peekToken();
|
|
1068
|
+
}
|
|
1069
|
+
return token;
|
|
1070
|
+
};
|
|
1071
|
+
/**
|
|
1072
|
+
* Parse expression in the single line.
|
|
1073
|
+
* @param cursor - Parser cursor
|
|
1074
|
+
* @param logs - Will be stored detected warnings/logs into it
|
|
1075
|
+
* @returns Parsed expression node when available
|
|
1076
|
+
*/
|
|
1077
|
+
var parseExpression = (cursor, logs) => {
|
|
1078
|
+
let token = drainEndOfLineAndPeek(cursor);
|
|
1079
|
+
if (!token) return;
|
|
1080
|
+
const partialNodes = [];
|
|
1081
|
+
while (true) {
|
|
1082
|
+
const partialNode = parsePartialExpression(cursor, logs);
|
|
1083
|
+
if (!partialNode) break;
|
|
1084
|
+
partialNodes.push(partialNode);
|
|
1085
|
+
token = cursor.peekToken();
|
|
1086
|
+
if (!token) break;
|
|
1087
|
+
if (token.kind === "eol") {
|
|
1088
|
+
cursor.skipToken();
|
|
1089
|
+
token = cursor.peekToken();
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
drainEndOfLineAndPeek(cursor);
|
|
1094
|
+
return finalizeApplicationException(partialNodes, logs);
|
|
1095
|
+
};
|
|
1096
|
+
var createBranchState = () => ({
|
|
1097
|
+
blocks: [],
|
|
1098
|
+
exprBuffer: []
|
|
1099
|
+
});
|
|
1100
|
+
var getBranchState = (statementState) => {
|
|
1101
|
+
switch (statementState.kind) {
|
|
1102
|
+
case "root": return statementState.branch;
|
|
1103
|
+
case "if": switch (statementState.currentBlock) {
|
|
1104
|
+
case "then": return statementState.then;
|
|
1105
|
+
case "else": return statementState.else;
|
|
1106
|
+
case "elseif": {
|
|
1107
|
+
var _statementState$curre;
|
|
1108
|
+
const elseIf = statementState.elseIfs[(_statementState$curre = statementState.currentElseIfIndex) !== null && _statementState$curre !== void 0 ? _statementState$curre : -1];
|
|
1109
|
+
return elseIf ? elseIf.then : statementState.else;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
case "while":
|
|
1113
|
+
case "for": return statementState.repeat;
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
var flushExpressions = (branch, logs) => {
|
|
1117
|
+
if (branch.exprBuffer.length === 0) return;
|
|
1118
|
+
if (branch.exprBuffer.length === 1) branch.blocks.push(branch.exprBuffer[0]);
|
|
1119
|
+
else branch.blocks.push({
|
|
1120
|
+
kind: "scope",
|
|
1121
|
+
nodes: branch.exprBuffer,
|
|
1122
|
+
range: widerRange(...branch.exprBuffer.map((node) => node.range), logs)
|
|
1123
|
+
});
|
|
1124
|
+
branch.exprBuffer = [];
|
|
1125
|
+
};
|
|
1126
|
+
var flushCurrentBranch = (statementStates, logs) => {
|
|
1127
|
+
const statementState = statementStates[statementStates.length - 1];
|
|
1128
|
+
flushExpressions(getBranchState(statementState), logs);
|
|
1129
|
+
};
|
|
1130
|
+
var flushStatementState = (statementState, logs) => {
|
|
1131
|
+
switch (statementState.kind) {
|
|
1132
|
+
case "root":
|
|
1133
|
+
flushExpressions(statementState.branch, logs);
|
|
1134
|
+
break;
|
|
1135
|
+
case "if":
|
|
1136
|
+
flushExpressions(statementState.then, logs);
|
|
1137
|
+
flushExpressions(statementState.else, logs);
|
|
1138
|
+
statementState.elseIfs.forEach((elseIf) => flushExpressions(elseIf.then, logs));
|
|
1139
|
+
break;
|
|
1140
|
+
case "while":
|
|
1141
|
+
case "for":
|
|
1142
|
+
flushExpressions(statementState.repeat, logs);
|
|
1143
|
+
break;
|
|
1144
|
+
}
|
|
1145
|
+
};
|
|
1146
|
+
var pushExpressionNode = (statementStates, node) => {
|
|
1147
|
+
const statementState = statementStates[statementStates.length - 1];
|
|
1148
|
+
getBranchState(statementState).exprBuffer.push(node);
|
|
1149
|
+
};
|
|
1150
|
+
var pushBlockNode = (statementStates, node, logs) => {
|
|
1151
|
+
const statementState = statementStates[statementStates.length - 1];
|
|
1152
|
+
const branch = getBranchState(statementState);
|
|
1153
|
+
flushExpressions(branch, logs);
|
|
1154
|
+
branch.blocks.push(node);
|
|
1155
|
+
};
|
|
1156
|
+
var pushNode = (statementStates, node, logs) => {
|
|
1157
|
+
switch (node.kind) {
|
|
1158
|
+
case "text":
|
|
1159
|
+
case "if":
|
|
1160
|
+
case "while":
|
|
1161
|
+
case "for":
|
|
1162
|
+
pushBlockNode(statementStates, node, logs);
|
|
1163
|
+
break;
|
|
1164
|
+
default:
|
|
1165
|
+
pushExpressionNode(statementStates, node);
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
};
|
|
1169
|
+
var parseStatementArguments = (cursor, logs) => {
|
|
1170
|
+
const args = [];
|
|
1171
|
+
while (true) {
|
|
1172
|
+
const token = cursor.peekToken();
|
|
1173
|
+
if (!token) break;
|
|
1174
|
+
if (token.kind === "eol") {
|
|
1175
|
+
cursor.skipToken();
|
|
1176
|
+
break;
|
|
1177
|
+
}
|
|
1178
|
+
const partialNode = parsePartialExpression(cursor, logs);
|
|
1179
|
+
if (!partialNode) break;
|
|
1180
|
+
args.push(normalizePartialUnitNode(partialNode, logs));
|
|
1181
|
+
}
|
|
1182
|
+
return args;
|
|
1183
|
+
};
|
|
1184
|
+
var parseBlockCore = (cursor, logs, mode) => {
|
|
1185
|
+
const isRepeatedSymbol = (symbol, ch, minLength) => {
|
|
1186
|
+
if (symbol.length < minLength) return false;
|
|
1187
|
+
for (let index = 0; index < symbol.length; index++) if (symbol[index] !== ch) return false;
|
|
1188
|
+
return true;
|
|
1189
|
+
};
|
|
1190
|
+
const isCodeBlockOpenSymbol = (symbol) => isRepeatedSymbol(symbol, "{", 2);
|
|
1191
|
+
const isCodeBlockCloseSymbol = (symbol) => isRepeatedSymbol(symbol, "}", 2);
|
|
1192
|
+
const rootState = {
|
|
1193
|
+
kind: "root",
|
|
1194
|
+
startRange: emptyRange,
|
|
1195
|
+
branch: createBranchState()
|
|
1196
|
+
};
|
|
1197
|
+
const statementStates = [rootState];
|
|
1198
|
+
const isCodeMode = mode === "code";
|
|
1199
|
+
let isInExpressionBlock = isCodeMode;
|
|
1200
|
+
let expectedCloseSymbol;
|
|
1201
|
+
while (true) {
|
|
1202
|
+
const token = drainEndOfLineAndPeek(cursor);
|
|
1203
|
+
if (!token) break;
|
|
1204
|
+
switch (token.kind) {
|
|
1205
|
+
case "text":
|
|
1206
|
+
cursor.skipToken();
|
|
1207
|
+
if (isInExpressionBlock) {
|
|
1208
|
+
logs.push({
|
|
1209
|
+
type: "error",
|
|
1210
|
+
description: `Already opened expression block (tokenizer bug?)`,
|
|
1211
|
+
range: token.range
|
|
1212
|
+
});
|
|
1213
|
+
break;
|
|
1214
|
+
}
|
|
1215
|
+
pushNode(statementStates, {
|
|
1216
|
+
kind: "text",
|
|
1217
|
+
text: token.text,
|
|
1218
|
+
range: token.range
|
|
1219
|
+
}, logs);
|
|
1220
|
+
break;
|
|
1221
|
+
case "open":
|
|
1222
|
+
if (isCodeBlockOpenSymbol(token.symbol)) {
|
|
1223
|
+
cursor.skipToken();
|
|
1224
|
+
if (!isCodeMode) if (isInExpressionBlock) logs.push({
|
|
1225
|
+
type: "error",
|
|
1226
|
+
description: `Already opened expression block`,
|
|
1227
|
+
range: token.range
|
|
1228
|
+
});
|
|
1229
|
+
else {
|
|
1230
|
+
isInExpressionBlock = true;
|
|
1231
|
+
expectedCloseSymbol = "}".repeat(token.symbol.length);
|
|
1232
|
+
}
|
|
1233
|
+
} else {
|
|
1234
|
+
const node = parseExpression(cursor, logs);
|
|
1235
|
+
if (node) pushNode(statementStates, node, logs);
|
|
1236
|
+
}
|
|
1237
|
+
break;
|
|
1238
|
+
case "close":
|
|
1239
|
+
cursor.skipToken();
|
|
1240
|
+
if (isCodeBlockCloseSymbol(token.symbol) && isCodeMode) {
|
|
1241
|
+
flushCurrentBranch(statementStates, logs);
|
|
1242
|
+
break;
|
|
1243
|
+
}
|
|
1244
|
+
if (!isInExpressionBlock) {
|
|
1245
|
+
logs.push({
|
|
1246
|
+
type: "error",
|
|
1247
|
+
description: `Mismatched close bracket`,
|
|
1248
|
+
range: token.range
|
|
1249
|
+
});
|
|
1250
|
+
break;
|
|
1251
|
+
}
|
|
1252
|
+
if (isCodeMode) {
|
|
1253
|
+
logs.push({
|
|
1254
|
+
type: "error",
|
|
1255
|
+
description: `Mismatched close bracket`,
|
|
1256
|
+
range: token.range
|
|
1257
|
+
});
|
|
1258
|
+
break;
|
|
1259
|
+
}
|
|
1260
|
+
if (!expectedCloseSymbol || token.symbol !== expectedCloseSymbol) {
|
|
1261
|
+
logs.push({
|
|
1262
|
+
type: "error",
|
|
1263
|
+
description: `Mismatched close bracket`,
|
|
1264
|
+
range: token.range
|
|
1265
|
+
});
|
|
1266
|
+
break;
|
|
1267
|
+
}
|
|
1268
|
+
flushCurrentBranch(statementStates, logs);
|
|
1269
|
+
isInExpressionBlock = false;
|
|
1270
|
+
expectedCloseSymbol = void 0;
|
|
1271
|
+
break;
|
|
1272
|
+
case "identity":
|
|
1273
|
+
if (!isInExpressionBlock) {
|
|
1274
|
+
logs.push({
|
|
1275
|
+
type: "error",
|
|
1276
|
+
description: `Invalid identity (tokenizer bug?)`,
|
|
1277
|
+
range: token.range
|
|
1278
|
+
});
|
|
1279
|
+
break;
|
|
1280
|
+
}
|
|
1281
|
+
switch (token.name) {
|
|
1282
|
+
case "if": {
|
|
1283
|
+
cursor.skipToken();
|
|
1284
|
+
const args = parseStatementArguments(cursor, logs);
|
|
1285
|
+
if (args.length !== 1) {
|
|
1286
|
+
logs.push({
|
|
1287
|
+
type: "error",
|
|
1288
|
+
description: "Required `if` condition",
|
|
1289
|
+
range: widerRange(token.range, ...args.map((node) => node.range), logs)
|
|
1290
|
+
});
|
|
1291
|
+
break;
|
|
1292
|
+
}
|
|
1293
|
+
const conditionNode = args[0];
|
|
1294
|
+
statementStates.push({
|
|
1295
|
+
kind: "if",
|
|
1296
|
+
startRange: token.range,
|
|
1297
|
+
condition: conditionNode,
|
|
1298
|
+
elseIfs: [],
|
|
1299
|
+
then: createBranchState(),
|
|
1300
|
+
else: createBranchState(),
|
|
1301
|
+
currentBlock: "then"
|
|
1302
|
+
});
|
|
1303
|
+
break;
|
|
1304
|
+
}
|
|
1305
|
+
case "else": {
|
|
1306
|
+
cursor.skipToken();
|
|
1307
|
+
const args = parseStatementArguments(cursor, logs);
|
|
1308
|
+
if (args.length !== 0) logs.push({
|
|
1309
|
+
type: "error",
|
|
1310
|
+
description: "Could not take any arguments in `else` statement",
|
|
1311
|
+
range: widerRange(token.range, ...args.map((node) => node.range), logs)
|
|
1312
|
+
});
|
|
1313
|
+
if (statementStates.length <= 1) {
|
|
1314
|
+
logs.push({
|
|
1315
|
+
type: "error",
|
|
1316
|
+
description: "Cound not find pair of `if` statement",
|
|
1317
|
+
range: token.range
|
|
1318
|
+
});
|
|
1319
|
+
break;
|
|
1320
|
+
}
|
|
1321
|
+
const lastState = statementStates[statementStates.length - 1];
|
|
1322
|
+
if (lastState.kind !== "if") {
|
|
1323
|
+
logs.push({
|
|
1324
|
+
type: "error",
|
|
1325
|
+
description: "Cound not find pair of `if` statement",
|
|
1326
|
+
range: token.range
|
|
1327
|
+
});
|
|
1328
|
+
break;
|
|
1329
|
+
}
|
|
1330
|
+
if (lastState.currentBlock === "else") {
|
|
1331
|
+
logs.push({
|
|
1332
|
+
type: "error",
|
|
1333
|
+
description: "Duplicated `else` statement",
|
|
1334
|
+
range: token.range
|
|
1335
|
+
});
|
|
1336
|
+
break;
|
|
1337
|
+
}
|
|
1338
|
+
flushExpressions(getBranchState(lastState), logs);
|
|
1339
|
+
lastState.currentBlock = "else";
|
|
1340
|
+
lastState.currentElseIfIndex = void 0;
|
|
1341
|
+
break;
|
|
1342
|
+
}
|
|
1343
|
+
case "elseif": {
|
|
1344
|
+
cursor.skipToken();
|
|
1345
|
+
const args = parseStatementArguments(cursor, logs);
|
|
1346
|
+
if (args.length !== 1) {
|
|
1347
|
+
logs.push({
|
|
1348
|
+
type: "error",
|
|
1349
|
+
description: "Required `elseif` condition",
|
|
1350
|
+
range: widerRange(token.range, ...args.map((node) => node.range), logs)
|
|
1351
|
+
});
|
|
1352
|
+
break;
|
|
1353
|
+
}
|
|
1354
|
+
if (statementStates.length <= 1) {
|
|
1355
|
+
logs.push({
|
|
1356
|
+
type: "error",
|
|
1357
|
+
description: "Cound not find pair of `if` statement",
|
|
1358
|
+
range: token.range
|
|
1359
|
+
});
|
|
1360
|
+
break;
|
|
1361
|
+
}
|
|
1362
|
+
const lastState = statementStates[statementStates.length - 1];
|
|
1363
|
+
if (lastState.kind !== "if") {
|
|
1364
|
+
logs.push({
|
|
1365
|
+
type: "error",
|
|
1366
|
+
description: "Cound not find pair of `if` statement",
|
|
1367
|
+
range: token.range
|
|
1368
|
+
});
|
|
1369
|
+
break;
|
|
1370
|
+
}
|
|
1371
|
+
if (lastState.currentBlock === "else") {
|
|
1372
|
+
logs.push({
|
|
1373
|
+
type: "error",
|
|
1374
|
+
description: "Could not place `elseif` after `else` statement",
|
|
1375
|
+
range: token.range
|
|
1376
|
+
});
|
|
1377
|
+
break;
|
|
1378
|
+
}
|
|
1379
|
+
flushExpressions(getBranchState(lastState), logs);
|
|
1380
|
+
const conditionNode = args[0];
|
|
1381
|
+
const elseIfIndex = lastState.elseIfs.length;
|
|
1382
|
+
lastState.elseIfs.push({
|
|
1383
|
+
startRange: token.range,
|
|
1384
|
+
condition: conditionNode,
|
|
1385
|
+
then: createBranchState()
|
|
1386
|
+
});
|
|
1387
|
+
lastState.currentBlock = "elseif";
|
|
1388
|
+
lastState.currentElseIfIndex = elseIfIndex;
|
|
1389
|
+
break;
|
|
1390
|
+
}
|
|
1391
|
+
case "while": {
|
|
1392
|
+
cursor.skipToken();
|
|
1393
|
+
const args = parseStatementArguments(cursor, logs);
|
|
1394
|
+
if (args.length !== 1) {
|
|
1395
|
+
logs.push({
|
|
1396
|
+
type: "error",
|
|
1397
|
+
description: "Required `while` condition",
|
|
1398
|
+
range: widerRange(token.range, ...args.map((node) => node.range), logs)
|
|
1399
|
+
});
|
|
1400
|
+
break;
|
|
1401
|
+
}
|
|
1402
|
+
const conditionNode = args[0];
|
|
1403
|
+
statementStates.push({
|
|
1404
|
+
kind: "while",
|
|
1405
|
+
startRange: token.range,
|
|
1406
|
+
condition: conditionNode,
|
|
1407
|
+
repeat: createBranchState()
|
|
1408
|
+
});
|
|
1409
|
+
break;
|
|
1410
|
+
}
|
|
1411
|
+
case "for": {
|
|
1412
|
+
cursor.skipToken();
|
|
1413
|
+
const args = parseStatementArguments(cursor, logs);
|
|
1414
|
+
if (args.length !== 2) {
|
|
1415
|
+
logs.push({
|
|
1416
|
+
type: "error",
|
|
1417
|
+
description: "Required `for` bind identity and iterable expression",
|
|
1418
|
+
range: widerRange(token.range, ...args.map((node) => node.range), logs)
|
|
1419
|
+
});
|
|
1420
|
+
break;
|
|
1421
|
+
}
|
|
1422
|
+
const bindNode = args[0];
|
|
1423
|
+
if (bindNode.kind !== "variable") {
|
|
1424
|
+
logs.push({
|
|
1425
|
+
type: "error",
|
|
1426
|
+
description: "Required `for` bind identity",
|
|
1427
|
+
range: bindNode.range
|
|
1428
|
+
});
|
|
1429
|
+
break;
|
|
1430
|
+
}
|
|
1431
|
+
const iterableNode = args[1];
|
|
1432
|
+
statementStates.push({
|
|
1433
|
+
kind: "for",
|
|
1434
|
+
startRange: token.range,
|
|
1435
|
+
bind: bindNode,
|
|
1436
|
+
iterable: iterableNode,
|
|
1437
|
+
repeat: createBranchState()
|
|
1438
|
+
});
|
|
1439
|
+
break;
|
|
1440
|
+
}
|
|
1441
|
+
case "end": {
|
|
1442
|
+
cursor.skipToken();
|
|
1443
|
+
const args = parseStatementArguments(cursor, logs);
|
|
1444
|
+
if (args.length !== 0) logs.push({
|
|
1445
|
+
type: "error",
|
|
1446
|
+
description: "Could not take any arguments in `end` statement",
|
|
1447
|
+
range: widerRange(token.range, ...args.map((node) => node.range), logs)
|
|
1448
|
+
});
|
|
1449
|
+
if (statementStates.length <= 1) {
|
|
1450
|
+
logs.push({
|
|
1451
|
+
type: "error",
|
|
1452
|
+
description: "Cound not find pair of `if`,`while` or `for` statement",
|
|
1453
|
+
range: token.range
|
|
1454
|
+
});
|
|
1455
|
+
break;
|
|
1456
|
+
}
|
|
1457
|
+
const lastState = statementStates.pop();
|
|
1458
|
+
flushStatementState(lastState, logs);
|
|
1459
|
+
switch (lastState.kind) {
|
|
1460
|
+
case "if": {
|
|
1461
|
+
let elseBlocks = lastState.else.blocks;
|
|
1462
|
+
for (let index = lastState.elseIfs.length - 1; index >= 0; index--) {
|
|
1463
|
+
const elseIf = lastState.elseIfs[index];
|
|
1464
|
+
elseBlocks = [{
|
|
1465
|
+
kind: "if",
|
|
1466
|
+
condition: elseIf.condition,
|
|
1467
|
+
then: elseIf.then.blocks,
|
|
1468
|
+
else: elseBlocks,
|
|
1469
|
+
range: widerRange(elseIf.startRange, elseIf.condition.range, ...elseIf.then.blocks.map((node) => node.range), ...elseBlocks.map((node) => node.range), token.range, logs)
|
|
1470
|
+
}];
|
|
1471
|
+
}
|
|
1472
|
+
pushNode(statementStates, {
|
|
1473
|
+
kind: "if",
|
|
1474
|
+
condition: lastState.condition,
|
|
1475
|
+
then: lastState.then.blocks,
|
|
1476
|
+
else: elseBlocks,
|
|
1477
|
+
range: widerRange(lastState.startRange, lastState.condition.range, ...lastState.then.blocks.map((node) => node.range), ...elseBlocks.map((node) => node.range), token.range, logs)
|
|
1478
|
+
}, logs);
|
|
1479
|
+
break;
|
|
1480
|
+
}
|
|
1481
|
+
case "while":
|
|
1482
|
+
pushNode(statementStates, {
|
|
1483
|
+
kind: "while",
|
|
1484
|
+
condition: lastState.condition,
|
|
1485
|
+
repeat: lastState.repeat.blocks,
|
|
1486
|
+
range: widerRange(lastState.startRange, lastState.condition.range, ...lastState.repeat.blocks.map((node) => node.range), token.range, logs)
|
|
1487
|
+
}, logs);
|
|
1488
|
+
break;
|
|
1489
|
+
case "for":
|
|
1490
|
+
pushNode(statementStates, {
|
|
1491
|
+
kind: "for",
|
|
1492
|
+
bind: lastState.bind,
|
|
1493
|
+
iterable: lastState.iterable,
|
|
1494
|
+
repeat: lastState.repeat.blocks,
|
|
1495
|
+
range: widerRange(lastState.startRange, lastState.bind.range, ...lastState.repeat.blocks.map((node) => node.range), token.range, logs)
|
|
1496
|
+
}, logs);
|
|
1497
|
+
break;
|
|
1498
|
+
}
|
|
1499
|
+
break;
|
|
1500
|
+
}
|
|
1501
|
+
default: {
|
|
1502
|
+
const node = parseExpression(cursor, logs);
|
|
1503
|
+
if (node) pushNode(statementStates, node, logs);
|
|
1504
|
+
break;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
break;
|
|
1508
|
+
default: {
|
|
1509
|
+
if (!isInExpressionBlock) {
|
|
1510
|
+
logs.push({
|
|
1511
|
+
type: "error",
|
|
1512
|
+
description: `Invalid ${token.kind} (tokenizer bug?)`,
|
|
1513
|
+
range: token.range
|
|
1514
|
+
});
|
|
1515
|
+
break;
|
|
1516
|
+
}
|
|
1517
|
+
const node = parseExpression(cursor, logs);
|
|
1518
|
+
if (node) pushNode(statementStates, node, logs);
|
|
1519
|
+
break;
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
flushStatementState(rootState, logs);
|
|
1524
|
+
if (statementStates.length !== 1) logs.push({
|
|
1525
|
+
type: "error",
|
|
1526
|
+
description: `Could not find statement closing`,
|
|
1527
|
+
range: widerRange(...statementStates.map((state) => state.startRange), logs)
|
|
1528
|
+
});
|
|
1529
|
+
return rootState.branch.blocks;
|
|
1530
|
+
};
|
|
1531
|
+
/**
|
|
1532
|
+
* Parse blocks.
|
|
1533
|
+
* @param cursor - Parser cursor
|
|
1534
|
+
* @param logs - Will be stored detected warnings/logs into it
|
|
1535
|
+
* @returns Parsed block nodes
|
|
1536
|
+
*/
|
|
1537
|
+
var parseBlock = (cursor, logs) => {
|
|
1538
|
+
return parseBlockCore(cursor, logs, "script");
|
|
1539
|
+
};
|
|
1540
|
+
/**
|
|
1541
|
+
* Create a parser cursor.
|
|
1542
|
+
* @param tokens - Target tokens
|
|
1543
|
+
* @returns Parser cursor
|
|
1544
|
+
*/
|
|
1545
|
+
var createParserCursor = (tokens) => {
|
|
1546
|
+
let index = 0;
|
|
1547
|
+
const peekToken = () => {
|
|
1548
|
+
return tokens[index];
|
|
1549
|
+
};
|
|
1550
|
+
const takeToken = () => {
|
|
1551
|
+
if (index >= tokens.length) return;
|
|
1552
|
+
const token = tokens[index];
|
|
1553
|
+
index++;
|
|
1554
|
+
return token;
|
|
1555
|
+
};
|
|
1556
|
+
const skipToken = () => {
|
|
1557
|
+
if (index >= tokens.length) return;
|
|
1558
|
+
index++;
|
|
1559
|
+
};
|
|
1560
|
+
return {
|
|
1561
|
+
peekToken,
|
|
1562
|
+
takeToken,
|
|
1563
|
+
skipToken
|
|
1564
|
+
};
|
|
1565
|
+
};
|
|
1566
|
+
/**
|
|
1567
|
+
* Parse expressions in code block.
|
|
1568
|
+
* @param tokens - Token list
|
|
1569
|
+
* @param logs - Will be stored detected warnings/logs into it
|
|
1570
|
+
* @returns Parsed node list
|
|
1571
|
+
*/
|
|
1572
|
+
var parseExpressions = (tokens, logs) => {
|
|
1573
|
+
return parseBlockCore(createParserCursor(tokens), logs, "code");
|
|
1574
|
+
};
|
|
1575
|
+
/**
|
|
1576
|
+
* Run the parser.
|
|
1577
|
+
* @param tokens - Token list
|
|
1578
|
+
* @param logs - Will be stored detected warnings/logs into it
|
|
1579
|
+
* @returns Parsed node list
|
|
1580
|
+
*/
|
|
1581
|
+
var runParser = (tokens, logs) => {
|
|
1582
|
+
return parseBlock(createParserCursor(tokens), logs);
|
|
1583
|
+
};
|
|
1584
|
+
//#endregion
|
|
1585
|
+
//#region src/reducer.ts
|
|
1586
|
+
var throwError$1 = (info) => {
|
|
1587
|
+
throw new FunCityReducerError({
|
|
1588
|
+
type: "error",
|
|
1589
|
+
...info
|
|
1590
|
+
});
|
|
1591
|
+
};
|
|
1592
|
+
var deconstructConditionalCombine$1 = (name) => {
|
|
1593
|
+
if (name.length >= 1) {
|
|
1594
|
+
if (name[name.length - 1] === "?") return {
|
|
1595
|
+
name: name.substring(0, name.length - 1),
|
|
1596
|
+
canIgnore: true
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
return {
|
|
1600
|
+
name,
|
|
1601
|
+
canIgnore: false
|
|
1602
|
+
};
|
|
1603
|
+
};
|
|
1604
|
+
var resolveVariable$1 = (context, name, signal) => {
|
|
1605
|
+
const result = deconstructConditionalCombine$1(name.name);
|
|
1606
|
+
const valueResult = context.getValue(result.name, signal);
|
|
1607
|
+
if (!valueResult.isFound) {
|
|
1608
|
+
if (!result.canIgnore) throwError$1({
|
|
1609
|
+
description: `variable is not bound: ${result.name}`,
|
|
1610
|
+
range: name.range
|
|
1611
|
+
});
|
|
1612
|
+
return;
|
|
1613
|
+
}
|
|
1614
|
+
return valueResult.value;
|
|
1615
|
+
};
|
|
1616
|
+
var resolveDotNode = async (context, node, signal) => {
|
|
1617
|
+
var _node$segments$0$opti, _node$segments$;
|
|
1618
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1619
|
+
const firstSegmentOptional = (_node$segments$0$opti = (_node$segments$ = node.segments[0]) === null || _node$segments$ === void 0 ? void 0 : _node$segments$.optional) !== null && _node$segments$0$opti !== void 0 ? _node$segments$0$opti : false;
|
|
1620
|
+
let value;
|
|
1621
|
+
if (node.base.kind === "variable") {
|
|
1622
|
+
const baseResult = deconstructConditionalCombine$1(node.base.name);
|
|
1623
|
+
const valueResult = context.getValue(baseResult.name, signal);
|
|
1624
|
+
if (!valueResult.isFound) {
|
|
1625
|
+
if (!baseResult.canIgnore && !firstSegmentOptional) throwError$1({
|
|
1626
|
+
description: `variable is not bound: ${baseResult.name}`,
|
|
1627
|
+
range: node.base.range
|
|
1628
|
+
});
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1631
|
+
value = valueResult.value;
|
|
1632
|
+
} else value = await reduceExpressionNode(context, node.base, signal);
|
|
1633
|
+
let parent;
|
|
1634
|
+
for (const segment of node.segments) {
|
|
1635
|
+
const result = deconstructConditionalCombine$1(segment.name);
|
|
1636
|
+
const isOptional = segment.optional || result.canIgnore;
|
|
1637
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
1638
|
+
const record = value;
|
|
1639
|
+
parent = value;
|
|
1640
|
+
value = record[result.name];
|
|
1641
|
+
} else {
|
|
1642
|
+
if (!isOptional) throwError$1({
|
|
1643
|
+
description: `variable is not bound: ${result.name}`,
|
|
1644
|
+
range: segment.range
|
|
1645
|
+
});
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
if (parent && typeof value === "function" && !isFunCityFunction(value)) return context.getBoundFunction(parent, value);
|
|
1650
|
+
return value;
|
|
1651
|
+
};
|
|
1652
|
+
var applyFunction = async (context, node, signal) => {
|
|
1653
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1654
|
+
const func = await reduceExpressionNode(context, node.func, signal);
|
|
1655
|
+
if (typeof func !== "function") {
|
|
1656
|
+
throwError$1({
|
|
1657
|
+
description: "could not apply it for function",
|
|
1658
|
+
range: node.range
|
|
1659
|
+
});
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1662
|
+
const args = isFunCityFunction(func) ? node.args : await Promise.all(node.args.map(async (argNode) => {
|
|
1663
|
+
return await reduceExpressionNode(context, argNode, signal);
|
|
1664
|
+
}));
|
|
1665
|
+
try {
|
|
1666
|
+
const thisProxy = context.createFunctionContext(node, signal);
|
|
1667
|
+
return await func.call(thisProxy, ...args);
|
|
1668
|
+
} catch (e) {
|
|
1669
|
+
if (e instanceof FunCityReducerError) throw e;
|
|
1670
|
+
if (e instanceof Error && e.name === "AbortError") throw e;
|
|
1671
|
+
throw new FunCityReducerError({
|
|
1672
|
+
type: "error",
|
|
1673
|
+
description: fromError(e),
|
|
1674
|
+
range: node.range
|
|
1675
|
+
});
|
|
1676
|
+
}
|
|
1677
|
+
};
|
|
1678
|
+
/**
|
|
1679
|
+
* Reduce expression node.
|
|
1680
|
+
* @param context - Reducer context
|
|
1681
|
+
* @param node - Target expression node
|
|
1682
|
+
* @param signal - AbortSignal
|
|
1683
|
+
* @returns Reduced native value
|
|
1684
|
+
*/
|
|
1685
|
+
var reduceExpressionNode = async (context, node, signal) => {
|
|
1686
|
+
switch (node.kind) {
|
|
1687
|
+
case "number":
|
|
1688
|
+
case "string": return node.value;
|
|
1689
|
+
case "template": {
|
|
1690
|
+
const resultList = [];
|
|
1691
|
+
for (const block of node.blocks) {
|
|
1692
|
+
const results = await reduceNode(context, block, signal);
|
|
1693
|
+
for (const result of results) if (result !== void 0) resultList.push(result);
|
|
1694
|
+
}
|
|
1695
|
+
return resultList.map((result) => context.convertToString(result)).join("");
|
|
1696
|
+
}
|
|
1697
|
+
case "variable": return resolveVariable$1(context, node, signal);
|
|
1698
|
+
case "dot": return await resolveDotNode(context, node, signal);
|
|
1699
|
+
case "apply": return await applyFunction(context, node, signal);
|
|
1700
|
+
case "list": return await Promise.all(node.items.map((item) => reduceExpressionNode(context, item, signal)));
|
|
1701
|
+
case "scope": {
|
|
1702
|
+
if (node.nodes.length === 0) return [];
|
|
1703
|
+
let result = void 0;
|
|
1704
|
+
for (const childNode of node.nodes) result = await reduceExpressionNode(context, childNode, signal);
|
|
1705
|
+
return result;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
};
|
|
1709
|
+
/**
|
|
1710
|
+
* Reduce a node.
|
|
1711
|
+
* @param context - Reducer context
|
|
1712
|
+
* @param node - Target node
|
|
1713
|
+
* @param signal - AbortSignal
|
|
1714
|
+
* @returns Reduced native value list
|
|
1715
|
+
*/
|
|
1716
|
+
var reduceNode = async (context, node, signal) => {
|
|
1717
|
+
switch (node.kind) {
|
|
1718
|
+
case "text": return [node.text];
|
|
1719
|
+
case "for": {
|
|
1720
|
+
const iterable = asIterable(await reduceExpressionNode(context, node.iterable, signal));
|
|
1721
|
+
if (!iterable) {
|
|
1722
|
+
throwError$1({
|
|
1723
|
+
description: "could not apply it for function",
|
|
1724
|
+
range: node.range
|
|
1725
|
+
});
|
|
1726
|
+
return [];
|
|
1727
|
+
}
|
|
1728
|
+
const resultList = [];
|
|
1729
|
+
for (const item of iterable) {
|
|
1730
|
+
context.setValue(node.bind.name, item, signal);
|
|
1731
|
+
for (const repeat of node.repeat) {
|
|
1732
|
+
const results = await reduceNode(context, repeat, signal);
|
|
1733
|
+
resultList.push(...results);
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
return resultList;
|
|
1737
|
+
}
|
|
1738
|
+
case "while": {
|
|
1739
|
+
const resultList = [];
|
|
1740
|
+
while (true) {
|
|
1741
|
+
if (!isConditionalTrue(await reduceExpressionNode(context, node.condition, signal))) break;
|
|
1742
|
+
for (const repeat of node.repeat) {
|
|
1743
|
+
const results = await reduceNode(context, repeat, signal);
|
|
1744
|
+
resultList.push(...results);
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
return resultList;
|
|
1748
|
+
}
|
|
1749
|
+
case "if": {
|
|
1750
|
+
const resultList = [];
|
|
1751
|
+
if (isConditionalTrue(await reduceExpressionNode(context, node.condition, signal))) for (const then of node.then) {
|
|
1752
|
+
const results = await reduceNode(context, then, signal);
|
|
1753
|
+
resultList.push(...results);
|
|
1754
|
+
}
|
|
1755
|
+
else for (const els of node.else) {
|
|
1756
|
+
const results = await reduceNode(context, els, signal);
|
|
1757
|
+
resultList.push(...results);
|
|
1758
|
+
}
|
|
1759
|
+
return resultList;
|
|
1760
|
+
}
|
|
1761
|
+
default: return [await reduceExpressionNode(context, node, signal)];
|
|
1762
|
+
}
|
|
1763
|
+
};
|
|
1764
|
+
var defaultReducerExecutor = {
|
|
1765
|
+
reduceExpressionNodeImmediate: (context, node, signal) => reduceExpressionNode(context, node, signal),
|
|
1766
|
+
reduceExpressionNode: (context, node, signal) => Promise.resolve(reduceExpressionNode(context, node, signal)),
|
|
1767
|
+
reduceNodeImmediate: (context, node, signal) => reduceNode(context, node, signal),
|
|
1768
|
+
reduceNode: (context, node, signal) => Promise.resolve(reduceNode(context, node, signal))
|
|
1769
|
+
};
|
|
1770
|
+
var reduceBlockImmediate = (context, nodeOrNodes, signal) => {
|
|
1771
|
+
const nodes = Array.isArray(nodeOrNodes) ? nodeOrNodes : [nodeOrNodes];
|
|
1772
|
+
const resultList = [];
|
|
1773
|
+
for (let index = 0; index < nodes.length; index++) {
|
|
1774
|
+
const results = context.reduceNodeImmediate(nodes[index], signal);
|
|
1775
|
+
if (isPromiseLike(results)) return (async () => {
|
|
1776
|
+
const firstResults = await results;
|
|
1777
|
+
for (const result of firstResults) if (result !== void 0) resultList.push(result);
|
|
1778
|
+
for (let continueIndex = index + 1; continueIndex < nodes.length; continueIndex++) {
|
|
1779
|
+
const continueResults = await context.reduceNodeImmediate(nodes[continueIndex], signal);
|
|
1780
|
+
for (const result of continueResults) if (result !== void 0) resultList.push(result);
|
|
1781
|
+
}
|
|
1782
|
+
return resultList;
|
|
1783
|
+
})();
|
|
1784
|
+
for (const result of results) if (result !== void 0) resultList.push(result);
|
|
1785
|
+
}
|
|
1786
|
+
return resultList;
|
|
1787
|
+
};
|
|
1788
|
+
var createPreparedSlotState = (slotNames, slotValues, signal) => {
|
|
1789
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1790
|
+
let preparedSlotIds;
|
|
1791
|
+
let preparedSlotValues;
|
|
1792
|
+
let preparedSlotVersion = 0;
|
|
1793
|
+
if (slotNames === void 0 || slotNames.length === 0) return {
|
|
1794
|
+
preparedSlotIds,
|
|
1795
|
+
preparedSlotValues,
|
|
1796
|
+
preparedSlotVersion
|
|
1797
|
+
};
|
|
1798
|
+
for (let index = 0; index < slotNames.length; index++) {
|
|
1799
|
+
const name = slotNames[index];
|
|
1800
|
+
const existingSlot = preparedSlotIds === null || preparedSlotIds === void 0 ? void 0 : preparedSlotIds.get(name);
|
|
1801
|
+
if (existingSlot !== void 0) {
|
|
1802
|
+
preparedSlotValues[existingSlot] = slotValues === null || slotValues === void 0 ? void 0 : slotValues[index];
|
|
1803
|
+
continue;
|
|
1804
|
+
}
|
|
1805
|
+
if (!preparedSlotIds) preparedSlotIds = /* @__PURE__ */ new Map();
|
|
1806
|
+
if (!preparedSlotValues) preparedSlotValues = [];
|
|
1807
|
+
const slot = preparedSlotValues.length;
|
|
1808
|
+
preparedSlotIds.set(name, slot);
|
|
1809
|
+
preparedSlotValues.push(slotValues === null || slotValues === void 0 ? void 0 : slotValues[index]);
|
|
1810
|
+
preparedSlotVersion++;
|
|
1811
|
+
}
|
|
1812
|
+
return {
|
|
1813
|
+
preparedSlotIds,
|
|
1814
|
+
preparedSlotValues,
|
|
1815
|
+
preparedSlotVersion
|
|
1816
|
+
};
|
|
1817
|
+
};
|
|
1818
|
+
var createScopedReducerContext = (parent, signal, executor, initialSlotNames, initialSlotValues) => {
|
|
1819
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1820
|
+
const preparedSlotState = createPreparedSlotState(initialSlotNames, initialSlotValues, signal);
|
|
1821
|
+
let thisSlotIds = preparedSlotState.preparedSlotIds;
|
|
1822
|
+
let thisSlotValues = preparedSlotState.preparedSlotValues;
|
|
1823
|
+
let thisSlotVersion = preparedSlotState.preparedSlotVersion;
|
|
1824
|
+
let thisContext;
|
|
1825
|
+
const getSlotVersion = () => thisSlotVersion;
|
|
1826
|
+
const resolveLocalSlot = (name, signal) => {
|
|
1827
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1828
|
+
return thisSlotIds === null || thisSlotIds === void 0 ? void 0 : thisSlotIds.get(name);
|
|
1829
|
+
};
|
|
1830
|
+
const ensureLocalSlot = (name, signal) => {
|
|
1831
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1832
|
+
let slot = thisSlotIds === null || thisSlotIds === void 0 ? void 0 : thisSlotIds.get(name);
|
|
1833
|
+
if (slot !== void 0) return slot;
|
|
1834
|
+
if (!thisSlotIds) thisSlotIds = /* @__PURE__ */ new Map();
|
|
1835
|
+
if (!thisSlotValues) thisSlotValues = [];
|
|
1836
|
+
slot = thisSlotValues.length;
|
|
1837
|
+
thisSlotIds.set(name, slot);
|
|
1838
|
+
thisSlotValues.push(void 0);
|
|
1839
|
+
thisSlotVersion++;
|
|
1840
|
+
return slot;
|
|
1841
|
+
};
|
|
1842
|
+
const getSlotValue = (slot, signal) => {
|
|
1843
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1844
|
+
return thisSlotValues === null || thisSlotValues === void 0 ? void 0 : thisSlotValues[slot];
|
|
1845
|
+
};
|
|
1846
|
+
const setSlotValue = (slot, value, signal) => {
|
|
1847
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1848
|
+
if (!thisSlotValues) thisSlotValues = [];
|
|
1849
|
+
thisSlotValues[slot] = value;
|
|
1850
|
+
};
|
|
1851
|
+
const getValue = (name, signal) => {
|
|
1852
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1853
|
+
const slot = resolveLocalSlot(name, signal);
|
|
1854
|
+
if (slot !== void 0) return {
|
|
1855
|
+
value: getSlotValue(slot, signal),
|
|
1856
|
+
isFound: true
|
|
1857
|
+
};
|
|
1858
|
+
return parent.getValue(name, signal);
|
|
1859
|
+
};
|
|
1860
|
+
const setValue = (name, value, signal) => {
|
|
1861
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1862
|
+
setSlotValue(ensureLocalSlot(name, signal), value, signal);
|
|
1863
|
+
};
|
|
1864
|
+
const createFunctionContext = (thisNode, signal) => {
|
|
1865
|
+
const reduceBlock = (nodeOrNodes) => Promise.resolve(reduceBlockImmediate(thisContext, nodeOrNodes, signal));
|
|
1866
|
+
return {
|
|
1867
|
+
thisNode,
|
|
1868
|
+
abortSignal: signal,
|
|
1869
|
+
getValue: (name) => getValue(name, signal),
|
|
1870
|
+
setValue: (name, value) => setValue(name, value, signal),
|
|
1871
|
+
appendWarning: parent.appendWarning,
|
|
1872
|
+
getBoundFunction: parent.getBoundFunction,
|
|
1873
|
+
newScope: () => createScopedReducerContext(thisContext, signal, executor, void 0, void 0),
|
|
1874
|
+
convertToString: parent.convertToString,
|
|
1875
|
+
reduceImmediate: (node) => thisContext.reduceExpressionNodeImmediate(node, signal),
|
|
1876
|
+
reduce: (node) => thisContext.reduceExpressionNode(node, signal),
|
|
1877
|
+
reduceBlockImmediate: (nodeOrNodes) => reduceBlockImmediate(thisContext, nodeOrNodes, signal),
|
|
1878
|
+
reduceBlock
|
|
1879
|
+
};
|
|
1880
|
+
};
|
|
1881
|
+
thisContext = {
|
|
1882
|
+
getValue,
|
|
1883
|
+
setValue,
|
|
1884
|
+
getBoundFunction: parent.getBoundFunction,
|
|
1885
|
+
appendWarning: parent.appendWarning,
|
|
1886
|
+
newScope: (signal) => createScopedReducerContext(thisContext, signal, executor, void 0, void 0),
|
|
1887
|
+
newCallScope: (slotNames, slotValues, signal) => createScopedReducerContext(thisContext, signal, executor, slotNames, slotValues),
|
|
1888
|
+
getSlotVersion,
|
|
1889
|
+
resolveLocalSlot,
|
|
1890
|
+
ensureLocalSlot,
|
|
1891
|
+
getSlotValue,
|
|
1892
|
+
setSlotValue,
|
|
1893
|
+
convertToString: parent.convertToString,
|
|
1894
|
+
reduceExpressionNode: (node, signal) => executor.reduceExpressionNode(thisContext, node, signal),
|
|
1895
|
+
reduceExpressionNodeImmediate: (node, signal) => executor.reduceExpressionNodeImmediate(thisContext, node, signal),
|
|
1896
|
+
reduceNode: (node, signal) => executor.reduceNode(thisContext, node, signal),
|
|
1897
|
+
reduceNodeImmediate: (node, signal) => executor.reduceNodeImmediate(thisContext, node, signal),
|
|
1898
|
+
isConstructable: parent.isConstructable,
|
|
1899
|
+
createFunctionContext
|
|
1900
|
+
};
|
|
1901
|
+
return thisContext;
|
|
1902
|
+
};
|
|
1903
|
+
/**
|
|
1904
|
+
* Create reducer context.
|
|
1905
|
+
* @param variables - Predefined variables
|
|
1906
|
+
* @returns Reducer context
|
|
1907
|
+
*/
|
|
1908
|
+
var createReducerContext = (variables, warningLogs, executor = defaultReducerExecutor) => {
|
|
1909
|
+
let thisSlotIds;
|
|
1910
|
+
let thisSlotValues;
|
|
1911
|
+
let thisSlotVersion = 0;
|
|
1912
|
+
let thisContext;
|
|
1913
|
+
const boundFunctionCache = /* @__PURE__ */ new WeakMap();
|
|
1914
|
+
const getBoundFunction = (owner, fn) => {
|
|
1915
|
+
let ownerCache = boundFunctionCache.get(owner);
|
|
1916
|
+
if (!ownerCache) {
|
|
1917
|
+
ownerCache = /* @__PURE__ */ new WeakMap();
|
|
1918
|
+
boundFunctionCache.set(owner, ownerCache);
|
|
1919
|
+
}
|
|
1920
|
+
const cached = ownerCache.get(fn);
|
|
1921
|
+
if (cached) return cached;
|
|
1922
|
+
const bound = fn.bind(owner);
|
|
1923
|
+
ownerCache.set(fn, bound);
|
|
1924
|
+
return bound;
|
|
1925
|
+
};
|
|
1926
|
+
const constructorCache = /* @__PURE__ */ new WeakMap();
|
|
1927
|
+
const getSlotVersion = () => thisSlotVersion;
|
|
1928
|
+
const resolveLocalSlot = (name, signal) => {
|
|
1929
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1930
|
+
return thisSlotIds === null || thisSlotIds === void 0 ? void 0 : thisSlotIds.get(name);
|
|
1931
|
+
};
|
|
1932
|
+
const ensureLocalSlot = (name, signal) => {
|
|
1933
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1934
|
+
let slot = thisSlotIds === null || thisSlotIds === void 0 ? void 0 : thisSlotIds.get(name);
|
|
1935
|
+
if (slot !== void 0) return slot;
|
|
1936
|
+
if (!thisSlotIds) thisSlotIds = /* @__PURE__ */ new Map();
|
|
1937
|
+
if (!thisSlotValues) thisSlotValues = [];
|
|
1938
|
+
slot = thisSlotValues.length;
|
|
1939
|
+
thisSlotIds.set(name, slot);
|
|
1940
|
+
thisSlotValues.push(void 0);
|
|
1941
|
+
thisSlotVersion++;
|
|
1942
|
+
return slot;
|
|
1943
|
+
};
|
|
1944
|
+
const getSlotValue = (slot, signal) => {
|
|
1945
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1946
|
+
return thisSlotValues === null || thisSlotValues === void 0 ? void 0 : thisSlotValues[slot];
|
|
1947
|
+
};
|
|
1948
|
+
const setSlotValue = (slot, value, signal) => {
|
|
1949
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1950
|
+
if (!thisSlotValues) thisSlotValues = [];
|
|
1951
|
+
thisSlotValues[slot] = value;
|
|
1952
|
+
};
|
|
1953
|
+
const getValue = (name, signal) => {
|
|
1954
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1955
|
+
const slot = resolveLocalSlot(name, signal);
|
|
1956
|
+
if (slot !== void 0) return {
|
|
1957
|
+
value: getSlotValue(slot, signal),
|
|
1958
|
+
isFound: true
|
|
1959
|
+
};
|
|
1960
|
+
if (variables.has(name)) return {
|
|
1961
|
+
value: variables.get(name),
|
|
1962
|
+
isFound: true
|
|
1963
|
+
};
|
|
1964
|
+
return {
|
|
1965
|
+
value: void 0,
|
|
1966
|
+
isFound: false
|
|
1967
|
+
};
|
|
1968
|
+
};
|
|
1969
|
+
const setValue = (name, value, signal) => {
|
|
1970
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
1971
|
+
setSlotValue(ensureLocalSlot(name, signal), value, signal);
|
|
1972
|
+
};
|
|
1973
|
+
const appendWarning = (warning) => {
|
|
1974
|
+
warningLogs.push(warning);
|
|
1975
|
+
};
|
|
1976
|
+
const isConstructable = (fn) => {
|
|
1977
|
+
if (constructorCache.has(fn)) return constructorCache.get(fn);
|
|
1978
|
+
let result = false;
|
|
1979
|
+
try {
|
|
1980
|
+
Reflect.construct(Object, [], fn);
|
|
1981
|
+
result = true;
|
|
1982
|
+
} catch (_unused) {
|
|
1983
|
+
result = false;
|
|
1984
|
+
}
|
|
1985
|
+
constructorCache.set(fn, result);
|
|
1986
|
+
return result;
|
|
1987
|
+
};
|
|
1988
|
+
const getFuncId = internalCreateFunctionIdGenerator();
|
|
1989
|
+
const convertToString = (v) => {
|
|
1990
|
+
return internalConvertToString(v, getFuncId);
|
|
1991
|
+
};
|
|
1992
|
+
const createFunctionContext = (thisNode, signal) => {
|
|
1993
|
+
const reduceBlock = (nodeOrNodes) => Promise.resolve(reduceBlockImmediate(thisContext, nodeOrNodes, signal));
|
|
1994
|
+
return {
|
|
1995
|
+
thisNode,
|
|
1996
|
+
abortSignal: signal,
|
|
1997
|
+
getValue: (name) => getValue(name, signal),
|
|
1998
|
+
setValue: (name, value) => setValue(name, value, signal),
|
|
1999
|
+
appendWarning,
|
|
2000
|
+
getBoundFunction,
|
|
2001
|
+
newScope: () => createScopedReducerContext(thisContext, signal, executor, void 0, void 0),
|
|
2002
|
+
convertToString,
|
|
2003
|
+
reduceImmediate: (node) => thisContext.reduceExpressionNodeImmediate(node, signal),
|
|
2004
|
+
reduce: (node) => thisContext.reduceExpressionNode(node, signal),
|
|
2005
|
+
reduceBlockImmediate: (nodeOrNodes) => reduceBlockImmediate(thisContext, nodeOrNodes, signal),
|
|
2006
|
+
reduceBlock
|
|
2007
|
+
};
|
|
2008
|
+
};
|
|
2009
|
+
thisContext = {
|
|
2010
|
+
getValue,
|
|
2011
|
+
setValue,
|
|
2012
|
+
getBoundFunction,
|
|
2013
|
+
appendWarning,
|
|
2014
|
+
newScope: (signal) => createScopedReducerContext(thisContext, signal, executor, void 0, void 0),
|
|
2015
|
+
newCallScope: (slotNames, slotValues, signal) => createScopedReducerContext(thisContext, signal, executor, slotNames, slotValues),
|
|
2016
|
+
getSlotVersion,
|
|
2017
|
+
resolveLocalSlot,
|
|
2018
|
+
ensureLocalSlot,
|
|
2019
|
+
getSlotValue,
|
|
2020
|
+
setSlotValue,
|
|
2021
|
+
convertToString,
|
|
2022
|
+
reduceExpressionNode: (node, signal) => executor.reduceExpressionNode(thisContext, node, signal),
|
|
2023
|
+
reduceExpressionNodeImmediate: (node, signal) => executor.reduceExpressionNodeImmediate(thisContext, node, signal),
|
|
2024
|
+
reduceNode: (node, signal) => executor.reduceNode(thisContext, node, signal),
|
|
2025
|
+
reduceNodeImmediate: (node, signal) => executor.reduceNodeImmediate(thisContext, node, signal),
|
|
2026
|
+
isConstructable,
|
|
2027
|
+
createFunctionContext
|
|
2028
|
+
};
|
|
2029
|
+
return thisContext;
|
|
2030
|
+
};
|
|
2031
|
+
/**
|
|
2032
|
+
* Run the reducer.
|
|
2033
|
+
* @param nodes - Target nodes
|
|
2034
|
+
* @param variables - Predefined variables
|
|
2035
|
+
* @param logs - Will be stored logs
|
|
2036
|
+
* @param signal - Abort signal
|
|
2037
|
+
* @returns Reduced native values
|
|
2038
|
+
*/
|
|
2039
|
+
async function runReducer(nodes, variables, warningLogs, signal) {
|
|
2040
|
+
const context = createReducerContext(variables, warningLogs);
|
|
2041
|
+
const resultList = [];
|
|
2042
|
+
for (const node of nodes) {
|
|
2043
|
+
const results = await reduceNode(context, node, signal);
|
|
2044
|
+
for (const result of results) if (result !== void 0) resultList.push(result);
|
|
2045
|
+
}
|
|
2046
|
+
return resultList;
|
|
2047
|
+
}
|
|
2048
|
+
//#endregion
|
|
2049
|
+
//#region src/variables/standard-variables.ts
|
|
2050
|
+
var resolveMaybePromise$1 = (value, onResolved) => {
|
|
2051
|
+
if (isPromiseLike(value)) return value.then((resolved) => onResolved(resolved));
|
|
2052
|
+
return onResolved(value);
|
|
2053
|
+
};
|
|
2054
|
+
var _cond = makeFunCityFunction(function(arg0, arg1, arg2) {
|
|
2055
|
+
if (!arg0 || !arg1 || !arg2) throw new FunCityReducerError({
|
|
2056
|
+
type: "error",
|
|
2057
|
+
description: "Required `cond` condition, true and false expressions",
|
|
2058
|
+
range: this.thisNode.range
|
|
2059
|
+
});
|
|
2060
|
+
return resolveMaybePromise$1(this.reduceImmediate(arg0), (cond) => isConditionalTrue(cond) ? this.reduceImmediate(arg1) : this.reduceImmediate(arg2));
|
|
2061
|
+
});
|
|
2062
|
+
var _defaults = makeFunCityFunction(function(arg0, arg1, ...rest) {
|
|
2063
|
+
if (!arg0 || !arg1 || rest.length !== 0) throw new FunCityReducerError({
|
|
2064
|
+
type: "error",
|
|
2065
|
+
description: "Required `defaults` value and default expression",
|
|
2066
|
+
range: this.thisNode.range
|
|
2067
|
+
});
|
|
2068
|
+
return resolveMaybePromise$1(this.reduceImmediate(arg0), (value) => {
|
|
2069
|
+
if (value !== void 0 && value !== null) return value;
|
|
2070
|
+
return this.reduceImmediate(arg1);
|
|
2071
|
+
});
|
|
2072
|
+
});
|
|
2073
|
+
var _set = makeFunCityFunction(function(arg0, arg1, ...rest) {
|
|
2074
|
+
if (!arg0 || !arg1 || rest.length !== 0) throw new FunCityReducerError({
|
|
2075
|
+
type: "error",
|
|
2076
|
+
description: "Required `set` bind identity and expression",
|
|
2077
|
+
range: this.thisNode.range
|
|
2078
|
+
});
|
|
2079
|
+
if (arg0.kind !== "variable") throw new FunCityReducerError({
|
|
2080
|
+
type: "error",
|
|
2081
|
+
description: "Required `set` bind identity",
|
|
2082
|
+
range: arg0.range
|
|
2083
|
+
});
|
|
2084
|
+
return resolveMaybePromise$1(this.reduceImmediate(arg1), (value) => {
|
|
2085
|
+
this.setValue(arg0.name, value);
|
|
2086
|
+
});
|
|
2087
|
+
});
|
|
2088
|
+
var isConstructable = (fn) => {
|
|
2089
|
+
try {
|
|
2090
|
+
Reflect.construct(Object, [], fn);
|
|
2091
|
+
return true;
|
|
2092
|
+
} catch (_unused) {
|
|
2093
|
+
return false;
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
var _new = makeFunCityFunction(function(arg0, ...rest) {
|
|
2097
|
+
if (!arg0) throw new FunCityReducerError({
|
|
2098
|
+
type: "error",
|
|
2099
|
+
description: "Required `new` constructor expression",
|
|
2100
|
+
range: this.thisNode.range
|
|
2101
|
+
});
|
|
2102
|
+
return resolveMaybePromise$1(this.reduceImmediate(arg0), (target) => {
|
|
2103
|
+
if (typeof target !== "function") throw new FunCityReducerError({
|
|
2104
|
+
type: "error",
|
|
2105
|
+
description: "Required `new` constructor function",
|
|
2106
|
+
range: arg0.range
|
|
2107
|
+
});
|
|
2108
|
+
if (!isConstructable(target)) throw new FunCityReducerError({
|
|
2109
|
+
type: "error",
|
|
2110
|
+
description: "Required `new` constructable function",
|
|
2111
|
+
range: arg0.range
|
|
2112
|
+
});
|
|
2113
|
+
return resolveMaybePromise$1(Promise.all(rest.map((arg) => this.reduce(arg))), (args) => Reflect.construct(target, args));
|
|
2114
|
+
});
|
|
2115
|
+
});
|
|
2116
|
+
var extractParameterArguments = (namesNode, _context) => {
|
|
2117
|
+
switch (namesNode.kind) {
|
|
2118
|
+
case "variable": return [namesNode];
|
|
2119
|
+
case "list": {
|
|
2120
|
+
const nameNodes = [];
|
|
2121
|
+
for (const nameNode of namesNode.items) if (nameNode.kind !== "variable") throw new FunCityReducerError({
|
|
2122
|
+
type: "error",
|
|
2123
|
+
description: "Required `fun` parameter identity",
|
|
2124
|
+
range: nameNode.range
|
|
2125
|
+
});
|
|
2126
|
+
else nameNodes.push(nameNode);
|
|
2127
|
+
return nameNodes;
|
|
2128
|
+
}
|
|
2129
|
+
default: throw new FunCityReducerError({
|
|
2130
|
+
type: "error",
|
|
2131
|
+
description: "Required `fun` parameter identity",
|
|
2132
|
+
range: namesNode.range
|
|
2133
|
+
});
|
|
2134
|
+
}
|
|
2135
|
+
};
|
|
2136
|
+
var _fun = makeFunCityFunction(function(arg0, arg1, ...rest) {
|
|
2137
|
+
if (!arg0 || !arg1 || rest.length !== 0) throw new FunCityReducerError({
|
|
2138
|
+
type: "error",
|
|
2139
|
+
description: "Required `fun` parameter identity and expression",
|
|
2140
|
+
range: this.thisNode.range
|
|
2141
|
+
});
|
|
2142
|
+
const nameNodes = extractParameterArguments(arg0, this);
|
|
2143
|
+
if (!nameNodes) return;
|
|
2144
|
+
const bodyNode = arg1;
|
|
2145
|
+
const lambdaRange = this.thisNode.range;
|
|
2146
|
+
const createScope = this.newScope;
|
|
2147
|
+
return (...args) => {
|
|
2148
|
+
if (args.length < nameNodes.length) throw new FunCityReducerError({
|
|
2149
|
+
type: "error",
|
|
2150
|
+
description: `Arguments are not filled: ${args.length} < ${nameNodes.length}`,
|
|
2151
|
+
range: lambdaRange
|
|
2152
|
+
});
|
|
2153
|
+
else if (args.length > nameNodes.length) this.appendWarning({
|
|
2154
|
+
type: "warning",
|
|
2155
|
+
description: `Too many arguments: ${args.length} > ${nameNodes.length}`,
|
|
2156
|
+
range: lambdaRange
|
|
2157
|
+
});
|
|
2158
|
+
const newContext = createScope();
|
|
2159
|
+
for (let index = 0; index < nameNodes.length; index++) newContext.setValue(nameNodes[index].name, args[index], this.abortSignal);
|
|
2160
|
+
return newContext.reduceExpressionNodeImmediate(bodyNode, this.abortSignal);
|
|
2161
|
+
};
|
|
2162
|
+
});
|
|
2163
|
+
var _typeof = (arg0) => {
|
|
2164
|
+
if (arg0 === null) return "null";
|
|
2165
|
+
else if (typeof arg0 === "string") return "string";
|
|
2166
|
+
else if (Array.isArray(arg0)) return "array";
|
|
2167
|
+
else if (asIterable(arg0)) return "iterable";
|
|
2168
|
+
else return typeof arg0;
|
|
2169
|
+
};
|
|
2170
|
+
var _toString = (...args) => {
|
|
2171
|
+
return args.map((arg0) => convertToString(arg0)).join(",");
|
|
2172
|
+
};
|
|
2173
|
+
var _toBoolean = (arg0) => {
|
|
2174
|
+
return isConditionalTrue(arg0);
|
|
2175
|
+
};
|
|
2176
|
+
var _toNumber = (arg0) => {
|
|
2177
|
+
return Number(arg0);
|
|
2178
|
+
};
|
|
2179
|
+
var _toBigInt = (arg0) => {
|
|
2180
|
+
switch (typeof arg0) {
|
|
2181
|
+
case "number":
|
|
2182
|
+
case "bigint":
|
|
2183
|
+
case "string":
|
|
2184
|
+
case "boolean": return BigInt(arg0);
|
|
2185
|
+
default: return BigInt(_toString(arg0));
|
|
2186
|
+
}
|
|
2187
|
+
};
|
|
2188
|
+
var _add = (arg0, ...args) => {
|
|
2189
|
+
return args.reduce((v0, v) => v0 + Number(v), Number(arg0));
|
|
2190
|
+
};
|
|
2191
|
+
var _sub = (arg0, ...args) => {
|
|
2192
|
+
return args.reduce((v0, v) => v0 - Number(v), Number(arg0));
|
|
2193
|
+
};
|
|
2194
|
+
var _mul = (arg0, ...args) => {
|
|
2195
|
+
return args.reduce((v0, v) => v0 * Number(v), Number(arg0));
|
|
2196
|
+
};
|
|
2197
|
+
var _div = (arg0, ...args) => {
|
|
2198
|
+
return args.reduce((v0, v) => v0 / Number(v), Number(arg0));
|
|
2199
|
+
};
|
|
2200
|
+
var _mod = (arg0, ...args) => {
|
|
2201
|
+
return args.reduce((v0, v) => v0 % Number(v), Number(arg0));
|
|
2202
|
+
};
|
|
2203
|
+
var _eq = (arg0, arg1) => {
|
|
2204
|
+
return arg0 === arg1;
|
|
2205
|
+
};
|
|
2206
|
+
var _ne = (arg0, arg1) => {
|
|
2207
|
+
return arg0 !== arg1;
|
|
2208
|
+
};
|
|
2209
|
+
var _lt = (arg0, arg1) => {
|
|
2210
|
+
return arg0 < arg1;
|
|
2211
|
+
};
|
|
2212
|
+
var _gt = (arg0, arg1) => {
|
|
2213
|
+
return arg0 > arg1;
|
|
2214
|
+
};
|
|
2215
|
+
var _le = (arg0, arg1) => {
|
|
2216
|
+
return arg0 <= arg1;
|
|
2217
|
+
};
|
|
2218
|
+
var _ge = (arg0, arg1) => {
|
|
2219
|
+
return arg0 >= arg1;
|
|
2220
|
+
};
|
|
2221
|
+
var _now = () => {
|
|
2222
|
+
return /* @__PURE__ */ new Date();
|
|
2223
|
+
};
|
|
2224
|
+
var _random = makeFunCityFunction(function(arg0, arg1, ...rest) {
|
|
2225
|
+
if (!arg0 || rest.length !== 0) throw new FunCityReducerError({
|
|
2226
|
+
type: "error",
|
|
2227
|
+
description: "Required `random` range arguments",
|
|
2228
|
+
range: this.thisNode.range
|
|
2229
|
+
});
|
|
2230
|
+
return resolveMaybePromise$1(this.reduceImmediate(arg0), (baseValue) => {
|
|
2231
|
+
return resolveMaybePromise$1(arg1 ? this.reduceImmediate(arg1) : baseValue, (resolvedSpanValue) => {
|
|
2232
|
+
const base = arg1 ? Number(baseValue) : 0;
|
|
2233
|
+
const span = Number(resolvedSpanValue);
|
|
2234
|
+
return base + Math.floor(Math.random() * span);
|
|
2235
|
+
});
|
|
2236
|
+
});
|
|
2237
|
+
});
|
|
2238
|
+
var _randomf = (arg0, arg1) => {
|
|
2239
|
+
if (arg0 === void 0) return Math.random();
|
|
2240
|
+
const base = arg1 === void 0 ? 0 : Number(arg0);
|
|
2241
|
+
const span = Number(arg1 !== null && arg1 !== void 0 ? arg1 : arg0);
|
|
2242
|
+
return base + Math.random() * span;
|
|
2243
|
+
};
|
|
2244
|
+
var concatInner = (sep, args) => {
|
|
2245
|
+
let v = "";
|
|
2246
|
+
let f = true;
|
|
2247
|
+
for (const arg of args) {
|
|
2248
|
+
let as;
|
|
2249
|
+
if (typeof arg === "string") as = arg;
|
|
2250
|
+
else {
|
|
2251
|
+
const iterable = asIterable(arg);
|
|
2252
|
+
if (iterable) as = concatInner(sep, iterable);
|
|
2253
|
+
else as = convertToString(arg);
|
|
2254
|
+
}
|
|
2255
|
+
if (f) {
|
|
2256
|
+
v = v + as;
|
|
2257
|
+
f = false;
|
|
2258
|
+
} else v = v + sep + as;
|
|
2259
|
+
}
|
|
2260
|
+
return v;
|
|
2261
|
+
};
|
|
2262
|
+
var _concat = (...args) => {
|
|
2263
|
+
return concatInner("", args);
|
|
2264
|
+
};
|
|
2265
|
+
var _join = (arg0, ...args) => {
|
|
2266
|
+
return concatInner(convertToString(arg0), args);
|
|
2267
|
+
};
|
|
2268
|
+
var _trim = (arg0) => {
|
|
2269
|
+
let v = arg0;
|
|
2270
|
+
if (v === void 0 || v === null) v = "";
|
|
2271
|
+
else if (typeof v !== "string") {
|
|
2272
|
+
var _v$toString;
|
|
2273
|
+
v = (_v$toString = v.toString()) !== null && _v$toString !== void 0 ? _v$toString : "";
|
|
2274
|
+
}
|
|
2275
|
+
return v.trim();
|
|
2276
|
+
};
|
|
2277
|
+
var _toUpper = (arg0) => {
|
|
2278
|
+
let v = arg0;
|
|
2279
|
+
if (typeof v !== "string") {
|
|
2280
|
+
var _v$toString2;
|
|
2281
|
+
v = (_v$toString2 = v.toString()) !== null && _v$toString2 !== void 0 ? _v$toString2 : "";
|
|
2282
|
+
}
|
|
2283
|
+
return v.toUpperCase();
|
|
2284
|
+
};
|
|
2285
|
+
var _toLower = (arg0) => {
|
|
2286
|
+
let v = arg0;
|
|
2287
|
+
if (typeof v !== "string") {
|
|
2288
|
+
var _v$toString3;
|
|
2289
|
+
v = (_v$toString3 = v.toString()) !== null && _v$toString3 !== void 0 ? _v$toString3 : "";
|
|
2290
|
+
}
|
|
2291
|
+
return v.toLowerCase();
|
|
2292
|
+
};
|
|
2293
|
+
var _length = (arg0) => {
|
|
2294
|
+
if (arg0) {
|
|
2295
|
+
if (typeof arg0 === "string") return arg0.length;
|
|
2296
|
+
else if (Array.isArray(arg0)) return arg0.length;
|
|
2297
|
+
else if (asIterable(arg0)) {
|
|
2298
|
+
let count = 0;
|
|
2299
|
+
for (const _item of arg0) count++;
|
|
2300
|
+
return count;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
return 0;
|
|
2304
|
+
};
|
|
2305
|
+
var _and = makeFunCityFunction(function(...args) {
|
|
2306
|
+
if (args.length === 0) throw new FunCityReducerError({
|
|
2307
|
+
type: "error",
|
|
2308
|
+
description: "empty arguments",
|
|
2309
|
+
range: this.thisNode.range
|
|
2310
|
+
});
|
|
2311
|
+
for (let index = 0; index < args.length; index++) {
|
|
2312
|
+
const value = this.reduceImmediate(args[index]);
|
|
2313
|
+
if (isPromiseLike(value)) return (async () => {
|
|
2314
|
+
if (!isConditionalTrue(await value)) return false;
|
|
2315
|
+
for (let continueIndex = index + 1; continueIndex < args.length; continueIndex++) if (!isConditionalTrue(await this.reduceImmediate(args[continueIndex]))) return false;
|
|
2316
|
+
return true;
|
|
2317
|
+
})();
|
|
2318
|
+
if (!isConditionalTrue(value)) return false;
|
|
2319
|
+
}
|
|
2320
|
+
return true;
|
|
2321
|
+
});
|
|
2322
|
+
var _or = makeFunCityFunction(function(...args) {
|
|
2323
|
+
if (args.length === 0) throw new FunCityReducerError({
|
|
2324
|
+
type: "error",
|
|
2325
|
+
description: "empty arguments",
|
|
2326
|
+
range: this.thisNode.range
|
|
2327
|
+
});
|
|
2328
|
+
for (let index = 0; index < args.length; index++) {
|
|
2329
|
+
const value = this.reduceImmediate(args[index]);
|
|
2330
|
+
if (isPromiseLike(value)) return (async () => {
|
|
2331
|
+
if (isConditionalTrue(await value)) return true;
|
|
2332
|
+
for (let continueIndex = index + 1; continueIndex < args.length; continueIndex++) if (isConditionalTrue(await this.reduceImmediate(args[continueIndex]))) return true;
|
|
2333
|
+
return false;
|
|
2334
|
+
})();
|
|
2335
|
+
if (isConditionalTrue(value)) return true;
|
|
2336
|
+
}
|
|
2337
|
+
return false;
|
|
2338
|
+
});
|
|
2339
|
+
var _not = (arg0) => {
|
|
2340
|
+
return !isConditionalTrue(arg0);
|
|
2341
|
+
};
|
|
2342
|
+
var _at = (arg0, arg1) => {
|
|
2343
|
+
const index = Number(arg0);
|
|
2344
|
+
if (arg1) if (typeof arg1 === "string") return arg1[index];
|
|
2345
|
+
else if (Array.isArray(arg1)) return arg1[index];
|
|
2346
|
+
else {
|
|
2347
|
+
const iterable = asIterable(arg1);
|
|
2348
|
+
if (iterable) {
|
|
2349
|
+
let current = 0;
|
|
2350
|
+
for (const item of iterable) {
|
|
2351
|
+
if (current >= index) return item;
|
|
2352
|
+
current++;
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
};
|
|
2357
|
+
var _first = (arg0) => {
|
|
2358
|
+
if (arg0) if (typeof arg0 === "string") return arg0[0];
|
|
2359
|
+
else if (Array.isArray(arg0)) return arg0[0];
|
|
2360
|
+
else {
|
|
2361
|
+
const iterable = asIterable(arg0);
|
|
2362
|
+
if (iterable) for (const item of iterable) return item;
|
|
2363
|
+
}
|
|
2364
|
+
};
|
|
2365
|
+
var _last = (arg0) => {
|
|
2366
|
+
if (arg0) if (typeof arg0 === "string") return arg0[arg0.length - 1];
|
|
2367
|
+
else if (Array.isArray(arg0)) return arg0[arg0.length - 1];
|
|
2368
|
+
else {
|
|
2369
|
+
const iterable = asIterable(arg0);
|
|
2370
|
+
if (iterable) {
|
|
2371
|
+
let lastItem = void 0;
|
|
2372
|
+
for (const item of iterable) lastItem = item;
|
|
2373
|
+
return lastItem;
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
var _range = (arg0, arg1) => {
|
|
2378
|
+
let value = Number(arg0);
|
|
2379
|
+
const count = Number(arg1);
|
|
2380
|
+
const resultList = [];
|
|
2381
|
+
for (let index = 0; index < count; index++) resultList.push(value++);
|
|
2382
|
+
return resultList;
|
|
2383
|
+
};
|
|
2384
|
+
var sliceIterable = (iter, start, end) => {
|
|
2385
|
+
const resultList = [];
|
|
2386
|
+
for (const item of iter) resultList.push(item);
|
|
2387
|
+
return resultList.slice(start, end);
|
|
2388
|
+
};
|
|
2389
|
+
var _slice = (arg0, arg1, arg2) => {
|
|
2390
|
+
const start = arg0 === void 0 ? void 0 : Number(arg0);
|
|
2391
|
+
if (arg2 === void 0) {
|
|
2392
|
+
if (typeof arg1 === "string") return arg1.slice(start);
|
|
2393
|
+
return sliceIterable(arg1, start, void 0);
|
|
2394
|
+
}
|
|
2395
|
+
const end = arg1 === void 0 ? void 0 : Number(arg1);
|
|
2396
|
+
if (typeof arg2 === "string") return arg2.slice(start, end);
|
|
2397
|
+
return sliceIterable(arg2, start, end);
|
|
2398
|
+
};
|
|
2399
|
+
var _reverse = (arg0) => {
|
|
2400
|
+
const iter = arg0;
|
|
2401
|
+
let resultList = [];
|
|
2402
|
+
for (const item of iter) resultList.push(item);
|
|
2403
|
+
return resultList.reverse();
|
|
2404
|
+
};
|
|
2405
|
+
var _sort = (arg0) => {
|
|
2406
|
+
const iter = arg0;
|
|
2407
|
+
let resultList = [];
|
|
2408
|
+
for (const item of iter) resultList.push(item);
|
|
2409
|
+
return resultList.sort();
|
|
2410
|
+
};
|
|
2411
|
+
var _map = async (arg0, arg1) => {
|
|
2412
|
+
const predicate = arg0;
|
|
2413
|
+
const iter = arg1;
|
|
2414
|
+
const resultList = [];
|
|
2415
|
+
for (const item of iter) {
|
|
2416
|
+
const result = await predicate(item);
|
|
2417
|
+
resultList.push(result);
|
|
2418
|
+
}
|
|
2419
|
+
return resultList;
|
|
2420
|
+
};
|
|
2421
|
+
var _flatMap = async (arg0, arg1) => {
|
|
2422
|
+
const predicate = arg0;
|
|
2423
|
+
const iter = arg1;
|
|
2424
|
+
const resultList = [];
|
|
2425
|
+
for (const item of iter) {
|
|
2426
|
+
const results = await predicate(item);
|
|
2427
|
+
resultList.push(...results);
|
|
2428
|
+
}
|
|
2429
|
+
return resultList;
|
|
2430
|
+
};
|
|
2431
|
+
var _flatten = (arg0) => {
|
|
2432
|
+
const iter = arg0;
|
|
2433
|
+
const resultList = [];
|
|
2434
|
+
for (const item of iter) {
|
|
2435
|
+
const iterable = asIterable(item);
|
|
2436
|
+
if (!iterable) throw new TypeError("flatten requires nested iterable items");
|
|
2437
|
+
resultList.push(...iterable);
|
|
2438
|
+
}
|
|
2439
|
+
return resultList;
|
|
2440
|
+
};
|
|
2441
|
+
var _filter = async (arg0, arg1) => {
|
|
2442
|
+
const predicate = arg0;
|
|
2443
|
+
const iter = arg1;
|
|
2444
|
+
const resultList = [];
|
|
2445
|
+
for (const item of iter) if (isConditionalTrue(await predicate(item))) resultList.push(item);
|
|
2446
|
+
return resultList;
|
|
2447
|
+
};
|
|
2448
|
+
var _collect = (arg0) => {
|
|
2449
|
+
const iter = arg0;
|
|
2450
|
+
const resultList = [];
|
|
2451
|
+
for (const item of iter) if (item !== void 0 && item !== null) resultList.push(item);
|
|
2452
|
+
return resultList;
|
|
2453
|
+
};
|
|
2454
|
+
var _distinct = (arg0) => {
|
|
2455
|
+
const iter = arg0;
|
|
2456
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2457
|
+
const resultList = [];
|
|
2458
|
+
for (const item of iter) if (!seen.has(item)) {
|
|
2459
|
+
seen.add(item);
|
|
2460
|
+
resultList.push(item);
|
|
2461
|
+
}
|
|
2462
|
+
return resultList;
|
|
2463
|
+
};
|
|
2464
|
+
var _distinctBy = async (arg0, arg1) => {
|
|
2465
|
+
const selector = arg0;
|
|
2466
|
+
const iter = arg1;
|
|
2467
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2468
|
+
const resultList = [];
|
|
2469
|
+
for (const item of iter) {
|
|
2470
|
+
const key = await selector(item);
|
|
2471
|
+
if (!seen.has(key)) {
|
|
2472
|
+
seen.add(key);
|
|
2473
|
+
resultList.push(item);
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
return resultList;
|
|
2477
|
+
};
|
|
2478
|
+
var _union = (arg0, arg1) => {
|
|
2479
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2480
|
+
const union = arg0.union;
|
|
2481
|
+
if (typeof union === "function") return Array.from(union.call(arg0, arg1));
|
|
2482
|
+
}
|
|
2483
|
+
const resultList = [];
|
|
2484
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2485
|
+
for (const item of arg0) if (!seen.has(item)) {
|
|
2486
|
+
seen.add(item);
|
|
2487
|
+
resultList.push(item);
|
|
2488
|
+
}
|
|
2489
|
+
for (const item of arg1) if (!seen.has(item)) {
|
|
2490
|
+
seen.add(item);
|
|
2491
|
+
resultList.push(item);
|
|
2492
|
+
}
|
|
2493
|
+
return resultList;
|
|
2494
|
+
};
|
|
2495
|
+
var _unionBy = async (arg0, arg1, arg2) => {
|
|
2496
|
+
const selector = arg0;
|
|
2497
|
+
const iterA = arg1;
|
|
2498
|
+
const iterB = arg2;
|
|
2499
|
+
const resultList = [];
|
|
2500
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2501
|
+
for (const item of iterA) {
|
|
2502
|
+
const key = await selector(item);
|
|
2503
|
+
if (!seen.has(key)) {
|
|
2504
|
+
seen.add(key);
|
|
2505
|
+
resultList.push(item);
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
for (const item of iterB) {
|
|
2509
|
+
const key = await selector(item);
|
|
2510
|
+
if (!seen.has(key)) {
|
|
2511
|
+
seen.add(key);
|
|
2512
|
+
resultList.push(item);
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
return resultList;
|
|
2516
|
+
};
|
|
2517
|
+
var _intersection = (arg0, arg1) => {
|
|
2518
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2519
|
+
const intersection = arg0.intersection;
|
|
2520
|
+
if (typeof intersection === "function") return Array.from(intersection.call(arg0, arg1));
|
|
2521
|
+
}
|
|
2522
|
+
const iterA = arg0;
|
|
2523
|
+
const setB = new Set(arg1);
|
|
2524
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2525
|
+
const resultList = [];
|
|
2526
|
+
for (const item of iterA) if (!seen.has(item) && setB.has(item)) {
|
|
2527
|
+
seen.add(item);
|
|
2528
|
+
resultList.push(item);
|
|
2529
|
+
}
|
|
2530
|
+
return resultList;
|
|
2531
|
+
};
|
|
2532
|
+
var _intersectionBy = async (arg0, arg1, arg2) => {
|
|
2533
|
+
const selector = arg0;
|
|
2534
|
+
const iterA = arg1;
|
|
2535
|
+
const iterB = arg2;
|
|
2536
|
+
const keysB = /* @__PURE__ */ new Set();
|
|
2537
|
+
for (const item of iterB) {
|
|
2538
|
+
const key = await selector(item);
|
|
2539
|
+
keysB.add(key);
|
|
2540
|
+
}
|
|
2541
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2542
|
+
const resultList = [];
|
|
2543
|
+
for (const item of iterA) {
|
|
2544
|
+
const key = await selector(item);
|
|
2545
|
+
if (!seen.has(key) && keysB.has(key)) {
|
|
2546
|
+
seen.add(key);
|
|
2547
|
+
resultList.push(item);
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
return resultList;
|
|
2551
|
+
};
|
|
2552
|
+
var _difference = (arg0, arg1) => {
|
|
2553
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2554
|
+
const difference = arg0.difference;
|
|
2555
|
+
if (typeof difference === "function") return Array.from(difference.call(arg0, arg1));
|
|
2556
|
+
}
|
|
2557
|
+
const iterA = arg0;
|
|
2558
|
+
const setB = new Set(arg1);
|
|
2559
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2560
|
+
const resultList = [];
|
|
2561
|
+
for (const item of iterA) if (!seen.has(item) && !setB.has(item)) {
|
|
2562
|
+
seen.add(item);
|
|
2563
|
+
resultList.push(item);
|
|
2564
|
+
}
|
|
2565
|
+
return resultList;
|
|
2566
|
+
};
|
|
2567
|
+
var _differenceBy = async (arg0, arg1, arg2) => {
|
|
2568
|
+
const selector = arg0;
|
|
2569
|
+
const iterA = arg1;
|
|
2570
|
+
const iterB = arg2;
|
|
2571
|
+
const keysB = /* @__PURE__ */ new Set();
|
|
2572
|
+
for (const item of iterB) {
|
|
2573
|
+
const key = await selector(item);
|
|
2574
|
+
keysB.add(key);
|
|
2575
|
+
}
|
|
2576
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2577
|
+
const resultList = [];
|
|
2578
|
+
for (const item of iterA) {
|
|
2579
|
+
const key = await selector(item);
|
|
2580
|
+
if (!seen.has(key) && !keysB.has(key)) {
|
|
2581
|
+
seen.add(key);
|
|
2582
|
+
resultList.push(item);
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
return resultList;
|
|
2586
|
+
};
|
|
2587
|
+
var _symmetricDifference = (arg0, arg1) => {
|
|
2588
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2589
|
+
const symmetricDifference = arg0.symmetricDifference;
|
|
2590
|
+
if (typeof symmetricDifference === "function") return Array.from(symmetricDifference.call(arg0, arg1));
|
|
2591
|
+
}
|
|
2592
|
+
const iterA = arg0;
|
|
2593
|
+
const iterB = arg1;
|
|
2594
|
+
const itemsA = [];
|
|
2595
|
+
const itemsB = [];
|
|
2596
|
+
const setA = /* @__PURE__ */ new Set();
|
|
2597
|
+
const setB = /* @__PURE__ */ new Set();
|
|
2598
|
+
for (const item of iterA) if (!setA.has(item)) {
|
|
2599
|
+
setA.add(item);
|
|
2600
|
+
itemsA.push(item);
|
|
2601
|
+
}
|
|
2602
|
+
for (const item of iterB) if (!setB.has(item)) {
|
|
2603
|
+
setB.add(item);
|
|
2604
|
+
itemsB.push(item);
|
|
2605
|
+
}
|
|
2606
|
+
const resultList = [];
|
|
2607
|
+
for (const item of itemsA) if (!setB.has(item)) resultList.push(item);
|
|
2608
|
+
for (const item of itemsB) if (!setA.has(item)) resultList.push(item);
|
|
2609
|
+
return resultList;
|
|
2610
|
+
};
|
|
2611
|
+
var _symmetricDifferenceBy = async (arg0, arg1, arg2) => {
|
|
2612
|
+
const selector = arg0;
|
|
2613
|
+
const iterA = arg1;
|
|
2614
|
+
const iterB = arg2;
|
|
2615
|
+
const keysA = /* @__PURE__ */ new Set();
|
|
2616
|
+
const keysB = /* @__PURE__ */ new Set();
|
|
2617
|
+
const itemsA = [];
|
|
2618
|
+
const itemsB = [];
|
|
2619
|
+
for (const item of iterA) {
|
|
2620
|
+
const key = await selector(item);
|
|
2621
|
+
if (!keysA.has(key)) {
|
|
2622
|
+
keysA.add(key);
|
|
2623
|
+
itemsA.push({
|
|
2624
|
+
key,
|
|
2625
|
+
item
|
|
2626
|
+
});
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
for (const item of iterB) {
|
|
2630
|
+
const key = await selector(item);
|
|
2631
|
+
if (!keysB.has(key)) {
|
|
2632
|
+
keysB.add(key);
|
|
2633
|
+
itemsB.push({
|
|
2634
|
+
key,
|
|
2635
|
+
item
|
|
2636
|
+
});
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
const resultList = [];
|
|
2640
|
+
for (const entry of itemsA) if (!keysB.has(entry.key)) resultList.push(entry.item);
|
|
2641
|
+
for (const entry of itemsB) if (!keysA.has(entry.key)) resultList.push(entry.item);
|
|
2642
|
+
return resultList;
|
|
2643
|
+
};
|
|
2644
|
+
var _isSubsetOf = (arg0, arg1) => {
|
|
2645
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2646
|
+
const isSubsetOf = arg0.isSubsetOf;
|
|
2647
|
+
if (typeof isSubsetOf === "function") return isSubsetOf.call(arg0, arg1);
|
|
2648
|
+
}
|
|
2649
|
+
const iterA = arg0;
|
|
2650
|
+
const setB = new Set(arg1);
|
|
2651
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2652
|
+
for (const item of iterA) {
|
|
2653
|
+
if (seen.has(item)) continue;
|
|
2654
|
+
seen.add(item);
|
|
2655
|
+
if (!setB.has(item)) return false;
|
|
2656
|
+
}
|
|
2657
|
+
return true;
|
|
2658
|
+
};
|
|
2659
|
+
var _isSubsetOfBy = async (arg0, arg1, arg2) => {
|
|
2660
|
+
const selector = arg0;
|
|
2661
|
+
const iterA = arg1;
|
|
2662
|
+
const iterB = arg2;
|
|
2663
|
+
const keysB = /* @__PURE__ */ new Set();
|
|
2664
|
+
for (const item of iterB) {
|
|
2665
|
+
const key = await selector(item);
|
|
2666
|
+
keysB.add(key);
|
|
2667
|
+
}
|
|
2668
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2669
|
+
for (const item of iterA) {
|
|
2670
|
+
const key = await selector(item);
|
|
2671
|
+
if (seen.has(key)) continue;
|
|
2672
|
+
seen.add(key);
|
|
2673
|
+
if (!keysB.has(key)) return false;
|
|
2674
|
+
}
|
|
2675
|
+
return true;
|
|
2676
|
+
};
|
|
2677
|
+
var _isSupersetOf = (arg0, arg1) => {
|
|
2678
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2679
|
+
const isSupersetOf = arg0.isSupersetOf;
|
|
2680
|
+
if (typeof isSupersetOf === "function") return isSupersetOf.call(arg0, arg1);
|
|
2681
|
+
}
|
|
2682
|
+
const setA = new Set(arg0);
|
|
2683
|
+
for (const item of arg1) if (!setA.has(item)) return false;
|
|
2684
|
+
return true;
|
|
2685
|
+
};
|
|
2686
|
+
var _isSupersetOfBy = async (arg0, arg1, arg2) => {
|
|
2687
|
+
const selector = arg0;
|
|
2688
|
+
const iterA = arg1;
|
|
2689
|
+
const iterB = arg2;
|
|
2690
|
+
const keysA = /* @__PURE__ */ new Set();
|
|
2691
|
+
for (const item of iterA) {
|
|
2692
|
+
const key = await selector(item);
|
|
2693
|
+
keysA.add(key);
|
|
2694
|
+
}
|
|
2695
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2696
|
+
for (const item of iterB) {
|
|
2697
|
+
const key = await selector(item);
|
|
2698
|
+
if (seen.has(key)) continue;
|
|
2699
|
+
seen.add(key);
|
|
2700
|
+
if (!keysA.has(key)) return false;
|
|
2701
|
+
}
|
|
2702
|
+
return true;
|
|
2703
|
+
};
|
|
2704
|
+
var _isDisjointFrom = (arg0, arg1) => {
|
|
2705
|
+
if (arg0 instanceof Set && arg1 instanceof Set) {
|
|
2706
|
+
const isDisjointFrom = arg0.isDisjointFrom;
|
|
2707
|
+
if (typeof isDisjointFrom === "function") return isDisjointFrom.call(arg0, arg1);
|
|
2708
|
+
}
|
|
2709
|
+
const setB = new Set(arg1);
|
|
2710
|
+
for (const item of arg0) if (setB.has(item)) return false;
|
|
2711
|
+
return true;
|
|
2712
|
+
};
|
|
2713
|
+
var _isDisjointFromBy = async (arg0, arg1, arg2) => {
|
|
2714
|
+
const selector = arg0;
|
|
2715
|
+
const iterA = arg1;
|
|
2716
|
+
const iterB = arg2;
|
|
2717
|
+
const keysB = /* @__PURE__ */ new Set();
|
|
2718
|
+
for (const item of iterB) {
|
|
2719
|
+
const key = await selector(item);
|
|
2720
|
+
keysB.add(key);
|
|
2721
|
+
}
|
|
2722
|
+
for (const item of iterA) {
|
|
2723
|
+
const key = await selector(item);
|
|
2724
|
+
if (keysB.has(key)) return false;
|
|
2725
|
+
}
|
|
2726
|
+
return true;
|
|
2727
|
+
};
|
|
2728
|
+
var _reduce = async (arg0, arg1, arg2) => {
|
|
2729
|
+
let acc = arg0;
|
|
2730
|
+
const predicate = arg1;
|
|
2731
|
+
const iter = arg2;
|
|
2732
|
+
for (const item of iter) acc = await predicate(acc, item);
|
|
2733
|
+
return acc;
|
|
2734
|
+
};
|
|
2735
|
+
var _match = (arg0, arg1) => {
|
|
2736
|
+
const re = arg0 instanceof RegExp ? arg0 : new RegExp(convertToString(arg0), "g");
|
|
2737
|
+
return convertToString(arg1).match(re);
|
|
2738
|
+
};
|
|
2739
|
+
var _replace = (arg0, arg1, arg2) => {
|
|
2740
|
+
const re = arg0 instanceof RegExp ? arg0 : new RegExp(convertToString(arg0), "g");
|
|
2741
|
+
const replace = convertToString(arg1);
|
|
2742
|
+
return convertToString(arg2).replace(re, replace);
|
|
2743
|
+
};
|
|
2744
|
+
var _regex = (arg0, arg1) => {
|
|
2745
|
+
if (arg1) return new RegExp(convertToString(arg0), convertToString(arg1));
|
|
2746
|
+
else return new RegExp(convertToString(arg0));
|
|
2747
|
+
};
|
|
2748
|
+
var _bind = (arg0, ...args) => {
|
|
2749
|
+
return arg0.bind(void 0, ...args);
|
|
2750
|
+
};
|
|
2751
|
+
var _url = (arg0, arg1) => {
|
|
2752
|
+
return new URL(convertToString(arg0), arg1 !== void 0 ? convertToString(arg1) : void 0);
|
|
2753
|
+
};
|
|
2754
|
+
var _delay = async function(ms, value) {
|
|
2755
|
+
const delayMs = Number(ms);
|
|
2756
|
+
const signal = this.abortSignal;
|
|
2757
|
+
if (!signal) return await new Promise((resolve) => {
|
|
2758
|
+
setTimeout(resolve, delayMs, value);
|
|
2759
|
+
});
|
|
2760
|
+
signal.throwIfAborted();
|
|
2761
|
+
return await new Promise((resolve, reject) => {
|
|
2762
|
+
let timer;
|
|
2763
|
+
const cleanup = () => {
|
|
2764
|
+
if (timer !== void 0) {
|
|
2765
|
+
clearTimeout(timer);
|
|
2766
|
+
timer = void 0;
|
|
2767
|
+
}
|
|
2768
|
+
signal.removeEventListener("abort", onAbort);
|
|
2769
|
+
};
|
|
2770
|
+
const onAbort = () => {
|
|
2771
|
+
cleanup();
|
|
2772
|
+
try {
|
|
2773
|
+
signal.throwIfAborted();
|
|
2774
|
+
} catch (error) {
|
|
2775
|
+
reject(error);
|
|
2776
|
+
return;
|
|
2777
|
+
}
|
|
2778
|
+
const abortError = /* @__PURE__ */ new Error("Aborted");
|
|
2779
|
+
abortError.name = "AbortError";
|
|
2780
|
+
reject(abortError);
|
|
2781
|
+
};
|
|
2782
|
+
timer = setTimeout(() => {
|
|
2783
|
+
if (signal.aborted) {
|
|
2784
|
+
onAbort();
|
|
2785
|
+
return;
|
|
2786
|
+
}
|
|
2787
|
+
cleanup();
|
|
2788
|
+
resolve(value);
|
|
2789
|
+
}, delayMs);
|
|
2790
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2791
|
+
});
|
|
2792
|
+
};
|
|
2793
|
+
var createIncludeFunction = (options) => {
|
|
2794
|
+
const { resolve, logs, mode = "template", scope = "child", includeMissing = "error", tryIncludeMissing = "empty" } = options;
|
|
2795
|
+
let compileCacheModulePromise;
|
|
2796
|
+
const getCompileCacheModule = async () => {
|
|
2797
|
+
var _compileCacheModulePr;
|
|
2798
|
+
(_compileCacheModulePr = compileCacheModulePromise) !== null && _compileCacheModulePr !== void 0 || (compileCacheModulePromise = Promise.resolve().then(() => compile_cache_exports));
|
|
2799
|
+
return await compileCacheModulePromise;
|
|
2800
|
+
};
|
|
2801
|
+
const parseScript = async (script, sourceId) => {
|
|
2802
|
+
const { compileScriptCached } = await getCompileCacheModule();
|
|
2803
|
+
return compileScriptCached(script, sourceId, mode, "reducer");
|
|
2804
|
+
};
|
|
2805
|
+
const resolveSource = async (request, context) => {
|
|
2806
|
+
const resolved = await resolve(request, context);
|
|
2807
|
+
if (resolved === void 0 || resolved === null) return;
|
|
2808
|
+
if (typeof resolved === "string") return {
|
|
2809
|
+
sourceId: request,
|
|
2810
|
+
script: resolved
|
|
2811
|
+
};
|
|
2812
|
+
return resolved;
|
|
2813
|
+
};
|
|
2814
|
+
const normalizeIncludeStack = (includeStack, sourceId) => includeStack[includeStack.length - 1] === sourceId ? includeStack : [...includeStack, sourceId];
|
|
2815
|
+
const throwPrimaryParseError = (parseLogs) => {
|
|
2816
|
+
let primaryError;
|
|
2817
|
+
for (const entry of parseLogs) if (entry.type === "error" && primaryError === void 0) primaryError = entry;
|
|
2818
|
+
else logs.push(entry);
|
|
2819
|
+
if ((primaryError === null || primaryError === void 0 ? void 0 : primaryError.type) === "error") throw new FunCityReducerError(primaryError);
|
|
2820
|
+
};
|
|
2821
|
+
const withSameScopeIncludeFunctions = async (context, includeFunctions, run) => {
|
|
2822
|
+
const previousInclude = context.getValue("include");
|
|
2823
|
+
const previousTryInclude = context.getValue("tryInclude");
|
|
2824
|
+
context.setValue("include", includeFunctions.include);
|
|
2825
|
+
context.setValue("tryInclude", includeFunctions.tryInclude);
|
|
2826
|
+
try {
|
|
2827
|
+
return await run();
|
|
2828
|
+
} finally {
|
|
2829
|
+
if (previousInclude.isFound) context.setValue("include", previousInclude.value);
|
|
2830
|
+
if (previousTryInclude.isFound) context.setValue("tryInclude", previousTryInclude.value);
|
|
2831
|
+
}
|
|
2832
|
+
};
|
|
2833
|
+
const installIncludeFunctions = (context, includeFunctions, signal) => {
|
|
2834
|
+
context.setValue("include", includeFunctions.include, signal);
|
|
2835
|
+
context.setValue("tryInclude", includeFunctions.tryInclude, signal);
|
|
2836
|
+
};
|
|
2837
|
+
const reduceWithScope = async (context, nodes, includeFunctions) => {
|
|
2838
|
+
if (scope === "same") return await withSameScopeIncludeFunctions(context, includeFunctions, () => context.reduceBlock(nodes));
|
|
2839
|
+
const scopedContext = context.newScope();
|
|
2840
|
+
installIncludeFunctions(scopedContext, includeFunctions, context.abortSignal);
|
|
2841
|
+
const resultList = [];
|
|
2842
|
+
for (const node of nodes) {
|
|
2843
|
+
const results = await scopedContext.reduceNode(node, context.abortSignal);
|
|
2844
|
+
for (const result of results) if (result !== void 0) resultList.push(result);
|
|
2845
|
+
}
|
|
2846
|
+
return resultList;
|
|
2847
|
+
};
|
|
2848
|
+
const createIncludeFunctions = (includeStack) => {
|
|
2849
|
+
const renderIncluded = async (context, arg0, missingBehavior) => {
|
|
2850
|
+
if (!arg0) throw new FunCityReducerError({
|
|
2851
|
+
type: "error",
|
|
2852
|
+
description: "Required `include` target",
|
|
2853
|
+
range: context.thisNode.range
|
|
2854
|
+
});
|
|
2855
|
+
const resolvedArg = await context.reduce(arg0);
|
|
2856
|
+
if (resolvedArg === void 0 || resolvedArg === null) {
|
|
2857
|
+
if (missingBehavior === "empty") return "";
|
|
2858
|
+
throw new FunCityReducerError({
|
|
2859
|
+
type: "error",
|
|
2860
|
+
description: "Required `include` target",
|
|
2861
|
+
range: context.thisNode.range
|
|
2862
|
+
});
|
|
2863
|
+
}
|
|
2864
|
+
const request = String(resolvedArg);
|
|
2865
|
+
const activeIncludeStack = normalizeIncludeStack(includeStack, context.thisNode.range.sourceId);
|
|
2866
|
+
const source = await resolveSource(request, {
|
|
2867
|
+
sourceId: context.thisNode.range.sourceId,
|
|
2868
|
+
range: context.thisNode.range,
|
|
2869
|
+
signal: context.abortSignal
|
|
2870
|
+
});
|
|
2871
|
+
if (!source) {
|
|
2872
|
+
if (missingBehavior === "empty") return "";
|
|
2873
|
+
throw new FunCityReducerError({
|
|
2874
|
+
type: "error",
|
|
2875
|
+
description: `Include source not found: ${request}`,
|
|
2876
|
+
range: context.thisNode.range
|
|
2877
|
+
});
|
|
2878
|
+
}
|
|
2879
|
+
if (activeIncludeStack.includes(source.sourceId)) throw new FunCityReducerError({
|
|
2880
|
+
type: "error",
|
|
2881
|
+
description: `circular include detected: ${source.sourceId}`,
|
|
2882
|
+
range: context.thisNode.range
|
|
2883
|
+
});
|
|
2884
|
+
const parsed = await parseScript(source.script, source.sourceId);
|
|
2885
|
+
if (parsed.logs.length > 0) throwPrimaryParseError(parsed.logs);
|
|
2886
|
+
const nestedIncludeFunctions = createIncludeFunctions([...activeIncludeStack, source.sourceId]);
|
|
2887
|
+
return (await reduceWithScope(context, parsed.nodes, nestedIncludeFunctions)).map((value) => context.convertToString(value)).join("");
|
|
2888
|
+
};
|
|
2889
|
+
return {
|
|
2890
|
+
include: makeFunCityFunction(async function(arg0) {
|
|
2891
|
+
return await renderIncluded(this, arg0, includeMissing);
|
|
2892
|
+
}),
|
|
2893
|
+
tryInclude: makeFunCityFunction(async function(arg0) {
|
|
2894
|
+
return await renderIncluded(this, arg0, tryIncludeMissing);
|
|
2895
|
+
})
|
|
2896
|
+
};
|
|
2897
|
+
};
|
|
2898
|
+
return createIncludeFunctions([]);
|
|
2899
|
+
};
|
|
2900
|
+
/**
|
|
2901
|
+
* Built-in standard variables and functions.
|
|
2902
|
+
*/
|
|
2903
|
+
var standardVariables = Object.freeze({
|
|
2904
|
+
undefined: void 0,
|
|
2905
|
+
null: null,
|
|
2906
|
+
true: true,
|
|
2907
|
+
false: false,
|
|
2908
|
+
cond: _cond,
|
|
2909
|
+
defaults: _defaults,
|
|
2910
|
+
set: _set,
|
|
2911
|
+
new: _new,
|
|
2912
|
+
fun: _fun,
|
|
2913
|
+
toString: _toString,
|
|
2914
|
+
toBoolean: _toBoolean,
|
|
2915
|
+
toNumber: _toNumber,
|
|
2916
|
+
toBigInt: _toBigInt,
|
|
2917
|
+
typeof: _typeof,
|
|
2918
|
+
add: _add,
|
|
2919
|
+
sub: _sub,
|
|
2920
|
+
mul: _mul,
|
|
2921
|
+
div: _div,
|
|
2922
|
+
mod: _mod,
|
|
2923
|
+
eq: _eq,
|
|
2924
|
+
ne: _ne,
|
|
2925
|
+
lt: _lt,
|
|
2926
|
+
gt: _gt,
|
|
2927
|
+
le: _le,
|
|
2928
|
+
ge: _ge,
|
|
2929
|
+
now: _now,
|
|
2930
|
+
random: _random,
|
|
2931
|
+
randomf: _randomf,
|
|
2932
|
+
concat: _concat,
|
|
2933
|
+
join: _join,
|
|
2934
|
+
trim: _trim,
|
|
2935
|
+
toUpper: _toUpper,
|
|
2936
|
+
toLower: _toLower,
|
|
2937
|
+
length: _length,
|
|
2938
|
+
and: _and,
|
|
2939
|
+
or: _or,
|
|
2940
|
+
not: _not,
|
|
2941
|
+
at: _at,
|
|
2942
|
+
first: _first,
|
|
2943
|
+
last: _last,
|
|
2944
|
+
range: _range,
|
|
2945
|
+
slice: _slice,
|
|
2946
|
+
sort: _sort,
|
|
2947
|
+
reverse: _reverse,
|
|
2948
|
+
map: _map,
|
|
2949
|
+
flatMap: _flatMap,
|
|
2950
|
+
flatten: _flatten,
|
|
2951
|
+
filter: _filter,
|
|
2952
|
+
collect: _collect,
|
|
2953
|
+
distinct: _distinct,
|
|
2954
|
+
distinctBy: _distinctBy,
|
|
2955
|
+
union: _union,
|
|
2956
|
+
unionBy: _unionBy,
|
|
2957
|
+
intersection: _intersection,
|
|
2958
|
+
intersectionBy: _intersectionBy,
|
|
2959
|
+
difference: _difference,
|
|
2960
|
+
differenceBy: _differenceBy,
|
|
2961
|
+
symmetricDifference: _symmetricDifference,
|
|
2962
|
+
symmetricDifferenceBy: _symmetricDifferenceBy,
|
|
2963
|
+
isSubsetOf: _isSubsetOf,
|
|
2964
|
+
isSubsetOfBy: _isSubsetOfBy,
|
|
2965
|
+
isSupersetOf: _isSupersetOf,
|
|
2966
|
+
isSupersetOfBy: _isSupersetOfBy,
|
|
2967
|
+
isDisjointFrom: _isDisjointFrom,
|
|
2968
|
+
isDisjointFromBy: _isDisjointFromBy,
|
|
2969
|
+
reduce: _reduce,
|
|
2970
|
+
match: _match,
|
|
2971
|
+
replace: _replace,
|
|
2972
|
+
regex: _regex,
|
|
2973
|
+
bind: _bind,
|
|
2974
|
+
url: _url,
|
|
2975
|
+
delay: _delay,
|
|
2976
|
+
console
|
|
2977
|
+
});
|
|
2978
|
+
/**
|
|
2979
|
+
* Build a variable map that includes standard variables.
|
|
2980
|
+
* @param variablesList - Additional variable sources.
|
|
2981
|
+
* @returns Combined variable map.
|
|
2982
|
+
*/
|
|
2983
|
+
var buildCandidateVariables = (...variablesList) => {
|
|
2984
|
+
return combineVariables(standardVariables, ...variablesList);
|
|
2985
|
+
};
|
|
2986
|
+
//#endregion
|
|
2987
|
+
//#region src/dcodegen.ts
|
|
2988
|
+
var throwError = (info) => {
|
|
2989
|
+
throw new FunCityReducerError({
|
|
2990
|
+
type: "error",
|
|
2991
|
+
...info
|
|
2992
|
+
});
|
|
2993
|
+
};
|
|
2994
|
+
var deconstructConditionalCombine = (name) => {
|
|
2995
|
+
if (name.length >= 1) {
|
|
2996
|
+
if (name[name.length - 1] === "?") return {
|
|
2997
|
+
name: name.substring(0, name.length - 1),
|
|
2998
|
+
canIgnore: true
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
return {
|
|
3002
|
+
name,
|
|
3003
|
+
canIgnore: false
|
|
3004
|
+
};
|
|
3005
|
+
};
|
|
3006
|
+
var extractLambdaParameterNames = (node) => {
|
|
3007
|
+
switch (node.kind) {
|
|
3008
|
+
case "variable": return [node.name];
|
|
3009
|
+
case "list": {
|
|
3010
|
+
const names = [];
|
|
3011
|
+
for (const item of node.items) {
|
|
3012
|
+
if (item.kind !== "variable") return;
|
|
3013
|
+
names.push(item.name);
|
|
3014
|
+
}
|
|
3015
|
+
return names;
|
|
3016
|
+
}
|
|
3017
|
+
default: return;
|
|
3018
|
+
}
|
|
3019
|
+
};
|
|
3020
|
+
var resolveVariable = (context, result, range, signal) => {
|
|
3021
|
+
const valueResult = context.getValue(result.name, signal);
|
|
3022
|
+
if (!valueResult.isFound) {
|
|
3023
|
+
if (!result.canIgnore) throwError({
|
|
3024
|
+
description: `variable is not bound: ${result.name}`,
|
|
3025
|
+
range
|
|
3026
|
+
});
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
return valueResult.value;
|
|
3030
|
+
};
|
|
3031
|
+
var filterUndefined = (results) => results.filter((result) => result !== void 0);
|
|
3032
|
+
var resolveMaybePromise = (value, onResolved) => {
|
|
3033
|
+
if (isPromiseLike(value)) return value.then((resolved) => onResolved(resolved));
|
|
3034
|
+
return onResolved(value);
|
|
3035
|
+
};
|
|
3036
|
+
var specializableStandardCallTargets = Object.freeze({
|
|
3037
|
+
toString: standardVariables.toString,
|
|
3038
|
+
toBoolean: standardVariables.toBoolean,
|
|
3039
|
+
toNumber: standardVariables.toNumber,
|
|
3040
|
+
toBigInt: standardVariables.toBigInt,
|
|
3041
|
+
typeof: standardVariables.typeof,
|
|
3042
|
+
add: standardVariables.add,
|
|
3043
|
+
sub: standardVariables.sub,
|
|
3044
|
+
mul: standardVariables.mul,
|
|
3045
|
+
div: standardVariables.div,
|
|
3046
|
+
mod: standardVariables.mod,
|
|
3047
|
+
eq: standardVariables.eq,
|
|
3048
|
+
ne: standardVariables.ne,
|
|
3049
|
+
lt: standardVariables.lt,
|
|
3050
|
+
gt: standardVariables.gt,
|
|
3051
|
+
le: standardVariables.le,
|
|
3052
|
+
ge: standardVariables.ge,
|
|
3053
|
+
now: standardVariables.now,
|
|
3054
|
+
randomf: standardVariables.randomf,
|
|
3055
|
+
concat: standardVariables.concat,
|
|
3056
|
+
join: standardVariables.join,
|
|
3057
|
+
trim: standardVariables.trim,
|
|
3058
|
+
toUpper: standardVariables.toUpper,
|
|
3059
|
+
toLower: standardVariables.toLower,
|
|
3060
|
+
length: standardVariables.length,
|
|
3061
|
+
not: standardVariables.not,
|
|
3062
|
+
at: standardVariables.at,
|
|
3063
|
+
first: standardVariables.first,
|
|
3064
|
+
last: standardVariables.last,
|
|
3065
|
+
range: standardVariables.range,
|
|
3066
|
+
slice: standardVariables.slice,
|
|
3067
|
+
sort: standardVariables.sort,
|
|
3068
|
+
reverse: standardVariables.reverse,
|
|
3069
|
+
map: standardVariables.map,
|
|
3070
|
+
flatMap: standardVariables.flatMap,
|
|
3071
|
+
flatten: standardVariables.flatten,
|
|
3072
|
+
filter: standardVariables.filter,
|
|
3073
|
+
collect: standardVariables.collect,
|
|
3074
|
+
distinct: standardVariables.distinct,
|
|
3075
|
+
distinctBy: standardVariables.distinctBy,
|
|
3076
|
+
union: standardVariables.union,
|
|
3077
|
+
unionBy: standardVariables.unionBy,
|
|
3078
|
+
intersection: standardVariables.intersection,
|
|
3079
|
+
intersectionBy: standardVariables.intersectionBy,
|
|
3080
|
+
difference: standardVariables.difference,
|
|
3081
|
+
differenceBy: standardVariables.differenceBy,
|
|
3082
|
+
symmetricDifference: standardVariables.symmetricDifference,
|
|
3083
|
+
symmetricDifferenceBy: standardVariables.symmetricDifferenceBy,
|
|
3084
|
+
isSubsetOf: standardVariables.isSubsetOf,
|
|
3085
|
+
isSubsetOfBy: standardVariables.isSubsetOfBy,
|
|
3086
|
+
isSupersetOf: standardVariables.isSupersetOf,
|
|
3087
|
+
isSupersetOfBy: standardVariables.isSupersetOfBy,
|
|
3088
|
+
isDisjointFrom: standardVariables.isDisjointFrom,
|
|
3089
|
+
isDisjointFromBy: standardVariables.isDisjointFromBy,
|
|
3090
|
+
reduce: standardVariables.reduce,
|
|
3091
|
+
match: standardVariables.match,
|
|
3092
|
+
replace: standardVariables.replace,
|
|
3093
|
+
regex: standardVariables.regex,
|
|
3094
|
+
bind: standardVariables.bind,
|
|
3095
|
+
url: standardVariables.url
|
|
3096
|
+
});
|
|
3097
|
+
var toSpecializableStandardCallTarget = (name) => {
|
|
3098
|
+
return specializableStandardCallTargets[name];
|
|
3099
|
+
};
|
|
3100
|
+
var AsyncFunction = Object.getPrototypeOf(async () => {}).constructor;
|
|
3101
|
+
var createRawBlockRunnerImmediate = (generators) => {
|
|
3102
|
+
return (context, signal) => {
|
|
3103
|
+
const resultList = [];
|
|
3104
|
+
for (let index = 0; index < generators.length; index++) {
|
|
3105
|
+
const results = generators[index](context, signal);
|
|
3106
|
+
if (isPromiseLike(results)) return (async () => {
|
|
3107
|
+
resultList.push(...await results);
|
|
3108
|
+
for (let continueIndex = index + 1; continueIndex < generators.length; continueIndex++) resultList.push(...await generators[continueIndex](context, signal));
|
|
3109
|
+
return resultList;
|
|
3110
|
+
})();
|
|
3111
|
+
resultList.push(...results);
|
|
3112
|
+
}
|
|
3113
|
+
return resultList;
|
|
3114
|
+
};
|
|
3115
|
+
};
|
|
3116
|
+
var createTextBlockRunnerImmediate = (generators) => {
|
|
3117
|
+
return (context, signal) => {
|
|
3118
|
+
let result = "";
|
|
3119
|
+
for (let index = 0; index < generators.length; index++) {
|
|
3120
|
+
const text = generators[index](context, signal);
|
|
3121
|
+
if (isPromiseLike(text)) return (async () => {
|
|
3122
|
+
result += await text;
|
|
3123
|
+
for (let continueIndex = index + 1; continueIndex < generators.length; continueIndex++) result += await generators[continueIndex](context, signal);
|
|
3124
|
+
return result;
|
|
3125
|
+
})();
|
|
3126
|
+
result += text;
|
|
3127
|
+
}
|
|
3128
|
+
return result;
|
|
3129
|
+
};
|
|
3130
|
+
};
|
|
3131
|
+
var collectExpressionValues = (generators, context, signal) => {
|
|
3132
|
+
const resultList = [];
|
|
3133
|
+
for (let index = 0; index < generators.length; index++) {
|
|
3134
|
+
const result = generators[index](context, signal);
|
|
3135
|
+
if (isPromiseLike(result)) return (async () => {
|
|
3136
|
+
resultList.push(await result);
|
|
3137
|
+
for (let continueIndex = index + 1; continueIndex < generators.length; continueIndex++) resultList.push(await generators[continueIndex](context, signal));
|
|
3138
|
+
return resultList;
|
|
3139
|
+
})();
|
|
3140
|
+
resultList.push(result);
|
|
3141
|
+
}
|
|
3142
|
+
return resultList;
|
|
3143
|
+
};
|
|
3144
|
+
var handleApplyError = (node, error) => {
|
|
3145
|
+
if (error instanceof FunCityReducerError) throw error;
|
|
3146
|
+
if (error instanceof Error && error.name === "AbortError") throw error;
|
|
3147
|
+
throw new FunCityReducerError({
|
|
3148
|
+
type: "error",
|
|
3149
|
+
description: fromError(error),
|
|
3150
|
+
range: node.range
|
|
3151
|
+
});
|
|
3152
|
+
};
|
|
3153
|
+
var resolveSourceVariable = (context, name, canIgnore, range, signal) => {
|
|
3154
|
+
const valueResult = context.getValue(name, signal);
|
|
3155
|
+
if (!valueResult.isFound) {
|
|
3156
|
+
if (!canIgnore) throwError({
|
|
3157
|
+
description: `variable is not bound: ${name}`,
|
|
3158
|
+
range
|
|
3159
|
+
});
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
return valueResult.value;
|
|
3163
|
+
};
|
|
3164
|
+
var resolveSourceDotSegments = (context, baseValue, segments) => {
|
|
3165
|
+
let value = baseValue;
|
|
3166
|
+
let parent;
|
|
3167
|
+
for (const segment of segments) {
|
|
3168
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
3169
|
+
const record = value;
|
|
3170
|
+
parent = value;
|
|
3171
|
+
value = record[segment.name];
|
|
3172
|
+
continue;
|
|
3173
|
+
}
|
|
3174
|
+
if (!segment.canIgnore) throwError({
|
|
3175
|
+
description: `variable is not bound: ${segment.name}`,
|
|
3176
|
+
range: segment.range
|
|
3177
|
+
});
|
|
3178
|
+
return;
|
|
3179
|
+
}
|
|
3180
|
+
if (parent && typeof value === "function" && !isFunCityFunction(value)) return context.getBoundFunction(parent, value);
|
|
3181
|
+
return value;
|
|
3182
|
+
};
|
|
3183
|
+
var invokeSourceCallable = async (context, node, signal, callable, args, _isSpecial) => {
|
|
3184
|
+
try {
|
|
3185
|
+
const thisProxy = context.createFunctionContext(node, signal);
|
|
3186
|
+
return await callable.call(thisProxy, ...args);
|
|
3187
|
+
} catch (error) {
|
|
3188
|
+
return handleApplyError(node, error);
|
|
3189
|
+
}
|
|
3190
|
+
};
|
|
3191
|
+
var invokeSourceBuiltin = async (node, builtin, args) => {
|
|
3192
|
+
try {
|
|
3193
|
+
return await builtin(...args);
|
|
3194
|
+
} catch (error) {
|
|
3195
|
+
return handleApplyError(node, error);
|
|
3196
|
+
}
|
|
3197
|
+
};
|
|
3198
|
+
/**
|
|
3199
|
+
* Create a dynamic code generator.
|
|
3200
|
+
* @returns Dynamic code generator instance.
|
|
3201
|
+
*/
|
|
3202
|
+
var createClosureDCodegen = () => {
|
|
3203
|
+
const expressionImmediateCache = /* @__PURE__ */ new WeakMap();
|
|
3204
|
+
const expressionCache = /* @__PURE__ */ new WeakMap();
|
|
3205
|
+
const blockImmediateCache = /* @__PURE__ */ new WeakMap();
|
|
3206
|
+
const blockCache = /* @__PURE__ */ new WeakMap();
|
|
3207
|
+
const rawProgramImmediateCache = /* @__PURE__ */ new WeakMap();
|
|
3208
|
+
const textBlockImmediateCache = /* @__PURE__ */ new WeakMap();
|
|
3209
|
+
const textProgramImmediateCache = /* @__PURE__ */ new WeakMap();
|
|
3210
|
+
const textProgramCache = /* @__PURE__ */ new WeakMap();
|
|
3211
|
+
const programImmediateCache = /* @__PURE__ */ new WeakMap();
|
|
3212
|
+
const programCache = /* @__PURE__ */ new WeakMap();
|
|
3213
|
+
const generateRawProgramImmediate = (nodes) => {
|
|
3214
|
+
const cached = rawProgramImmediateCache.get(nodes);
|
|
3215
|
+
if (cached) return cached;
|
|
3216
|
+
const generator = createRawBlockRunnerImmediate(nodes.map(generateBlockImmediate));
|
|
3217
|
+
rawProgramImmediateCache.set(nodes, generator);
|
|
3218
|
+
return generator;
|
|
3219
|
+
};
|
|
3220
|
+
const generateTextProgramImmediate = (nodes) => {
|
|
3221
|
+
const cached = textProgramImmediateCache.get(nodes);
|
|
3222
|
+
if (cached) return cached;
|
|
3223
|
+
const generator = createTextBlockRunnerImmediate(nodes.map(generateTextBlockImmediate));
|
|
3224
|
+
textProgramImmediateCache.set(nodes, generator);
|
|
3225
|
+
return generator;
|
|
3226
|
+
};
|
|
3227
|
+
const resolveDotNode = (context, node, signal, compiledBase, baseResult) => {
|
|
3228
|
+
var _node$segments$0$opti, _node$segments$;
|
|
3229
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
3230
|
+
const firstSegmentOptional = (_node$segments$0$opti = (_node$segments$ = node.segments[0]) === null || _node$segments$ === void 0 ? void 0 : _node$segments$.optional) !== null && _node$segments$0$opti !== void 0 ? _node$segments$0$opti : false;
|
|
3231
|
+
const resolveSegments = (baseValue) => {
|
|
3232
|
+
let value = baseValue;
|
|
3233
|
+
let parent;
|
|
3234
|
+
for (const segment of node.segments) {
|
|
3235
|
+
const result = deconstructConditionalCombine(segment.name);
|
|
3236
|
+
const isOptional = segment.optional || result.canIgnore;
|
|
3237
|
+
if (value !== null && (typeof value === "object" || typeof value === "function")) {
|
|
3238
|
+
const record = value;
|
|
3239
|
+
parent = value;
|
|
3240
|
+
value = record[result.name];
|
|
3241
|
+
} else {
|
|
3242
|
+
if (!isOptional) throwError({
|
|
3243
|
+
description: `variable is not bound: ${result.name}`,
|
|
3244
|
+
range: segment.range
|
|
3245
|
+
});
|
|
3246
|
+
return;
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
if (parent && typeof value === "function" && !isFunCityFunction(value)) return context.getBoundFunction(parent, value);
|
|
3250
|
+
return value;
|
|
3251
|
+
};
|
|
3252
|
+
if (baseResult) {
|
|
3253
|
+
const valueResult = context.getValue(baseResult.name, signal);
|
|
3254
|
+
if (!valueResult.isFound) {
|
|
3255
|
+
if (!baseResult.canIgnore && !firstSegmentOptional) throwError({
|
|
3256
|
+
description: `variable is not bound: ${baseResult.name}`,
|
|
3257
|
+
range: node.base.range
|
|
3258
|
+
});
|
|
3259
|
+
return;
|
|
3260
|
+
}
|
|
3261
|
+
return resolveSegments(valueResult.value);
|
|
3262
|
+
}
|
|
3263
|
+
if (!compiledBase) return;
|
|
3264
|
+
return resolveMaybePromise(compiledBase(context, signal), resolveSegments);
|
|
3265
|
+
};
|
|
3266
|
+
const applyResolvedFunction = (context, node, signal, callable, compiledArgs) => {
|
|
3267
|
+
const resolvedArgs = isFunCityFunction(callable) ? node.args : collectExpressionValues(compiledArgs, context, signal);
|
|
3268
|
+
const invokeCallable = (args) => {
|
|
3269
|
+
try {
|
|
3270
|
+
const thisProxy = context.createFunctionContext(node, signal);
|
|
3271
|
+
return callable.call(thisProxy, ...args);
|
|
3272
|
+
} catch (error) {
|
|
3273
|
+
handleApplyError(node, error);
|
|
3274
|
+
}
|
|
3275
|
+
};
|
|
3276
|
+
const result = resolveMaybePromise(resolvedArgs, (args) => invokeCallable(args));
|
|
3277
|
+
if (isPromiseLike(result)) return result.catch((error) => handleApplyError(node, error));
|
|
3278
|
+
return result;
|
|
3279
|
+
};
|
|
3280
|
+
const applySpecializedStandardFunction = (context, node, signal, builtin, compiledArgs) => {
|
|
3281
|
+
const invokeBuiltin = (args) => {
|
|
3282
|
+
try {
|
|
3283
|
+
return builtin(...args);
|
|
3284
|
+
} catch (error) {
|
|
3285
|
+
handleApplyError(node, error);
|
|
3286
|
+
}
|
|
3287
|
+
};
|
|
3288
|
+
const result = resolveMaybePromise(collectExpressionValues(compiledArgs, context, signal), (args) => invokeBuiltin(args));
|
|
3289
|
+
if (isPromiseLike(result)) return result.catch((error) => handleApplyError(node, error));
|
|
3290
|
+
return result;
|
|
3291
|
+
};
|
|
3292
|
+
const applyFunction = (context, node, signal, compiledFunc, compiledArgs) => {
|
|
3293
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
3294
|
+
return resolveMaybePromise(compiledFunc(context, signal), (func) => {
|
|
3295
|
+
if (typeof func !== "function") throwError({
|
|
3296
|
+
description: "could not apply it for function",
|
|
3297
|
+
range: node.range
|
|
3298
|
+
});
|
|
3299
|
+
return applyResolvedFunction(context, node, signal, func, compiledArgs);
|
|
3300
|
+
});
|
|
3301
|
+
};
|
|
3302
|
+
const generateExpressionImmediate = (node) => {
|
|
3303
|
+
const cached = expressionImmediateCache.get(node);
|
|
3304
|
+
if (cached) return cached;
|
|
3305
|
+
let generator;
|
|
3306
|
+
switch (node.kind) {
|
|
3307
|
+
case "number":
|
|
3308
|
+
case "string":
|
|
3309
|
+
generator = () => node.value;
|
|
3310
|
+
break;
|
|
3311
|
+
case "template": {
|
|
3312
|
+
const generatedText = generateTextProgramImmediate(node.blocks);
|
|
3313
|
+
generator = (context, signal) => generatedText(context, signal);
|
|
3314
|
+
break;
|
|
3315
|
+
}
|
|
3316
|
+
case "variable": {
|
|
3317
|
+
const variableResult = deconstructConditionalCombine(node.name);
|
|
3318
|
+
generator = (context, signal) => resolveVariable(context, variableResult, node.range, signal);
|
|
3319
|
+
break;
|
|
3320
|
+
}
|
|
3321
|
+
case "dot": {
|
|
3322
|
+
const compiledBase = node.base.kind === "variable" ? void 0 : generateExpressionImmediate(node.base);
|
|
3323
|
+
const baseResult = node.base.kind === "variable" ? deconstructConditionalCombine(node.base.name) : void 0;
|
|
3324
|
+
generator = (context, signal) => resolveDotNode(context, node, signal, compiledBase, baseResult);
|
|
3325
|
+
break;
|
|
3326
|
+
}
|
|
3327
|
+
case "apply": {
|
|
3328
|
+
const compiledFunc = generateExpressionImmediate(node.func);
|
|
3329
|
+
const compiledArgs = node.args.map(generateExpressionImmediate);
|
|
3330
|
+
const isIntrinsicCond = node.func.kind === "variable" && node.func.name === "cond" && node.args.length === 3;
|
|
3331
|
+
const intrinsicFunParameters = node.func.kind === "variable" && node.func.name === "fun" && node.args.length === 2 ? extractLambdaParameterNames(node.args[0]) : void 0;
|
|
3332
|
+
const intrinsicFunBody = intrinsicFunParameters !== void 0 ? node.args[1] : void 0;
|
|
3333
|
+
const compiledIntrinsicFunBody = intrinsicFunBody !== void 0 ? generateExpressionImmediate(intrinsicFunBody) : void 0;
|
|
3334
|
+
const specializedBuiltinName = node.func.kind === "variable" ? node.func.name : void 0;
|
|
3335
|
+
const specializedBuiltin = specializedBuiltinName !== void 0 ? toSpecializableStandardCallTarget(specializedBuiltinName) : void 0;
|
|
3336
|
+
if (isIntrinsicCond) {
|
|
3337
|
+
generator = (context, signal) => {
|
|
3338
|
+
const boundFunction = context.getValue("cond", signal);
|
|
3339
|
+
if (boundFunction.isFound && boundFunction.value === standardVariables.cond) return resolveMaybePromise(compiledArgs[0](context, signal), (condition) => isConditionalTrue(condition) ? compiledArgs[1](context, signal) : compiledArgs[2](context, signal));
|
|
3340
|
+
return applyFunction(context, node, signal, compiledFunc, compiledArgs);
|
|
3341
|
+
};
|
|
3342
|
+
break;
|
|
3343
|
+
}
|
|
3344
|
+
if (compiledIntrinsicFunBody !== void 0 && intrinsicFunParameters !== void 0) {
|
|
3345
|
+
generator = (context, signal) => {
|
|
3346
|
+
const boundFunction = context.getValue("fun", signal);
|
|
3347
|
+
if (boundFunction.isFound && boundFunction.value === standardVariables.fun) return (...args) => {
|
|
3348
|
+
if (args.length < intrinsicFunParameters.length) throwError({
|
|
3349
|
+
description: `Arguments are not filled: ${args.length} < ${intrinsicFunParameters.length}`,
|
|
3350
|
+
range: node.range
|
|
3351
|
+
});
|
|
3352
|
+
if (args.length > intrinsicFunParameters.length) context.appendWarning({
|
|
3353
|
+
type: "warning",
|
|
3354
|
+
description: `Too many arguments: ${args.length} > ${intrinsicFunParameters.length}`,
|
|
3355
|
+
range: node.range
|
|
3356
|
+
});
|
|
3357
|
+
return compiledIntrinsicFunBody(context.newCallScope(intrinsicFunParameters, args, signal), signal);
|
|
3358
|
+
};
|
|
3359
|
+
if (specializedBuiltin === void 0) return applyFunction(context, node, signal, compiledFunc, compiledArgs);
|
|
3360
|
+
const specializedFunction = context.getValue(specializedBuiltinName, signal);
|
|
3361
|
+
if (specializedFunction.isFound && specializedFunction.value === specializedBuiltin) return applySpecializedStandardFunction(context, node, signal, specializedBuiltin, compiledArgs);
|
|
3362
|
+
return applyFunction(context, node, signal, compiledFunc, compiledArgs);
|
|
3363
|
+
};
|
|
3364
|
+
break;
|
|
3365
|
+
}
|
|
3366
|
+
if (specializedBuiltin === void 0) {
|
|
3367
|
+
generator = (context, signal) => applyFunction(context, node, signal, compiledFunc, compiledArgs);
|
|
3368
|
+
break;
|
|
3369
|
+
}
|
|
3370
|
+
generator = (context, signal) => {
|
|
3371
|
+
const boundFunction = context.getValue(specializedBuiltinName, signal);
|
|
3372
|
+
if (boundFunction.isFound && boundFunction.value === specializedBuiltin) return applySpecializedStandardFunction(context, node, signal, specializedBuiltin, compiledArgs);
|
|
3373
|
+
return applyFunction(context, node, signal, compiledFunc, compiledArgs);
|
|
3374
|
+
};
|
|
3375
|
+
break;
|
|
3376
|
+
}
|
|
3377
|
+
case "list": {
|
|
3378
|
+
const compiledItems = node.items.map(generateExpressionImmediate);
|
|
3379
|
+
generator = (context, signal) => collectExpressionValues(compiledItems, context, signal);
|
|
3380
|
+
break;
|
|
3381
|
+
}
|
|
3382
|
+
case "scope": {
|
|
3383
|
+
const compiledNodes = node.nodes.map(generateExpressionImmediate);
|
|
3384
|
+
generator = (context, signal) => {
|
|
3385
|
+
if (compiledNodes.length === 0) return [];
|
|
3386
|
+
let result = void 0;
|
|
3387
|
+
for (let index = 0; index < compiledNodes.length; index++) {
|
|
3388
|
+
const current = compiledNodes[index](context, signal);
|
|
3389
|
+
if (isPromiseLike(current)) return (async () => {
|
|
3390
|
+
result = await current;
|
|
3391
|
+
for (let continueIndex = index + 1; continueIndex < compiledNodes.length; continueIndex++) result = await compiledNodes[continueIndex](context, signal);
|
|
3392
|
+
return result;
|
|
3393
|
+
})();
|
|
3394
|
+
result = current;
|
|
3395
|
+
}
|
|
3396
|
+
return result;
|
|
3397
|
+
};
|
|
3398
|
+
break;
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
expressionImmediateCache.set(node, generator);
|
|
3402
|
+
return generator;
|
|
3403
|
+
};
|
|
3404
|
+
const generateExpression = (node) => {
|
|
3405
|
+
const cached = expressionCache.get(node);
|
|
3406
|
+
if (cached) return cached;
|
|
3407
|
+
const immediate = generateExpressionImmediate(node);
|
|
3408
|
+
const generator = (context, signal) => Promise.resolve(immediate(context, signal));
|
|
3409
|
+
expressionCache.set(node, generator);
|
|
3410
|
+
return generator;
|
|
3411
|
+
};
|
|
3412
|
+
const generateBlockImmediate = (node) => {
|
|
3413
|
+
const cached = blockImmediateCache.get(node);
|
|
3414
|
+
if (cached) return cached;
|
|
3415
|
+
let generator;
|
|
3416
|
+
switch (node.kind) {
|
|
3417
|
+
case "text":
|
|
3418
|
+
generator = () => [node.text];
|
|
3419
|
+
break;
|
|
3420
|
+
case "for": {
|
|
3421
|
+
const iterableGenerator = generateExpressionImmediate(node.iterable);
|
|
3422
|
+
const repeatGenerator = generateRawProgramImmediate(node.repeat);
|
|
3423
|
+
generator = (context, signal) => resolveMaybePromise(iterableGenerator(context, signal), (result) => {
|
|
3424
|
+
const iterable = asIterable(result);
|
|
3425
|
+
if (!iterable) throwError({
|
|
3426
|
+
description: "could not apply it for function",
|
|
3427
|
+
range: node.range
|
|
3428
|
+
});
|
|
3429
|
+
const resolvedIterable = iterable;
|
|
3430
|
+
const resultList = [];
|
|
3431
|
+
const iterator = resolvedIterable[Symbol.iterator]();
|
|
3432
|
+
for (let current = iterator.next(); !current.done; current = iterator.next()) {
|
|
3433
|
+
context.setValue(node.bind.name, current.value, signal);
|
|
3434
|
+
const repeated = repeatGenerator(context, signal);
|
|
3435
|
+
if (isPromiseLike(repeated)) return (async () => {
|
|
3436
|
+
resultList.push(...await repeated);
|
|
3437
|
+
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
3438
|
+
context.setValue(node.bind.name, next.value, signal);
|
|
3439
|
+
resultList.push(...await repeatGenerator(context, signal));
|
|
3440
|
+
}
|
|
3441
|
+
return resultList;
|
|
3442
|
+
})();
|
|
3443
|
+
resultList.push(...repeated);
|
|
3444
|
+
}
|
|
3445
|
+
return resultList;
|
|
3446
|
+
});
|
|
3447
|
+
break;
|
|
3448
|
+
}
|
|
3449
|
+
case "while": {
|
|
3450
|
+
const conditionGenerator = generateExpressionImmediate(node.condition);
|
|
3451
|
+
const repeatGenerator = generateRawProgramImmediate(node.repeat);
|
|
3452
|
+
generator = (context, signal) => {
|
|
3453
|
+
const resultList = [];
|
|
3454
|
+
while (true) {
|
|
3455
|
+
const condition = conditionGenerator(context, signal);
|
|
3456
|
+
if (isPromiseLike(condition)) return (async () => {
|
|
3457
|
+
let currentCondition = await condition;
|
|
3458
|
+
while (isConditionalTrue(currentCondition)) {
|
|
3459
|
+
resultList.push(...await repeatGenerator(context, signal));
|
|
3460
|
+
currentCondition = await conditionGenerator(context, signal);
|
|
3461
|
+
}
|
|
3462
|
+
return resultList;
|
|
3463
|
+
})();
|
|
3464
|
+
if (!isConditionalTrue(condition)) return resultList;
|
|
3465
|
+
const repeated = repeatGenerator(context, signal);
|
|
3466
|
+
if (isPromiseLike(repeated)) return (async () => {
|
|
3467
|
+
resultList.push(...await repeated);
|
|
3468
|
+
while (true) {
|
|
3469
|
+
if (!isConditionalTrue(await conditionGenerator(context, signal))) break;
|
|
3470
|
+
resultList.push(...await repeatGenerator(context, signal));
|
|
3471
|
+
}
|
|
3472
|
+
return resultList;
|
|
3473
|
+
})();
|
|
3474
|
+
resultList.push(...repeated);
|
|
3475
|
+
}
|
|
3476
|
+
};
|
|
3477
|
+
break;
|
|
3478
|
+
}
|
|
3479
|
+
case "if": {
|
|
3480
|
+
const conditionGenerator = generateExpressionImmediate(node.condition);
|
|
3481
|
+
const thenGenerator = generateRawProgramImmediate(node.then);
|
|
3482
|
+
const elseGenerator = generateRawProgramImmediate(node.else);
|
|
3483
|
+
generator = (context, signal) => resolveMaybePromise(conditionGenerator(context, signal), (condition) => isConditionalTrue(condition) ? thenGenerator(context, signal) : elseGenerator(context, signal));
|
|
3484
|
+
break;
|
|
3485
|
+
}
|
|
3486
|
+
default: {
|
|
3487
|
+
const expressionGenerator = generateExpressionImmediate(node);
|
|
3488
|
+
generator = (context, signal) => resolveMaybePromise(expressionGenerator(context, signal), (result) => [result]);
|
|
3489
|
+
break;
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
blockImmediateCache.set(node, generator);
|
|
3493
|
+
return generator;
|
|
3494
|
+
};
|
|
3495
|
+
const generateBlock = (node) => {
|
|
3496
|
+
const cached = blockCache.get(node);
|
|
3497
|
+
if (cached) return cached;
|
|
3498
|
+
const immediate = generateBlockImmediate(node);
|
|
3499
|
+
const generator = (context, signal) => Promise.resolve(immediate(context, signal));
|
|
3500
|
+
blockCache.set(node, generator);
|
|
3501
|
+
return generator;
|
|
3502
|
+
};
|
|
3503
|
+
const generateTextBlockImmediate = (node) => {
|
|
3504
|
+
const cached = textBlockImmediateCache.get(node);
|
|
3505
|
+
if (cached) return cached;
|
|
3506
|
+
let generator;
|
|
3507
|
+
switch (node.kind) {
|
|
3508
|
+
case "text":
|
|
3509
|
+
generator = () => node.text;
|
|
3510
|
+
break;
|
|
3511
|
+
case "for": {
|
|
3512
|
+
const iterableGenerator = generateExpressionImmediate(node.iterable);
|
|
3513
|
+
const repeatGenerator = generateTextProgramImmediate(node.repeat);
|
|
3514
|
+
generator = (context, signal) => resolveMaybePromise(iterableGenerator(context, signal), (result) => {
|
|
3515
|
+
const iterable = asIterable(result);
|
|
3516
|
+
if (!iterable) throwError({
|
|
3517
|
+
description: "could not apply it for function",
|
|
3518
|
+
range: node.range
|
|
3519
|
+
});
|
|
3520
|
+
const iterator = iterable[Symbol.iterator]();
|
|
3521
|
+
let text = "";
|
|
3522
|
+
for (let current = iterator.next(); !current.done; current = iterator.next()) {
|
|
3523
|
+
context.setValue(node.bind.name, current.value, signal);
|
|
3524
|
+
const repeated = repeatGenerator(context, signal);
|
|
3525
|
+
if (isPromiseLike(repeated)) return (async () => {
|
|
3526
|
+
text += await repeated;
|
|
3527
|
+
for (let next = iterator.next(); !next.done; next = iterator.next()) {
|
|
3528
|
+
context.setValue(node.bind.name, next.value, signal);
|
|
3529
|
+
text += await repeatGenerator(context, signal);
|
|
3530
|
+
}
|
|
3531
|
+
return text;
|
|
3532
|
+
})();
|
|
3533
|
+
text += repeated;
|
|
3534
|
+
}
|
|
3535
|
+
return text;
|
|
3536
|
+
});
|
|
3537
|
+
break;
|
|
3538
|
+
}
|
|
3539
|
+
case "while": {
|
|
3540
|
+
const conditionGenerator = generateExpressionImmediate(node.condition);
|
|
3541
|
+
const repeatGenerator = generateTextProgramImmediate(node.repeat);
|
|
3542
|
+
generator = (context, signal) => {
|
|
3543
|
+
let text = "";
|
|
3544
|
+
while (true) {
|
|
3545
|
+
const condition = conditionGenerator(context, signal);
|
|
3546
|
+
if (isPromiseLike(condition)) return (async () => {
|
|
3547
|
+
let currentCondition = await condition;
|
|
3548
|
+
while (isConditionalTrue(currentCondition)) {
|
|
3549
|
+
text += await repeatGenerator(context, signal);
|
|
3550
|
+
currentCondition = await conditionGenerator(context, signal);
|
|
3551
|
+
}
|
|
3552
|
+
return text;
|
|
3553
|
+
})();
|
|
3554
|
+
if (!isConditionalTrue(condition)) return text;
|
|
3555
|
+
const repeated = repeatGenerator(context, signal);
|
|
3556
|
+
if (isPromiseLike(repeated)) return (async () => {
|
|
3557
|
+
text += await repeated;
|
|
3558
|
+
while (true) {
|
|
3559
|
+
if (!isConditionalTrue(await conditionGenerator(context, signal))) break;
|
|
3560
|
+
text += await repeatGenerator(context, signal);
|
|
3561
|
+
}
|
|
3562
|
+
return text;
|
|
3563
|
+
})();
|
|
3564
|
+
text += repeated;
|
|
3565
|
+
}
|
|
3566
|
+
};
|
|
3567
|
+
break;
|
|
3568
|
+
}
|
|
3569
|
+
case "if": {
|
|
3570
|
+
const conditionGenerator = generateExpressionImmediate(node.condition);
|
|
3571
|
+
const thenGenerator = generateTextProgramImmediate(node.then);
|
|
3572
|
+
const elseGenerator = generateTextProgramImmediate(node.else);
|
|
3573
|
+
generator = (context, signal) => resolveMaybePromise(conditionGenerator(context, signal), (condition) => isConditionalTrue(condition) ? thenGenerator(context, signal) : elseGenerator(context, signal));
|
|
3574
|
+
break;
|
|
3575
|
+
}
|
|
3576
|
+
default: {
|
|
3577
|
+
const expressionGenerator = generateExpressionImmediate(node);
|
|
3578
|
+
generator = (context, signal) => resolveMaybePromise(expressionGenerator(context, signal), (result) => result === void 0 ? "" : context.convertToString(result));
|
|
3579
|
+
break;
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
textBlockImmediateCache.set(node, generator);
|
|
3583
|
+
return generator;
|
|
3584
|
+
};
|
|
3585
|
+
const generateProgramImmediate = (nodes) => {
|
|
3586
|
+
const cached = programImmediateCache.get(nodes);
|
|
3587
|
+
if (cached) return cached;
|
|
3588
|
+
const generatedBlocks = generateRawProgramImmediate(nodes);
|
|
3589
|
+
const generator = (context, signal) => resolveMaybePromise(generatedBlocks(context, signal), (results) => filterUndefined(results));
|
|
3590
|
+
programImmediateCache.set(nodes, generator);
|
|
3591
|
+
return generator;
|
|
3592
|
+
};
|
|
3593
|
+
const generateProgram = (nodes) => {
|
|
3594
|
+
const cached = programCache.get(nodes);
|
|
3595
|
+
if (cached) return cached;
|
|
3596
|
+
const immediate = generateProgramImmediate(nodes);
|
|
3597
|
+
const generator = (context, signal) => Promise.resolve(immediate(context, signal));
|
|
3598
|
+
programCache.set(nodes, generator);
|
|
3599
|
+
return generator;
|
|
3600
|
+
};
|
|
3601
|
+
const generateTextProgram = (nodes) => {
|
|
3602
|
+
const cached = textProgramCache.get(nodes);
|
|
3603
|
+
if (cached) return cached;
|
|
3604
|
+
const immediate = generateTextProgramImmediate(nodes);
|
|
3605
|
+
const generator = (context, signal) => Promise.resolve(immediate(context, signal));
|
|
3606
|
+
textProgramCache.set(nodes, generator);
|
|
3607
|
+
return generator;
|
|
3608
|
+
};
|
|
3609
|
+
const createExecutor = () => {
|
|
3610
|
+
const reduceExpressionNodeImmediate = (context, node, signal) => generateExpressionImmediate(node)(context, signal);
|
|
3611
|
+
const reduceNodeImmediate = (context, node, signal) => generateBlockImmediate(node)(context, signal);
|
|
3612
|
+
return {
|
|
3613
|
+
reduceExpressionNode: (context, node, signal) => Promise.resolve(reduceExpressionNodeImmediate(context, node, signal)),
|
|
3614
|
+
reduceExpressionNodeImmediate,
|
|
3615
|
+
reduceNode: (context, node, signal) => Promise.resolve(reduceNodeImmediate(context, node, signal)),
|
|
3616
|
+
reduceNodeImmediate
|
|
3617
|
+
};
|
|
3618
|
+
};
|
|
3619
|
+
return {
|
|
3620
|
+
generateExpression,
|
|
3621
|
+
generateBlock,
|
|
3622
|
+
generateProgram,
|
|
3623
|
+
generateTextProgram,
|
|
3624
|
+
createExecutor
|
|
3625
|
+
};
|
|
3626
|
+
};
|
|
3627
|
+
var createSourceRunner = (body) => {
|
|
3628
|
+
return new AsyncFunction("context", "signal", "runtime", `'use strict';\n${body}`);
|
|
3629
|
+
};
|
|
3630
|
+
var stripAbortChecksFromSource = (body) => {
|
|
3631
|
+
return body.replace(/(^|\n)signal\?\.throwIfAborted\(\);\n?/g, "$1");
|
|
3632
|
+
};
|
|
3633
|
+
var createAdaptiveSourceRunner = (body) => {
|
|
3634
|
+
const runnerWithSignal = createSourceRunner(body);
|
|
3635
|
+
const runnerWithoutSignal = createSourceRunner(stripAbortChecksFromSource(body));
|
|
3636
|
+
return (context, signal, runtime) => signal === void 0 ? runnerWithoutSignal(context, void 0, runtime) : runnerWithSignal(context, signal, runtime);
|
|
3637
|
+
};
|
|
3638
|
+
var createSourceDCodegen = (options) => {
|
|
3639
|
+
var _options$aggressiveOp;
|
|
3640
|
+
const closureExecutor = createClosureDCodegen().createExecutor();
|
|
3641
|
+
const aggressiveOptimize = (_options$aggressiveOp = options === null || options === void 0 ? void 0 : options.aggressiveOptimize) !== null && _options$aggressiveOp !== void 0 ? _options$aggressiveOp : false;
|
|
3642
|
+
const expressionCache = /* @__PURE__ */ new WeakMap();
|
|
3643
|
+
const blockCache = /* @__PURE__ */ new WeakMap();
|
|
3644
|
+
const programCache = /* @__PURE__ */ new WeakMap();
|
|
3645
|
+
const textProgramCache = /* @__PURE__ */ new WeakMap();
|
|
3646
|
+
const addConstant = (state, value) => {
|
|
3647
|
+
const index = state.constants.length;
|
|
3648
|
+
state.constants.push(value);
|
|
3649
|
+
return index;
|
|
3650
|
+
};
|
|
3651
|
+
const allocateTemp = (state, prefix) => {
|
|
3652
|
+
return `__${prefix}${state.nextTempId++}`;
|
|
3653
|
+
};
|
|
3654
|
+
const emptyCompileScope = {
|
|
3655
|
+
localSlots: /* @__PURE__ */ new Map(),
|
|
3656
|
+
directBindings: /* @__PURE__ */ new Map(),
|
|
3657
|
+
selfBindings: /* @__PURE__ */ new Map()
|
|
3658
|
+
};
|
|
3659
|
+
const extendCompileScope = (scope, name, slotVar) => {
|
|
3660
|
+
return {
|
|
3661
|
+
localSlots: new Map(scope.localSlots).set(name, slotVar),
|
|
3662
|
+
directBindings: scope.directBindings,
|
|
3663
|
+
selfBindings: scope.selfBindings
|
|
3664
|
+
};
|
|
3665
|
+
};
|
|
3666
|
+
const extendDirectBindingCompileScope = (scope, name, bindingRef) => {
|
|
3667
|
+
return {
|
|
3668
|
+
localSlots: scope.localSlots,
|
|
3669
|
+
directBindings: new Map(scope.directBindings).set(name, bindingRef),
|
|
3670
|
+
selfBindings: scope.selfBindings
|
|
3671
|
+
};
|
|
3672
|
+
};
|
|
3673
|
+
const extendSelfBindingCompileScope = (scope, name, bindingRef) => {
|
|
3674
|
+
return {
|
|
3675
|
+
localSlots: scope.localSlots,
|
|
3676
|
+
directBindings: scope.directBindings,
|
|
3677
|
+
selfBindings: new Map(scope.selfBindings).set(name, bindingRef)
|
|
3678
|
+
};
|
|
3679
|
+
};
|
|
3680
|
+
const resolveLocalSlotRef = (scope, name) => {
|
|
3681
|
+
return scope.localSlots.get(name);
|
|
3682
|
+
};
|
|
3683
|
+
const resolveSelfBindingRef = (scope, name) => {
|
|
3684
|
+
return scope.selfBindings.get(name);
|
|
3685
|
+
};
|
|
3686
|
+
const resolveDirectBindingRef = (scope, name) => {
|
|
3687
|
+
return scope.directBindings.get(name);
|
|
3688
|
+
};
|
|
3689
|
+
const createLookupResultSource = (scope, name) => {
|
|
3690
|
+
const localSlotRef = resolveLocalSlotRef(scope, name);
|
|
3691
|
+
return localSlotRef !== void 0 ? `{ isFound: true, value: context.getSlotValue(${localSlotRef}, signal) }` : `context.getValue(${JSON.stringify(name)}, signal)`;
|
|
3692
|
+
};
|
|
3693
|
+
const resolveAggressiveVariableSource = (state, name) => {
|
|
3694
|
+
if (!state.aggressiveOptimize) return;
|
|
3695
|
+
switch (name) {
|
|
3696
|
+
case "undefined": return "undefined";
|
|
3697
|
+
case "null": return "null";
|
|
3698
|
+
case "true": return "true";
|
|
3699
|
+
case "false": return "false";
|
|
3700
|
+
case "cond": return "runtime.standardIntrinsics.cond";
|
|
3701
|
+
case "fun": return "runtime.standardIntrinsics.fun";
|
|
3702
|
+
case "set": return "runtime.standardIntrinsics.set";
|
|
3703
|
+
case "add":
|
|
3704
|
+
case "sub":
|
|
3705
|
+
case "mul":
|
|
3706
|
+
case "div":
|
|
3707
|
+
case "mod":
|
|
3708
|
+
case "eq":
|
|
3709
|
+
case "ne":
|
|
3710
|
+
case "lt":
|
|
3711
|
+
case "gt":
|
|
3712
|
+
case "le":
|
|
3713
|
+
case "ge":
|
|
3714
|
+
case "not": return `runtime.standardBuiltins.${name}`;
|
|
3715
|
+
case "and":
|
|
3716
|
+
case "or": return `runtime.constants[${addConstant(state, standardVariables[name])}]`;
|
|
3717
|
+
case "range":
|
|
3718
|
+
case "map":
|
|
3719
|
+
case "filter":
|
|
3720
|
+
case "reduce": return `runtime.standardBuiltins.${name}`;
|
|
3721
|
+
default: return;
|
|
3722
|
+
}
|
|
3723
|
+
};
|
|
3724
|
+
const canExpressionSuspend = (node) => {
|
|
3725
|
+
switch (node.kind) {
|
|
3726
|
+
case "number":
|
|
3727
|
+
case "string":
|
|
3728
|
+
case "variable": return false;
|
|
3729
|
+
case "template": return canBlockListSuspend(node.blocks);
|
|
3730
|
+
case "dot": return canExpressionSuspend(node.base);
|
|
3731
|
+
case "apply": return true;
|
|
3732
|
+
case "list": return node.items.some((item) => canExpressionSuspend(item));
|
|
3733
|
+
case "scope": return node.nodes.some((childNode) => canExpressionSuspend(childNode));
|
|
3734
|
+
}
|
|
3735
|
+
};
|
|
3736
|
+
const canBlockSuspend = (node) => {
|
|
3737
|
+
switch (node.kind) {
|
|
3738
|
+
case "text": return false;
|
|
3739
|
+
case "for": return canExpressionSuspend(node.iterable) || canBlockListSuspend(node.repeat);
|
|
3740
|
+
case "while": return canExpressionSuspend(node.condition) || canBlockListSuspend(node.repeat);
|
|
3741
|
+
case "if": return canExpressionSuspend(node.condition) || canBlockListSuspend(node.then) || canBlockListSuspend(node.else);
|
|
3742
|
+
default: return canExpressionSuspend(node);
|
|
3743
|
+
}
|
|
3744
|
+
};
|
|
3745
|
+
const canBlockListSuspend = (nodes) => {
|
|
3746
|
+
return nodes.some((node) => canBlockSuspend(node));
|
|
3747
|
+
};
|
|
3748
|
+
const expressionContainsSetForName = (node, name) => {
|
|
3749
|
+
switch (node.kind) {
|
|
3750
|
+
case "number":
|
|
3751
|
+
case "string":
|
|
3752
|
+
case "variable": return false;
|
|
3753
|
+
case "template": return blockListContainsSetForName(node.blocks, name);
|
|
3754
|
+
case "dot": return expressionContainsSetForName(node.base, name);
|
|
3755
|
+
case "apply":
|
|
3756
|
+
var _node$args$;
|
|
3757
|
+
if (node.func.kind === "variable" && node.func.name === "set" && ((_node$args$ = node.args[0]) === null || _node$args$ === void 0 ? void 0 : _node$args$.kind) === "variable" && node.args[0].name === name) return true;
|
|
3758
|
+
if (expressionContainsSetForName(node.func, name)) return true;
|
|
3759
|
+
return node.args.some((arg) => expressionContainsSetForName(arg, name));
|
|
3760
|
+
case "list": return node.items.some((item) => expressionContainsSetForName(item, name));
|
|
3761
|
+
case "scope": return node.nodes.some((childNode) => blockContainsSetForName(childNode, name));
|
|
3762
|
+
}
|
|
3763
|
+
};
|
|
3764
|
+
const blockContainsSetForName = (node, name) => {
|
|
3765
|
+
switch (node.kind) {
|
|
3766
|
+
case "text": return false;
|
|
3767
|
+
case "for": return expressionContainsSetForName(node.iterable, name) || blockListContainsSetForName(node.repeat, name);
|
|
3768
|
+
case "while": return expressionContainsSetForName(node.condition, name) || blockListContainsSetForName(node.repeat, name);
|
|
3769
|
+
case "if": return expressionContainsSetForName(node.condition, name) || blockListContainsSetForName(node.then, name) || blockListContainsSetForName(node.else, name);
|
|
3770
|
+
default: return expressionContainsSetForName(node, name);
|
|
3771
|
+
}
|
|
3772
|
+
};
|
|
3773
|
+
const blockListContainsSetForName = (nodes, name) => {
|
|
3774
|
+
return nodes.some((node) => blockContainsSetForName(node, name));
|
|
3775
|
+
};
|
|
3776
|
+
const wrapAwaitedSource = (source, canSuspend) => {
|
|
3777
|
+
return canSuspend ? `await (${source})` : `(${source})`;
|
|
3778
|
+
};
|
|
3779
|
+
const wrapSourceClosure = (body, canSuspend) => {
|
|
3780
|
+
return canSuspend ? `(async () => {\n${body}\n})()` : `(() => {\n${body}\n})()`;
|
|
3781
|
+
};
|
|
3782
|
+
const getBuiltinArgSource = (argVars, index) => {
|
|
3783
|
+
var _argVars$index;
|
|
3784
|
+
return (_argVars$index = argVars[index]) !== null && _argVars$index !== void 0 ? _argVars$index : "undefined";
|
|
3785
|
+
};
|
|
3786
|
+
const compileNumericFoldSource = (argVars, operator) => {
|
|
3787
|
+
const initial = `Number(${getBuiltinArgSource(argVars, 0)})`;
|
|
3788
|
+
return argVars.slice(1).reduce((expression, argVar) => `(${expression} ${operator} Number(${argVar}))`, initial);
|
|
3789
|
+
};
|
|
3790
|
+
const compileInlineStandardBuiltinSource = (name, argVars) => {
|
|
3791
|
+
switch (name) {
|
|
3792
|
+
case "toString": return `[${argVars.map((argVar) => `context.convertToString(${argVar})`).join(", ")}].join(',')`;
|
|
3793
|
+
case "toBoolean": return `runtime.isConditionalTrue(${getBuiltinArgSource(argVars, 0)})`;
|
|
3794
|
+
case "toNumber": return `Number(${getBuiltinArgSource(argVars, 0)})`;
|
|
3795
|
+
case "toBigInt": return `(() => {
|
|
3796
|
+
const __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3797
|
+
switch (typeof __value) {
|
|
3798
|
+
case 'number':
|
|
3799
|
+
case 'bigint':
|
|
3800
|
+
case 'string':
|
|
3801
|
+
case 'boolean':
|
|
3802
|
+
return BigInt(__value);
|
|
3803
|
+
default:
|
|
3804
|
+
return BigInt(context.convertToString(__value));
|
|
3805
|
+
}
|
|
3806
|
+
})()`;
|
|
3807
|
+
case "typeof": return `(() => {
|
|
3808
|
+
const __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3809
|
+
if (__value === null) {
|
|
3810
|
+
return 'null';
|
|
3811
|
+
}
|
|
3812
|
+
if (typeof __value === 'string') {
|
|
3813
|
+
return 'string';
|
|
3814
|
+
}
|
|
3815
|
+
if (Array.isArray(__value)) {
|
|
3816
|
+
return 'array';
|
|
3817
|
+
}
|
|
3818
|
+
if (runtime.asIterable(__value)) {
|
|
3819
|
+
return 'iterable';
|
|
3820
|
+
}
|
|
3821
|
+
return typeof __value;
|
|
3822
|
+
})()`;
|
|
3823
|
+
case "add": return compileNumericFoldSource(argVars, "+");
|
|
3824
|
+
case "sub": return compileNumericFoldSource(argVars, "-");
|
|
3825
|
+
case "mul": return compileNumericFoldSource(argVars, "*");
|
|
3826
|
+
case "div": return compileNumericFoldSource(argVars, "/");
|
|
3827
|
+
case "mod": return compileNumericFoldSource(argVars, "%");
|
|
3828
|
+
case "eq": return `(${getBuiltinArgSource(argVars, 0)} === ${getBuiltinArgSource(argVars, 1)})`;
|
|
3829
|
+
case "ne": return `(${getBuiltinArgSource(argVars, 0)} !== ${getBuiltinArgSource(argVars, 1)})`;
|
|
3830
|
+
case "lt": return `(${getBuiltinArgSource(argVars, 0)} < ${getBuiltinArgSource(argVars, 1)})`;
|
|
3831
|
+
case "gt": return `(${getBuiltinArgSource(argVars, 0)} > ${getBuiltinArgSource(argVars, 1)})`;
|
|
3832
|
+
case "le": return `(${getBuiltinArgSource(argVars, 0)} <= ${getBuiltinArgSource(argVars, 1)})`;
|
|
3833
|
+
case "ge": return `(${getBuiltinArgSource(argVars, 0)} >= ${getBuiltinArgSource(argVars, 1)})`;
|
|
3834
|
+
case "not": return `(!runtime.isConditionalTrue(${getBuiltinArgSource(argVars, 0)}))`;
|
|
3835
|
+
case "trim": return `(() => {
|
|
3836
|
+
let __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3837
|
+
if (__value === undefined || __value === null) {
|
|
3838
|
+
__value = '';
|
|
3839
|
+
} else if (typeof __value !== 'string') {
|
|
3840
|
+
__value = __value.toString() ?? '';
|
|
3841
|
+
}
|
|
3842
|
+
return __value.trim();
|
|
3843
|
+
})()`;
|
|
3844
|
+
case "toUpper": return `(() => {
|
|
3845
|
+
let __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3846
|
+
if (typeof __value !== 'string') {
|
|
3847
|
+
__value = __value.toString() ?? '';
|
|
3848
|
+
}
|
|
3849
|
+
return __value.toUpperCase();
|
|
3850
|
+
})()`;
|
|
3851
|
+
case "toLower": return `(() => {
|
|
3852
|
+
let __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3853
|
+
if (typeof __value !== 'string') {
|
|
3854
|
+
__value = __value.toString() ?? '';
|
|
3855
|
+
}
|
|
3856
|
+
return __value.toLowerCase();
|
|
3857
|
+
})()`;
|
|
3858
|
+
case "length": return `(() => {
|
|
3859
|
+
const __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3860
|
+
if (!__value) {
|
|
3861
|
+
return 0;
|
|
3862
|
+
}
|
|
3863
|
+
if (typeof __value === 'string' || Array.isArray(__value)) {
|
|
3864
|
+
return __value.length;
|
|
3865
|
+
}
|
|
3866
|
+
const __iterable = runtime.asIterable(__value);
|
|
3867
|
+
if (!__iterable) {
|
|
3868
|
+
return 0;
|
|
3869
|
+
}
|
|
3870
|
+
let __count = 0;
|
|
3871
|
+
for (const __item of __iterable) {
|
|
3872
|
+
__count++;
|
|
3873
|
+
}
|
|
3874
|
+
return __count;
|
|
3875
|
+
})()`;
|
|
3876
|
+
case "at": return `(() => {
|
|
3877
|
+
const __index = Number(${getBuiltinArgSource(argVars, 0)});
|
|
3878
|
+
const __value = ${getBuiltinArgSource(argVars, 1)};
|
|
3879
|
+
if (!__value) {
|
|
3880
|
+
return undefined;
|
|
3881
|
+
}
|
|
3882
|
+
if (typeof __value === 'string' || Array.isArray(__value)) {
|
|
3883
|
+
return __value[__index];
|
|
3884
|
+
}
|
|
3885
|
+
const __iterable = runtime.asIterable(__value);
|
|
3886
|
+
if (!__iterable) {
|
|
3887
|
+
return undefined;
|
|
3888
|
+
}
|
|
3889
|
+
let __current = 0;
|
|
3890
|
+
for (const __item of __iterable) {
|
|
3891
|
+
if (__current >= __index) {
|
|
3892
|
+
return __item;
|
|
3893
|
+
}
|
|
3894
|
+
__current++;
|
|
3895
|
+
}
|
|
3896
|
+
return undefined;
|
|
3897
|
+
})()`;
|
|
3898
|
+
case "first": return `(() => {
|
|
3899
|
+
const __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3900
|
+
if (!__value) {
|
|
3901
|
+
return undefined;
|
|
3902
|
+
}
|
|
3903
|
+
if (typeof __value === 'string' || Array.isArray(__value)) {
|
|
3904
|
+
return __value[0];
|
|
3905
|
+
}
|
|
3906
|
+
const __iterable = runtime.asIterable(__value);
|
|
3907
|
+
if (!__iterable) {
|
|
3908
|
+
return undefined;
|
|
3909
|
+
}
|
|
3910
|
+
for (const __item of __iterable) {
|
|
3911
|
+
return __item;
|
|
3912
|
+
}
|
|
3913
|
+
return undefined;
|
|
3914
|
+
})()`;
|
|
3915
|
+
case "last": return `(() => {
|
|
3916
|
+
const __value = ${getBuiltinArgSource(argVars, 0)};
|
|
3917
|
+
if (!__value) {
|
|
3918
|
+
return undefined;
|
|
3919
|
+
}
|
|
3920
|
+
if (typeof __value === 'string' || Array.isArray(__value)) {
|
|
3921
|
+
return __value[__value.length - 1];
|
|
3922
|
+
}
|
|
3923
|
+
const __iterable = runtime.asIterable(__value);
|
|
3924
|
+
if (!__iterable) {
|
|
3925
|
+
return undefined;
|
|
3926
|
+
}
|
|
3927
|
+
let __lastItem = undefined;
|
|
3928
|
+
for (const __item of __iterable) {
|
|
3929
|
+
__lastItem = __item;
|
|
3930
|
+
}
|
|
3931
|
+
return __lastItem;
|
|
3932
|
+
})()`;
|
|
3933
|
+
case "slice": {
|
|
3934
|
+
const startSource = getBuiltinArgSource(argVars, 0);
|
|
3935
|
+
const middleSource = getBuiltinArgSource(argVars, 1);
|
|
3936
|
+
const tailSource = getBuiltinArgSource(argVars, 2);
|
|
3937
|
+
return `(() => {
|
|
3938
|
+
const __start = ${startSource} === undefined ? undefined : Number(${startSource});
|
|
3939
|
+
if (${tailSource} === undefined) {
|
|
3940
|
+
const __value = ${middleSource};
|
|
3941
|
+
if (typeof __value === 'string') {
|
|
3942
|
+
return __value.slice(__start);
|
|
3943
|
+
}
|
|
3944
|
+
return Array.from(__value).slice(__start, undefined);
|
|
3945
|
+
}
|
|
3946
|
+
const __end = ${middleSource} === undefined ? undefined : Number(${middleSource});
|
|
3947
|
+
const __value = ${tailSource};
|
|
3948
|
+
if (typeof __value === 'string') {
|
|
3949
|
+
return __value.slice(__start, __end);
|
|
3950
|
+
}
|
|
3951
|
+
return Array.from(__value).slice(__start, __end);
|
|
3952
|
+
})()`;
|
|
3953
|
+
}
|
|
3954
|
+
default: return;
|
|
3955
|
+
}
|
|
3956
|
+
};
|
|
3957
|
+
const compileDirectInlineBuiltinApplySource = (state, node, scope, name) => {
|
|
3958
|
+
const builtinArgVars = node.args.map(() => allocateTemp(state, "arg"));
|
|
3959
|
+
const inlineBuiltinSource = compileInlineStandardBuiltinSource(name, builtinArgVars);
|
|
3960
|
+
if (inlineBuiltinSource === void 0) return;
|
|
3961
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
3962
|
+
${node.args.map((arg, index) => {
|
|
3963
|
+
const argSource = compileExpressionSource(state, arg, scope);
|
|
3964
|
+
return `const ${builtinArgVars[index]} = ${wrapAwaitedSource(argSource, canExpressionSuspend(arg))};`;
|
|
3965
|
+
}).join("\n")}
|
|
3966
|
+
return ${inlineBuiltinSource};`, node.args.some((arg) => canExpressionSuspend(arg)));
|
|
3967
|
+
};
|
|
3968
|
+
const compileDirectLogicalApplySource = (state, node, scope, kind) => {
|
|
3969
|
+
const rangeIndex = addConstant(state, node.range);
|
|
3970
|
+
if (node.args.length === 0) return wrapSourceClosure(`signal?.throwIfAborted();
|
|
3971
|
+
runtime.throwError({ description: 'empty arguments', range: runtime.constants[${rangeIndex}] });`, false);
|
|
3972
|
+
const valueVars = node.args.map(() => allocateTemp(state, "value"));
|
|
3973
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
3974
|
+
${node.args.map((arg, index) => {
|
|
3975
|
+
const valueVar = valueVars[index];
|
|
3976
|
+
const argSource = compileExpressionSource(state, arg, scope);
|
|
3977
|
+
const condition = kind === "and" ? `!runtime.isConditionalTrue(${valueVar})` : `runtime.isConditionalTrue(${valueVar})`;
|
|
3978
|
+
const result = kind === "and" ? "false" : "true";
|
|
3979
|
+
return `const ${valueVar} = ${wrapAwaitedSource(argSource, canExpressionSuspend(arg))};
|
|
3980
|
+
if (${condition}) {
|
|
3981
|
+
return ${result};
|
|
3982
|
+
}`;
|
|
3983
|
+
}).join("\n")}
|
|
3984
|
+
return ${kind === "and" ? "true" : "false"};`, node.args.some((arg) => canExpressionSuspend(arg)));
|
|
3985
|
+
};
|
|
3986
|
+
const compileDirectRangeApplySource = (state, node, scope) => {
|
|
3987
|
+
const startVar = allocateTemp(state, "start");
|
|
3988
|
+
const countVar = allocateTemp(state, "count");
|
|
3989
|
+
const resultVar = allocateTemp(state, "range");
|
|
3990
|
+
const indexVar = allocateTemp(state, "index");
|
|
3991
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
3992
|
+
let ${startVar} = Number(${node.args[0] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[0], scope), canExpressionSuspend(node.args[0]))});
|
|
3993
|
+
const ${countVar} = Number(${node.args[1] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[1], scope), canExpressionSuspend(node.args[1]))});
|
|
3994
|
+
const ${resultVar} = [];
|
|
3995
|
+
for (let ${indexVar} = 0; ${indexVar} < ${countVar}; ${indexVar}++) {
|
|
3996
|
+
${resultVar}.push(${startVar}++);
|
|
3997
|
+
}
|
|
3998
|
+
return ${resultVar};`, node.args[0] !== void 0 && canExpressionSuspend(node.args[0]) || node.args[1] !== void 0 && canExpressionSuspend(node.args[1]));
|
|
3999
|
+
};
|
|
4000
|
+
const compileDirectCollectionApplySource = (state, node, scope, name) => {
|
|
4001
|
+
if (name === "map") {
|
|
4002
|
+
const mapperVar = allocateTemp(state, "mapper");
|
|
4003
|
+
const iterableVar = allocateTemp(state, "iterable");
|
|
4004
|
+
const resultVar = allocateTemp(state, "mapped");
|
|
4005
|
+
const itemVar = allocateTemp(state, "item");
|
|
4006
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4007
|
+
const ${mapperVar} = ${node.args[0] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[0], scope), canExpressionSuspend(node.args[0]))};
|
|
4008
|
+
const ${iterableVar} = ${node.args[1] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[1], scope), canExpressionSuspend(node.args[1]))};
|
|
4009
|
+
const ${resultVar} = [];
|
|
4010
|
+
for (const ${itemVar} of ${iterableVar}) {
|
|
4011
|
+
${resultVar}.push(await ${mapperVar}(${itemVar}));
|
|
4012
|
+
}
|
|
4013
|
+
return ${resultVar};`, true);
|
|
4014
|
+
}
|
|
4015
|
+
if (name === "filter") {
|
|
4016
|
+
const predicateVar = allocateTemp(state, "predicate");
|
|
4017
|
+
const iterableVar = allocateTemp(state, "iterable");
|
|
4018
|
+
const resultVar = allocateTemp(state, "filtered");
|
|
4019
|
+
const itemVar = allocateTemp(state, "item");
|
|
4020
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4021
|
+
const ${predicateVar} = ${node.args[0] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[0], scope), canExpressionSuspend(node.args[0]))};
|
|
4022
|
+
const ${iterableVar} = ${node.args[1] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[1], scope), canExpressionSuspend(node.args[1]))};
|
|
4023
|
+
const ${resultVar} = [];
|
|
4024
|
+
for (const ${itemVar} of ${iterableVar}) {
|
|
4025
|
+
if (runtime.isConditionalTrue(await ${predicateVar}(${itemVar}))) {
|
|
4026
|
+
${resultVar}.push(${itemVar});
|
|
4027
|
+
}
|
|
4028
|
+
}
|
|
4029
|
+
return ${resultVar};`, true);
|
|
4030
|
+
}
|
|
4031
|
+
const accVar = allocateTemp(state, "acc");
|
|
4032
|
+
const reducerVar = allocateTemp(state, "reducer");
|
|
4033
|
+
const iterableVar = allocateTemp(state, "iterable");
|
|
4034
|
+
const itemVar = allocateTemp(state, "item");
|
|
4035
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4036
|
+
let ${accVar} = ${node.args[0] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[0], scope), canExpressionSuspend(node.args[0]))};
|
|
4037
|
+
const ${reducerVar} = ${node.args[1] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[1], scope), canExpressionSuspend(node.args[1]))};
|
|
4038
|
+
const ${iterableVar} = ${node.args[2] === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, node.args[2], scope), canExpressionSuspend(node.args[2]))};
|
|
4039
|
+
for (const ${itemVar} of ${iterableVar}) {
|
|
4040
|
+
${accVar} = await ${reducerVar}(${accVar}, ${itemVar});
|
|
4041
|
+
}
|
|
4042
|
+
return ${accVar};`, true);
|
|
4043
|
+
};
|
|
4044
|
+
const compileAggressiveApplySource = (state, node, scope) => {
|
|
4045
|
+
if (!state.aggressiveOptimize || node.func.kind !== "variable") return;
|
|
4046
|
+
switch (node.func.name) {
|
|
4047
|
+
case "add":
|
|
4048
|
+
case "sub":
|
|
4049
|
+
case "mul":
|
|
4050
|
+
case "div":
|
|
4051
|
+
case "mod":
|
|
4052
|
+
case "eq":
|
|
4053
|
+
case "ne":
|
|
4054
|
+
case "lt":
|
|
4055
|
+
case "gt":
|
|
4056
|
+
case "le":
|
|
4057
|
+
case "ge":
|
|
4058
|
+
case "not": return compileDirectInlineBuiltinApplySource(state, node, scope, node.func.name);
|
|
4059
|
+
case "and":
|
|
4060
|
+
case "or": return compileDirectLogicalApplySource(state, node, scope, node.func.name);
|
|
4061
|
+
case "range": return compileDirectRangeApplySource(state, node, scope);
|
|
4062
|
+
case "map":
|
|
4063
|
+
case "filter":
|
|
4064
|
+
case "reduce": return compileDirectCollectionApplySource(state, node, scope, node.func.name);
|
|
4065
|
+
default: return;
|
|
4066
|
+
}
|
|
4067
|
+
};
|
|
4068
|
+
const deconstructAggressiveRangeLoop = (state, node) => {
|
|
4069
|
+
if (!state.aggressiveOptimize || node.kind !== "apply") return;
|
|
4070
|
+
if (node.func.kind !== "variable" || node.func.name !== "range") return;
|
|
4071
|
+
return {
|
|
4072
|
+
startNode: node.args[0],
|
|
4073
|
+
countNode: node.args[1]
|
|
4074
|
+
};
|
|
4075
|
+
};
|
|
4076
|
+
const toNumberLiteral = (state, value) => {
|
|
4077
|
+
if (Object.is(value, -0)) return "-0";
|
|
4078
|
+
if (Number.isFinite(value)) return String(value);
|
|
4079
|
+
return `runtime.constants[${addConstant(state, value)}]`;
|
|
4080
|
+
};
|
|
4081
|
+
const createRuntime = (constants) => {
|
|
4082
|
+
return {
|
|
4083
|
+
constants,
|
|
4084
|
+
standardBuiltins: specializableStandardCallTargets,
|
|
4085
|
+
standardIntrinsics: {
|
|
4086
|
+
cond: standardVariables.cond,
|
|
4087
|
+
fun: standardVariables.fun,
|
|
4088
|
+
set: standardVariables.set
|
|
4089
|
+
},
|
|
4090
|
+
asIterable,
|
|
4091
|
+
isConditionalTrue,
|
|
4092
|
+
isFunCityFunction,
|
|
4093
|
+
throwError,
|
|
4094
|
+
handleApplyError,
|
|
4095
|
+
resolveVariable: resolveSourceVariable,
|
|
4096
|
+
resolveDotSegments: resolveSourceDotSegments,
|
|
4097
|
+
invokeCallable: invokeSourceCallable,
|
|
4098
|
+
invokeBuiltin: invokeSourceBuiltin
|
|
4099
|
+
};
|
|
4100
|
+
};
|
|
4101
|
+
const compileBlockStatements = (state, node, targetVar, filterUndefinedValues, scope) => {
|
|
4102
|
+
switch (node.kind) {
|
|
4103
|
+
case "text": return `${targetVar}.push(${JSON.stringify(node.text)});\n`;
|
|
4104
|
+
case "for": {
|
|
4105
|
+
const iterableVar = allocateTemp(state, "iterable");
|
|
4106
|
+
const slotVar = allocateTemp(state, "slot");
|
|
4107
|
+
const itemVar = allocateTemp(state, "item");
|
|
4108
|
+
const rangeIndex = addConstant(state, node.range);
|
|
4109
|
+
return `{
|
|
4110
|
+
const ${iterableVar} = runtime.asIterable(${wrapAwaitedSource(compileExpressionSource(state, node.iterable, scope), canExpressionSuspend(node.iterable))});
|
|
4111
|
+
if (!${iterableVar}) {
|
|
4112
|
+
runtime.throwError({ description: 'could not apply it for function', range: runtime.constants[${rangeIndex}] });
|
|
4113
|
+
}
|
|
4114
|
+
const ${slotVar} = context.ensureLocalSlot(${JSON.stringify(node.bind.name)}, signal);
|
|
4115
|
+
for (const ${itemVar} of ${iterableVar}) {
|
|
4116
|
+
context.setSlotValue(${slotVar}, ${itemVar}, signal);
|
|
4117
|
+
${compileBlockListStatements(state, node.repeat, targetVar, filterUndefinedValues, extendCompileScope(scope, node.bind.name, slotVar))}
|
|
4118
|
+
}
|
|
4119
|
+
}\n`;
|
|
4120
|
+
}
|
|
4121
|
+
case "while": return `while (runtime.isConditionalTrue(${wrapAwaitedSource(compileExpressionSource(state, node.condition, scope), canExpressionSuspend(node.condition))})) {
|
|
4122
|
+
${compileBlockListStatements(state, node.repeat, targetVar, filterUndefinedValues, scope)}
|
|
4123
|
+
}\n`;
|
|
4124
|
+
case "if": return `if (runtime.isConditionalTrue(${wrapAwaitedSource(compileExpressionSource(state, node.condition, scope), canExpressionSuspend(node.condition))})) {
|
|
4125
|
+
${compileBlockListStatements(state, node.then, targetVar, filterUndefinedValues, scope)}
|
|
4126
|
+
} else {
|
|
4127
|
+
${compileBlockListStatements(state, node.else, targetVar, filterUndefinedValues, scope)}
|
|
4128
|
+
}\n`;
|
|
4129
|
+
default: {
|
|
4130
|
+
const valueVar = allocateTemp(state, "value");
|
|
4131
|
+
return `{
|
|
4132
|
+
const ${valueVar} = ${wrapAwaitedSource(compileExpressionSource(state, node, scope), canExpressionSuspend(node))};
|
|
4133
|
+
${filterUndefinedValues ? `if (${valueVar} !== undefined) { ${targetVar}.push(${valueVar}); }` : `${targetVar}.push(${valueVar});`}
|
|
4134
|
+
}\n`;
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
};
|
|
4138
|
+
const compileBlockListStatements = (state, nodes, targetVar, filterUndefinedValues, scope) => {
|
|
4139
|
+
return nodes.map((node) => compileBlockStatements(state, node, targetVar, filterUndefinedValues, scope)).join("");
|
|
4140
|
+
};
|
|
4141
|
+
const compileTextBlockStatements = (state, node, targetVar, scope) => {
|
|
4142
|
+
switch (node.kind) {
|
|
4143
|
+
case "text": return `${targetVar} += ${JSON.stringify(node.text)};\n`;
|
|
4144
|
+
case "for": {
|
|
4145
|
+
const aggressiveRangeLoop = deconstructAggressiveRangeLoop(state, node.iterable);
|
|
4146
|
+
if (aggressiveRangeLoop !== void 0) {
|
|
4147
|
+
const startVar = allocateTemp(state, "start");
|
|
4148
|
+
const countVar = allocateTemp(state, "count");
|
|
4149
|
+
const indexVar = allocateTemp(state, "index");
|
|
4150
|
+
const itemVar = allocateTemp(state, "item");
|
|
4151
|
+
const startSource = aggressiveRangeLoop.startNode === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, aggressiveRangeLoop.startNode, scope), canExpressionSuspend(aggressiveRangeLoop.startNode));
|
|
4152
|
+
const countSource = aggressiveRangeLoop.countNode === void 0 ? "undefined" : wrapAwaitedSource(compileExpressionSource(state, aggressiveRangeLoop.countNode, scope), canExpressionSuspend(aggressiveRangeLoop.countNode));
|
|
4153
|
+
if (!blockListContainsSetForName(node.repeat, node.bind.name)) return `{
|
|
4154
|
+
let ${startVar} = Number(${startSource});
|
|
4155
|
+
const ${countVar} = Number(${countSource});
|
|
4156
|
+
for (let ${indexVar} = 0; ${indexVar} < ${countVar}; ${indexVar}++) {
|
|
4157
|
+
const ${itemVar} = ${startVar}++;
|
|
4158
|
+
${compileTextBlockListStatements(state, node.repeat, targetVar, extendDirectBindingCompileScope(scope, node.bind.name, itemVar))}
|
|
4159
|
+
}
|
|
4160
|
+
}\n`;
|
|
4161
|
+
const slotVar = allocateTemp(state, "slot");
|
|
4162
|
+
return `{
|
|
4163
|
+
let ${startVar} = Number(${startSource});
|
|
4164
|
+
const ${countVar} = Number(${countSource});
|
|
4165
|
+
const ${slotVar} = context.ensureLocalSlot(${JSON.stringify(node.bind.name)}, signal);
|
|
4166
|
+
for (let ${indexVar} = 0; ${indexVar} < ${countVar}; ${indexVar}++) {
|
|
4167
|
+
const ${itemVar} = ${startVar}++;
|
|
4168
|
+
context.setSlotValue(${slotVar}, ${itemVar}, signal);
|
|
4169
|
+
${compileTextBlockListStatements(state, node.repeat, targetVar, extendCompileScope(scope, node.bind.name, slotVar))}
|
|
4170
|
+
}
|
|
4171
|
+
}\n`;
|
|
4172
|
+
}
|
|
4173
|
+
const iterableVar = allocateTemp(state, "iterable");
|
|
4174
|
+
const slotVar = allocateTemp(state, "slot");
|
|
4175
|
+
const itemVar = allocateTemp(state, "item");
|
|
4176
|
+
const rangeIndex = addConstant(state, node.range);
|
|
4177
|
+
return `{
|
|
4178
|
+
const ${iterableVar} = runtime.asIterable(${wrapAwaitedSource(compileExpressionSource(state, node.iterable, scope), canExpressionSuspend(node.iterable))});
|
|
4179
|
+
if (!${iterableVar}) {
|
|
4180
|
+
runtime.throwError({ description: 'could not apply it for function', range: runtime.constants[${rangeIndex}] });
|
|
4181
|
+
}
|
|
4182
|
+
const ${slotVar} = context.ensureLocalSlot(${JSON.stringify(node.bind.name)}, signal);
|
|
4183
|
+
for (const ${itemVar} of ${iterableVar}) {
|
|
4184
|
+
context.setSlotValue(${slotVar}, ${itemVar}, signal);
|
|
4185
|
+
${compileTextBlockListStatements(state, node.repeat, targetVar, extendCompileScope(scope, node.bind.name, slotVar))}
|
|
4186
|
+
}
|
|
4187
|
+
}\n`;
|
|
4188
|
+
}
|
|
4189
|
+
case "while": return `while (runtime.isConditionalTrue(${wrapAwaitedSource(compileExpressionSource(state, node.condition, scope), canExpressionSuspend(node.condition))})) {
|
|
4190
|
+
${compileTextBlockListStatements(state, node.repeat, targetVar, scope)}
|
|
4191
|
+
}\n`;
|
|
4192
|
+
case "if": return `if (runtime.isConditionalTrue(${wrapAwaitedSource(compileExpressionSource(state, node.condition, scope), canExpressionSuspend(node.condition))})) {
|
|
4193
|
+
${compileTextBlockListStatements(state, node.then, targetVar, scope)}
|
|
4194
|
+
} else {
|
|
4195
|
+
${compileTextBlockListStatements(state, node.else, targetVar, scope)}
|
|
4196
|
+
}\n`;
|
|
4197
|
+
default: {
|
|
4198
|
+
const valueVar = allocateTemp(state, "value");
|
|
4199
|
+
const valueSource = compileExpressionSource(state, node, scope);
|
|
4200
|
+
if (state.aggressiveOptimize) return `{
|
|
4201
|
+
const ${valueVar} = ${wrapAwaitedSource(valueSource, canExpressionSuspend(node))};
|
|
4202
|
+
if (${valueVar} !== undefined) {
|
|
4203
|
+
if (${valueVar} === null) {
|
|
4204
|
+
${targetVar} += '(null)';
|
|
4205
|
+
} else {
|
|
4206
|
+
switch (typeof ${valueVar}) {
|
|
4207
|
+
case 'string':
|
|
4208
|
+
${targetVar} += ${valueVar};
|
|
4209
|
+
break;
|
|
4210
|
+
case 'boolean':
|
|
4211
|
+
case 'number':
|
|
4212
|
+
case 'bigint':
|
|
4213
|
+
case 'symbol':
|
|
4214
|
+
${targetVar} += ${valueVar}.toString();
|
|
4215
|
+
break;
|
|
4216
|
+
default:
|
|
4217
|
+
${targetVar} += context.convertToString(${valueVar});
|
|
4218
|
+
break;
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
}\n`;
|
|
4223
|
+
return `{
|
|
4224
|
+
const ${valueVar} = ${wrapAwaitedSource(valueSource, canExpressionSuspend(node))};
|
|
4225
|
+
if (${valueVar} !== undefined) {
|
|
4226
|
+
${targetVar} += context.convertToString(${valueVar});
|
|
4227
|
+
}
|
|
4228
|
+
}\n`;
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
};
|
|
4232
|
+
const compileTextBlockListStatements = (state, nodes, targetVar, scope) => {
|
|
4233
|
+
return nodes.map((node) => compileTextBlockStatements(state, node, targetVar, scope)).join("");
|
|
4234
|
+
};
|
|
4235
|
+
const compileIntrinsicLambdaSource = (state, lambdaRange, parameterNames, bodyNode, scope, selfBinding) => {
|
|
4236
|
+
const lambdaArgsVar = allocateTemp(state, "args");
|
|
4237
|
+
const lambdaContextVar = allocateTemp(state, "context");
|
|
4238
|
+
const rangeIndex = addConstant(state, lambdaRange);
|
|
4239
|
+
const parameterNamesIndex = addConstant(state, [...parameterNames]);
|
|
4240
|
+
const parameterSlotRefs = /* @__PURE__ */ new Map();
|
|
4241
|
+
for (const parameterName of parameterNames) if (!parameterSlotRefs.has(parameterName)) parameterSlotRefs.set(parameterName, String(parameterSlotRefs.size));
|
|
4242
|
+
const bodySource = compileExpressionSource(state, bodyNode, Array.from(parameterSlotRefs.entries()).reduce((currentScope, [parameterName, slotRef]) => extendCompileScope(currentScope, parameterName, slotRef), selfBinding === void 0 ? scope : extendSelfBindingCompileScope(scope, selfBinding.name, selfBinding.bindingRef)));
|
|
4243
|
+
return `(...${lambdaArgsVar}) => {
|
|
4244
|
+
if (${lambdaArgsVar}.length < ${parameterNames.length}) {
|
|
4245
|
+
runtime.throwError({ description: 'Arguments are not filled: ' + ${lambdaArgsVar}.length + ' < ${parameterNames.length}', range: runtime.constants[${rangeIndex}] });
|
|
4246
|
+
}
|
|
4247
|
+
if (${lambdaArgsVar}.length > ${parameterNames.length}) {
|
|
4248
|
+
context.appendWarning({ type: 'warning', description: 'Too many arguments: ' + ${lambdaArgsVar}.length + ' > ${parameterNames.length}', range: runtime.constants[${rangeIndex}] });
|
|
4249
|
+
}
|
|
4250
|
+
const ${lambdaContextVar} = context.newCallScope(runtime.constants[${parameterNamesIndex}], ${lambdaArgsVar}, signal);
|
|
4251
|
+
return ((context) => {
|
|
4252
|
+
return ${bodySource};
|
|
4253
|
+
})(${lambdaContextVar});
|
|
4254
|
+
}`;
|
|
4255
|
+
};
|
|
4256
|
+
const compileGenericApplySource = (state, node, scope) => {
|
|
4257
|
+
const applyNodeIndex = addConstant(state, node);
|
|
4258
|
+
const rangeIndex = addConstant(state, node.range);
|
|
4259
|
+
const argsNodeIndex = addConstant(state, node.args);
|
|
4260
|
+
const argArraySource = `[${node.args.map((arg) => wrapAwaitedSource(compileExpressionSource(state, arg, scope), canExpressionSuspend(arg))).join(", ")}]`;
|
|
4261
|
+
if (node.func.kind === "variable") {
|
|
4262
|
+
if (toSpecializableStandardCallTarget(node.func.name) !== void 0) {
|
|
4263
|
+
const bindingVar = allocateTemp(state, "binding");
|
|
4264
|
+
const funcVar = allocateTemp(state, "func");
|
|
4265
|
+
const callArgsVar = allocateTemp(state, "args");
|
|
4266
|
+
const builtinArgVars = node.args.map(() => allocateTemp(state, "arg"));
|
|
4267
|
+
const inlineBuiltinSource = compileInlineStandardBuiltinSource(node.func.name, builtinArgVars);
|
|
4268
|
+
const builtinArgStatements = node.args.map((arg, index) => {
|
|
4269
|
+
const argSource = compileExpressionSource(state, arg, scope);
|
|
4270
|
+
return `const ${builtinArgVars[index]} = ${wrapAwaitedSource(argSource, canExpressionSuspend(arg))};`;
|
|
4271
|
+
}).join("\n");
|
|
4272
|
+
return `(async () => {
|
|
4273
|
+
signal?.throwIfAborted();
|
|
4274
|
+
const ${bindingVar} = ${createLookupResultSource(scope, node.func.name)};
|
|
4275
|
+
if (${bindingVar}.isFound && ${bindingVar}.value === runtime.standardBuiltins.${node.func.name}) {
|
|
4276
|
+
${builtinArgStatements}
|
|
4277
|
+
try {
|
|
4278
|
+
return ${inlineBuiltinSource !== null && inlineBuiltinSource !== void 0 ? inlineBuiltinSource : `await runtime.standardBuiltins.${node.func.name}(${builtinArgVars.join(", ")})`};
|
|
4279
|
+
} catch (error) {
|
|
4280
|
+
return runtime.handleApplyError(runtime.constants[${applyNodeIndex}], error);
|
|
4281
|
+
}
|
|
4282
|
+
}
|
|
4283
|
+
const ${funcVar} = ${bindingVar}.isFound
|
|
4284
|
+
? ${bindingVar}.value
|
|
4285
|
+
: runtime.resolveVariable(context, ${JSON.stringify(node.func.name)}, false, runtime.constants[${addConstant(state, node.func.range)}], signal);
|
|
4286
|
+
if (typeof ${funcVar} !== 'function') {
|
|
4287
|
+
runtime.throwError({ description: 'could not apply it for function', range: runtime.constants[${rangeIndex}] });
|
|
4288
|
+
}
|
|
4289
|
+
if (runtime.isFunCityFunction(${funcVar})) {
|
|
4290
|
+
return runtime.invokeCallable(context, runtime.constants[${applyNodeIndex}], signal, ${funcVar}, runtime.constants[${argsNodeIndex}], true);
|
|
4291
|
+
}
|
|
4292
|
+
const ${callArgsVar} = ${argArraySource};
|
|
4293
|
+
return runtime.invokeCallable(context, runtime.constants[${applyNodeIndex}], signal, ${funcVar}, ${callArgsVar}, false);
|
|
4294
|
+
})()`;
|
|
4295
|
+
}
|
|
4296
|
+
}
|
|
4297
|
+
const funcVar = allocateTemp(state, "func");
|
|
4298
|
+
const argsVar = allocateTemp(state, "args");
|
|
4299
|
+
return `(async () => {
|
|
4300
|
+
signal?.throwIfAborted();
|
|
4301
|
+
const ${funcVar} = ${wrapAwaitedSource(compileExpressionSource(state, node.func, scope), canExpressionSuspend(node.func))};
|
|
4302
|
+
if (typeof ${funcVar} !== 'function') {
|
|
4303
|
+
runtime.throwError({ description: 'could not apply it for function', range: runtime.constants[${rangeIndex}] });
|
|
4304
|
+
}
|
|
4305
|
+
if (runtime.isFunCityFunction(${funcVar})) {
|
|
4306
|
+
return runtime.invokeCallable(context, runtime.constants[${applyNodeIndex}], signal, ${funcVar}, runtime.constants[${argsNodeIndex}], true);
|
|
4307
|
+
}
|
|
4308
|
+
const ${argsVar} = ${argArraySource};
|
|
4309
|
+
return runtime.invokeCallable(context, runtime.constants[${applyNodeIndex}], signal, ${funcVar}, ${argsVar}, false);
|
|
4310
|
+
})()`;
|
|
4311
|
+
};
|
|
4312
|
+
const compileExpressionSource = (state, node, scope) => {
|
|
4313
|
+
switch (node.kind) {
|
|
4314
|
+
case "number": return toNumberLiteral(state, node.value);
|
|
4315
|
+
case "string": return JSON.stringify(node.value);
|
|
4316
|
+
case "template": {
|
|
4317
|
+
const textVar = allocateTemp(state, "text");
|
|
4318
|
+
return wrapSourceClosure(`let ${textVar} = '';
|
|
4319
|
+
${compileTextBlockListStatements(state, node.blocks, textVar, scope)}
|
|
4320
|
+
return ${textVar};`, canBlockListSuspend(node.blocks));
|
|
4321
|
+
}
|
|
4322
|
+
case "variable": {
|
|
4323
|
+
const variableResult = deconstructConditionalCombine(node.name);
|
|
4324
|
+
const aggressiveSource = resolveAggressiveVariableSource(state, variableResult.name);
|
|
4325
|
+
if (aggressiveSource !== void 0) return aggressiveSource;
|
|
4326
|
+
const localSlotRef = resolveLocalSlotRef(scope, variableResult.name);
|
|
4327
|
+
if (localSlotRef !== void 0) return `context.getSlotValue(${localSlotRef}, signal)`;
|
|
4328
|
+
const directBindingRef = resolveDirectBindingRef(scope, variableResult.name);
|
|
4329
|
+
if (directBindingRef !== void 0) return directBindingRef;
|
|
4330
|
+
const selfBindingRef = resolveSelfBindingRef(scope, variableResult.name);
|
|
4331
|
+
if (selfBindingRef !== void 0) return selfBindingRef;
|
|
4332
|
+
const rangeIndex = addConstant(state, node.range);
|
|
4333
|
+
return `runtime.resolveVariable(context, ${JSON.stringify(variableResult.name)}, ${variableResult.canIgnore ? "true" : "false"}, runtime.constants[${rangeIndex}], signal)`;
|
|
4334
|
+
}
|
|
4335
|
+
case "dot": {
|
|
4336
|
+
const segmentsIndex = addConstant(state, node.segments.map((segment) => {
|
|
4337
|
+
const result = deconstructConditionalCombine(segment.name);
|
|
4338
|
+
return {
|
|
4339
|
+
name: result.name,
|
|
4340
|
+
canIgnore: segment.optional || result.canIgnore,
|
|
4341
|
+
range: segment.range
|
|
4342
|
+
};
|
|
4343
|
+
}));
|
|
4344
|
+
if (node.base.kind === "variable") {
|
|
4345
|
+
var _node$segments$0$opti2, _node$segments$2;
|
|
4346
|
+
const baseResult = deconstructConditionalCombine(node.base.name);
|
|
4347
|
+
const localSlotRef = resolveLocalSlotRef(scope, baseResult.name);
|
|
4348
|
+
const baseRangeIndex = addConstant(state, node.base.range);
|
|
4349
|
+
const baseValueVar = allocateTemp(state, "base");
|
|
4350
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4351
|
+
const ${baseValueVar} = ${localSlotRef !== void 0 ? `{ isFound: true, value: context.getSlotValue(${localSlotRef}, signal) }` : createLookupResultSource(scope, baseResult.name)};
|
|
4352
|
+
if (!${baseValueVar}.isFound) {
|
|
4353
|
+
${baseResult.canIgnore || ((_node$segments$0$opti2 = (_node$segments$2 = node.segments[0]) === null || _node$segments$2 === void 0 ? void 0 : _node$segments$2.optional) !== null && _node$segments$0$opti2 !== void 0 ? _node$segments$0$opti2 : false) ? "return undefined;" : `runtime.throwError({ description: ${JSON.stringify(`variable is not bound: ${baseResult.name}`)}, range: runtime.constants[${baseRangeIndex}] });`}
|
|
4354
|
+
}
|
|
4355
|
+
return runtime.resolveDotSegments(context, ${baseValueVar}.value, runtime.constants[${segmentsIndex}]);`, false);
|
|
4356
|
+
}
|
|
4357
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4358
|
+
return runtime.resolveDotSegments(
|
|
4359
|
+
context,
|
|
4360
|
+
${wrapAwaitedSource(compileExpressionSource(state, node.base, scope), canExpressionSuspend(node.base))},
|
|
4361
|
+
runtime.constants[${segmentsIndex}]
|
|
4362
|
+
);`, canExpressionSuspend(node.base));
|
|
4363
|
+
}
|
|
4364
|
+
case "apply": {
|
|
4365
|
+
if (node.func.kind === "variable" && resolveLocalSlotRef(scope, node.func.name) === void 0) {
|
|
4366
|
+
const selfBindingRef = resolveSelfBindingRef(scope, node.func.name);
|
|
4367
|
+
if (selfBindingRef !== void 0) return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4368
|
+
return ${selfBindingRef}(${node.args.map((arg) => wrapAwaitedSource(compileExpressionSource(state, arg, scope), canExpressionSuspend(arg))).join(", ")});`, node.args.some((arg) => canExpressionSuspend(arg)));
|
|
4369
|
+
}
|
|
4370
|
+
if (node.func.kind === "variable" && node.func.name === "set" && node.args.length === 2 && node.args[0].kind === "variable" && node.args[1].kind === "apply" && node.args[1].func.kind === "variable" && node.args[1].func.name === "fun" && node.args[1].args.length === 2) {
|
|
4371
|
+
const parameterNames = extractLambdaParameterNames(node.args[1].args[0]);
|
|
4372
|
+
if (parameterNames !== void 0) {
|
|
4373
|
+
const boundName = node.args[0].name;
|
|
4374
|
+
const lambdaVar = allocateTemp(state, "lambda");
|
|
4375
|
+
const lambdaSource = compileIntrinsicLambdaSource(state, node.args[1].range, parameterNames, node.args[1].args[1], scope, {
|
|
4376
|
+
name: boundName,
|
|
4377
|
+
bindingRef: lambdaVar
|
|
4378
|
+
});
|
|
4379
|
+
if (state.aggressiveOptimize) return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4380
|
+
const ${lambdaVar} = ${lambdaSource};
|
|
4381
|
+
context.setValue(${JSON.stringify(boundName)}, ${lambdaVar}, signal);
|
|
4382
|
+
return undefined;`, true);
|
|
4383
|
+
const setBindingVar = allocateTemp(state, "binding");
|
|
4384
|
+
const funBindingVar = allocateTemp(state, "binding");
|
|
4385
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4386
|
+
const ${setBindingVar} = ${createLookupResultSource(scope, "set")};
|
|
4387
|
+
const ${funBindingVar} = ${createLookupResultSource(scope, "fun")};
|
|
4388
|
+
if (${setBindingVar}.isFound && ${setBindingVar}.value === runtime.standardIntrinsics.set && ${funBindingVar}.isFound && ${funBindingVar}.value === runtime.standardIntrinsics.fun) {
|
|
4389
|
+
const ${lambdaVar} = ${lambdaSource};
|
|
4390
|
+
context.setValue(${JSON.stringify(boundName)}, ${lambdaVar}, signal);
|
|
4391
|
+
return undefined;
|
|
4392
|
+
}
|
|
4393
|
+
return ${compileGenericApplySource(state, node, scope)};`, true);
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
if (node.func.kind === "variable" && state.aggressiveOptimize && node.func.name === "set" && node.args.length === 2 && node.args[0].kind === "variable") {
|
|
4397
|
+
const valueSource = compileExpressionSource(state, node.args[1], scope);
|
|
4398
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4399
|
+
context.setValue(${JSON.stringify(node.args[0].name)}, ${wrapAwaitedSource(valueSource, canExpressionSuspend(node.args[1]))}, signal);
|
|
4400
|
+
return undefined;`, canExpressionSuspend(node.args[1]));
|
|
4401
|
+
}
|
|
4402
|
+
if (node.func.kind === "variable" && node.func.name === "cond" && node.args.length === 3) {
|
|
4403
|
+
const conditionNode = node.args[0];
|
|
4404
|
+
const thenNode = node.args[1];
|
|
4405
|
+
const elseNode = node.args[2];
|
|
4406
|
+
const bindingVar = allocateTemp(state, "binding");
|
|
4407
|
+
const conditionVar = allocateTemp(state, "condition");
|
|
4408
|
+
const conditionSource = compileExpressionSource(state, conditionNode, scope);
|
|
4409
|
+
const thenSource = compileExpressionSource(state, thenNode, scope);
|
|
4410
|
+
const elseSource = compileExpressionSource(state, elseNode, scope);
|
|
4411
|
+
if (state.aggressiveOptimize) return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4412
|
+
const ${conditionVar} = ${wrapAwaitedSource(conditionSource, canExpressionSuspend(conditionNode))};
|
|
4413
|
+
if (runtime.isConditionalTrue(${conditionVar})) {
|
|
4414
|
+
return ${wrapAwaitedSource(thenSource, canExpressionSuspend(thenNode))};
|
|
4415
|
+
}
|
|
4416
|
+
return ${wrapAwaitedSource(elseSource, canExpressionSuspend(elseNode))};`, true);
|
|
4417
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4418
|
+
const ${bindingVar} = ${createLookupResultSource(scope, "cond")};
|
|
4419
|
+
if (${bindingVar}.isFound && ${bindingVar}.value === runtime.standardIntrinsics.cond) {
|
|
4420
|
+
const ${conditionVar} = ${wrapAwaitedSource(conditionSource, canExpressionSuspend(conditionNode))};
|
|
4421
|
+
if (runtime.isConditionalTrue(${conditionVar})) {
|
|
4422
|
+
return ${wrapAwaitedSource(thenSource, canExpressionSuspend(thenNode))};
|
|
4423
|
+
}
|
|
4424
|
+
return ${wrapAwaitedSource(elseSource, canExpressionSuspend(elseNode))};
|
|
4425
|
+
}
|
|
4426
|
+
return ${compileGenericApplySource(state, node, scope)};`, true);
|
|
4427
|
+
}
|
|
4428
|
+
if (node.func.kind === "variable" && node.func.name === "fun" && node.args.length === 2) {
|
|
4429
|
+
const parameterNames = extractLambdaParameterNames(node.args[0]);
|
|
4430
|
+
if (parameterNames !== void 0) {
|
|
4431
|
+
const lambdaSource = compileIntrinsicLambdaSource(state, node.range, parameterNames, node.args[1], scope, void 0);
|
|
4432
|
+
if (state.aggressiveOptimize) return lambdaSource;
|
|
4433
|
+
const bindingVar = allocateTemp(state, "binding");
|
|
4434
|
+
return wrapSourceClosure(`signal?.throwIfAborted();
|
|
4435
|
+
const ${bindingVar} = ${createLookupResultSource(scope, "fun")};
|
|
4436
|
+
if (${bindingVar}.isFound && ${bindingVar}.value === runtime.standardIntrinsics.fun) {
|
|
4437
|
+
return ${lambdaSource};
|
|
4438
|
+
}
|
|
4439
|
+
return ${compileGenericApplySource(state, node, scope)};`, true);
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
const aggressiveApplySource = compileAggressiveApplySource(state, node, scope);
|
|
4443
|
+
if (aggressiveApplySource !== void 0) return aggressiveApplySource;
|
|
4444
|
+
return compileGenericApplySource(state, node, scope);
|
|
4445
|
+
}
|
|
4446
|
+
case "list": return `[${node.items.map((item) => wrapAwaitedSource(compileExpressionSource(state, item, scope), canExpressionSuspend(item))).join(", ")}]`;
|
|
4447
|
+
case "scope": {
|
|
4448
|
+
if (node.nodes.length === 0) return "[]";
|
|
4449
|
+
const resultVar = allocateTemp(state, "result");
|
|
4450
|
+
return wrapSourceClosure(`let ${resultVar} = undefined;
|
|
4451
|
+
${node.nodes.map((childNode) => {
|
|
4452
|
+
return `${resultVar} = ${wrapAwaitedSource(compileExpressionSource(state, childNode, scope), canExpressionSuspend(childNode))};`;
|
|
4453
|
+
}).join("\n")}
|
|
4454
|
+
return ${resultVar};`, node.nodes.some((childNode) => canExpressionSuspend(childNode)));
|
|
4455
|
+
}
|
|
4456
|
+
}
|
|
4457
|
+
};
|
|
4458
|
+
const createExpressionRunner = (node) => {
|
|
4459
|
+
const cached = expressionCache.get(node);
|
|
4460
|
+
if (cached) return cached;
|
|
4461
|
+
const state = {
|
|
4462
|
+
nextTempId: 0,
|
|
4463
|
+
constants: [],
|
|
4464
|
+
aggressiveOptimize
|
|
4465
|
+
};
|
|
4466
|
+
const runner = createAdaptiveSourceRunner(`const {
|
|
4467
|
+
constants,
|
|
4468
|
+
standardBuiltins,
|
|
4469
|
+
asIterable,
|
|
4470
|
+
isConditionalTrue,
|
|
4471
|
+
isFunCityFunction,
|
|
4472
|
+
throwError,
|
|
4473
|
+
resolveVariable,
|
|
4474
|
+
resolveDotSegments,
|
|
4475
|
+
invokeCallable,
|
|
4476
|
+
invokeBuiltin
|
|
4477
|
+
} = runtime;
|
|
4478
|
+
return ${compileExpressionSource(state, node, emptyCompileScope)};`);
|
|
4479
|
+
const runtime = createRuntime(state.constants);
|
|
4480
|
+
const generated = (context, signal) => runner(context, signal, runtime);
|
|
4481
|
+
expressionCache.set(node, generated);
|
|
4482
|
+
return generated;
|
|
4483
|
+
};
|
|
4484
|
+
const createBlockRunner = (node) => {
|
|
4485
|
+
const cached = blockCache.get(node);
|
|
4486
|
+
if (cached) return cached;
|
|
4487
|
+
const state = {
|
|
4488
|
+
nextTempId: 0,
|
|
4489
|
+
constants: [],
|
|
4490
|
+
aggressiveOptimize
|
|
4491
|
+
};
|
|
4492
|
+
const resultVar = allocateTemp(state, "result");
|
|
4493
|
+
const runner = createAdaptiveSourceRunner(`const {
|
|
4494
|
+
constants,
|
|
4495
|
+
standardBuiltins,
|
|
4496
|
+
asIterable,
|
|
4497
|
+
isConditionalTrue,
|
|
4498
|
+
isFunCityFunction,
|
|
4499
|
+
throwError,
|
|
4500
|
+
resolveVariable,
|
|
4501
|
+
resolveDotSegments,
|
|
4502
|
+
invokeCallable,
|
|
4503
|
+
invokeBuiltin
|
|
4504
|
+
} = runtime;
|
|
4505
|
+
const ${resultVar} = [];
|
|
4506
|
+
${compileBlockStatements(state, node, resultVar, false, emptyCompileScope)}
|
|
4507
|
+
return ${resultVar};`);
|
|
4508
|
+
const runtime = createRuntime(state.constants);
|
|
4509
|
+
const generated = (context, signal) => runner(context, signal, runtime);
|
|
4510
|
+
blockCache.set(node, generated);
|
|
4511
|
+
return generated;
|
|
4512
|
+
};
|
|
4513
|
+
const createProgramRunner = (nodes) => {
|
|
4514
|
+
const cached = programCache.get(nodes);
|
|
4515
|
+
if (cached) return cached;
|
|
4516
|
+
const state = {
|
|
4517
|
+
nextTempId: 0,
|
|
4518
|
+
constants: [],
|
|
4519
|
+
aggressiveOptimize
|
|
4520
|
+
};
|
|
4521
|
+
const resultVar = allocateTemp(state, "result");
|
|
4522
|
+
const runner = createAdaptiveSourceRunner(`const {
|
|
4523
|
+
constants,
|
|
4524
|
+
standardBuiltins,
|
|
4525
|
+
asIterable,
|
|
4526
|
+
isConditionalTrue,
|
|
4527
|
+
isFunCityFunction,
|
|
4528
|
+
throwError,
|
|
4529
|
+
resolveVariable,
|
|
4530
|
+
resolveDotSegments,
|
|
4531
|
+
invokeCallable,
|
|
4532
|
+
invokeBuiltin
|
|
4533
|
+
} = runtime;
|
|
4534
|
+
const ${resultVar} = [];
|
|
4535
|
+
${compileBlockListStatements(state, nodes, resultVar, true, emptyCompileScope)}
|
|
4536
|
+
return ${resultVar};`);
|
|
4537
|
+
const runtime = createRuntime(state.constants);
|
|
4538
|
+
const generated = (context, signal) => runner(context, signal, runtime);
|
|
4539
|
+
programCache.set(nodes, generated);
|
|
4540
|
+
return generated;
|
|
4541
|
+
};
|
|
4542
|
+
const createTextProgramRunner = (nodes) => {
|
|
4543
|
+
const cached = textProgramCache.get(nodes);
|
|
4544
|
+
if (cached) return cached;
|
|
4545
|
+
const state = {
|
|
4546
|
+
nextTempId: 0,
|
|
4547
|
+
constants: [],
|
|
4548
|
+
aggressiveOptimize
|
|
4549
|
+
};
|
|
4550
|
+
const textVar = allocateTemp(state, "text");
|
|
4551
|
+
const runner = createAdaptiveSourceRunner(`const {
|
|
4552
|
+
constants,
|
|
4553
|
+
standardBuiltins,
|
|
4554
|
+
asIterable,
|
|
4555
|
+
isConditionalTrue,
|
|
4556
|
+
isFunCityFunction,
|
|
4557
|
+
throwError,
|
|
4558
|
+
resolveVariable,
|
|
4559
|
+
resolveDotSegments,
|
|
4560
|
+
invokeCallable,
|
|
4561
|
+
invokeBuiltin
|
|
4562
|
+
} = runtime;
|
|
4563
|
+
let ${textVar} = '';
|
|
4564
|
+
${compileTextBlockListStatements(state, nodes, textVar, emptyCompileScope)}
|
|
4565
|
+
return ${textVar};`);
|
|
4566
|
+
const runtime = createRuntime(state.constants);
|
|
4567
|
+
const generated = (context, signal) => runner(context, signal, runtime);
|
|
4568
|
+
textProgramCache.set(nodes, generated);
|
|
4569
|
+
return generated;
|
|
4570
|
+
};
|
|
4571
|
+
const createExecutor = () => {
|
|
4572
|
+
return {
|
|
4573
|
+
reduceExpressionNode: (context, node, signal) => createExpressionRunner(node)(context, signal),
|
|
4574
|
+
reduceExpressionNodeImmediate: closureExecutor.reduceExpressionNodeImmediate,
|
|
4575
|
+
reduceNode: (context, node, signal) => createBlockRunner(node)(context, signal),
|
|
4576
|
+
reduceNodeImmediate: closureExecutor.reduceNodeImmediate
|
|
4577
|
+
};
|
|
4578
|
+
};
|
|
4579
|
+
return {
|
|
4580
|
+
generateExpression: createExpressionRunner,
|
|
4581
|
+
generateBlock: createBlockRunner,
|
|
4582
|
+
generateProgram: createProgramRunner,
|
|
4583
|
+
generateTextProgram: createTextProgramRunner,
|
|
4584
|
+
createExecutor
|
|
4585
|
+
};
|
|
4586
|
+
};
|
|
4587
|
+
/**
|
|
4588
|
+
* Create a dynamic code generator.
|
|
4589
|
+
* @param options - Generator options.
|
|
4590
|
+
* @returns Dynamic code generator instance.
|
|
4591
|
+
*/
|
|
4592
|
+
var createDCodegen = (options) => {
|
|
4593
|
+
switch (options === null || options === void 0 ? void 0 : options.backend) {
|
|
4594
|
+
case "source": return createSourceDCodegen(options);
|
|
4595
|
+
case "closure":
|
|
4596
|
+
case void 0: return createClosureDCodegen();
|
|
4597
|
+
}
|
|
4598
|
+
};
|
|
4599
|
+
/**
|
|
4600
|
+
* Run a node list with the dynamic code generator.
|
|
4601
|
+
* @param nodes - Target nodes.
|
|
4602
|
+
* @param variables - Predefined variables.
|
|
4603
|
+
* @param warningLogs - Warning sink.
|
|
4604
|
+
* @param signal - AbortSignal when available.
|
|
4605
|
+
* @returns Reduced native values.
|
|
4606
|
+
*/
|
|
4607
|
+
var runDCodegen = async (nodes, variables, warningLogs, signal) => {
|
|
4608
|
+
const dcodegen = createDCodegen();
|
|
4609
|
+
const context = createReducerContext(variables, warningLogs, dcodegen.createExecutor());
|
|
4610
|
+
return await dcodegen.generateProgram(nodes)(context, signal);
|
|
4611
|
+
};
|
|
4612
|
+
//#endregion
|
|
4613
|
+
//#region src/compile-cache.ts
|
|
4614
|
+
var compile_cache_exports = /* @__PURE__ */ require_node.__exportAll({
|
|
4615
|
+
compileScriptCached: () => compileScriptCached,
|
|
4616
|
+
createSharedDCodegenExecutor: () => createSharedDCodegenExecutor
|
|
4617
|
+
});
|
|
4618
|
+
var compilationCacheLimit = 64;
|
|
4619
|
+
var sharedSourceDCodegen = createDCodegen({ backend: "source" });
|
|
4620
|
+
var sharedAggressiveSourceDCodegen = createDCodegen({
|
|
4621
|
+
backend: "source",
|
|
4622
|
+
aggressiveOptimize: true
|
|
4623
|
+
});
|
|
4624
|
+
var sharedClosureDCodegen = createDCodegen({ backend: "closure" });
|
|
4625
|
+
var compiledScriptCache = /* @__PURE__ */ new Map();
|
|
4626
|
+
var defaultExecutionBackend = "source";
|
|
4627
|
+
var resolveExecutionBackend = (backend) => backend !== null && backend !== void 0 ? backend : defaultExecutionBackend;
|
|
4628
|
+
var isDynamicCodegenBackend = (backend) => backend !== "reducer";
|
|
4629
|
+
var resolveAggressiveOptimize = (backend, aggressiveOptimize) => backend === "source" ? aggressiveOptimize !== null && aggressiveOptimize !== void 0 ? aggressiveOptimize : false : false;
|
|
4630
|
+
var getSharedDCodegen = (backend, aggressiveOptimize) => {
|
|
4631
|
+
if (backend === "closure") return sharedClosureDCodegen;
|
|
4632
|
+
return resolveAggressiveOptimize(backend, aggressiveOptimize) ? sharedAggressiveSourceDCodegen : sharedSourceDCodegen;
|
|
4633
|
+
};
|
|
4634
|
+
var toCompilationCacheKey = (script, sourceId, mode, backend, aggressiveOptimize) => `${mode}\u0000${backend}\u0000${aggressiveOptimize ? "aggr1" : "aggr0"}\u0000${sourceId}\u0000${script}`;
|
|
4635
|
+
var setCompiledScriptCache = (key, compiled) => {
|
|
4636
|
+
compiledScriptCache.set(key, compiled);
|
|
4637
|
+
if (compiledScriptCache.size <= compilationCacheLimit) return;
|
|
4638
|
+
const firstKey = compiledScriptCache.keys().next().value;
|
|
4639
|
+
if (firstKey !== void 0) compiledScriptCache.delete(firstKey);
|
|
4640
|
+
};
|
|
4641
|
+
/**
|
|
4642
|
+
* Create a reducer executor backed by the shared dynamic code generator.
|
|
4643
|
+
* @param backend - Dynamic code generator backend.
|
|
4644
|
+
* @returns Reducer executor.
|
|
4645
|
+
*/
|
|
4646
|
+
var createSharedDCodegenExecutor = (backend, aggressiveOptimize) => {
|
|
4647
|
+
return getSharedDCodegen(backend !== null && backend !== void 0 ? backend : defaultExecutionBackend, aggressiveOptimize).createExecutor();
|
|
4648
|
+
};
|
|
4649
|
+
var createReducerBackedProgram = (nodes) => {
|
|
4650
|
+
return async (context, signal) => {
|
|
4651
|
+
const resultList = [];
|
|
4652
|
+
for (const node of nodes) {
|
|
4653
|
+
const results = await context.reduceNode(node, signal);
|
|
4654
|
+
for (const result of results) if (result !== void 0) resultList.push(result);
|
|
4655
|
+
}
|
|
4656
|
+
return resultList;
|
|
4657
|
+
};
|
|
4658
|
+
};
|
|
4659
|
+
var createReducerBackedTextProgram = (nodes) => {
|
|
4660
|
+
const reducerProgram = createReducerBackedProgram(nodes);
|
|
4661
|
+
return async (context, signal) => {
|
|
4662
|
+
return (await reducerProgram(context, signal)).map((value) => context.convertToString(value)).join("");
|
|
4663
|
+
};
|
|
4664
|
+
};
|
|
4665
|
+
/**
|
|
4666
|
+
* Compile a script with cache.
|
|
4667
|
+
* @param script - Source text.
|
|
4668
|
+
* @param sourceId - Source identifier.
|
|
4669
|
+
* @param mode - Parse mode.
|
|
4670
|
+
* @param backend - Execution backend.
|
|
4671
|
+
* @returns Cached compilation result.
|
|
4672
|
+
*/
|
|
4673
|
+
var compileScriptCached = (script, sourceId, mode, backend, aggressiveOptimize) => {
|
|
4674
|
+
var _sharedDCodegen$gener, _sharedDCodegen$gener2;
|
|
4675
|
+
const resolvedBackend = resolveExecutionBackend(backend);
|
|
4676
|
+
const resolvedAggressiveOptimize = resolveAggressiveOptimize(resolvedBackend, aggressiveOptimize);
|
|
4677
|
+
const cacheKey = toCompilationCacheKey(script, sourceId, mode, resolvedBackend, resolvedAggressiveOptimize);
|
|
4678
|
+
const cached = compiledScriptCache.get(cacheKey);
|
|
4679
|
+
if (cached) {
|
|
4680
|
+
compiledScriptCache.delete(cacheKey);
|
|
4681
|
+
compiledScriptCache.set(cacheKey, cached);
|
|
4682
|
+
return cached;
|
|
4683
|
+
}
|
|
4684
|
+
const logs = [];
|
|
4685
|
+
const tokens = mode === "code" ? runCodeTokenizer(script, logs, sourceId) : runTokenizer(script, logs, sourceId);
|
|
4686
|
+
const nodes = mode === "code" ? parseExpressions(tokens, logs) : runParser(tokens, logs);
|
|
4687
|
+
const sharedDCodegen = isDynamicCodegenBackend(resolvedBackend) ? getSharedDCodegen(resolvedBackend, resolvedAggressiveOptimize) : void 0;
|
|
4688
|
+
const compiled = {
|
|
4689
|
+
sourceId,
|
|
4690
|
+
mode,
|
|
4691
|
+
nodes,
|
|
4692
|
+
logs: logs.slice(),
|
|
4693
|
+
program: (_sharedDCodegen$gener = sharedDCodegen === null || sharedDCodegen === void 0 ? void 0 : sharedDCodegen.generateProgram(nodes)) !== null && _sharedDCodegen$gener !== void 0 ? _sharedDCodegen$gener : createReducerBackedProgram(nodes),
|
|
4694
|
+
textProgram: (_sharedDCodegen$gener2 = sharedDCodegen === null || sharedDCodegen === void 0 ? void 0 : sharedDCodegen.generateTextProgram(nodes)) !== null && _sharedDCodegen$gener2 !== void 0 ? _sharedDCodegen$gener2 : createReducerBackedTextProgram(nodes)
|
|
4695
|
+
};
|
|
4696
|
+
setCompiledScriptCache(cacheKey, compiled);
|
|
4697
|
+
return compiled;
|
|
4698
|
+
};
|
|
4699
|
+
//#endregion
|
|
4700
|
+
Object.defineProperty(exports, "FunCityReducerError", {
|
|
4701
|
+
enumerable: true,
|
|
4702
|
+
get: function() {
|
|
4703
|
+
return FunCityReducerError;
|
|
4704
|
+
}
|
|
4705
|
+
});
|
|
4706
|
+
Object.defineProperty(exports, "buildCandidateVariables", {
|
|
4707
|
+
enumerable: true,
|
|
4708
|
+
get: function() {
|
|
4709
|
+
return buildCandidateVariables;
|
|
4710
|
+
}
|
|
4711
|
+
});
|
|
4712
|
+
Object.defineProperty(exports, "combineVariables", {
|
|
4713
|
+
enumerable: true,
|
|
4714
|
+
get: function() {
|
|
4715
|
+
return combineVariables;
|
|
4716
|
+
}
|
|
4717
|
+
});
|
|
4718
|
+
Object.defineProperty(exports, "compileScriptCached", {
|
|
4719
|
+
enumerable: true,
|
|
4720
|
+
get: function() {
|
|
4721
|
+
return compileScriptCached;
|
|
4722
|
+
}
|
|
4723
|
+
});
|
|
4724
|
+
Object.defineProperty(exports, "compile_cache_exports", {
|
|
4725
|
+
enumerable: true,
|
|
4726
|
+
get: function() {
|
|
4727
|
+
return compile_cache_exports;
|
|
4728
|
+
}
|
|
4729
|
+
});
|
|
4730
|
+
Object.defineProperty(exports, "convertToString", {
|
|
4731
|
+
enumerable: true,
|
|
4732
|
+
get: function() {
|
|
4733
|
+
return convertToString;
|
|
4734
|
+
}
|
|
4735
|
+
});
|
|
4736
|
+
Object.defineProperty(exports, "createDCodegen", {
|
|
4737
|
+
enumerable: true,
|
|
4738
|
+
get: function() {
|
|
4739
|
+
return createDCodegen;
|
|
4740
|
+
}
|
|
4741
|
+
});
|
|
4742
|
+
Object.defineProperty(exports, "createIncludeFunction", {
|
|
4743
|
+
enumerable: true,
|
|
4744
|
+
get: function() {
|
|
4745
|
+
return createIncludeFunction;
|
|
4746
|
+
}
|
|
4747
|
+
});
|
|
4748
|
+
Object.defineProperty(exports, "createParserCursor", {
|
|
4749
|
+
enumerable: true,
|
|
4750
|
+
get: function() {
|
|
4751
|
+
return createParserCursor;
|
|
4752
|
+
}
|
|
4753
|
+
});
|
|
4754
|
+
Object.defineProperty(exports, "createReducerContext", {
|
|
4755
|
+
enumerable: true,
|
|
4756
|
+
get: function() {
|
|
4757
|
+
return createReducerContext;
|
|
4758
|
+
}
|
|
4759
|
+
});
|
|
4760
|
+
Object.defineProperty(exports, "createSharedDCodegenExecutor", {
|
|
4761
|
+
enumerable: true,
|
|
4762
|
+
get: function() {
|
|
4763
|
+
return createSharedDCodegenExecutor;
|
|
4764
|
+
}
|
|
4765
|
+
});
|
|
4766
|
+
Object.defineProperty(exports, "emptyLocation", {
|
|
4767
|
+
enumerable: true,
|
|
4768
|
+
get: function() {
|
|
4769
|
+
return emptyLocation;
|
|
4770
|
+
}
|
|
4771
|
+
});
|
|
4772
|
+
Object.defineProperty(exports, "emptyRange", {
|
|
4773
|
+
enumerable: true,
|
|
4774
|
+
get: function() {
|
|
4775
|
+
return emptyRange;
|
|
4776
|
+
}
|
|
4777
|
+
});
|
|
4778
|
+
Object.defineProperty(exports, "isConditionalTrue", {
|
|
4779
|
+
enumerable: true,
|
|
4780
|
+
get: function() {
|
|
4781
|
+
return isConditionalTrue;
|
|
4782
|
+
}
|
|
4783
|
+
});
|
|
4784
|
+
Object.defineProperty(exports, "isFunCityFunction", {
|
|
4785
|
+
enumerable: true,
|
|
4786
|
+
get: function() {
|
|
4787
|
+
return isFunCityFunction;
|
|
4788
|
+
}
|
|
4789
|
+
});
|
|
4790
|
+
Object.defineProperty(exports, "makeFunCityFunction", {
|
|
4791
|
+
enumerable: true,
|
|
4792
|
+
get: function() {
|
|
4793
|
+
return makeFunCityFunction;
|
|
4794
|
+
}
|
|
4795
|
+
});
|
|
4796
|
+
Object.defineProperty(exports, "outputErrors", {
|
|
4797
|
+
enumerable: true,
|
|
4798
|
+
get: function() {
|
|
4799
|
+
return outputErrors;
|
|
4800
|
+
}
|
|
4801
|
+
});
|
|
4802
|
+
Object.defineProperty(exports, "parseBlock", {
|
|
4803
|
+
enumerable: true,
|
|
4804
|
+
get: function() {
|
|
4805
|
+
return parseBlock;
|
|
4806
|
+
}
|
|
4807
|
+
});
|
|
4808
|
+
Object.defineProperty(exports, "parseExpression", {
|
|
4809
|
+
enumerable: true,
|
|
4810
|
+
get: function() {
|
|
4811
|
+
return parseExpression;
|
|
4812
|
+
}
|
|
4813
|
+
});
|
|
4814
|
+
Object.defineProperty(exports, "parseExpressions", {
|
|
4815
|
+
enumerable: true,
|
|
4816
|
+
get: function() {
|
|
4817
|
+
return parseExpressions;
|
|
4818
|
+
}
|
|
4819
|
+
});
|
|
4820
|
+
Object.defineProperty(exports, "reduceExpressionNode", {
|
|
4821
|
+
enumerable: true,
|
|
4822
|
+
get: function() {
|
|
4823
|
+
return reduceExpressionNode;
|
|
4824
|
+
}
|
|
4825
|
+
});
|
|
4826
|
+
Object.defineProperty(exports, "reduceNode", {
|
|
4827
|
+
enumerable: true,
|
|
4828
|
+
get: function() {
|
|
4829
|
+
return reduceNode;
|
|
4830
|
+
}
|
|
4831
|
+
});
|
|
4832
|
+
Object.defineProperty(exports, "runCodeTokenizer", {
|
|
4833
|
+
enumerable: true,
|
|
4834
|
+
get: function() {
|
|
4835
|
+
return runCodeTokenizer;
|
|
4836
|
+
}
|
|
4837
|
+
});
|
|
4838
|
+
Object.defineProperty(exports, "runDCodegen", {
|
|
4839
|
+
enumerable: true,
|
|
4840
|
+
get: function() {
|
|
4841
|
+
return runDCodegen;
|
|
4842
|
+
}
|
|
4843
|
+
});
|
|
4844
|
+
Object.defineProperty(exports, "runParser", {
|
|
4845
|
+
enumerable: true,
|
|
4846
|
+
get: function() {
|
|
4847
|
+
return runParser;
|
|
4848
|
+
}
|
|
4849
|
+
});
|
|
4850
|
+
Object.defineProperty(exports, "runReducer", {
|
|
4851
|
+
enumerable: true,
|
|
4852
|
+
get: function() {
|
|
4853
|
+
return runReducer;
|
|
4854
|
+
}
|
|
4855
|
+
});
|
|
4856
|
+
Object.defineProperty(exports, "runTokenizer", {
|
|
4857
|
+
enumerable: true,
|
|
4858
|
+
get: function() {
|
|
4859
|
+
return runTokenizer;
|
|
4860
|
+
}
|
|
4861
|
+
});
|
|
4862
|
+
Object.defineProperty(exports, "standardVariables", {
|
|
4863
|
+
enumerable: true,
|
|
4864
|
+
get: function() {
|
|
4865
|
+
return standardVariables;
|
|
4866
|
+
}
|
|
4867
|
+
});
|
|
4868
|
+
|
|
4869
|
+
//# sourceMappingURL=compile-cache-D9XyNhoC.cjs.map
|