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