functionalscript 0.8.2 → 0.9.2
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 -5
- package/bnf/data/module.f.d.ts +10 -1
- package/bnf/data/module.f.js +58 -19
- package/bnf/data/test.f.d.ts +2 -0
- package/bnf/data/test.f.js +244 -3
- package/bnf/module.f.d.ts +6 -2
- package/bnf/module.f.js +8 -9
- package/cas/module.f.d.ts +18 -0
- package/cas/module.f.js +95 -0
- package/cas/test.f.d.ts +2 -0
- package/cas/test.f.js +1 -0
- package/ci/module.f.d.ts +3 -2
- package/ci/module.f.js +11 -9
- package/ci/module.js +3 -3
- package/crypto/sha2/module.f.js +0 -1
- package/dev/module.f.d.ts +1 -1
- package/dev/module.f.js +14 -6
- package/dev/version/module.f.d.ts +2 -11
- package/dev/version/module.f.js +17 -14
- package/dev/version/test.f.d.ts +3 -1
- package/dev/version/test.f.js +26 -10
- package/djs/module.f.d.ts +1 -1
- package/djs/module.f.js +4 -4
- package/djs/parser-new/module.f.d.ts +3 -0
- package/djs/parser-new/module.f.js +150 -0
- package/djs/parser-new/test.f.d.ts +5 -0
- package/djs/parser-new/test.f.js +201 -0
- package/djs/serializer/module.f.js +6 -6
- package/djs/transpiler/module.f.js +3 -2
- package/djs/transpiler/test.f.js +12 -11
- package/fjs/module.f.d.ts +2 -0
- package/fjs/module.f.js +25 -0
- package/{dev/tf → fjs}/module.js +1 -1
- package/fsc/module.f.js +1 -1
- package/io/module.d.ts +4 -0
- package/io/module.f.d.ts +14 -13
- package/io/module.f.js +21 -0
- package/io/module.js +7 -1
- package/io/virtual/module.f.d.ts +1 -1
- package/io/virtual/module.f.js +3 -3
- package/js/tokenizer/module.f.d.ts +1 -1
- package/js/tokenizer/module.f.js +0 -1
- package/json/module.f.js +3 -3
- package/nanvm-lib/tests/test.f.d.ts +1 -1
- package/nanvm-lib/tests/test.f.js +114 -104
- package/package.json +6 -7
- package/path/module.f.d.ts +1 -0
- package/path/module.f.js +6 -3
- package/text/utf16/module.f.js +1 -1
- package/types/bit_vec/module.f.d.ts +1 -0
- package/types/bit_vec/module.f.js +1 -0
- package/types/btree/find/module.f.d.ts +7 -8
- package/types/btree/set/module.f.js +21 -0
- package/types/cbase32/module.f.d.ts +6 -0
- package/types/cbase32/module.f.js +71 -0
- package/types/cbase32/test.f.d.ts +7 -0
- package/types/cbase32/test.f.js +74 -0
- package/types/effect/mock/module.f.d.ts +5 -0
- package/types/effect/mock/module.f.js +14 -0
- package/types/effect/module.d.ts +2 -0
- package/types/effect/module.f.d.ts +23 -0
- package/types/effect/module.f.js +14 -0
- package/types/effect/module.js +11 -0
- package/types/effect/node/module.f.d.ts +52 -0
- package/types/effect/node/module.f.js +7 -0
- package/types/effect/node/test.f.d.ts +27 -0
- package/types/effect/node/test.f.js +259 -0
- package/types/effect/node/virtual/module.f.d.ts +13 -0
- package/types/effect/node/virtual/module.f.js +98 -0
- package/types/function/module.f.d.ts +1 -1
- package/types/function/module.f.js +1 -1
- package/types/function/test.f.js +1 -1
- package/types/list/module.f.d.ts +1 -0
- package/types/list/module.f.js +6 -6
- package/types/nullable/module.f.d.ts +2 -0
- package/types/nullable/module.f.js +1 -0
- package/types/nullable/test.f.d.ts +1 -1
- package/types/nullable/test.f.js +23 -11
- package/types/option/module.f.d.ts +9 -0
- package/types/option/module.f.js +6 -0
- package/types/uint8array/module.f.d.ts +11 -0
- package/types/uint8array/module.f.js +21 -0
- package/types/uint8array/test.f.d.ts +12 -0
- package/types/uint8array/test.f.js +58 -0
- package/website/module.d.ts +1 -0
- package/website/module.f.d.ts +3 -0
- package/website/module.f.js +9 -0
- package/website/module.js +3 -0
- package/fsc/module.d.ts +0 -2
- package/fsc/module.js +0 -4
- /package/{dev/tf → fjs}/module.d.ts +0 -0
package/README.md
CHANGED
|
@@ -26,22 +26,22 @@ This repository is a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and dist
|
|
|
26
26
|
Install FunctionalScript via npm:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npm install functionalscript
|
|
29
|
+
npm install -g functionalscript
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
The FunctionalScript compiler (`
|
|
32
|
+
The FunctionalScript compiler command (`fjs compile`) currently supports:
|
|
33
33
|
|
|
34
34
|
* `import` statements
|
|
35
35
|
* `const` declarations
|
|
36
36
|
|
|
37
37
|
It does **not** yet support functions or complex expressions.
|
|
38
38
|
|
|
39
|
-
Example usage with `
|
|
39
|
+
Example usage with `fjs`:
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
|
|
42
|
+
fjs compile example.f.js output.json
|
|
43
43
|
# or
|
|
44
|
-
|
|
44
|
+
fjs compile example.f.js output.f.js
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
FunctionalScript code can be compiled directly into either JSON or JavaScript without imports.
|
package/bnf/data/module.f.d.ts
CHANGED
|
@@ -29,7 +29,15 @@ type DispatchMap = {
|
|
|
29
29
|
type EmptyTagMap = {
|
|
30
30
|
readonly [id in string]: EmptyTagEntry;
|
|
31
31
|
};
|
|
32
|
-
export type DescentMatchRule = (
|
|
32
|
+
export type DescentMatchRule<T> = (name: string, tag: AstTag, s: readonly CodePointMeta<T>[], idx: number) => DescentMatchResult<T>;
|
|
33
|
+
export type DescentMatchResult<T> = readonly [AstRuleMeta<T>, boolean, number];
|
|
34
|
+
export type DescentMatch<T> = (name: string, s: readonly CodePointMeta<T>[]) => DescentMatchResult<T>;
|
|
35
|
+
export type CodePointMeta<T> = readonly [CodePoint, T];
|
|
36
|
+
export type AstSequenceMeta<T> = readonly (AstRuleMeta<T> | CodePointMeta<T>)[];
|
|
37
|
+
export type AstRuleMeta<T> = {
|
|
38
|
+
readonly tag: AstTag;
|
|
39
|
+
readonly sequence: AstSequenceMeta<T>;
|
|
40
|
+
};
|
|
33
41
|
/**
|
|
34
42
|
* Represents a parsed Abstract Syntax Tree (AST) sequence.
|
|
35
43
|
*/
|
|
@@ -58,6 +66,7 @@ export type MatchRule = (dr: DispatchRule, s: readonly CodePoint[]) => MatchResu
|
|
|
58
66
|
export declare const toData: (fr: FRule) => readonly [RuleSet, string];
|
|
59
67
|
export declare const dispatchMap: (ruleSet: RuleSet) => DispatchMap;
|
|
60
68
|
export declare const createEmptyTagMap: (data: readonly [RuleSet, string]) => EmptyTagMap;
|
|
69
|
+
export declare const descentParser: <T>(fr: FRule) => DescentMatch<T>;
|
|
61
70
|
export declare const parser: (fr: FRule) => Match;
|
|
62
71
|
export declare const parserRuleSet: (ruleSet: RuleSet) => Match;
|
|
63
72
|
export {};
|
package/bnf/data/module.f.js
CHANGED
|
@@ -3,6 +3,7 @@ import { strictEqual } from "../../types/function/operator/module.f.js";
|
|
|
3
3
|
import { map, toArray } from "../../types/list/module.f.js";
|
|
4
4
|
import { rangeMap } from "../../types/range_map/module.f.js";
|
|
5
5
|
import { contains, set } from "../../types/string_set/module.f.js";
|
|
6
|
+
import { contains as rangeContains } from "../../types/range/module.f.js";
|
|
6
7
|
import { oneEncode, rangeDecode, } from "../module.f.js";
|
|
7
8
|
const { entries } = Object;
|
|
8
9
|
const find = (map) => (fr) => {
|
|
@@ -198,25 +199,63 @@ const emptyTagMapAdd = (ruleSet) => (map) => (name) => {
|
|
|
198
199
|
export const createEmptyTagMap = (data) => {
|
|
199
200
|
return emptyTagMapAdd(data[0])({})(data[1])[1];
|
|
200
201
|
};
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
202
|
+
export const descentParser = (fr) => {
|
|
203
|
+
const data = toData(fr);
|
|
204
|
+
const emptyTagMap = createEmptyTagMap(data);
|
|
205
|
+
const getEmptyTag = (name) => {
|
|
206
|
+
const res = emptyTagMap[name];
|
|
207
|
+
return res === false ? undefined : res;
|
|
208
|
+
};
|
|
209
|
+
const f = (name, tag, cp, idx) => {
|
|
210
|
+
const mrSuccess = (tag, sequence, idx) => [{ tag, sequence }, true, idx];
|
|
211
|
+
const mrFail = (tag, sequence, idx) => [{ tag, sequence }, false, idx];
|
|
212
|
+
const rule = data[0][name];
|
|
213
|
+
if (typeof rule === 'number') {
|
|
214
|
+
const emptyTag = getEmptyTag(name);
|
|
215
|
+
if (idx >= cp.length) {
|
|
216
|
+
return emptyTag === undefined ? mrFail(emptyTag, [], idx) : mrSuccess(emptyTag, [], idx);
|
|
217
|
+
}
|
|
218
|
+
const cpi = cp[idx];
|
|
219
|
+
const range = rangeDecode(rule);
|
|
220
|
+
if (rangeContains(range)(cpi[0])) {
|
|
221
|
+
return mrSuccess(tag, [cpi], idx + 1);
|
|
222
|
+
}
|
|
223
|
+
return mrFail(emptyTag, [], idx);
|
|
224
|
+
}
|
|
225
|
+
else if (rule instanceof Array) {
|
|
226
|
+
let seq = [];
|
|
227
|
+
let tidx = idx;
|
|
228
|
+
for (const item of rule) {
|
|
229
|
+
const m = f(item, undefined, cp, tidx);
|
|
230
|
+
const [astRule, success, nidx] = m;
|
|
231
|
+
tidx = nidx;
|
|
232
|
+
if (success === false) {
|
|
233
|
+
return mrFail(tag, [], idx);
|
|
234
|
+
}
|
|
235
|
+
seq = [...seq, astRule];
|
|
236
|
+
}
|
|
237
|
+
return mrSuccess(tag, seq, tidx);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
const entries = Object.entries(rule);
|
|
241
|
+
const emptyTag = getEmptyTag(name);
|
|
242
|
+
let emptyResult = mrFail(emptyTag, [], idx);
|
|
243
|
+
for (const [tag, item] of entries) {
|
|
244
|
+
const m = f(item, tag, cp, idx);
|
|
245
|
+
if (m[1]) {
|
|
246
|
+
if (idx !== m[2])
|
|
247
|
+
return m;
|
|
248
|
+
emptyResult = m;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return emptyResult;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const match = (name, cp) => {
|
|
255
|
+
return f(name, undefined, cp, 0);
|
|
256
|
+
};
|
|
257
|
+
return match;
|
|
258
|
+
};
|
|
220
259
|
export const parser = (fr) => {
|
|
221
260
|
const data = toData(fr);
|
|
222
261
|
return parserRuleSet(data[0]);
|
package/bnf/data/test.f.d.ts
CHANGED
package/bnf/data/test.f.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { stringify } from "../../json/module.f.js";
|
|
2
2
|
import { stringToCodePointList } from "../../text/utf16/module.f.js";
|
|
3
3
|
import { identity } from "../../types/function/module.f.js";
|
|
4
|
-
import { toArray } from "../../types/list/module.f.js";
|
|
4
|
+
import { map, toArray } from "../../types/list/module.f.js";
|
|
5
5
|
import { sort } from "../../types/object/module.f.js";
|
|
6
|
-
import { join0Plus,
|
|
6
|
+
import { join0Plus, option, range, repeat0Plus, set } from "../module.f.js";
|
|
7
7
|
import { classic, deterministic } from "../testlib.f.js";
|
|
8
|
-
import { dispatchMap, parser, parserRuleSet, toData, createEmptyTagMap } from "./module.f.js";
|
|
8
|
+
import { dispatchMap, parser, parserRuleSet, toData, createEmptyTagMap, descentParser } from "./module.f.js";
|
|
9
|
+
const mapCodePoint = (cp) => [cp, undefined];
|
|
10
|
+
const descentParserCpOnly = (m, name, cp) => {
|
|
11
|
+
const cpm = toArray(map(mapCodePoint)(cp));
|
|
12
|
+
return m(name, cpm);
|
|
13
|
+
};
|
|
9
14
|
export default {
|
|
10
15
|
toData: [
|
|
11
16
|
() => {
|
|
@@ -366,6 +371,19 @@ export default {
|
|
|
366
371
|
throw result;
|
|
367
372
|
}
|
|
368
373
|
},
|
|
374
|
+
() => {
|
|
375
|
+
const emptyRule = '';
|
|
376
|
+
const minusRule = range('--');
|
|
377
|
+
const optionalMinusRule = { 'none': emptyRule, 'minus': minusRule };
|
|
378
|
+
const digitRule = range('09');
|
|
379
|
+
const numberRule = [optionalMinusRule, digitRule];
|
|
380
|
+
const m = parser(numberRule);
|
|
381
|
+
const mr = m("", []);
|
|
382
|
+
const result = JSON.stringify(mr);
|
|
383
|
+
if (result !== '[{"sequence":[]},true,null]') {
|
|
384
|
+
throw result;
|
|
385
|
+
} //if remainder is null it means failed
|
|
386
|
+
},
|
|
369
387
|
() => {
|
|
370
388
|
const m = parser(option('a'));
|
|
371
389
|
const isSuccess = (mr) => mr[1] && mr[2]?.length === 0;
|
|
@@ -401,6 +419,7 @@ export default {
|
|
|
401
419
|
throw mr;
|
|
402
420
|
}
|
|
403
421
|
};
|
|
422
|
+
expect('', false);
|
|
404
423
|
expect('[]', true);
|
|
405
424
|
expect('[a]', true);
|
|
406
425
|
expect('[a, a]', true);
|
|
@@ -437,6 +456,228 @@ export default {
|
|
|
437
456
|
expect(' [{ "q": [ 12, false, [}], "a"] }] ', false);
|
|
438
457
|
}
|
|
439
458
|
],
|
|
459
|
+
descentParser: [
|
|
460
|
+
() => {
|
|
461
|
+
const emptyRule = '';
|
|
462
|
+
const m = descentParser(emptyRule);
|
|
463
|
+
const mr = m("", []);
|
|
464
|
+
const result = JSON.stringify(mr);
|
|
465
|
+
if (result !== '[{"sequence":[]},true,0]') {
|
|
466
|
+
throw result;
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
() => {
|
|
470
|
+
const emptyRule = '';
|
|
471
|
+
const m = descentParser(emptyRule);
|
|
472
|
+
const mr = descentParserCpOnly(m, "", [65, 70]);
|
|
473
|
+
const result = JSON.stringify(mr);
|
|
474
|
+
if (result !== '[{"sequence":[]},true,0]') {
|
|
475
|
+
throw result;
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
() => {
|
|
479
|
+
const terminalRangeRule = range('AF');
|
|
480
|
+
const m = descentParser(terminalRangeRule);
|
|
481
|
+
const mr = descentParserCpOnly(m, "", [65]);
|
|
482
|
+
const result = JSON.stringify(mr);
|
|
483
|
+
if (result !== '[{"sequence":[[65,null]]},true,1]') {
|
|
484
|
+
throw result;
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
() => {
|
|
488
|
+
const terminalRangeRule = range('AF');
|
|
489
|
+
const m = descentParser(terminalRangeRule);
|
|
490
|
+
const mr = descentParserCpOnly(m, "", [64]);
|
|
491
|
+
const result = JSON.stringify(mr);
|
|
492
|
+
if (result !== '[{"sequence":[]},false,0]') {
|
|
493
|
+
throw result;
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
() => {
|
|
497
|
+
const variantRule = { 'a': range('AA'), 'b': range('BB') };
|
|
498
|
+
const m = descentParser(variantRule);
|
|
499
|
+
const mr = descentParserCpOnly(m, "", [65]);
|
|
500
|
+
const result = JSON.stringify(mr);
|
|
501
|
+
if (result !== '[{"tag":"a","sequence":[[65,null]]},true,1]') {
|
|
502
|
+
throw result;
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
() => {
|
|
506
|
+
const variantRule = { 'a': range('AA'), 'b': range('BB') };
|
|
507
|
+
const m = descentParser(variantRule);
|
|
508
|
+
const mr = descentParserCpOnly(m, "", [64]);
|
|
509
|
+
const result = JSON.stringify(mr);
|
|
510
|
+
if (result !== '[{"sequence":[]},false,0]') {
|
|
511
|
+
throw result;
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
() => {
|
|
515
|
+
const emptyRule = '';
|
|
516
|
+
const variantRule = { 'e': emptyRule, 'a': range('AA') };
|
|
517
|
+
const m = descentParser(variantRule);
|
|
518
|
+
const mr = m("", []);
|
|
519
|
+
const result = JSON.stringify(mr);
|
|
520
|
+
if (result !== '[{"tag":"e","sequence":[]},true,0]') {
|
|
521
|
+
throw result;
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
() => {
|
|
525
|
+
const emptyRule = '';
|
|
526
|
+
const variantRule = { 'e': emptyRule, 'a': range('AA') };
|
|
527
|
+
const m = descentParser(variantRule);
|
|
528
|
+
const mr = descentParserCpOnly(m, "", [64]);
|
|
529
|
+
const result = JSON.stringify(mr);
|
|
530
|
+
if (result !== '[{"tag":"e","sequence":[]},true,0]') {
|
|
531
|
+
throw result;
|
|
532
|
+
}
|
|
533
|
+
},
|
|
534
|
+
() => {
|
|
535
|
+
const stringRule = 'AB';
|
|
536
|
+
const m = descentParser(stringRule);
|
|
537
|
+
const mr = descentParserCpOnly(m, "", [65, 66]);
|
|
538
|
+
const result = JSON.stringify(mr);
|
|
539
|
+
if (result !== '[{"sequence":[{"sequence":[[65,null]]},{"sequence":[[66,null]]}]},true,2]') {
|
|
540
|
+
throw result;
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
() => {
|
|
544
|
+
const stringRule = 'AB';
|
|
545
|
+
const m = descentParser(stringRule);
|
|
546
|
+
const mr = descentParserCpOnly(m, "", [65, 67]);
|
|
547
|
+
const result = JSON.stringify(mr);
|
|
548
|
+
if (result !== '[{"sequence":[]},false,0]') {
|
|
549
|
+
throw result;
|
|
550
|
+
}
|
|
551
|
+
},
|
|
552
|
+
() => {
|
|
553
|
+
const emptyRule = '';
|
|
554
|
+
const minursRule = range('--');
|
|
555
|
+
const optionalMinusRule = { 'none': emptyRule, 'minus': minursRule };
|
|
556
|
+
const digitRule = range('09');
|
|
557
|
+
const numberRule = [optionalMinusRule, digitRule];
|
|
558
|
+
const m = descentParser(numberRule);
|
|
559
|
+
const mr = descentParserCpOnly(m, "", [50]);
|
|
560
|
+
const result = JSON.stringify(mr);
|
|
561
|
+
if (result !== '[{"sequence":[{"tag":"none","sequence":[]},{"sequence":[[50,null]]}]},true,1]') {
|
|
562
|
+
throw result;
|
|
563
|
+
}
|
|
564
|
+
},
|
|
565
|
+
() => {
|
|
566
|
+
const emptyRule = '';
|
|
567
|
+
const minusRule = range('--');
|
|
568
|
+
const optionalMinusRule = { 'none': emptyRule, 'minus': minusRule };
|
|
569
|
+
const digitRule = range('09');
|
|
570
|
+
const numberRule = [optionalMinusRule, digitRule];
|
|
571
|
+
const m = descentParser(numberRule);
|
|
572
|
+
const mr = descentParserCpOnly(m, "", [45, 50]);
|
|
573
|
+
const result = JSON.stringify(mr);
|
|
574
|
+
if (result !== '[{"sequence":[{"tag":"minus","sequence":[[45,null]]},{"sequence":[[50,null]]}]},true,2]') {
|
|
575
|
+
throw result;
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
() => {
|
|
579
|
+
const emptyRule = '';
|
|
580
|
+
const minursRule = range('--');
|
|
581
|
+
const optionalMinusRule = { 'none': emptyRule, 'minus': minursRule };
|
|
582
|
+
const digitRule = range('09');
|
|
583
|
+
const numberRule = [optionalMinusRule, digitRule];
|
|
584
|
+
const m = descentParser(numberRule);
|
|
585
|
+
const mr = m("", []);
|
|
586
|
+
const result = JSON.stringify(mr);
|
|
587
|
+
if (result !== '[{"sequence":[]},false,0]') {
|
|
588
|
+
throw result;
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
() => {
|
|
592
|
+
const m = descentParser(option('a'));
|
|
593
|
+
const expect = (s, expected) => {
|
|
594
|
+
const cp = toArray(stringToCodePointList(s));
|
|
595
|
+
const mr = descentParserCpOnly(m, '', cp);
|
|
596
|
+
const success = mr[1] && mr[2] === cp.length;
|
|
597
|
+
if (success !== expected) {
|
|
598
|
+
throw mr;
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
expect('a', true);
|
|
602
|
+
expect('', true);
|
|
603
|
+
expect('aa', false);
|
|
604
|
+
expect('b', false);
|
|
605
|
+
},
|
|
606
|
+
() => {
|
|
607
|
+
const ws = repeat0Plus(set(' \n\r\t'));
|
|
608
|
+
const commaJoin0Plus = ([open, close], a) => [
|
|
609
|
+
open,
|
|
610
|
+
ws,
|
|
611
|
+
join0Plus([a, ws], [',', ws]),
|
|
612
|
+
close,
|
|
613
|
+
];
|
|
614
|
+
const value = () => ({
|
|
615
|
+
object: commaJoin0Plus('{}', 'a'),
|
|
616
|
+
array: commaJoin0Plus('[]', 'a')
|
|
617
|
+
});
|
|
618
|
+
value.name; //bun will fail if no usage of name found
|
|
619
|
+
const m = descentParser(value);
|
|
620
|
+
const expect = (s, expected) => {
|
|
621
|
+
const cp = toArray(stringToCodePointList(s));
|
|
622
|
+
const mr = descentParserCpOnly(m, 'value', cp);
|
|
623
|
+
const success = mr[1] && mr[2] === cp.length;
|
|
624
|
+
if (success !== expected) {
|
|
625
|
+
throw mr;
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
expect('', false);
|
|
629
|
+
expect('[]', true);
|
|
630
|
+
expect('[a]', true);
|
|
631
|
+
expect('[a, a]', true);
|
|
632
|
+
expect('{a}', true);
|
|
633
|
+
},
|
|
634
|
+
() => {
|
|
635
|
+
const m = descentParser(deterministic());
|
|
636
|
+
const expect = (s, expected) => {
|
|
637
|
+
const cp = toArray(stringToCodePointList(s));
|
|
638
|
+
const mr = descentParserCpOnly(m, '', cp);
|
|
639
|
+
const success = mr[1] && mr[2] === cp.length;
|
|
640
|
+
if (success !== expected) {
|
|
641
|
+
throw mr;
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
expect(' true ', true);
|
|
645
|
+
expect(' tr2ue ', false);
|
|
646
|
+
expect(' true" ', false);
|
|
647
|
+
expect(' "Hello" ', true);
|
|
648
|
+
expect(' "Hello ', false);
|
|
649
|
+
expect(' "Hello\\n\\r\\"" ', true);
|
|
650
|
+
expect(' -56.7e+5 ', true);
|
|
651
|
+
expect(' h-56.7e+5 ', false);
|
|
652
|
+
expect(' -56.7e+5 3', false);
|
|
653
|
+
expect(' [] ', true);
|
|
654
|
+
expect(' {} ', true);
|
|
655
|
+
expect(' [[[]]] ', true);
|
|
656
|
+
expect(' [1] ', true);
|
|
657
|
+
expect(' [ 12, false, "a"] ', true);
|
|
658
|
+
expect(' [ 12, false2, "a"] ', false);
|
|
659
|
+
expect(' { "q": [ 12, false, [{"b" : "c"}], "a"] } ', true);
|
|
660
|
+
expect(' { "q": [ 12, false, [{}], "a"] } ', true);
|
|
661
|
+
expect(' { "q": [ 12, false, [}], "a"] } ', false);
|
|
662
|
+
expect(' [{ "q": [ 12, false, [{}], "a"] }] ', true);
|
|
663
|
+
expect(' [{ "q": [ 12, false, [}], "a"] }] ', false);
|
|
664
|
+
}
|
|
665
|
+
],
|
|
666
|
+
descentParserWithMeta: [
|
|
667
|
+
() => {
|
|
668
|
+
const emptyRule = '';
|
|
669
|
+
const minusRule = range('--');
|
|
670
|
+
const optionalMinusRule = { 'none': emptyRule, 'minus': minusRule };
|
|
671
|
+
const digitRule = range('09');
|
|
672
|
+
const numberRule = [optionalMinusRule, digitRule];
|
|
673
|
+
const m = descentParser(numberRule);
|
|
674
|
+
const mr = m("", [[45, 'minus'], [50, 'two']]);
|
|
675
|
+
const result = JSON.stringify(mr);
|
|
676
|
+
if (result !== '[{"sequence":[{"tag":"minus","sequence":[[45,"minus"]]},{"sequence":[[50,"two"]]}]},true,2]') {
|
|
677
|
+
throw result;
|
|
678
|
+
}
|
|
679
|
+
},
|
|
680
|
+
],
|
|
440
681
|
repeat: [
|
|
441
682
|
() => {
|
|
442
683
|
const repeatData = [{ "": ["ws", "repa"], "ws": [], "repa": ["a", ""], "a": 1090519105 }, ""];
|
package/bnf/module.f.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ import { type Array2 } from '../types/array/module.f.ts';
|
|
|
7
7
|
* - 0xEEEEEE is the last symbol (24 bits)
|
|
8
8
|
*/
|
|
9
9
|
export type TerminalRange = number;
|
|
10
|
+
export declare const fullRange: TerminalRange;
|
|
11
|
+
export declare const unicodeRange: TerminalRange;
|
|
12
|
+
export declare const eof = 1114112;
|
|
10
13
|
/** A sequence of rules. */
|
|
11
14
|
export type Sequence = readonly Rule[];
|
|
12
15
|
/** A variant */
|
|
@@ -30,8 +33,9 @@ export declare const range: (ab: string) => TerminalRange;
|
|
|
30
33
|
export type RangeVariant = {
|
|
31
34
|
readonly [k in string]: TerminalRange;
|
|
32
35
|
};
|
|
33
|
-
export declare const
|
|
34
|
-
export declare const
|
|
36
|
+
export declare const remove: (range: TerminalRange, v: RangeVariant) => RangeVariant;
|
|
37
|
+
export declare const not: (v: RangeVariant) => RangeVariant;
|
|
38
|
+
export declare const notSet: (s: string) => RangeVariant;
|
|
35
39
|
export type None = readonly [];
|
|
36
40
|
export declare const none: None;
|
|
37
41
|
export type Option<S> = {
|
package/bnf/module.f.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { codePointListToString, stringToCodePointList } from "../text/utf16/module.f.js";
|
|
2
2
|
import { isArray2 } from "../types/array/module.f.js";
|
|
3
3
|
import { map, toArray, repeat as listRepeat } from "../types/list/module.f.js";
|
|
4
|
+
export const fullRange = 0x000000_FFFFFF;
|
|
5
|
+
export const unicodeRange = 0x000000_10FFFF;
|
|
6
|
+
export const eof = 0x110000;
|
|
4
7
|
// Internals:
|
|
5
8
|
const { fromEntries, values } = Object;
|
|
6
9
|
const { fromCodePoint } = String;
|
|
@@ -34,13 +37,7 @@ export const range = (ab) => {
|
|
|
34
37
|
}
|
|
35
38
|
return rangeEncode(...a);
|
|
36
39
|
};
|
|
37
|
-
|
|
38
|
-
const ab = rangeDecode(r);
|
|
39
|
-
const [a, b] = ab;
|
|
40
|
-
const cp = a === b ? [a] : ab;
|
|
41
|
-
return fromCodePoint(...cp);
|
|
42
|
-
};
|
|
43
|
-
const rangeToEntry = (r) => [rangeToId(r), r];
|
|
40
|
+
const rangeToEntry = (r) => ['0x' + r.toString(16), r];
|
|
44
41
|
const toVariantRangeSet = (r) => fromEntries(r.map(rangeToEntry));
|
|
45
42
|
const removeOne = (list, ab) => {
|
|
46
43
|
const [a, b] = rangeDecode(ab);
|
|
@@ -60,13 +57,15 @@ const removeOne = (list, ab) => {
|
|
|
60
57
|
}
|
|
61
58
|
return result;
|
|
62
59
|
};
|
|
63
|
-
export const remove = (range,
|
|
60
|
+
export const remove = (range, v) => {
|
|
64
61
|
let result = [range];
|
|
65
|
-
for (const r of values(
|
|
62
|
+
for (const r of values(v)) {
|
|
66
63
|
result = removeOne(result, r);
|
|
67
64
|
}
|
|
68
65
|
return toVariantRangeSet(result);
|
|
69
66
|
};
|
|
67
|
+
export const not = (v) => remove(fullRange, v);
|
|
68
|
+
export const notSet = (s) => not(set(s));
|
|
70
69
|
export const none = [];
|
|
71
70
|
export const option = (some) => ({
|
|
72
71
|
some,
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Sha2 } from "../crypto/sha2/module.f.ts";
|
|
2
|
+
import type { Vec } from "../types/bit_vec/module.f.ts";
|
|
3
|
+
import { type Effect, type Operations } from "../types/effect/module.f.ts";
|
|
4
|
+
import { type Fs, type NodeOperations } from "../types/effect/node/module.f.ts";
|
|
5
|
+
export type KvStore<O extends Operations> = {
|
|
6
|
+
readonly read: (key: Vec) => Effect<O, Vec | undefined>;
|
|
7
|
+
readonly write: (key: Vec, value: Vec) => Effect<O, void>;
|
|
8
|
+
readonly list: () => Effect<O, readonly Vec[]>;
|
|
9
|
+
};
|
|
10
|
+
export type Kv = readonly [Vec, Vec];
|
|
11
|
+
export declare const fileKvStore: (path: string) => KvStore<Fs>;
|
|
12
|
+
export type Cas<O extends Operations> = {
|
|
13
|
+
readonly read: (key: Vec) => Effect<O, Vec | undefined>;
|
|
14
|
+
readonly write: (value: Vec) => Effect<O, Vec>;
|
|
15
|
+
readonly list: () => Effect<O, readonly Vec[]>;
|
|
16
|
+
};
|
|
17
|
+
export declare const cas: (sha2: Sha2) => <O extends Operations>(_: KvStore<O>) => Cas<O>;
|
|
18
|
+
export declare const main: (args: readonly string[]) => Effect<NodeOperations, number>;
|
package/cas/module.f.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { computeSync, sha256 } from "../crypto/sha2/module.f.js";
|
|
2
|
+
import { parse } from "../path/module.f.js";
|
|
3
|
+
import { cBase32ToVec, vecToCBase32 } from "../types/cbase32/module.f.js";
|
|
4
|
+
import { pure } from "../types/effect/module.f.js";
|
|
5
|
+
import { error, log, mkdir, readdir, readFile, writeFile } from "../types/effect/node/module.f.js";
|
|
6
|
+
import { toOption } from "../types/nullable/module.f.js";
|
|
7
|
+
import { unwrap } from "../types/result/module.f.js";
|
|
8
|
+
const o = { withFileTypes: true };
|
|
9
|
+
const split = (s) => [s.substring(0, 2), s.substring(2)];
|
|
10
|
+
const prefix = '.cas';
|
|
11
|
+
const toPath = (key) => {
|
|
12
|
+
const s = vecToCBase32(key);
|
|
13
|
+
const [a, bc] = split(s);
|
|
14
|
+
const [b, c] = split(bc);
|
|
15
|
+
return `${prefix}/${a}/${b}/${c}`;
|
|
16
|
+
};
|
|
17
|
+
export const fileKvStore = (path) => ({
|
|
18
|
+
read: (key) => readFile(toPath(key))
|
|
19
|
+
.map(([status, data]) => status === 'error' ? undefined : data),
|
|
20
|
+
write: (key, value) => {
|
|
21
|
+
const p = toPath(key);
|
|
22
|
+
const parts = parse(p);
|
|
23
|
+
const dir = `${path}/${parts.slice(0, -1).join('/')}`;
|
|
24
|
+
// TODO: error handling
|
|
25
|
+
return mkdir(dir, { recursive: true })
|
|
26
|
+
.pipe(() => writeFile(`${path}/${p}`, value))
|
|
27
|
+
.map(() => undefined);
|
|
28
|
+
},
|
|
29
|
+
list: () => readdir('.cas', { recursive: true })
|
|
30
|
+
// TODO: remove unwrap
|
|
31
|
+
.map(r => unwrap(r).flatMap(({ name, parentPath, isFile }) => toOption(isFile ? cBase32ToVec(parentPath.substring(prefix.length).replaceAll('/', '') + name) : null))),
|
|
32
|
+
});
|
|
33
|
+
export const cas = (sha2) => {
|
|
34
|
+
const compute = computeSync(sha2);
|
|
35
|
+
return ({ read, write, list }) => ({
|
|
36
|
+
read,
|
|
37
|
+
write: (value) => {
|
|
38
|
+
const hash = compute([value]);
|
|
39
|
+
return write(hash, value)
|
|
40
|
+
.map(() => hash);
|
|
41
|
+
},
|
|
42
|
+
list,
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const e = (s) => error(s).map(() => 1);
|
|
46
|
+
export const main = (args) => {
|
|
47
|
+
const c = cas(sha256)(fileKvStore('.'));
|
|
48
|
+
const [cmd, ...options] = args;
|
|
49
|
+
switch (cmd) {
|
|
50
|
+
case 'add': {
|
|
51
|
+
if (options.length !== 1) {
|
|
52
|
+
return e("'cas add' expects one parameter");
|
|
53
|
+
}
|
|
54
|
+
const [path] = options;
|
|
55
|
+
return readFile(path)
|
|
56
|
+
.pipe(v => c.write(unwrap(v)))
|
|
57
|
+
.pipe(hash => log(vecToCBase32(hash)))
|
|
58
|
+
.map(() => 0);
|
|
59
|
+
}
|
|
60
|
+
case 'get': {
|
|
61
|
+
if (options.length !== 2) {
|
|
62
|
+
return e("'cas get' expects two parameters");
|
|
63
|
+
}
|
|
64
|
+
const [hashCBase32, path] = options;
|
|
65
|
+
const hash = cBase32ToVec(hashCBase32);
|
|
66
|
+
if (hash === null) {
|
|
67
|
+
return e(`invalid hash format: ${hashCBase32}`);
|
|
68
|
+
}
|
|
69
|
+
return c.read(hash)
|
|
70
|
+
.pipe(v => {
|
|
71
|
+
const result = v === undefined
|
|
72
|
+
? e(`no such hash: ${hashCBase32}`)
|
|
73
|
+
: writeFile(path, v).map(() => 0);
|
|
74
|
+
return result;
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
case 'list': {
|
|
78
|
+
return c.list()
|
|
79
|
+
.pipe(v => {
|
|
80
|
+
// TODO: make it lazy.
|
|
81
|
+
let i = pure(undefined);
|
|
82
|
+
for (const j of v) {
|
|
83
|
+
i = i.pipe(() => log(vecToCBase32(j)));
|
|
84
|
+
}
|
|
85
|
+
return i;
|
|
86
|
+
})
|
|
87
|
+
.map(() => 0);
|
|
88
|
+
}
|
|
89
|
+
case undefined: {
|
|
90
|
+
return e('Error: CAS command requires subcommand');
|
|
91
|
+
}
|
|
92
|
+
default:
|
|
93
|
+
return e(`Error: Unknown CAS subcommand "${args[0]}"`);
|
|
94
|
+
}
|
|
95
|
+
};
|
package/cas/test.f.d.ts
ADDED
package/cas/test.f.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default () => { };
|
package/ci/module.f.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
declare const
|
|
1
|
+
import { type NodeEffect } from '../types/effect/node/module.f.ts';
|
|
2
|
+
export declare const effect: NodeEffect<number>;
|
|
3
|
+
declare const _default: () => NodeEffect<number>;
|
|
3
4
|
export default _default;
|