funcity 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs ADDED
@@ -0,0 +1,2005 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const emptyLocation = {
4
+ line: 0,
5
+ column: 0
6
+ };
7
+ const emptyRange = {
8
+ start: emptyLocation,
9
+ end: emptyLocation
10
+ };
11
+ const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
12
+ const makeSpecialFunction = (f) => {
13
+ f[specialFunctionMarker] = true;
14
+ return f;
15
+ };
16
+ const isSpecialFunction = (f) => {
17
+ var _a;
18
+ return (_a = f[specialFunctionMarker]) != null ? _a : false;
19
+ };
20
+ const isConditionalTrue = (v) => {
21
+ if (v === void 0 || v === null) {
22
+ return false;
23
+ }
24
+ switch (typeof v) {
25
+ case "boolean":
26
+ return v;
27
+ case "number":
28
+ case "bigint":
29
+ return v !== 0;
30
+ default:
31
+ return true;
32
+ }
33
+ };
34
+ const asIterable = (v) => {
35
+ if (typeof v[Symbol.iterator] === "function") {
36
+ return v;
37
+ } else {
38
+ return void 0;
39
+ }
40
+ };
41
+ const combineVariables = (...variablesList) => {
42
+ const variables = /* @__PURE__ */ new Map();
43
+ const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
44
+ const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
45
+ variablesList.forEach((vs) => {
46
+ if (vs["forEach"] !== void 0) {
47
+ appendVariables(vs);
48
+ } else {
49
+ appendRecord(vs);
50
+ }
51
+ });
52
+ return variables;
53
+ };
54
+ const fromError = (error) => {
55
+ var _a;
56
+ if (error.message) {
57
+ return error.message;
58
+ } else if (typeof error.toString === "function") {
59
+ return (_a = error.toString()) != null ? _a : "unknown";
60
+ } else {
61
+ return "unknown";
62
+ }
63
+ };
64
+ const widerRange = (...ranges) => {
65
+ let start = emptyRange.start;
66
+ let end = emptyRange.end;
67
+ for (const range of ranges) {
68
+ if (range.start.line >= 1 && range.start.column >= 1) {
69
+ if (start.line === 0 || start.column === 0) {
70
+ start = range.start;
71
+ } else if (range.start.line < start.line) {
72
+ start = range.start;
73
+ } else if (range.start.line === start.line && range.start.column < start.column) {
74
+ start = range.start;
75
+ }
76
+ if (end.line === 0 || end.column === 0) {
77
+ end = range.end;
78
+ } else if (range.end.line > end.line) {
79
+ end = range.end;
80
+ } else if (range.end.line === end.line && range.end.column > end.column) {
81
+ end = range.end;
82
+ }
83
+ }
84
+ }
85
+ return { start, end };
86
+ };
87
+ const locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
88
+ const getLocationString = (range) => locationEquals(range.start, range.end) ? `${range.start.line}:${range.start.column}` : `${range.start.line}:${range.start.column}:${range.end.line}:${range.end.column}`;
89
+ const printErrorString = (path, error) => {
90
+ switch (error.type) {
91
+ case "warning":
92
+ console.warn(
93
+ `${path}:${getLocationString(error.range)}: warning: ${error.description}`
94
+ );
95
+ break;
96
+ case "error":
97
+ console.error(
98
+ `${path}:${getLocationString(error.range)}: error: ${error.description}`
99
+ );
100
+ return true;
101
+ }
102
+ return false;
103
+ };
104
+ const outputErrors = (path, errors) => {
105
+ let isError = false;
106
+ for (const error of errors) {
107
+ const result = printErrorString(path, error);
108
+ isError || (isError = result);
109
+ }
110
+ return isError;
111
+ };
112
+ const tokenizeString = (context) => {
113
+ const start = context.cursor.location("start");
114
+ context.cursor.skip(1);
115
+ let value = context.cursor.getUntil("'");
116
+ if (value !== void 0) {
117
+ context.cursor.skip(1);
118
+ } else {
119
+ const location = context.cursor.location("start");
120
+ context.errors.push({
121
+ type: "error",
122
+ description: "string close quote is not found",
123
+ range: { start: location, end: location }
124
+ });
125
+ value = "";
126
+ }
127
+ return {
128
+ kind: "string",
129
+ value,
130
+ range: { start, end: context.cursor.location("end") }
131
+ };
132
+ };
133
+ const firstNumericChars = "0123456789-+";
134
+ const numericCharsWithDot = "0123456789.";
135
+ const numericChars = "0123456789";
136
+ const tokenizeNumber = (context) => {
137
+ const start = context.cursor.location("start");
138
+ let index = 1;
139
+ while (true) {
140
+ if (context.cursor.eot()) {
141
+ return {
142
+ kind: "number",
143
+ value: Number(context.cursor.getRangeAndSkip(index)),
144
+ range: { start, end: context.cursor.location("end") }
145
+ };
146
+ }
147
+ const ch = context.cursor.getChar(index);
148
+ if (numericCharsWithDot.indexOf(ch) < 0) {
149
+ if (ch === ".") {
150
+ break;
151
+ }
152
+ return {
153
+ kind: "number",
154
+ value: Number(context.cursor.getRangeAndSkip(index)),
155
+ range: { start, end: context.cursor.location("end") }
156
+ };
157
+ }
158
+ index++;
159
+ }
160
+ while (true) {
161
+ if (context.cursor.eot()) {
162
+ return {
163
+ kind: "number",
164
+ value: Number(context.cursor.getRangeAndSkip(index)),
165
+ range: { start, end: context.cursor.location("end") }
166
+ };
167
+ }
168
+ const ch = context.cursor.getChar(index);
169
+ if (numericChars.indexOf(ch) < 0) {
170
+ return {
171
+ kind: "number",
172
+ value: Number(context.cursor.getRangeAndSkip(index)),
173
+ range: { start, end: context.cursor.location("end") }
174
+ };
175
+ }
176
+ index++;
177
+ }
178
+ };
179
+ const firstVariableChars = "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
180
+ const variableChars = "_-.?0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
181
+ const tokenizeIdentity = (context) => {
182
+ const start = context.cursor.location("start");
183
+ let index = 1;
184
+ let lastCh = "";
185
+ while (true) {
186
+ if (context.cursor.eot()) {
187
+ break;
188
+ }
189
+ const ch = context.cursor.getChar(index);
190
+ if (variableChars.indexOf(ch) < 0) {
191
+ break;
192
+ }
193
+ if (lastCh === "?") {
194
+ index--;
195
+ break;
196
+ }
197
+ lastCh = ch;
198
+ index++;
199
+ }
200
+ return {
201
+ kind: "identity",
202
+ name: context.cursor.getRangeAndSkip(index),
203
+ range: { start, end: context.cursor.location("end") }
204
+ };
205
+ };
206
+ const tokenizeCodeBlock = (context) => {
207
+ const openStart = context.cursor.location("start");
208
+ context.cursor.skip(2);
209
+ const tokens = [
210
+ {
211
+ kind: "open",
212
+ symbol: "{{",
213
+ range: { start: openStart, end: context.cursor.location("end") }
214
+ }
215
+ ];
216
+ let unknownStartLocation;
217
+ const finalizeUnknown = () => {
218
+ if (unknownStartLocation) {
219
+ context.errors.push({
220
+ type: "warning",
221
+ description: "unknown words",
222
+ range: {
223
+ start: unknownStartLocation,
224
+ end: context.cursor.location("end")
225
+ }
226
+ });
227
+ unknownStartLocation = void 0;
228
+ }
229
+ };
230
+ while (!context.cursor.eot()) {
231
+ if (context.cursor.assert("}}")) {
232
+ finalizeUnknown();
233
+ const location = context.cursor.location("start");
234
+ context.cursor.skip(2);
235
+ tokens.push({
236
+ kind: "close",
237
+ symbol: "}}",
238
+ range: { start: location, end: context.cursor.location("end") }
239
+ });
240
+ return tokens;
241
+ }
242
+ const ch = context.cursor.getChar();
243
+ if (ch === "\\") {
244
+ const next = context.cursor.getChar(1);
245
+ if (next === "{" || next === "}") {
246
+ context.cursor.skip(2);
247
+ continue;
248
+ }
249
+ }
250
+ if (ch === "'") {
251
+ finalizeUnknown();
252
+ tokens.push(tokenizeString(context));
253
+ } else if (firstNumericChars.indexOf(ch) >= 0) {
254
+ finalizeUnknown();
255
+ tokens.push(tokenizeNumber(context));
256
+ } else if (ch === "(") {
257
+ finalizeUnknown();
258
+ const location = context.cursor.location("start");
259
+ tokens.push({
260
+ kind: "open",
261
+ symbol: "(",
262
+ range: { start: location, end: location }
263
+ });
264
+ context.cursor.skip(1);
265
+ } else if (ch === ")") {
266
+ finalizeUnknown();
267
+ const location = context.cursor.location("start");
268
+ tokens.push({
269
+ kind: "close",
270
+ symbol: ")",
271
+ range: { start: location, end: location }
272
+ });
273
+ context.cursor.skip(1);
274
+ } else if (ch === "[") {
275
+ finalizeUnknown();
276
+ const location = context.cursor.location("start");
277
+ tokens.push({
278
+ kind: "open",
279
+ symbol: "[",
280
+ range: { start: location, end: location }
281
+ });
282
+ context.cursor.skip(1);
283
+ } else if (ch === "]") {
284
+ finalizeUnknown();
285
+ const location = context.cursor.location("start");
286
+ tokens.push({
287
+ kind: "close",
288
+ symbol: "]",
289
+ range: { start: location, end: location }
290
+ });
291
+ context.cursor.skip(1);
292
+ } else if (firstVariableChars.indexOf(ch) >= 0) {
293
+ finalizeUnknown();
294
+ tokens.push(tokenizeIdentity(context));
295
+ } else if (ch === "\n") {
296
+ finalizeUnknown();
297
+ const location = context.cursor.location("start");
298
+ tokens.push({
299
+ kind: "eol",
300
+ range: { start: location, end: location }
301
+ });
302
+ context.cursor.skip(1);
303
+ } else if (ch === "\r") {
304
+ finalizeUnknown();
305
+ context.cursor.skip(1);
306
+ } else if (ch === " ") {
307
+ finalizeUnknown();
308
+ context.cursor.skip(1);
309
+ } else if (!unknownStartLocation) {
310
+ unknownStartLocation = context.cursor.location("start");
311
+ context.cursor.skip(1);
312
+ }
313
+ context.cursor.skipChars(" ");
314
+ }
315
+ const causeLocation = context.cursor.location("start");
316
+ context.errors.push({
317
+ type: "error",
318
+ description: "required code block closer: `}}`",
319
+ range: { start: causeLocation, end: causeLocation }
320
+ });
321
+ return tokens;
322
+ };
323
+ const createTokenizerCursor = (text) => {
324
+ let currentIndex = 0;
325
+ let rawLine = 0;
326
+ let rawColumn = 0;
327
+ let lastLine = 0;
328
+ let lastColumn = 0;
329
+ const eot = () => currentIndex >= text.length;
330
+ const getChar = (index) => text[(index != null ? index : 0) + currentIndex];
331
+ const skip = (length) => {
332
+ let lastch = "\0";
333
+ while (length > 0) {
334
+ lastColumn = rawColumn;
335
+ lastLine = rawLine;
336
+ const ch = text[currentIndex];
337
+ if (ch === "\r") {
338
+ rawColumn = 0;
339
+ } else if (ch === "\n" && lastch !== "\r") {
340
+ rawColumn = 0;
341
+ rawLine++;
342
+ } else {
343
+ rawColumn++;
344
+ }
345
+ currentIndex++;
346
+ length--;
347
+ lastch = ch;
348
+ }
349
+ };
350
+ const skipChars = (ch) => {
351
+ while (!eot()) {
352
+ if (getChar() !== ch) {
353
+ return true;
354
+ }
355
+ skip(1);
356
+ }
357
+ return false;
358
+ };
359
+ const skipUntil = (word) => {
360
+ while (!eot()) {
361
+ const index = text.indexOf(word, currentIndex);
362
+ if (index === currentIndex) {
363
+ skip(word.length);
364
+ return true;
365
+ }
366
+ skip(1);
367
+ }
368
+ return false;
369
+ };
370
+ const assert = (word) => {
371
+ if (text.length - currentIndex < word.length) {
372
+ return false;
373
+ }
374
+ if (text.substring(currentIndex, currentIndex + word.length) === word) {
375
+ return true;
376
+ }
377
+ return false;
378
+ };
379
+ const getRangeAndSkip = (length) => {
380
+ const result = text.substring(currentIndex, currentIndex + length);
381
+ skip(result.length);
382
+ return result;
383
+ };
384
+ const getUntil = (word) => {
385
+ if (currentIndex >= text.length) {
386
+ return void 0;
387
+ }
388
+ const index = text.indexOf(word, currentIndex);
389
+ if (index >= 0) {
390
+ const result = text.substring(currentIndex, index);
391
+ skip(index - currentIndex);
392
+ return result;
393
+ } else {
394
+ const result = text.substring(currentIndex, text.length);
395
+ skip(text.length - currentIndex);
396
+ return result;
397
+ }
398
+ };
399
+ const location = (type) => type === "end" ? {
400
+ line: lastLine + 1,
401
+ column: lastColumn + 1
402
+ } : {
403
+ line: rawLine + 1,
404
+ column: rawColumn + 1
405
+ };
406
+ return {
407
+ eot,
408
+ getChar,
409
+ skip,
410
+ skipChars,
411
+ skipUntil,
412
+ assert,
413
+ getRangeAndSkip,
414
+ getUntil,
415
+ location
416
+ };
417
+ };
418
+ const runTokenizer = (script, errors) => {
419
+ const context = {
420
+ cursor: createTokenizerCursor(script),
421
+ errors
422
+ };
423
+ const tokens = [];
424
+ const readTextBlock = () => {
425
+ if (context.cursor.eot()) {
426
+ return void 0;
427
+ }
428
+ let text = "";
429
+ while (!context.cursor.eot()) {
430
+ if (context.cursor.assert("{{")) {
431
+ return text;
432
+ }
433
+ const ch = context.cursor.getChar();
434
+ if (ch === "\\") {
435
+ const next = context.cursor.getChar(1);
436
+ if (next === "{" || next === "}") {
437
+ text += next;
438
+ context.cursor.skip(2);
439
+ continue;
440
+ }
441
+ }
442
+ text += ch;
443
+ context.cursor.skip(1);
444
+ }
445
+ return text;
446
+ };
447
+ while (!context.cursor.eot()) {
448
+ const start = context.cursor.location("start");
449
+ const text = readTextBlock();
450
+ if (text) {
451
+ tokens.push({
452
+ kind: "text",
453
+ text,
454
+ range: { start, end: context.cursor.location("end") }
455
+ });
456
+ } else {
457
+ tokens.push(...tokenizeCodeBlock(context));
458
+ }
459
+ }
460
+ return tokens;
461
+ };
462
+ const parseNumber = (cursor, _errors) => {
463
+ const token = cursor.takeToken();
464
+ return {
465
+ kind: "number",
466
+ value: token.value,
467
+ range: token.range
468
+ };
469
+ };
470
+ const parseString = (cursor, _errors) => {
471
+ const token = cursor.takeToken();
472
+ return {
473
+ kind: "string",
474
+ value: token.value,
475
+ range: token.range
476
+ };
477
+ };
478
+ const parseIdentity = (cursor, _errors) => {
479
+ const token = cursor.takeToken();
480
+ return {
481
+ kind: "variable",
482
+ name: token.name,
483
+ range: token.range
484
+ };
485
+ };
486
+ const unitKind = "'()'";
487
+ const combineIntoScopeMultipleExpressions = (expressionList, ...outerRanges) => {
488
+ switch (expressionList.length) {
489
+ case 0: {
490
+ return void 0;
491
+ }
492
+ case 1: {
493
+ return expressionList[0];
494
+ }
495
+ default: {
496
+ return {
497
+ kind: "scope",
498
+ nodes: expressionList,
499
+ range: widerRange(
500
+ ...expressionList.map((node) => node.range),
501
+ ...outerRanges
502
+ )
503
+ };
504
+ }
505
+ }
506
+ };
507
+ const parseLambdaExpression = (cursor, errors) => {
508
+ const funToken = cursor.takeToken();
509
+ const namesPartial = parsePartialExpression(cursor, errors);
510
+ const bodyPartial = namesPartial ? parsePartialExpression(cursor, errors) : void 0;
511
+ if (!namesPartial || !bodyPartial) {
512
+ const ranges = [funToken.range];
513
+ if (namesPartial) {
514
+ ranges.push(namesPartial.range);
515
+ }
516
+ if (bodyPartial) {
517
+ ranges.push(bodyPartial.range);
518
+ }
519
+ errors.push({
520
+ type: "error",
521
+ description: "Required `fun` parameter identity and expression",
522
+ range: widerRange(...ranges)
523
+ });
524
+ return void 0;
525
+ }
526
+ const namesNode = normalizePartialUnitNode(namesPartial, errors);
527
+ if (namesNode.kind !== "variable" && namesNode.kind !== "list") {
528
+ errors.push({
529
+ type: "error",
530
+ description: "Required `fun` parameter identity",
531
+ range: namesNode.range
532
+ });
533
+ return void 0;
534
+ }
535
+ const nameNodes = extractParameterArguments(namesNode, errors);
536
+ if (!nameNodes) {
537
+ return void 0;
538
+ }
539
+ const bodyNode = normalizePartialUnitNode(bodyPartial, errors);
540
+ return {
541
+ kind: "lambda",
542
+ names: nameNodes,
543
+ body: bodyNode,
544
+ range: widerRange(funToken.range, namesNode.range, bodyNode.range)
545
+ };
546
+ };
547
+ const parsePartialExpression = (cursor, errors) => {
548
+ const token = cursor.peekToken();
549
+ switch (token.kind) {
550
+ case "number": {
551
+ const node = parseNumber(cursor);
552
+ return node;
553
+ }
554
+ case "string": {
555
+ const node = parseString(cursor);
556
+ return node;
557
+ }
558
+ case "identity": {
559
+ if (token.name === "fun") {
560
+ const node2 = parseLambdaExpression(cursor, errors);
561
+ return node2;
562
+ }
563
+ const node = parseIdentity(cursor);
564
+ return node;
565
+ }
566
+ case "open": {
567
+ cursor.takeToken();
568
+ switch (token.symbol) {
569
+ // Parenthesis surrounding expression list `( ... )` (Scope)
570
+ case "(": {
571
+ const innerNodes = parseMultipleApplicationExpressions(
572
+ cursor,
573
+ errors
574
+ );
575
+ const closeToken = cursor.peekToken();
576
+ let range;
577
+ if (!closeToken) {
578
+ range = widerRange(
579
+ token.range,
580
+ ...innerNodes.map((node) => node.range)
581
+ );
582
+ errors.push({
583
+ type: "error",
584
+ description: "Could not find close parenthesis",
585
+ range: widerRange(
586
+ token.range,
587
+ ...innerNodes.map((node) => node.range)
588
+ )
589
+ });
590
+ } else {
591
+ cursor.takeToken();
592
+ range = widerRange(
593
+ token.range,
594
+ ...innerNodes.map((node) => node.range),
595
+ closeToken.range
596
+ );
597
+ if (closeToken.kind !== "close" || closeToken.symbol !== ")") {
598
+ errors.push({
599
+ type: "error",
600
+ description: `Mismatched close parenthesis`,
601
+ range
602
+ });
603
+ }
604
+ }
605
+ if (innerNodes.length === 0) {
606
+ return {
607
+ kind: unitKind,
608
+ range
609
+ };
610
+ } else {
611
+ const node = combineIntoScopeMultipleExpressions(innerNodes, range);
612
+ return node;
613
+ }
614
+ }
615
+ // Bracket surrounding expression list `[ ... ]` (Iterable list)
616
+ case "[": {
617
+ const itemNodes = parseListExpression(cursor, errors);
618
+ const closeToken = cursor.peekToken();
619
+ let range;
620
+ if (!closeToken) {
621
+ range = widerRange(
622
+ token.range,
623
+ ...itemNodes.map((node) => node.range)
624
+ );
625
+ errors.push({
626
+ type: "error",
627
+ description: "Could not find close bracket",
628
+ range
629
+ });
630
+ } else {
631
+ cursor.takeToken();
632
+ range = widerRange(
633
+ token.range,
634
+ ...itemNodes.map((node) => node.range),
635
+ closeToken.range
636
+ );
637
+ if (closeToken.kind !== "close" || closeToken.symbol !== "]") {
638
+ errors.push({
639
+ type: "error",
640
+ description: `Mismatched close bracket`,
641
+ range
642
+ });
643
+ }
644
+ }
645
+ return {
646
+ kind: "list",
647
+ items: itemNodes,
648
+ range
649
+ };
650
+ }
651
+ default: {
652
+ errors.push({
653
+ type: "error",
654
+ description: `Invalid open parenthesis/bracket`,
655
+ range: token.range
656
+ });
657
+ return void 0;
658
+ }
659
+ }
660
+ }
661
+ }
662
+ return void 0;
663
+ };
664
+ const normalizePartialUnitNode = (node, errors) => {
665
+ if (node.kind === unitKind) {
666
+ errors.push({
667
+ type: "error",
668
+ description: `Invalid ${unitKind} at this location`,
669
+ range: node.range
670
+ });
671
+ return {
672
+ kind: "variable",
673
+ name: "undefined",
674
+ range: node.range
675
+ };
676
+ } else {
677
+ return node;
678
+ }
679
+ };
680
+ const finalizeApplicationException = (partialNodes, errors) => {
681
+ if (partialNodes.length === 0) {
682
+ return;
683
+ }
684
+ if (partialNodes.length === 1) {
685
+ return normalizePartialUnitNode(partialNodes[0], errors);
686
+ }
687
+ const func = partialNodes[0];
688
+ if (func.kind !== "variable" && func.kind !== "lambda") {
689
+ errors.push({
690
+ type: "error",
691
+ description: `Invalid ${func.kind} at this location`,
692
+ range: func.range
693
+ });
694
+ return void 0;
695
+ }
696
+ const arg0 = partialNodes[1];
697
+ if (arg0.kind === unitKind) {
698
+ return {
699
+ kind: "apply",
700
+ func,
701
+ args: [],
702
+ // Unit application: `foobar ()`
703
+ range: widerRange(func.range, arg0.range)
704
+ };
705
+ }
706
+ const args = partialNodes.slice(1).map((node) => normalizePartialUnitNode(node, errors));
707
+ return {
708
+ kind: "apply",
709
+ func,
710
+ args,
711
+ range: widerRange(func.range, ...args.map((node) => node.range))
712
+ };
713
+ };
714
+ const parseMultipleApplicationExpressions = (cursor, errors) => {
715
+ const expressionList = [];
716
+ const partialNodes = [];
717
+ while (true) {
718
+ const token = cursor.peekToken();
719
+ if (!token) {
720
+ break;
721
+ }
722
+ switch (token.kind) {
723
+ case "eol": {
724
+ cursor.takeToken();
725
+ const expr2 = finalizeApplicationException(partialNodes, errors);
726
+ if (expr2) {
727
+ expressionList.push(expr2);
728
+ }
729
+ partialNodes.length = 0;
730
+ continue;
731
+ }
732
+ }
733
+ const partialNode = parsePartialExpression(cursor, errors);
734
+ if (!partialNode) {
735
+ break;
736
+ }
737
+ partialNodes.push(partialNode);
738
+ }
739
+ const expr = finalizeApplicationException(partialNodes, errors);
740
+ if (expr) {
741
+ expressionList.push(expr);
742
+ }
743
+ return expressionList;
744
+ };
745
+ const parseListExpression = (cursor, errors) => {
746
+ const itemNodes = [];
747
+ while (true) {
748
+ const token = cursor.peekToken();
749
+ if (!token) {
750
+ break;
751
+ }
752
+ switch (token.kind) {
753
+ case "eol": {
754
+ continue;
755
+ }
756
+ }
757
+ const partialNode = parsePartialExpression(cursor, errors);
758
+ if (!partialNode) {
759
+ break;
760
+ }
761
+ itemNodes.push(normalizePartialUnitNode(partialNode, errors));
762
+ }
763
+ return itemNodes;
764
+ };
765
+ const drainEndOfLineAndPeek = (cursor) => {
766
+ let token = cursor.peekToken();
767
+ while (token) {
768
+ if (token.kind === "eol") {
769
+ cursor.takeToken();
770
+ } else {
771
+ break;
772
+ }
773
+ token = cursor.peekToken();
774
+ }
775
+ return token;
776
+ };
777
+ const parseExpression = (cursor, errors) => {
778
+ let token = drainEndOfLineAndPeek(cursor);
779
+ if (!token) {
780
+ return void 0;
781
+ }
782
+ const partialNodes = [];
783
+ while (true) {
784
+ const partialNode = parsePartialExpression(cursor, errors);
785
+ if (!partialNode) {
786
+ break;
787
+ }
788
+ partialNodes.push(partialNode);
789
+ token = cursor.peekToken();
790
+ if (!token) {
791
+ break;
792
+ }
793
+ if (token.kind === "eol") {
794
+ cursor.takeToken();
795
+ token = cursor.peekToken();
796
+ break;
797
+ }
798
+ }
799
+ drainEndOfLineAndPeek(cursor);
800
+ const expr = finalizeApplicationException(partialNodes, errors);
801
+ return expr;
802
+ };
803
+ const createBranchState = () => ({
804
+ blocks: [],
805
+ exprBuffer: []
806
+ });
807
+ const getBranchState = (statementState) => {
808
+ switch (statementState.kind) {
809
+ case "root": {
810
+ return statementState.branch;
811
+ }
812
+ case "if": {
813
+ return statementState.currentBlock === "then" ? statementState.then : statementState.else;
814
+ }
815
+ case "while":
816
+ case "for": {
817
+ return statementState.repeat;
818
+ }
819
+ }
820
+ };
821
+ const flushExpressions = (branch) => {
822
+ if (branch.exprBuffer.length === 0) {
823
+ return;
824
+ }
825
+ if (branch.exprBuffer.length === 1) {
826
+ branch.blocks.push(branch.exprBuffer[0]);
827
+ } else {
828
+ branch.blocks.push({
829
+ kind: "scope",
830
+ nodes: branch.exprBuffer,
831
+ range: widerRange(...branch.exprBuffer.map((node) => node.range))
832
+ });
833
+ }
834
+ branch.exprBuffer = [];
835
+ };
836
+ const flushCurrentBranch = (statementStates) => {
837
+ const statementState = statementStates[statementStates.length - 1];
838
+ flushExpressions(getBranchState(statementState));
839
+ };
840
+ const flushStatementState = (statementState) => {
841
+ switch (statementState.kind) {
842
+ case "root": {
843
+ flushExpressions(statementState.branch);
844
+ break;
845
+ }
846
+ case "if": {
847
+ flushExpressions(statementState.then);
848
+ flushExpressions(statementState.else);
849
+ break;
850
+ }
851
+ case "while":
852
+ case "for": {
853
+ flushExpressions(statementState.repeat);
854
+ break;
855
+ }
856
+ }
857
+ };
858
+ const pushExpressionNode = (statementStates, node) => {
859
+ const statementState = statementStates[statementStates.length - 1];
860
+ const branch = getBranchState(statementState);
861
+ branch.exprBuffer.push(node);
862
+ };
863
+ const pushBlockNode = (statementStates, node) => {
864
+ const statementState = statementStates[statementStates.length - 1];
865
+ const branch = getBranchState(statementState);
866
+ flushExpressions(branch);
867
+ branch.blocks.push(node);
868
+ };
869
+ const pushNode = (statementStates, node) => {
870
+ switch (node.kind) {
871
+ case "text":
872
+ case "if":
873
+ case "while":
874
+ case "for": {
875
+ pushBlockNode(statementStates, node);
876
+ break;
877
+ }
878
+ default: {
879
+ pushExpressionNode(statementStates, node);
880
+ break;
881
+ }
882
+ }
883
+ };
884
+ const parseStatementArguments = (cursor, errors) => {
885
+ const args = [];
886
+ while (true) {
887
+ const token = cursor.peekToken();
888
+ if (!token) {
889
+ break;
890
+ }
891
+ if (token.kind === "eol") {
892
+ cursor.takeToken();
893
+ break;
894
+ }
895
+ const partialNode = parsePartialExpression(cursor, errors);
896
+ if (!partialNode) {
897
+ break;
898
+ }
899
+ args.push(normalizePartialUnitNode(partialNode, errors));
900
+ }
901
+ return args;
902
+ };
903
+ const extractParameterArguments = (namesNode, errors) => {
904
+ switch (namesNode.kind) {
905
+ case "variable": {
906
+ return [namesNode];
907
+ }
908
+ case "list": {
909
+ const nameNodes = [];
910
+ for (const nameNode of namesNode.items) {
911
+ if (nameNode.kind !== "variable") {
912
+ errors.push({
913
+ type: "error",
914
+ description: "Required lambda parameter identity",
915
+ range: nameNode.range
916
+ });
917
+ } else {
918
+ nameNodes.push(nameNode);
919
+ }
920
+ }
921
+ return nameNodes;
922
+ }
923
+ default: {
924
+ errors.push({
925
+ type: "error",
926
+ description: "Required lambda parameter identity",
927
+ range: namesNode.range
928
+ });
929
+ return void 0;
930
+ }
931
+ }
932
+ };
933
+ const parseBlock = (cursor, errors) => {
934
+ const rootState = {
935
+ kind: "root",
936
+ startRange: emptyRange,
937
+ branch: createBranchState()
938
+ };
939
+ const statementStates = [rootState];
940
+ let isInExpressionBlock = false;
941
+ while (true) {
942
+ const token = drainEndOfLineAndPeek(cursor);
943
+ if (!token) {
944
+ break;
945
+ }
946
+ switch (token.kind) {
947
+ case "text": {
948
+ cursor.takeToken();
949
+ if (isInExpressionBlock) {
950
+ errors.push({
951
+ type: "error",
952
+ description: `Already opened expression block (tokenizer bug?)`,
953
+ range: token.range
954
+ });
955
+ break;
956
+ }
957
+ pushNode(statementStates, {
958
+ kind: "text",
959
+ text: token.text,
960
+ range: token.range
961
+ });
962
+ break;
963
+ }
964
+ case "open": {
965
+ if (token.symbol === "{{") {
966
+ cursor.takeToken();
967
+ if (isInExpressionBlock) {
968
+ errors.push({
969
+ type: "error",
970
+ description: `Already opened expression block`,
971
+ range: token.range
972
+ });
973
+ }
974
+ isInExpressionBlock = true;
975
+ } else {
976
+ const node = parseExpression(cursor, errors);
977
+ if (node) {
978
+ pushNode(statementStates, node);
979
+ }
980
+ }
981
+ break;
982
+ }
983
+ case "close": {
984
+ cursor.takeToken();
985
+ if (!isInExpressionBlock) {
986
+ errors.push({
987
+ type: "error",
988
+ description: `Mismatched close bracket`,
989
+ range: token.range
990
+ });
991
+ break;
992
+ }
993
+ flushCurrentBranch(statementStates);
994
+ isInExpressionBlock = false;
995
+ break;
996
+ }
997
+ case "identity": {
998
+ if (!isInExpressionBlock) {
999
+ errors.push({
1000
+ type: "error",
1001
+ description: `Invalid identity (tokenizer bug?)`,
1002
+ range: token.range
1003
+ });
1004
+ break;
1005
+ }
1006
+ switch (token.name) {
1007
+ case "if": {
1008
+ cursor.takeToken();
1009
+ const args = parseStatementArguments(cursor, errors);
1010
+ if (args.length !== 1) {
1011
+ errors.push({
1012
+ type: "error",
1013
+ description: "Required `if` condition",
1014
+ range: widerRange(
1015
+ token.range,
1016
+ ...args.map((node) => node.range)
1017
+ )
1018
+ });
1019
+ break;
1020
+ }
1021
+ const conditionNode = args[0];
1022
+ statementStates.push({
1023
+ kind: "if",
1024
+ startRange: token.range,
1025
+ condition: conditionNode,
1026
+ then: createBranchState(),
1027
+ else: createBranchState(),
1028
+ currentBlock: "then"
1029
+ });
1030
+ break;
1031
+ }
1032
+ case "else": {
1033
+ cursor.takeToken();
1034
+ const args = parseStatementArguments(cursor, errors);
1035
+ if (args.length !== 0) {
1036
+ errors.push({
1037
+ type: "error",
1038
+ description: "Could not take any arguments in `else` statement",
1039
+ range: widerRange(
1040
+ token.range,
1041
+ ...args.map((node) => node.range)
1042
+ )
1043
+ });
1044
+ }
1045
+ if (statementStates.length <= 1) {
1046
+ errors.push({
1047
+ type: "error",
1048
+ description: "Cound not find pair of `if` statement",
1049
+ range: token.range
1050
+ });
1051
+ break;
1052
+ }
1053
+ const lastState = statementStates[statementStates.length - 1];
1054
+ if (lastState.kind !== "if") {
1055
+ errors.push({
1056
+ type: "error",
1057
+ description: "Cound not find pair of `if` statement",
1058
+ range: token.range
1059
+ });
1060
+ break;
1061
+ }
1062
+ if (lastState.currentBlock === "else") {
1063
+ errors.push({
1064
+ type: "error",
1065
+ description: "Duplicated `else` statement",
1066
+ range: token.range
1067
+ });
1068
+ break;
1069
+ }
1070
+ flushExpressions(lastState.then);
1071
+ lastState.currentBlock = "else";
1072
+ break;
1073
+ }
1074
+ case "while": {
1075
+ cursor.takeToken();
1076
+ const args = parseStatementArguments(cursor, errors);
1077
+ if (args.length !== 1) {
1078
+ errors.push({
1079
+ type: "error",
1080
+ description: "Required `while` condition",
1081
+ range: widerRange(
1082
+ token.range,
1083
+ ...args.map((node) => node.range)
1084
+ )
1085
+ });
1086
+ break;
1087
+ }
1088
+ const conditionNode = args[0];
1089
+ statementStates.push({
1090
+ kind: "while",
1091
+ startRange: token.range,
1092
+ condition: conditionNode,
1093
+ repeat: createBranchState()
1094
+ });
1095
+ break;
1096
+ }
1097
+ case "for": {
1098
+ cursor.takeToken();
1099
+ const args = parseStatementArguments(cursor, errors);
1100
+ if (args.length !== 2) {
1101
+ errors.push({
1102
+ type: "error",
1103
+ description: "Required `for` bind identity and iterable expression",
1104
+ range: widerRange(
1105
+ token.range,
1106
+ ...args.map((node) => node.range)
1107
+ )
1108
+ });
1109
+ break;
1110
+ }
1111
+ const bindNode = args[0];
1112
+ if (bindNode.kind !== "variable") {
1113
+ errors.push({
1114
+ type: "error",
1115
+ description: "Required `for` bind identity",
1116
+ range: bindNode.range
1117
+ });
1118
+ break;
1119
+ }
1120
+ const iterableNode = args[1];
1121
+ statementStates.push({
1122
+ kind: "for",
1123
+ startRange: token.range,
1124
+ bind: bindNode,
1125
+ iterable: iterableNode,
1126
+ repeat: createBranchState()
1127
+ });
1128
+ break;
1129
+ }
1130
+ case "end": {
1131
+ cursor.takeToken();
1132
+ const args = parseStatementArguments(cursor, errors);
1133
+ if (args.length !== 0) {
1134
+ errors.push({
1135
+ type: "error",
1136
+ description: "Could not take any arguments in `end` statement",
1137
+ range: widerRange(
1138
+ token.range,
1139
+ ...args.map((node) => node.range)
1140
+ )
1141
+ });
1142
+ }
1143
+ if (statementStates.length <= 1) {
1144
+ errors.push({
1145
+ type: "error",
1146
+ description: "Cound not find pair of `if`,`while` or `for` statement",
1147
+ range: token.range
1148
+ });
1149
+ break;
1150
+ }
1151
+ const lastState = statementStates.pop();
1152
+ flushStatementState(lastState);
1153
+ switch (lastState.kind) {
1154
+ case "if": {
1155
+ pushNode(statementStates, {
1156
+ kind: "if",
1157
+ condition: lastState.condition,
1158
+ then: lastState.then.blocks,
1159
+ else: lastState.else.blocks,
1160
+ range: widerRange(
1161
+ lastState.startRange,
1162
+ lastState.condition.range,
1163
+ ...lastState.then.blocks.map((node) => node.range),
1164
+ ...lastState.else.blocks.map((node) => node.range),
1165
+ token.range
1166
+ )
1167
+ });
1168
+ break;
1169
+ }
1170
+ case "while": {
1171
+ pushNode(statementStates, {
1172
+ kind: "while",
1173
+ condition: lastState.condition,
1174
+ repeat: lastState.repeat.blocks,
1175
+ range: widerRange(
1176
+ lastState.startRange,
1177
+ lastState.condition.range,
1178
+ ...lastState.repeat.blocks.map((node) => node.range),
1179
+ token.range
1180
+ )
1181
+ });
1182
+ break;
1183
+ }
1184
+ case "for": {
1185
+ pushNode(statementStates, {
1186
+ kind: "for",
1187
+ bind: lastState.bind,
1188
+ iterable: lastState.iterable,
1189
+ repeat: lastState.repeat.blocks,
1190
+ range: widerRange(
1191
+ lastState.startRange,
1192
+ lastState.bind.range,
1193
+ ...lastState.repeat.blocks.map((node) => node.range),
1194
+ token.range
1195
+ )
1196
+ });
1197
+ break;
1198
+ }
1199
+ }
1200
+ break;
1201
+ }
1202
+ case "set": {
1203
+ cursor.takeToken();
1204
+ const args = parseStatementArguments(cursor, errors);
1205
+ if (args.length !== 2) {
1206
+ errors.push({
1207
+ type: "error",
1208
+ description: "Required `set` bind identity and expression",
1209
+ range: widerRange(
1210
+ token.range,
1211
+ ...args.map((node) => node.range)
1212
+ )
1213
+ });
1214
+ break;
1215
+ }
1216
+ const bindNode = args[0];
1217
+ if (bindNode.kind !== "variable") {
1218
+ errors.push({
1219
+ type: "error",
1220
+ description: "Required `set` bind identity",
1221
+ range: bindNode.range
1222
+ });
1223
+ break;
1224
+ }
1225
+ const exprNode = args[1];
1226
+ pushNode(statementStates, {
1227
+ kind: "set",
1228
+ name: bindNode,
1229
+ expr: exprNode,
1230
+ range: widerRange(token.range, bindNode.range, exprNode.range)
1231
+ });
1232
+ break;
1233
+ }
1234
+ default: {
1235
+ const node = parseExpression(cursor, errors);
1236
+ if (node) {
1237
+ pushNode(statementStates, node);
1238
+ }
1239
+ break;
1240
+ }
1241
+ }
1242
+ break;
1243
+ }
1244
+ default: {
1245
+ if (!isInExpressionBlock) {
1246
+ errors.push({
1247
+ type: "error",
1248
+ description: `Invalid ${token.kind} (tokenizer bug?)`,
1249
+ range: token.range
1250
+ });
1251
+ break;
1252
+ }
1253
+ const node = parseExpression(cursor, errors);
1254
+ if (node) {
1255
+ pushNode(statementStates, node);
1256
+ }
1257
+ break;
1258
+ }
1259
+ }
1260
+ }
1261
+ flushStatementState(rootState);
1262
+ if (statementStates.length !== 1) {
1263
+ errors.push({
1264
+ type: "error",
1265
+ description: `Could not find statement closing`,
1266
+ range: widerRange(...statementStates.map((state) => state.startRange))
1267
+ });
1268
+ }
1269
+ return rootState.branch.blocks;
1270
+ };
1271
+ const createParserCursor = (tokens) => {
1272
+ let index = 0;
1273
+ const peekToken = () => {
1274
+ return tokens[index];
1275
+ };
1276
+ const takeToken = () => {
1277
+ if (index >= tokens.length) {
1278
+ return void 0;
1279
+ }
1280
+ const token = tokens[index];
1281
+ index++;
1282
+ return token;
1283
+ };
1284
+ return {
1285
+ peekToken,
1286
+ takeToken
1287
+ };
1288
+ };
1289
+ const runParser = (tokens, errors) => {
1290
+ const cursor = createParserCursor(tokens);
1291
+ const blockNodes = parseBlock(cursor, errors);
1292
+ return blockNodes;
1293
+ };
1294
+ const deconstructConditionalCombine = (name) => {
1295
+ if (name.length >= 1) {
1296
+ const last = name[name.length - 1];
1297
+ if (last === "?") {
1298
+ return {
1299
+ name: name.substring(0, name.length - 1),
1300
+ canIgnore: true
1301
+ };
1302
+ }
1303
+ }
1304
+ return {
1305
+ name,
1306
+ canIgnore: false
1307
+ };
1308
+ };
1309
+ const traverseVariable = (context, name) => {
1310
+ const names = name.name.split(".");
1311
+ const n0 = names[0];
1312
+ const n0r = deconstructConditionalCombine(n0);
1313
+ const result0 = context.getValue(n0r.name);
1314
+ if (!result0.isFound) {
1315
+ if (!n0r.canIgnore) {
1316
+ context.appendError({
1317
+ type: "error",
1318
+ description: `variable is not bound: ${names[0]}`,
1319
+ range: name.range
1320
+ });
1321
+ }
1322
+ return void 0;
1323
+ }
1324
+ let value = result0.value;
1325
+ for (const n of names.slice(1)) {
1326
+ const nr = deconstructConditionalCombine(n);
1327
+ if (typeof value === "object") {
1328
+ const r = value;
1329
+ const v = r[nr.name];
1330
+ value = v;
1331
+ } else {
1332
+ if (!nr.canIgnore) {
1333
+ context.appendError({
1334
+ type: "error",
1335
+ description: `variable is not bound: ${n}`,
1336
+ range: name.range
1337
+ });
1338
+ }
1339
+ return void 0;
1340
+ }
1341
+ }
1342
+ return value;
1343
+ };
1344
+ const fromLambda = (context, lambda) => {
1345
+ return async (...args) => {
1346
+ if (args.length < lambda.names.length) {
1347
+ context.appendError({
1348
+ type: "error",
1349
+ description: `Arguments are not filled: ${args.length} < ${lambda.names.length}`,
1350
+ range: lambda.range
1351
+ });
1352
+ return void 0;
1353
+ } else if (args.length > lambda.names.length) {
1354
+ context.appendError({
1355
+ type: "warning",
1356
+ description: `Too many arguments: ${args.length} > ${lambda.names.length}`,
1357
+ range: lambda.range
1358
+ });
1359
+ }
1360
+ const newContext = context.newScope();
1361
+ for (let index = 0; index < lambda.names.length; index++) {
1362
+ newContext.setValue(lambda.names[index].name, args[index]);
1363
+ }
1364
+ const result = await reduceExpressionNode(newContext, lambda.body);
1365
+ return result;
1366
+ };
1367
+ };
1368
+ const reduceExpressionNode = async (context, node) => {
1369
+ switch (node.kind) {
1370
+ case "number":
1371
+ case "string": {
1372
+ return node.value;
1373
+ }
1374
+ case "variable": {
1375
+ return traverseVariable(context, node);
1376
+ }
1377
+ case "apply": {
1378
+ const func = await reduceExpressionNode(context, node.func);
1379
+ if (typeof func !== "function") {
1380
+ context.appendError({
1381
+ type: "error",
1382
+ description: "could not apply it for function",
1383
+ range: node.range
1384
+ });
1385
+ return void 0;
1386
+ }
1387
+ const thisProxy = context.createFunctionContext(node);
1388
+ if (isSpecialFunction(func)) {
1389
+ const value = await func.call(thisProxy, ...node.args);
1390
+ return value;
1391
+ } else {
1392
+ const args = await Promise.all(
1393
+ node.args.map(async (argNode) => {
1394
+ try {
1395
+ const arg = await reduceExpressionNode(context, argNode);
1396
+ return arg;
1397
+ } catch (e) {
1398
+ context.appendError({
1399
+ type: "error",
1400
+ description: fromError(e),
1401
+ range: argNode.range
1402
+ });
1403
+ return void 0;
1404
+ }
1405
+ })
1406
+ );
1407
+ const value = await func.call(thisProxy, ...args);
1408
+ return value;
1409
+ }
1410
+ }
1411
+ case "lambda": {
1412
+ return fromLambda(context, node);
1413
+ }
1414
+ case "list": {
1415
+ const results = await Promise.all(
1416
+ node.items.map((item) => reduceExpressionNode(context, item))
1417
+ );
1418
+ return results;
1419
+ }
1420
+ case "set": {
1421
+ const expr = await reduceExpressionNode(context, node.expr);
1422
+ context.setValue(node.name.name, expr);
1423
+ return void 0;
1424
+ }
1425
+ case "scope": {
1426
+ if (node.nodes.length === 0) {
1427
+ return [];
1428
+ }
1429
+ let index = 0;
1430
+ while (!context.isFailed()) {
1431
+ const result = await reduceExpressionNode(context, node.nodes[index]);
1432
+ index++;
1433
+ if (index >= node.nodes.length) {
1434
+ return result;
1435
+ }
1436
+ }
1437
+ return void 0;
1438
+ }
1439
+ }
1440
+ };
1441
+ const reduceNode = async (context, node) => {
1442
+ switch (node.kind) {
1443
+ case "text": {
1444
+ return [node.text];
1445
+ }
1446
+ case "for": {
1447
+ const result = await reduceExpressionNode(context, node.iterable);
1448
+ const iterable = asIterable(result);
1449
+ if (!iterable) {
1450
+ context.appendError({
1451
+ type: "error",
1452
+ description: "could not apply it for function",
1453
+ range: node.range
1454
+ });
1455
+ return [];
1456
+ }
1457
+ const resultList = [];
1458
+ for (const item of iterable) {
1459
+ if (context.isFailed()) {
1460
+ break;
1461
+ }
1462
+ context.setValue(node.bind.name, item);
1463
+ for (const repeat of node.repeat) {
1464
+ const results = await reduceNode(context, repeat);
1465
+ resultList.push(...results);
1466
+ }
1467
+ }
1468
+ return resultList;
1469
+ }
1470
+ case "while": {
1471
+ const resultList = [];
1472
+ while (!context.isFailed()) {
1473
+ const condition = await reduceExpressionNode(context, node.condition);
1474
+ if (!isConditionalTrue(condition)) {
1475
+ break;
1476
+ }
1477
+ for (const repeat of node.repeat) {
1478
+ const results = await reduceNode(context, repeat);
1479
+ resultList.push(...results);
1480
+ }
1481
+ }
1482
+ return resultList;
1483
+ }
1484
+ case "if": {
1485
+ const resultList = [];
1486
+ const condition = await reduceExpressionNode(context, node.condition);
1487
+ if (isConditionalTrue(condition)) {
1488
+ for (const then of node.then) {
1489
+ const results = await reduceNode(context, then);
1490
+ resultList.push(...results);
1491
+ }
1492
+ } else {
1493
+ for (const els of node.else) {
1494
+ const results = await reduceNode(context, els);
1495
+ resultList.push(...results);
1496
+ }
1497
+ }
1498
+ return resultList;
1499
+ }
1500
+ default: {
1501
+ const result = await reduceExpressionNode(context, node);
1502
+ return [result];
1503
+ }
1504
+ }
1505
+ };
1506
+ const createReducerContext = (variables, errors) => {
1507
+ let vs = variables;
1508
+ let mvs;
1509
+ let variablesProxy;
1510
+ const getValue = (name) => {
1511
+ if (vs.has(name)) {
1512
+ return { value: vs.get(name), isFound: true };
1513
+ } else {
1514
+ return { value: void 0, isFound: false };
1515
+ }
1516
+ };
1517
+ const setValue = (name, value) => {
1518
+ if (!mvs) {
1519
+ mvs = new Map(vs);
1520
+ vs = mvs;
1521
+ }
1522
+ mvs.set(name, value);
1523
+ if (variablesProxy !== void 0) {
1524
+ Object.defineProperty(variablesProxy, name, {
1525
+ get() {
1526
+ return vs.get(name);
1527
+ },
1528
+ configurable: true,
1529
+ enumerable: true
1530
+ });
1531
+ }
1532
+ };
1533
+ const appendError = (error) => {
1534
+ errors.push(error);
1535
+ };
1536
+ const isFailed = () => {
1537
+ return errors.some((error) => error.type === "error");
1538
+ };
1539
+ const newScope = () => {
1540
+ const newContext = createReducerContext(vs, errors);
1541
+ return newContext;
1542
+ };
1543
+ let context;
1544
+ const reduceByProxy = (node) => reduceExpressionNode(context, node);
1545
+ const getVariablesFromProxy = () => {
1546
+ if (variablesProxy === void 0) {
1547
+ variablesProxy = {};
1548
+ for (const key of vs.keys()) {
1549
+ Object.defineProperty(variablesProxy, key, {
1550
+ get: () => vs.get(key),
1551
+ configurable: true,
1552
+ enumerable: true
1553
+ });
1554
+ }
1555
+ }
1556
+ return variablesProxy;
1557
+ };
1558
+ const createFunctionContext = (thisNode) => {
1559
+ return {
1560
+ get variables() {
1561
+ return getVariablesFromProxy();
1562
+ },
1563
+ thisNode,
1564
+ appendError,
1565
+ reduce: reduceByProxy
1566
+ };
1567
+ };
1568
+ context = {
1569
+ getValue,
1570
+ setValue,
1571
+ appendError,
1572
+ isFailed,
1573
+ newScope,
1574
+ createFunctionContext
1575
+ };
1576
+ return context;
1577
+ };
1578
+ const unwrap = (results) => {
1579
+ return results.flatMap((result) => {
1580
+ if (result === void 0) {
1581
+ return [];
1582
+ } else {
1583
+ return [result];
1584
+ }
1585
+ });
1586
+ };
1587
+ async function runReducer(nodes, variables, errors) {
1588
+ const context = createReducerContext(variables, errors);
1589
+ if (Array.isArray(nodes)) {
1590
+ const resultList = [];
1591
+ for (const node of nodes) {
1592
+ const results = await reduceNode(context, node);
1593
+ resultList.push(...results);
1594
+ }
1595
+ return unwrap(resultList);
1596
+ } else {
1597
+ const results = await reduceNode(context, nodes);
1598
+ return unwrap(results);
1599
+ }
1600
+ }
1601
+ const _cond = makeSpecialFunction(async function(arg0, arg1, arg2) {
1602
+ const cond = await this.reduce(arg0);
1603
+ if (isConditionalTrue(cond)) {
1604
+ return await this.reduce(arg1);
1605
+ } else {
1606
+ return await this.reduce(arg2);
1607
+ }
1608
+ });
1609
+ const _typeof = async (arg0) => {
1610
+ if (arg0 === null) {
1611
+ return "null";
1612
+ } else if (typeof arg0 === "string") {
1613
+ return "string";
1614
+ } else if (Array.isArray(arg0)) {
1615
+ return "array";
1616
+ } else if (asIterable(arg0)) {
1617
+ return "iterable";
1618
+ } else {
1619
+ return typeof arg0;
1620
+ }
1621
+ };
1622
+ const funcIds = /* @__PURE__ */ new WeakMap();
1623
+ let nextId = 1;
1624
+ const getFuncId = (fn) => {
1625
+ const cached = funcIds.get(fn);
1626
+ if (cached) return cached;
1627
+ const id = nextId++;
1628
+ funcIds.set(fn, id);
1629
+ return id;
1630
+ };
1631
+ const _toString = async (...args) => {
1632
+ const results = args.map((arg0) => {
1633
+ switch (arg0) {
1634
+ case void 0:
1635
+ return "(undefined)";
1636
+ case null:
1637
+ return "(null)";
1638
+ default:
1639
+ switch (typeof arg0) {
1640
+ case "string":
1641
+ return arg0;
1642
+ case "boolean":
1643
+ return arg0 ? "true" : "false";
1644
+ case "number":
1645
+ case "bigint":
1646
+ case "symbol":
1647
+ return arg0.toString();
1648
+ case "function":
1649
+ if (arg0.name) {
1650
+ return `fun<${arg0.name}:#${getFuncId(arg0)}>`;
1651
+ } else {
1652
+ return `fun<#${getFuncId(arg0)}>`;
1653
+ }
1654
+ default:
1655
+ if (Array.isArray(arg0)) {
1656
+ return JSON.stringify(arg0);
1657
+ }
1658
+ const iterable = asIterable(arg0);
1659
+ if (iterable) {
1660
+ const arr = Array.from(iterable);
1661
+ return JSON.stringify(arr);
1662
+ } else {
1663
+ return JSON.stringify(arg0);
1664
+ }
1665
+ }
1666
+ }
1667
+ });
1668
+ return results.join(",");
1669
+ };
1670
+ const _add = async (arg0, ...args) => {
1671
+ const r = args.reduce((v0, v) => v0 + Number(v), Number(arg0));
1672
+ return r;
1673
+ };
1674
+ const _sub = async (arg0, ...args) => {
1675
+ const r = args.reduce((v0, v) => v0 - Number(v), Number(arg0));
1676
+ return r;
1677
+ };
1678
+ const _mul = async (arg0, ...args) => {
1679
+ const r = args.reduce((v0, v) => v0 * Number(v), Number(arg0));
1680
+ return r;
1681
+ };
1682
+ const _div = async (arg0, ...args) => {
1683
+ const r = args.reduce((v0, v) => v0 / Number(v), Number(arg0));
1684
+ return r;
1685
+ };
1686
+ const _mod = async (arg0, ...args) => {
1687
+ const r = args.reduce((v0, v) => v0 % Number(v), Number(arg0));
1688
+ return r;
1689
+ };
1690
+ const _equal = async (arg0, arg1) => {
1691
+ const r = arg0 === arg1;
1692
+ return r;
1693
+ };
1694
+ const _now = async () => {
1695
+ return Date.now();
1696
+ };
1697
+ const concatInner = (args) => {
1698
+ let v = "";
1699
+ for (const arg of args) {
1700
+ if (typeof arg === "string") {
1701
+ v = v + arg;
1702
+ } else {
1703
+ const iterable = asIterable(arg);
1704
+ if (iterable) {
1705
+ v = v + concatInner(iterable);
1706
+ } else {
1707
+ v = v + String(arg);
1708
+ }
1709
+ }
1710
+ }
1711
+ return v;
1712
+ };
1713
+ const _concat = async (...args) => {
1714
+ const r = concatInner(args);
1715
+ return r;
1716
+ };
1717
+ const _join = async (arg0, ...args) => {
1718
+ const sep = String(arg0);
1719
+ const r = args.map((v) => String(v)).join(sep);
1720
+ return r;
1721
+ };
1722
+ const _trim = async (arg0) => {
1723
+ var _a;
1724
+ let v = arg0;
1725
+ if (v === void 0 || v === null) {
1726
+ v = "";
1727
+ } else if (typeof v !== "string") {
1728
+ v = (_a = v.toString()) != null ? _a : "";
1729
+ }
1730
+ return v.trim();
1731
+ };
1732
+ const _toUpper = async (arg0) => {
1733
+ var _a;
1734
+ let v = arg0;
1735
+ if (typeof v !== "string") {
1736
+ v = (_a = v.toString()) != null ? _a : "";
1737
+ }
1738
+ return v.toUpperCase();
1739
+ };
1740
+ const _toLower = async (arg0) => {
1741
+ var _a;
1742
+ let v = arg0;
1743
+ if (typeof v !== "string") {
1744
+ v = (_a = v.toString()) != null ? _a : "";
1745
+ }
1746
+ return v.toLowerCase();
1747
+ };
1748
+ const _length = async (arg0) => {
1749
+ if (arg0) {
1750
+ if (typeof arg0 === "string") {
1751
+ return arg0.length;
1752
+ } else if (Array.isArray(arg0)) {
1753
+ return arg0.length;
1754
+ } else {
1755
+ const iterable = asIterable(arg0);
1756
+ if (iterable) {
1757
+ let count = 0;
1758
+ for (const _item of arg0) {
1759
+ count++;
1760
+ }
1761
+ return count;
1762
+ }
1763
+ }
1764
+ }
1765
+ return 0;
1766
+ };
1767
+ const _and = async (...args) => {
1768
+ if (args.length === 0) {
1769
+ throw new Error("empty arguments");
1770
+ }
1771
+ const r = args.reduce((v0, v) => v0 && isConditionalTrue(v), true);
1772
+ return r;
1773
+ };
1774
+ const _or = async (...args) => {
1775
+ if (args.length === 0) {
1776
+ throw new Error("empty arguments");
1777
+ }
1778
+ const r = args.reduce((v0, v) => v0 || isConditionalTrue(v), false);
1779
+ return r;
1780
+ };
1781
+ const _not = async (arg0) => {
1782
+ return !isConditionalTrue(arg0);
1783
+ };
1784
+ const _at = async (arg0, arg1) => {
1785
+ const index = Number(arg0);
1786
+ if (arg1) {
1787
+ if (typeof arg1 === "string") {
1788
+ return arg1[index];
1789
+ } else if (Array.isArray(arg1)) {
1790
+ return arg1[index];
1791
+ } else {
1792
+ const iterable = asIterable(arg1);
1793
+ if (iterable) {
1794
+ let current = 0;
1795
+ for (const item of iterable) {
1796
+ if (current >= index) {
1797
+ return item;
1798
+ }
1799
+ current++;
1800
+ }
1801
+ }
1802
+ }
1803
+ }
1804
+ return void 0;
1805
+ };
1806
+ const _first = async (arg0) => {
1807
+ if (arg0) {
1808
+ if (typeof arg0 === "string") {
1809
+ return arg0[0];
1810
+ } else if (Array.isArray(arg0)) {
1811
+ return arg0[0];
1812
+ } else {
1813
+ const iterable = asIterable(arg0);
1814
+ if (iterable) {
1815
+ for (const item of iterable) {
1816
+ return item;
1817
+ }
1818
+ }
1819
+ }
1820
+ }
1821
+ return void 0;
1822
+ };
1823
+ const _last = async (arg0) => {
1824
+ if (arg0) {
1825
+ if (typeof arg0 === "string") {
1826
+ return arg0[arg0.length - 1];
1827
+ } else if (Array.isArray(arg0)) {
1828
+ return arg0[arg0.length - 1];
1829
+ } else {
1830
+ const iterable = asIterable(arg0);
1831
+ if (iterable) {
1832
+ let lastItem = void 0;
1833
+ for (const item of iterable) {
1834
+ lastItem = item;
1835
+ }
1836
+ return lastItem;
1837
+ }
1838
+ }
1839
+ }
1840
+ return void 0;
1841
+ };
1842
+ const _range = async (arg0, arg1) => {
1843
+ let value = Number(arg0);
1844
+ const count = Number(arg1);
1845
+ const resultList = [];
1846
+ for (let index = 0; index < count; index++) {
1847
+ resultList.push(value++);
1848
+ }
1849
+ return resultList;
1850
+ };
1851
+ const _reverse = async (arg0) => {
1852
+ const iter = arg0;
1853
+ let resultList = [];
1854
+ for (const item of iter) {
1855
+ resultList.push(item);
1856
+ }
1857
+ return resultList.reverse();
1858
+ };
1859
+ const _sort = async (arg0) => {
1860
+ const iter = arg0;
1861
+ let resultList = [];
1862
+ for (const item of iter) {
1863
+ resultList.push(item);
1864
+ }
1865
+ return resultList.sort();
1866
+ };
1867
+ const _map = async (arg0, arg1) => {
1868
+ const predicate = arg0;
1869
+ const iter = arg1;
1870
+ const resultList = [];
1871
+ for (const item of iter) {
1872
+ const result = await predicate(item);
1873
+ resultList.push(result);
1874
+ }
1875
+ return resultList;
1876
+ };
1877
+ const _flatMap = async (arg0, arg1) => {
1878
+ const predicate = arg0;
1879
+ const iter = arg1;
1880
+ const resultList = [];
1881
+ for (const item of iter) {
1882
+ const results = await predicate(item);
1883
+ resultList.push(...results);
1884
+ }
1885
+ return resultList;
1886
+ };
1887
+ const _filter = async (arg0, arg1) => {
1888
+ const predicate = arg0;
1889
+ const iter = arg1;
1890
+ const resultList = [];
1891
+ for (const item of iter) {
1892
+ const result = await predicate(item);
1893
+ if (isConditionalTrue(result)) {
1894
+ resultList.push(item);
1895
+ }
1896
+ }
1897
+ return resultList;
1898
+ };
1899
+ const _collect = async (arg0) => {
1900
+ const iter = arg0;
1901
+ const resultList = [];
1902
+ for (const item of iter) {
1903
+ if (item !== void 0 && item !== null) {
1904
+ resultList.push(item);
1905
+ }
1906
+ }
1907
+ return resultList;
1908
+ };
1909
+ const _reduce = async (arg0, arg1, arg2) => {
1910
+ let acc = arg0;
1911
+ const predicate = arg1;
1912
+ const iter = arg2;
1913
+ for (const item of iter) {
1914
+ acc = await predicate(acc, item);
1915
+ }
1916
+ return acc;
1917
+ };
1918
+ const _match = async (arg0, arg1) => {
1919
+ const re = arg0 instanceof RegExp ? arg0 : new RegExp(String(arg0), "g");
1920
+ const results = String(arg1).match(re);
1921
+ return results;
1922
+ };
1923
+ const _replace = async (arg0, arg1, arg2) => {
1924
+ const re = arg0 instanceof RegExp ? arg0 : new RegExp(String(arg0), "g");
1925
+ const replace = String(arg1);
1926
+ const results = String(arg2).replace(re, replace);
1927
+ return results;
1928
+ };
1929
+ const _regex = async (arg0, arg1) => {
1930
+ if (arg1) {
1931
+ const re = new RegExp(String(arg0), String(arg1));
1932
+ return re;
1933
+ } else {
1934
+ const re = new RegExp(String(arg0));
1935
+ return re;
1936
+ }
1937
+ };
1938
+ const _bind = async (arg0, ...args) => {
1939
+ const predicate = arg0;
1940
+ return predicate.bind(void 0, ...args);
1941
+ };
1942
+ const standardVariables = {
1943
+ undefined: void 0,
1944
+ null: null,
1945
+ true: true,
1946
+ false: false,
1947
+ cond: _cond,
1948
+ toString: _toString,
1949
+ typeof: _typeof,
1950
+ add: _add,
1951
+ sub: _sub,
1952
+ mul: _mul,
1953
+ div: _div,
1954
+ mod: _mod,
1955
+ equal: _equal,
1956
+ now: _now,
1957
+ concat: _concat,
1958
+ join: _join,
1959
+ trim: _trim,
1960
+ toUpper: _toUpper,
1961
+ toLower: _toLower,
1962
+ length: _length,
1963
+ and: _and,
1964
+ or: _or,
1965
+ not: _not,
1966
+ at: _at,
1967
+ first: _first,
1968
+ last: _last,
1969
+ range: _range,
1970
+ sort: _sort,
1971
+ reverse: _reverse,
1972
+ map: _map,
1973
+ flatMap: _flatMap,
1974
+ filter: _filter,
1975
+ collect: _collect,
1976
+ reduce: _reduce,
1977
+ match: _match,
1978
+ replace: _replace,
1979
+ regex: _regex,
1980
+ bind: _bind
1981
+ };
1982
+ const buildCandidateVariables = (...variablesList) => {
1983
+ return combineVariables(standardVariables, ...variablesList);
1984
+ };
1985
+ exports.asIterable = asIterable;
1986
+ exports.buildCandidateVariables = buildCandidateVariables;
1987
+ exports.combineVariables = combineVariables;
1988
+ exports.createReducerContext = createReducerContext;
1989
+ exports.emptyLocation = emptyLocation;
1990
+ exports.emptyRange = emptyRange;
1991
+ exports.fromError = fromError;
1992
+ exports.isConditionalTrue = isConditionalTrue;
1993
+ exports.isSpecialFunction = isSpecialFunction;
1994
+ exports.makeSpecialFunction = makeSpecialFunction;
1995
+ exports.outputErrors = outputErrors;
1996
+ exports.parseBlock = parseBlock;
1997
+ exports.parseExpression = parseExpression;
1998
+ exports.reduceExpressionNode = reduceExpressionNode;
1999
+ exports.reduceNode = reduceNode;
2000
+ exports.runParser = runParser;
2001
+ exports.runReducer = runReducer;
2002
+ exports.runTokenizer = runTokenizer;
2003
+ exports.standardVariables = standardVariables;
2004
+ exports.widerRange = widerRange;
2005
+ //# sourceMappingURL=index.cjs.map