funcity 0.1.0 → 0.2.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/README.md +5 -1
- package/dist/index.cjs +165 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +11 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +165 -159
- package/dist/index.mjs.map +1 -1
- package/dist/parser.d.ts +137 -55
- package/dist/parser.d.ts.map +1 -1
- package/dist/reducer.d.ts +18 -26
- package/dist/reducer.d.ts.map +1 -1
- package/dist/scripting.d.ts +99 -16
- package/dist/scripting.d.ts.map +1 -1
- package/dist/standards.d.ts +14 -6
- package/dist/standards.d.ts.map +1 -1
- package/dist/tokenizer.d.ts +63 -21
- package/dist/tokenizer.d.ts.map +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A functional language interpreter with text processing.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
[](https://www.repostatus.org/#wip)
|
|
6
8
|
[](https://opensource.org/licenses/MIT)
|
|
7
9
|
|
|
@@ -43,7 +45,7 @@ The following code may further interest you:
|
|
|
43
45
|
|
|
44
46
|
```funcity
|
|
45
47
|
{{
|
|
46
|
-
set printWeather (fun w cond w.sunny 'nice' 'bad')
|
|
48
|
+
set printWeather (fun w (cond w.sunny 'nice' 'bad'))
|
|
47
49
|
}}
|
|
48
50
|
Today is {{printWeather weather}} weather.
|
|
49
51
|
```
|
|
@@ -75,6 +77,8 @@ In other words, funcity is an interpreter that brings the power of functional pr
|
|
|
75
77
|
|
|
76
78
|
## Installation (CLI)
|
|
77
79
|
|
|
80
|
+
TODO:
|
|
81
|
+
|
|
78
82
|
```bash
|
|
79
83
|
npm install -D funcity-cli
|
|
80
84
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -1,114 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const emptyLocation = {
|
|
4
|
-
line: 0,
|
|
5
|
-
column: 0
|
|
6
|
-
};
|
|
7
|
-
const emptyRange = {
|
|
8
|
-
start: emptyLocation,
|
|
9
|
-
end: emptyLocation
|
|
10
|
-
};
|
|
11
|
-
const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
|
|
12
|
-
const 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
3
|
const tokenizeString = (context) => {
|
|
113
4
|
const start = context.cursor.location("start");
|
|
114
5
|
context.cursor.skip(1);
|
|
@@ -320,20 +211,20 @@ const tokenizeCodeBlock = (context) => {
|
|
|
320
211
|
});
|
|
321
212
|
return tokens;
|
|
322
213
|
};
|
|
323
|
-
const createTokenizerCursor = (
|
|
214
|
+
const createTokenizerCursor = (script) => {
|
|
324
215
|
let currentIndex = 0;
|
|
325
216
|
let rawLine = 0;
|
|
326
217
|
let rawColumn = 0;
|
|
327
218
|
let lastLine = 0;
|
|
328
219
|
let lastColumn = 0;
|
|
329
|
-
const eot = () => currentIndex >=
|
|
330
|
-
const getChar = (index) =>
|
|
220
|
+
const eot = () => currentIndex >= script.length;
|
|
221
|
+
const getChar = (index) => script[(index != null ? index : 0) + currentIndex];
|
|
331
222
|
const skip = (length) => {
|
|
332
223
|
let lastch = "\0";
|
|
333
224
|
while (length > 0) {
|
|
334
225
|
lastColumn = rawColumn;
|
|
335
226
|
lastLine = rawLine;
|
|
336
|
-
const ch =
|
|
227
|
+
const ch = script[currentIndex];
|
|
337
228
|
if (ch === "\r") {
|
|
338
229
|
rawColumn = 0;
|
|
339
230
|
} else if (ch === "\n" && lastch !== "\r") {
|
|
@@ -358,7 +249,7 @@ const createTokenizerCursor = (text) => {
|
|
|
358
249
|
};
|
|
359
250
|
const skipUntil = (word) => {
|
|
360
251
|
while (!eot()) {
|
|
361
|
-
const index =
|
|
252
|
+
const index = script.indexOf(word, currentIndex);
|
|
362
253
|
if (index === currentIndex) {
|
|
363
254
|
skip(word.length);
|
|
364
255
|
return true;
|
|
@@ -368,31 +259,31 @@ const createTokenizerCursor = (text) => {
|
|
|
368
259
|
return false;
|
|
369
260
|
};
|
|
370
261
|
const assert = (word) => {
|
|
371
|
-
if (
|
|
262
|
+
if (script.length - currentIndex < word.length) {
|
|
372
263
|
return false;
|
|
373
264
|
}
|
|
374
|
-
if (
|
|
265
|
+
if (script.substring(currentIndex, currentIndex + word.length) === word) {
|
|
375
266
|
return true;
|
|
376
267
|
}
|
|
377
268
|
return false;
|
|
378
269
|
};
|
|
379
270
|
const getRangeAndSkip = (length) => {
|
|
380
|
-
const result =
|
|
271
|
+
const result = script.substring(currentIndex, currentIndex + length);
|
|
381
272
|
skip(result.length);
|
|
382
273
|
return result;
|
|
383
274
|
};
|
|
384
275
|
const getUntil = (word) => {
|
|
385
|
-
if (currentIndex >=
|
|
276
|
+
if (currentIndex >= script.length) {
|
|
386
277
|
return void 0;
|
|
387
278
|
}
|
|
388
|
-
const index =
|
|
279
|
+
const index = script.indexOf(word, currentIndex);
|
|
389
280
|
if (index >= 0) {
|
|
390
|
-
const result =
|
|
281
|
+
const result = script.substring(currentIndex, index);
|
|
391
282
|
skip(index - currentIndex);
|
|
392
283
|
return result;
|
|
393
284
|
} else {
|
|
394
|
-
const result =
|
|
395
|
-
skip(
|
|
285
|
+
const result = script.substring(currentIndex, script.length);
|
|
286
|
+
skip(script.length - currentIndex);
|
|
396
287
|
return result;
|
|
397
288
|
}
|
|
398
289
|
};
|
|
@@ -459,6 +350,115 @@ const runTokenizer = (script, errors) => {
|
|
|
459
350
|
}
|
|
460
351
|
return tokens;
|
|
461
352
|
};
|
|
353
|
+
const emptyLocation = {
|
|
354
|
+
line: 0,
|
|
355
|
+
column: 0
|
|
356
|
+
};
|
|
357
|
+
const emptyRange = {
|
|
358
|
+
start: emptyLocation,
|
|
359
|
+
end: emptyLocation
|
|
360
|
+
};
|
|
361
|
+
const specialFunctionMarker = /* @__PURE__ */ Symbol("$$special$$");
|
|
362
|
+
const makeSpecialFunction = (f) => {
|
|
363
|
+
f[specialFunctionMarker] = true;
|
|
364
|
+
return f;
|
|
365
|
+
};
|
|
366
|
+
const isSpecialFunction = (f) => {
|
|
367
|
+
var _a;
|
|
368
|
+
return (_a = f[specialFunctionMarker]) != null ? _a : false;
|
|
369
|
+
};
|
|
370
|
+
const isConditionalTrue = (v) => {
|
|
371
|
+
if (v === void 0 || v === null) {
|
|
372
|
+
return false;
|
|
373
|
+
}
|
|
374
|
+
switch (typeof v) {
|
|
375
|
+
case "boolean":
|
|
376
|
+
return v;
|
|
377
|
+
case "number":
|
|
378
|
+
case "bigint":
|
|
379
|
+
return v !== 0;
|
|
380
|
+
default:
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
const asIterable = (v) => {
|
|
385
|
+
if (typeof v[Symbol.iterator] === "function") {
|
|
386
|
+
return v;
|
|
387
|
+
} else {
|
|
388
|
+
return void 0;
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
const combineVariables = (...variablesList) => {
|
|
392
|
+
const variables = /* @__PURE__ */ new Map();
|
|
393
|
+
const appendVariables = (vs) => vs.forEach((v, k) => variables.set(k, v));
|
|
394
|
+
const appendRecord = (vs) => Object.keys(vs).forEach((k) => variables.set(k, vs[k]));
|
|
395
|
+
variablesList.forEach((vs) => {
|
|
396
|
+
if (vs["forEach"] !== void 0) {
|
|
397
|
+
appendVariables(vs);
|
|
398
|
+
} else {
|
|
399
|
+
appendRecord(vs);
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
return variables;
|
|
403
|
+
};
|
|
404
|
+
const fromError = (error) => {
|
|
405
|
+
var _a;
|
|
406
|
+
if (error.message) {
|
|
407
|
+
return error.message;
|
|
408
|
+
} else if (typeof error.toString === "function") {
|
|
409
|
+
return (_a = error.toString()) != null ? _a : "unknown";
|
|
410
|
+
} else {
|
|
411
|
+
return "unknown";
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
const widerRange = (...ranges) => {
|
|
415
|
+
let start = emptyRange.start;
|
|
416
|
+
let end = emptyRange.end;
|
|
417
|
+
for (const range of ranges) {
|
|
418
|
+
if (range.start.line >= 1 && range.start.column >= 1) {
|
|
419
|
+
if (start.line === 0 || start.column === 0) {
|
|
420
|
+
start = range.start;
|
|
421
|
+
} else if (range.start.line < start.line) {
|
|
422
|
+
start = range.start;
|
|
423
|
+
} else if (range.start.line === start.line && range.start.column < start.column) {
|
|
424
|
+
start = range.start;
|
|
425
|
+
}
|
|
426
|
+
if (end.line === 0 || end.column === 0) {
|
|
427
|
+
end = range.end;
|
|
428
|
+
} else if (range.end.line > end.line) {
|
|
429
|
+
end = range.end;
|
|
430
|
+
} else if (range.end.line === end.line && range.end.column > end.column) {
|
|
431
|
+
end = range.end;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return { start, end };
|
|
436
|
+
};
|
|
437
|
+
const locationEquals = (lhs, rhs) => lhs.line === rhs.line && lhs.column === rhs.column;
|
|
438
|
+
const getLocationString = (range) => locationEquals(range.start, range.end) ? `${range.start.line}:${range.start.column}` : `${range.start.line}:${range.start.column}:${range.end.line}:${range.end.column}`;
|
|
439
|
+
const printErrorString = (path, error) => {
|
|
440
|
+
switch (error.type) {
|
|
441
|
+
case "warning":
|
|
442
|
+
console.warn(
|
|
443
|
+
`${path}:${getLocationString(error.range)}: warning: ${error.description}`
|
|
444
|
+
);
|
|
445
|
+
break;
|
|
446
|
+
case "error":
|
|
447
|
+
console.error(
|
|
448
|
+
`${path}:${getLocationString(error.range)}: error: ${error.description}`
|
|
449
|
+
);
|
|
450
|
+
return true;
|
|
451
|
+
}
|
|
452
|
+
return false;
|
|
453
|
+
};
|
|
454
|
+
const outputErrors = (path, errors) => {
|
|
455
|
+
let isError = false;
|
|
456
|
+
for (const error of errors) {
|
|
457
|
+
const result = printErrorString(path, error);
|
|
458
|
+
isError || (isError = result);
|
|
459
|
+
}
|
|
460
|
+
return isError;
|
|
461
|
+
};
|
|
462
462
|
const parseNumber = (cursor, _errors) => {
|
|
463
463
|
const token = cursor.takeToken();
|
|
464
464
|
return {
|
|
@@ -564,7 +564,7 @@ const parsePartialExpression = (cursor, errors) => {
|
|
|
564
564
|
return node;
|
|
565
565
|
}
|
|
566
566
|
case "open": {
|
|
567
|
-
cursor.
|
|
567
|
+
cursor.skipToken();
|
|
568
568
|
switch (token.symbol) {
|
|
569
569
|
// Parenthesis surrounding expression list `( ... )` (Scope)
|
|
570
570
|
case "(": {
|
|
@@ -588,7 +588,7 @@ const parsePartialExpression = (cursor, errors) => {
|
|
|
588
588
|
)
|
|
589
589
|
});
|
|
590
590
|
} else {
|
|
591
|
-
cursor.
|
|
591
|
+
cursor.skipToken();
|
|
592
592
|
range = widerRange(
|
|
593
593
|
token.range,
|
|
594
594
|
...innerNodes.map((node) => node.range),
|
|
@@ -628,7 +628,7 @@ const parsePartialExpression = (cursor, errors) => {
|
|
|
628
628
|
range
|
|
629
629
|
});
|
|
630
630
|
} else {
|
|
631
|
-
cursor.
|
|
631
|
+
cursor.skipToken();
|
|
632
632
|
range = widerRange(
|
|
633
633
|
token.range,
|
|
634
634
|
...itemNodes.map((node) => node.range),
|
|
@@ -721,7 +721,7 @@ const parseMultipleApplicationExpressions = (cursor, errors) => {
|
|
|
721
721
|
}
|
|
722
722
|
switch (token.kind) {
|
|
723
723
|
case "eol": {
|
|
724
|
-
cursor.
|
|
724
|
+
cursor.skipToken();
|
|
725
725
|
const expr2 = finalizeApplicationException(partialNodes, errors);
|
|
726
726
|
if (expr2) {
|
|
727
727
|
expressionList.push(expr2);
|
|
@@ -766,7 +766,7 @@ const drainEndOfLineAndPeek = (cursor) => {
|
|
|
766
766
|
let token = cursor.peekToken();
|
|
767
767
|
while (token) {
|
|
768
768
|
if (token.kind === "eol") {
|
|
769
|
-
cursor.
|
|
769
|
+
cursor.skipToken();
|
|
770
770
|
} else {
|
|
771
771
|
break;
|
|
772
772
|
}
|
|
@@ -791,7 +791,7 @@ const parseExpression = (cursor, errors) => {
|
|
|
791
791
|
break;
|
|
792
792
|
}
|
|
793
793
|
if (token.kind === "eol") {
|
|
794
|
-
cursor.
|
|
794
|
+
cursor.skipToken();
|
|
795
795
|
token = cursor.peekToken();
|
|
796
796
|
break;
|
|
797
797
|
}
|
|
@@ -889,7 +889,7 @@ const parseStatementArguments = (cursor, errors) => {
|
|
|
889
889
|
break;
|
|
890
890
|
}
|
|
891
891
|
if (token.kind === "eol") {
|
|
892
|
-
cursor.
|
|
892
|
+
cursor.skipToken();
|
|
893
893
|
break;
|
|
894
894
|
}
|
|
895
895
|
const partialNode = parsePartialExpression(cursor, errors);
|
|
@@ -945,7 +945,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
945
945
|
}
|
|
946
946
|
switch (token.kind) {
|
|
947
947
|
case "text": {
|
|
948
|
-
cursor.
|
|
948
|
+
cursor.skipToken();
|
|
949
949
|
if (isInExpressionBlock) {
|
|
950
950
|
errors.push({
|
|
951
951
|
type: "error",
|
|
@@ -963,7 +963,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
963
963
|
}
|
|
964
964
|
case "open": {
|
|
965
965
|
if (token.symbol === "{{") {
|
|
966
|
-
cursor.
|
|
966
|
+
cursor.skipToken();
|
|
967
967
|
if (isInExpressionBlock) {
|
|
968
968
|
errors.push({
|
|
969
969
|
type: "error",
|
|
@@ -981,7 +981,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
981
981
|
break;
|
|
982
982
|
}
|
|
983
983
|
case "close": {
|
|
984
|
-
cursor.
|
|
984
|
+
cursor.skipToken();
|
|
985
985
|
if (!isInExpressionBlock) {
|
|
986
986
|
errors.push({
|
|
987
987
|
type: "error",
|
|
@@ -1005,7 +1005,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
1005
1005
|
}
|
|
1006
1006
|
switch (token.name) {
|
|
1007
1007
|
case "if": {
|
|
1008
|
-
cursor.
|
|
1008
|
+
cursor.skipToken();
|
|
1009
1009
|
const args = parseStatementArguments(cursor, errors);
|
|
1010
1010
|
if (args.length !== 1) {
|
|
1011
1011
|
errors.push({
|
|
@@ -1030,7 +1030,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
1030
1030
|
break;
|
|
1031
1031
|
}
|
|
1032
1032
|
case "else": {
|
|
1033
|
-
cursor.
|
|
1033
|
+
cursor.skipToken();
|
|
1034
1034
|
const args = parseStatementArguments(cursor, errors);
|
|
1035
1035
|
if (args.length !== 0) {
|
|
1036
1036
|
errors.push({
|
|
@@ -1072,7 +1072,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
1072
1072
|
break;
|
|
1073
1073
|
}
|
|
1074
1074
|
case "while": {
|
|
1075
|
-
cursor.
|
|
1075
|
+
cursor.skipToken();
|
|
1076
1076
|
const args = parseStatementArguments(cursor, errors);
|
|
1077
1077
|
if (args.length !== 1) {
|
|
1078
1078
|
errors.push({
|
|
@@ -1095,7 +1095,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
1095
1095
|
break;
|
|
1096
1096
|
}
|
|
1097
1097
|
case "for": {
|
|
1098
|
-
cursor.
|
|
1098
|
+
cursor.skipToken();
|
|
1099
1099
|
const args = parseStatementArguments(cursor, errors);
|
|
1100
1100
|
if (args.length !== 2) {
|
|
1101
1101
|
errors.push({
|
|
@@ -1128,7 +1128,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
1128
1128
|
break;
|
|
1129
1129
|
}
|
|
1130
1130
|
case "end": {
|
|
1131
|
-
cursor.
|
|
1131
|
+
cursor.skipToken();
|
|
1132
1132
|
const args = parseStatementArguments(cursor, errors);
|
|
1133
1133
|
if (args.length !== 0) {
|
|
1134
1134
|
errors.push({
|
|
@@ -1200,7 +1200,7 @@ const parseBlock = (cursor, errors) => {
|
|
|
1200
1200
|
break;
|
|
1201
1201
|
}
|
|
1202
1202
|
case "set": {
|
|
1203
|
-
cursor.
|
|
1203
|
+
cursor.skipToken();
|
|
1204
1204
|
const args = parseStatementArguments(cursor, errors);
|
|
1205
1205
|
if (args.length !== 2) {
|
|
1206
1206
|
errors.push({
|
|
@@ -1281,9 +1281,16 @@ const createParserCursor = (tokens) => {
|
|
|
1281
1281
|
index++;
|
|
1282
1282
|
return token;
|
|
1283
1283
|
};
|
|
1284
|
+
const skipToken = () => {
|
|
1285
|
+
if (index >= tokens.length) {
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
index++;
|
|
1289
|
+
};
|
|
1284
1290
|
return {
|
|
1285
1291
|
peekToken,
|
|
1286
|
-
takeToken
|
|
1292
|
+
takeToken,
|
|
1293
|
+
skipToken
|
|
1287
1294
|
};
|
|
1288
1295
|
};
|
|
1289
1296
|
const runParser = (tokens, errors) => {
|
|
@@ -1575,28 +1582,18 @@ const createReducerContext = (variables, errors) => {
|
|
|
1575
1582
|
};
|
|
1576
1583
|
return context;
|
|
1577
1584
|
};
|
|
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
1585
|
async function runReducer(nodes, variables, errors) {
|
|
1588
1586
|
const context = createReducerContext(variables, errors);
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1587
|
+
const resultList = [];
|
|
1588
|
+
for (const node of nodes) {
|
|
1589
|
+
const results = await reduceNode(context, node);
|
|
1590
|
+
for (const result of results) {
|
|
1591
|
+
if (result !== void 0) {
|
|
1592
|
+
resultList.push(result);
|
|
1593
|
+
}
|
|
1594
1594
|
}
|
|
1595
|
-
return unwrap(resultList);
|
|
1596
|
-
} else {
|
|
1597
|
-
const results = await reduceNode(context, nodes);
|
|
1598
|
-
return unwrap(results);
|
|
1599
1595
|
}
|
|
1596
|
+
return resultList;
|
|
1600
1597
|
}
|
|
1601
1598
|
const _cond = makeSpecialFunction(async function(arg0, arg1, arg2) {
|
|
1602
1599
|
const cond = await this.reduce(arg0);
|
|
@@ -1939,7 +1936,7 @@ const _bind = async (arg0, ...args) => {
|
|
|
1939
1936
|
const predicate = arg0;
|
|
1940
1937
|
return predicate.bind(void 0, ...args);
|
|
1941
1938
|
};
|
|
1942
|
-
const standardVariables = {
|
|
1939
|
+
const standardVariables = Object.freeze({
|
|
1943
1940
|
undefined: void 0,
|
|
1944
1941
|
null: null,
|
|
1945
1942
|
true: true,
|
|
@@ -1978,13 +1975,21 @@ const standardVariables = {
|
|
|
1978
1975
|
replace: _replace,
|
|
1979
1976
|
regex: _regex,
|
|
1980
1977
|
bind: _bind
|
|
1981
|
-
};
|
|
1978
|
+
});
|
|
1982
1979
|
const buildCandidateVariables = (...variablesList) => {
|
|
1983
1980
|
return combineVariables(standardVariables, ...variablesList);
|
|
1984
1981
|
};
|
|
1982
|
+
const runScriptOnce = async (script, variables, errors = []) => {
|
|
1983
|
+
const blocks = runTokenizer(script, errors);
|
|
1984
|
+
const nodes = runParser(blocks, errors);
|
|
1985
|
+
const results = await runReducer(nodes, variables, errors);
|
|
1986
|
+
const text = results.join("");
|
|
1987
|
+
return text;
|
|
1988
|
+
};
|
|
1985
1989
|
exports.asIterable = asIterable;
|
|
1986
1990
|
exports.buildCandidateVariables = buildCandidateVariables;
|
|
1987
1991
|
exports.combineVariables = combineVariables;
|
|
1992
|
+
exports.createParserCursor = createParserCursor;
|
|
1988
1993
|
exports.createReducerContext = createReducerContext;
|
|
1989
1994
|
exports.emptyLocation = emptyLocation;
|
|
1990
1995
|
exports.emptyRange = emptyRange;
|
|
@@ -1999,6 +2004,7 @@ exports.reduceExpressionNode = reduceExpressionNode;
|
|
|
1999
2004
|
exports.reduceNode = reduceNode;
|
|
2000
2005
|
exports.runParser = runParser;
|
|
2001
2006
|
exports.runReducer = runReducer;
|
|
2007
|
+
exports.runScriptOnce = runScriptOnce;
|
|
2002
2008
|
exports.runTokenizer = runTokenizer;
|
|
2003
2009
|
exports.standardVariables = standardVariables;
|
|
2004
2010
|
exports.widerRange = widerRange;
|