functionalscript 0.32.3 → 0.33.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.
Files changed (41) hide show
  1. package/fs/bnf/data/proof.f.d.ts +3 -0
  2. package/fs/bnf/data/proof.f.js +7 -0
  3. package/fs/cas/mcp/module.f.d.ts +4 -4
  4. package/fs/cas/mcp/module.f.js +21 -17
  5. package/fs/cas/mcp/proof.f.d.ts +1 -0
  6. package/fs/cas/mcp/proof.f.js +62 -42
  7. package/fs/cas/module.f.d.ts +13 -21
  8. package/fs/cas/module.f.js +100 -54
  9. package/fs/cas/proof.f.js +15 -24
  10. package/fs/ci/config/module.f.d.ts +6 -6
  11. package/fs/ci/config/module.f.js +6 -6
  12. package/fs/ci/proof.f.js +8 -6
  13. package/fs/cli/proof.f.js +2 -12
  14. package/fs/djs/parser/module.f.d.ts +0 -5
  15. package/fs/djs/proof.f.js +5 -6
  16. package/fs/djs/serializer/module.f.d.ts +1 -3
  17. package/fs/djs/tokenizer-new/module.f.js +2 -1
  18. package/fs/djs/tokenizer-new/proof.f.d.ts +1 -0
  19. package/fs/djs/tokenizer-new/proof.f.js +101 -67
  20. package/fs/djs/transpiler/proof.f.js +10 -10
  21. package/fs/effects/node/module.f.d.ts +8 -2
  22. package/fs/effects/node/module.f.js +3 -0
  23. package/fs/effects/node/module.js +21 -1
  24. package/fs/effects/node/proof.f.d.ts +15 -0
  25. package/fs/effects/node/proof.f.js +137 -26
  26. package/fs/effects/node/virtual/module.f.d.ts +18 -2
  27. package/fs/effects/node/virtual/module.f.js +185 -10
  28. package/fs/effects/node/virtual/proof.f.d.ts +14 -0
  29. package/fs/effects/node/virtual/proof.f.js +98 -5
  30. package/fs/emergent_testing/proof.f.js +3 -11
  31. package/fs/fjs/module.f.js +3 -3
  32. package/fs/fjs/proof.f.js +2 -11
  33. package/fs/js/tokenizer/module.f.d.ts +5 -0
  34. package/fs/js/tokenizer/module.f.js +13 -0
  35. package/fs/json/serializer/module.f.js +0 -1
  36. package/fs/text/sgr/proof.f.js +2 -11
  37. package/fs/types/bigint/module.f.d.ts +8 -15
  38. package/fs/types/bigint/module.f.js +9 -22
  39. package/fs/types/bigint/proof.f.d.ts +0 -2
  40. package/fs/types/bigint/proof.f.js +6 -16
  41. package/package.json +2 -2
package/fs/cas/proof.f.js CHANGED
@@ -1,25 +1,17 @@
1
- import { cas, commands } from "./module.f.js";
2
- import { sha256 } from "../crypto/sha2/module.f.js";
1
+ import { commands } from "./module.f.js";
2
+ import { computeSync, sha256 } from "../crypto/sha2/module.f.js";
3
3
  import { empty, length, vec8 } from "../types/bit_vec/module.f.js";
4
4
  import { pure } from "../effects/module.f.js";
5
5
  import { run } from "../effects/mock/module.f.js";
6
- import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
6
+ import { defaultNodeProgramOptions, emptyState, virtual } from "../effects/node/virtual/module.f.js";
7
7
  import { dispatch } from "../cli/module.f.js";
8
- const makeOptions = (args) => ({
9
- args,
10
- env: {},
11
- home: '.',
12
- std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
13
- testContext: { test: async () => { } },
14
- bunTestContext: { test: async () => { } },
15
- playwrightTestContext: { test: async () => { } },
16
- engine: 'node',
17
- });
8
+ import { assert } from "../asserts/module.f.js";
9
+ const makeOptions = (args) => ({ ...defaultNodeProgramOptions, args });
18
10
  const main = dispatch(commands);
19
11
  export const proof = {
20
12
  mainAdd: () => {
21
13
  const content = vec8(0x2an);
22
- const state = { ...emptyState, root: { myfile: content } };
14
+ const state = { ...emptyState, root: { myfile: [content] } };
23
15
  const [finalState, exitCode] = virtual(state)(main(makeOptions(['add', 'myfile'])));
24
16
  if (exitCode !== 0) {
25
17
  throw ['expected exit 0', exitCode];
@@ -39,7 +31,7 @@ export const proof = {
39
31
  },
40
32
  mainGetFound: () => {
41
33
  const content = vec8(0x2an);
42
- const state = { ...emptyState, root: { myfile: content } };
34
+ const state = { ...emptyState, root: { myfile: [content] } };
43
35
  const [state1, exitCode1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
44
36
  if (exitCode1 !== 0) {
45
37
  throw ['expected add exit 0', exitCode1];
@@ -53,7 +45,7 @@ export const proof = {
53
45
  mainGetNotFound: () => {
54
46
  // valid cBase32 hash that has not been stored
55
47
  const content = vec8(0x2an);
56
- const state = { ...emptyState, root: { myfile: content } };
48
+ const state = { ...emptyState, root: { myfile: [content] } };
57
49
  const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
58
50
  const hashStr = state1.stdout.trim();
59
51
  // use an empty store so the hash is not found
@@ -85,7 +77,7 @@ export const proof = {
85
77
  },
86
78
  mainList: () => {
87
79
  const content = vec8(0x2an);
88
- const state = { ...emptyState, root: { myfile: content } };
80
+ const state = { ...emptyState, root: { myfile: [content] } };
89
81
  const [state1] = virtual(state)(main(makeOptions(['add', 'myfile'])));
90
82
  const [, exitCode] = virtual(state1)(main(makeOptions(['list'])));
91
83
  if (exitCode !== 0) {
@@ -106,7 +98,7 @@ export const proof = {
106
98
  mainListCorruptStore: () => {
107
99
  // `.cas` exists but is a file, not a directory: a real storage error
108
100
  // that must surface, not be masked as an empty list.
109
- const state = { ...emptyState, root: { '.cas': vec8(0x2an) } };
101
+ const state = { ...emptyState, root: { '.cas': [vec8(0x2an)] } };
110
102
  let threw = false;
111
103
  try {
112
104
  virtual(state)(main(makeOptions(['list'])));
@@ -137,26 +129,25 @@ export const proof = {
137
129
  }
138
130
  },
139
131
  casWrite: () => {
140
- const store = {
132
+ const c = {
141
133
  read: (_key) => pure(undefined),
142
- write: (_key, _value) => pure(undefined),
134
+ write: (value) => pure(computeSync(sha256)([value])),
143
135
  list: () => pure([]),
144
136
  };
145
- const c = cas(sha256)(store);
146
137
  const [, hash] = run({})(undefined)(c.write(empty));
147
138
  // sha256 of empty input produces a 256-bit hash
139
+ assert(hash !== undefined);
148
140
  if (length(hash) !== 256n) {
149
141
  throw ['expected 256-bit hash', length(hash)];
150
142
  }
151
143
  },
152
144
  casReadPassthrough: () => {
153
145
  const stored = empty;
154
- const store = {
146
+ const c = {
155
147
  read: (_key) => pure(stored),
156
- write: (_key, _value) => pure(undefined),
148
+ write: (value) => pure(computeSync(sha256)([value])),
157
149
  list: () => pure([stored]),
158
150
  };
159
- const c = cas(sha256)(store);
160
151
  const [, readResult] = run({})(undefined)(c.read(empty));
161
152
  if (readResult !== stored) {
162
153
  throw ['read should pass through', readResult];
@@ -19,20 +19,20 @@ export declare const images: {
19
19
  readonly arm: "windows-11-arm";
20
20
  };
21
21
  };
22
- export declare const functionalscript: "0.30.0";
22
+ export declare const functionalscript: "0.32.4";
23
23
  export declare const bun = "1.3.14";
24
24
  export declare const deno = "2.8.3";
25
25
  export declare const playwright = "1.61.0";
26
26
  export declare const node: {
27
- readonly default: "26.3.0";
28
- readonly node22: "22.22.3";
29
- readonly node24: "24.16.0";
27
+ readonly default: "26.3.1";
28
+ readonly node22: "22.23.0";
29
+ readonly node24: "24.17.0";
30
30
  };
31
31
  export declare const wasmtime = "45.0.2";
32
32
  export declare const wasmer = "7.1.0";
33
- export declare const tsgo = "7.0.0-dev.20260615.1";
33
+ export declare const tsgo = "7.0.0-dev.20260620.1";
34
34
  export declare const actions: {
35
- readonly 'actions/checkout': "v6";
35
+ readonly 'actions/checkout': "v7";
36
36
  readonly 'actions/setup-node': "v6";
37
37
  readonly 'actions/cache': "v5";
38
38
  readonly 'denoland/setup-deno': "v2";
@@ -24,7 +24,7 @@ export const images = {
24
24
  // published FunctionalScript release; do not tie it to package.json's current
25
25
  // in-repo version. A separate maintenance job advances this pin.
26
26
  // https://www.npmjs.com/package/functionalscript
27
- export const functionalscript = '0.30.0';
27
+ export const functionalscript = '0.32.4';
28
28
  // https://bun.sh/
29
29
  export const bun = '1.3.14';
30
30
  // https://deno.com/
@@ -33,23 +33,23 @@ export const deno = '2.8.3';
33
33
  export const playwright = '1.61.0';
34
34
  // https://nodejs.org/en/download
35
35
  export const node = {
36
- default: '26.3.0',
37
- node22: '22.22.3',
38
- node24: '24.16.0',
36
+ default: '26.3.1',
37
+ node22: '22.23.0',
38
+ node24: '24.17.0',
39
39
  };
40
40
  // https://github.com/bytecodealliance/wasmtime/releases
41
41
  export const wasmtime = '45.0.2';
42
42
  // https://github.com/wasmerio/wasmer/releases
43
43
  export const wasmer = '7.1.0';
44
44
  // https://www.npmjs.com/package/@typescript/native-preview?activeTab=versions
45
- export const tsgo = '7.0.0-dev.20260615.1';
45
+ export const tsgo = '7.0.0-dev.20260620.1';
46
46
  // GitHub Action versions used by CI step builders. The key is the action
47
47
  // `owner/name`; call sites compose the full ref as
48
48
  // `` `${name}@${actions[name]}` ``.
49
49
  // Note: dtolnay/rust-toolchain value is a Rust version, not an action version.
50
50
  export const actions = {
51
51
  // https://github.com/marketplace/actions/checkout
52
- 'actions/checkout': 'v6',
52
+ 'actions/checkout': 'v7',
53
53
  // https://github.com/marketplace/actions/setup-node-js-environment
54
54
  'actions/setup-node': 'v6',
55
55
  // https://github.com/marketplace/actions/cache
package/fs/ci/proof.f.js CHANGED
@@ -14,18 +14,20 @@ const makeState = (rust, packageJson) => ({
14
14
  ...emptyState,
15
15
  root: {
16
16
  '.github': { workflows: {} },
17
- ...(packageJson !== undefined ? { 'package.json': utf8(packageJson) } : {}),
18
- ...(rust ? { 'Cargo.toml': emptyVec } : {}),
17
+ ...(packageJson !== undefined ? { 'package.json': [utf8(packageJson)] } : {}),
18
+ ...(rust ? { 'Cargo.toml': [emptyVec] } : {}),
19
19
  },
20
20
  });
21
21
  const workflow = (state) => {
22
22
  const dotGithub = state.root['.github'];
23
- assert(typeof dotGithub === 'object', dotGithub);
23
+ assert(typeof dotGithub === 'object' && !Array.isArray(dotGithub), dotGithub);
24
24
  const workflows = dotGithub['workflows'];
25
- assert(typeof workflows === 'object', workflows);
25
+ assert(typeof workflows === 'object' && !Array.isArray(workflows), workflows);
26
26
  const file = workflows['ci.yml'];
27
- assert(isVec(file), file);
28
- return unwrap(parseGitHubAction(jsonParse(utf8ToString(file))));
27
+ if (!Array.isArray(file) || file.length === 0) {
28
+ throw file;
29
+ }
30
+ return unwrap(parseGitHubAction(jsonParse(utf8ToString(file[0]))));
29
31
  };
30
32
  const run = (rust, nodeExtra = () => []) => {
31
33
  const [state, result] = virtual(makeState(rust))(ci({ nodeExtra }));
package/fs/cli/proof.f.js CHANGED
@@ -1,17 +1,7 @@
1
1
  import { pure } from "../effects/module.f.js";
2
- import {} from "../effects/node/module.f.js";
3
- import { emptyState, virtual } from "../effects/node/virtual/module.f.js";
2
+ import { defaultNodeProgramOptions, emptyState, virtual } from "../effects/node/virtual/module.f.js";
4
3
  import { dispatch } from "./module.f.js";
5
- const makeOptions = (args) => ({
6
- args,
7
- env: {},
8
- home: '.',
9
- std: { stdout: { isTTY: false }, stderr: { isTTY: false } },
10
- testContext: { test: async () => { } },
11
- bunTestContext: { test: async () => { } },
12
- playwrightTestContext: { test: async () => { } },
13
- engine: 'node',
14
- });
4
+ const makeOptions = (args) => ({ ...defaultNodeProgramOptions, args });
15
5
  const echoCommands = [
16
6
  {
17
7
  names: ['echo', 'e'],
@@ -6,13 +6,8 @@
6
6
  import { type Result } from '../../types/result/module.f.ts';
7
7
  import { type List } from '../../types/list/module.f.ts';
8
8
  import type { DjsTokenWithMetadata } from '../tokenizer/module.f.ts';
9
- import { type OrderedMap } from '../../types/ordered_map/module.f.ts';
10
9
  import type { AstModule } from '../ast/module.f.ts';
11
10
  import type { TokenMetadata } from '../../js/tokenizer/module.f.ts';
12
- export type ParseContext = {
13
- readonly complete: OrderedMap<Result<AstModule, string>>;
14
- readonly stack: List<string>;
15
- };
16
11
  export type ParseError = {
17
12
  readonly message: string;
18
13
  readonly metadata: TokenMetadata | null;
package/fs/djs/proof.f.js CHANGED
@@ -1,13 +1,12 @@
1
1
  import { compile } from "./module.f.js";
2
2
  import { virtual, emptyState } from "../effects/node/virtual/module.f.js";
3
- import { isVec } from "../types/bit_vec/module.f.js";
4
3
  import { utf8, utf8ToString } from "../text/module.f.js";
5
4
  const readOutput = (root, path) => {
6
5
  const file = root[path];
7
- if (!isVec(file)) {
6
+ if (!Array.isArray(file) || file.length === 0) {
8
7
  throw `${path} is not a file`;
9
8
  }
10
- return utf8ToString(file);
9
+ return utf8ToString(file[0]);
11
10
  };
12
11
  export const proof = {
13
12
  tooFewArgs: {
@@ -31,7 +30,7 @@ export const proof = {
31
30
  },
32
31
  },
33
32
  success: () => {
34
- const root = { 'input.f.js': utf8('export default 42') };
33
+ const root = { 'input.f.js': [utf8('export default 42')] };
35
34
  const [state, code] = virtual({ ...emptyState, root })(compile(['input.f.js', 'output.f.js']));
36
35
  if (code !== 0) {
37
36
  throw code;
@@ -42,7 +41,7 @@ export const proof = {
42
41
  }
43
42
  },
44
43
  jsonOutput: () => {
45
- const root = { 'input.f.js': utf8('export default 42') };
44
+ const root = { 'input.f.js': [utf8('export default 42')] };
46
45
  const [state, code] = virtual({ ...emptyState, root })(compile(['input.f.js', 'output.json']));
47
46
  if (code !== 0) {
48
47
  throw code;
@@ -62,7 +61,7 @@ export const proof = {
62
61
  }
63
62
  },
64
63
  parseError: () => {
65
- const root = { 'bad.f.js': utf8('export default @') };
64
+ const root = { 'bad.f.js': [utf8('export default @')] };
66
65
  const [state, code] = virtual({ ...emptyState, root })(compile(['bad.f.js', 'output.f.js']));
67
66
  if (code !== 0) {
68
67
  throw code;
@@ -8,9 +8,7 @@ import type { Entry as ObjectEntry } from '../../types/object/module.f.ts';
8
8
  import { type List } from '../../types/list/module.f.ts';
9
9
  export declare const undefinedSerialize: string[];
10
10
  type RefCounter = readonly [number, number];
11
- type Entry = ObjectEntry<Unknown>;
12
- type Entries = List<Entry>;
13
- type MapEntries = (entries: Entries) => Entries;
11
+ type MapEntries = (entries: List<ObjectEntry<Unknown>>) => List<ObjectEntry<Unknown>>;
14
12
  type Refs = ReadonlyMap<Unknown, RefCounter>;
15
13
  export declare const serializeWithoutConst: (mapEntries: MapEntries) => (value: Unknown) => List<string>;
16
14
  export declare const stringify: (sort: MapEntries) => (djs: Unknown) => string;
@@ -20,7 +20,8 @@ export const jsGrammar = () => {
20
20
  escape: [
21
21
  '\\',
22
22
  {
23
- ...set('"\\/bfnrt'),
23
+ ...set('"\\bfnrt'),
24
+ solidus: '/',
24
25
  u: [
25
26
  'u',
26
27
  ...repeat(4)({
@@ -3,6 +3,7 @@ export declare const proof: {
3
3
  tokenizer: (() => void)[];
4
4
  djs: (() => void)[];
5
5
  operators: (() => void)[];
6
+ ws: (() => void)[];
6
7
  throw: {
7
8
  parse: () => void;
8
9
  };
@@ -38,6 +38,8 @@ const scanFunc = (input, state) => {
38
38
  return [null, state];
39
39
  if (isNlTag(input) && isWsTag(state[0]))
40
40
  return [null, [input, []]];
41
+ if (isWsTag(input) && isNlTag(state[0]))
42
+ return [null, state];
41
43
  const newState = [input, []];
42
44
  if (state[0] === '') {
43
45
  return [null, newState];
@@ -53,7 +55,7 @@ const operatorTags = new Set([
53
55
  '>>>=', '>>>', '>>=', '>>', '>=', '>',
54
56
  '<<<=', '<<<', '<<=', '<<', '<=', '<',
55
57
  '+=', '++', '+', '-=', '--', '-',
56
- '**=', '**', '*=', '*', '/=', '%=', '%',
58
+ '**=', '**', '*=', '*', '/=', '/', '%=', '%', // TODO: '/' here causes multi-char line comments (e.g. //ab\n) to fall through as two '/' operator tokens because the oneline rule only consumes one non-newline character (option vs repeat0Plus). Fix the comment rule to use repeat0Plus, or make filterFunc distinguish operator-branch '/' from slash characters inside comments.
57
59
  '&&=', '&&', '&=', '&', '||=', '||', '|=', '|',
58
60
  '^=', '^', '~', '??=', '??', '?.', '?',
59
61
  '[', ']', '{', '}', '(', ')', ',', ':'
@@ -664,76 +666,108 @@ export const proof = {
664
666
  // const result = tokenizeString('=a')
665
667
  // if (result !== '[{"kind":"="},{"kind":"id","value":"a"},{"kind":"eof"}]') { throw result }
666
668
  // },
667
- // () => {
668
- // const result = tokenizeString('-')
669
- // if (result !== '[{"kind":"-"},{"kind":"eof"}]') { throw result }
670
- // },
669
+ () => {
670
+ const result = tokenizeString('-');
671
+ if (result !== '[{"kind":"-"},{"kind":"eof"}]') {
672
+ throw result;
673
+ }
674
+ },
671
675
  // () => {
672
676
  // const result = tokenizeString('1*2')
673
677
  // if (result !== '[{"bf":[1n,0],"kind":"number","value":"1"},{"kind":"*"},{"bf":[2n,0],"kind":"number","value":"2"},{"kind":"eof"}]') { throw result }
674
678
  // },
675
- // () => {
676
- // const result = tokenizeString('( )')
677
- // if (result !== '[{"kind":"("},{"kind":"ws"},{"kind":")"},{"kind":"eof"}]') { throw result }
678
- // },
679
- // () => {
680
- // const result = tokenizeString('== != === !== > >= < <=')
681
- // if (result !== '[{"kind":"=="},{"kind":"ws"},{"kind":"!="},{"kind":"ws"},{"kind":"==="},{"kind":"ws"},{"kind":"!=="},{"kind":"ws"},{"kind":">"},{"kind":"ws"},{"kind":">="},{"kind":"ws"},{"kind":"<"},{"kind":"ws"},{"kind":"<="},{"kind":"eof"}]') { throw result }
682
- // },
683
- // () => {
684
- // const result = tokenizeString('+ - * / % ++ -- **')
685
- // if (result !== '[{"kind":"+"},{"kind":"ws"},{"kind":"-"},{"kind":"ws"},{"kind":"*"},{"kind":"ws"},{"kind":"/"},{"kind":"ws"},{"kind":"%"},{"kind":"ws"},{"kind":"++"},{"kind":"ws"},{"kind":"--"},{"kind":"ws"},{"kind":"**"},{"kind":"eof"}]') { throw result }
686
- // },
687
- // () => {
688
- // const result = tokenizeString('= += -= *= /= %= **=')
689
- // if (result !== '[{"kind":"="},{"kind":"ws"},{"kind":"+="},{"kind":"ws"},{"kind":"-="},{"kind":"ws"},{"kind":"*="},{"kind":"ws"},{"kind":"/="},{"kind":"ws"},{"kind":"%="},{"kind":"ws"},{"kind":"**="},{"kind":"eof"}]') { throw result }
690
- // },
691
- // () => {
692
- // const result = tokenizeString('& | ^ ~ << >> >>>')
693
- // if (result !== '[{"kind":"&"},{"kind":"ws"},{"kind":"|"},{"kind":"ws"},{"kind":"^"},{"kind":"ws"},{"kind":"~"},{"kind":"ws"},{"kind":"<<"},{"kind":"ws"},{"kind":">>"},{"kind":"ws"},{"kind":">>>"},{"kind":"eof"}]') { throw result }
694
- // },
695
- // () => {
696
- // const result = tokenizeString('&= |= ^= <<= >>= >>>=')
697
- // if (result !== '[{"kind":"&="},{"kind":"ws"},{"kind":"|="},{"kind":"ws"},{"kind":"^="},{"kind":"ws"},{"kind":"<<="},{"kind":"ws"},{"kind":">>="},{"kind":"ws"},{"kind":">>>="},{"kind":"eof"}]') { throw result }
698
- // },
699
- // () => {
700
- // const result = tokenizeString('&& || ! ??')
701
- // if (result !== '[{"kind":"&&"},{"kind":"ws"},{"kind":"||"},{"kind":"ws"},{"kind":"!"},{"kind":"ws"},{"kind":"??"},{"kind":"eof"}]') { throw result }
702
- // },
703
- // () => {
704
- // const result = tokenizeString('&&= ||= ??=')
705
- // if (result !== '[{"kind":"&&="},{"kind":"ws"},{"kind":"||="},{"kind":"ws"},{"kind":"??="},{"kind":"eof"}]') { throw result }
706
- // },
707
- // () => {
708
- // const result = tokenizeString('? ?. . =>')
709
- // if (result !== '[{"kind":"?"},{"kind":"ws"},{"kind":"?."},{"kind":"ws"},{"kind":"."},{"kind":"ws"},{"kind":"=>"},{"kind":"eof"}]') { throw result }
710
- // },
711
- // ],
712
- // ws: [
713
- // () => {
714
- // const result = tokenizeString(' ')
715
- // if (result !== '[{"kind":"ws"},{"kind":"eof"}]') { throw result }
716
- // },
717
- // () => {
718
- // const result = tokenizeString('\t')
719
- // if (result !== '[{"kind":"ws"},{"kind":"eof"}]') { throw result }
720
- // },
721
- // () => {
722
- // const result = tokenizeString(' \t')
723
- // if (result !== '[{"kind":"ws"},{"kind":"eof"}]') { throw result }
724
- // },
725
- // () => {
726
- // const result = tokenizeString('\n')
727
- // if (result !== '[{"kind":"nl"},{"kind":"eof"}]') { throw result }
728
- // },
729
- // () => {
730
- // const result = tokenizeString('\r')
731
- // if (result !== '[{"kind":"nl"},{"kind":"eof"}]') { throw result }
732
- // },
733
- // () => {
734
- // const result = tokenizeString(' \t\n\r ')
735
- // if (result !== '[{"kind":"nl"},{"kind":"eof"}]') { throw result }
736
- // },
679
+ () => {
680
+ const result = tokenizeString('( )');
681
+ if (result !== '[{"kind":"("},{"kind":"ws"},{"kind":")"},{"kind":"eof"}]') {
682
+ throw result;
683
+ }
684
+ },
685
+ () => {
686
+ const result = tokenizeString('== != === !== > >= < <=');
687
+ if (result !== '[{"kind":"=="},{"kind":"ws"},{"kind":"!="},{"kind":"ws"},{"kind":"==="},{"kind":"ws"},{"kind":"!=="},{"kind":"ws"},{"kind":">"},{"kind":"ws"},{"kind":">="},{"kind":"ws"},{"kind":"<"},{"kind":"ws"},{"kind":"<="},{"kind":"eof"}]') {
688
+ throw result;
689
+ }
690
+ },
691
+ () => {
692
+ const result = tokenizeString('+ - * / % ++ -- **');
693
+ if (result !== '[{"kind":"+"},{"kind":"ws"},{"kind":"-"},{"kind":"ws"},{"kind":"*"},{"kind":"ws"},{"kind":"/"},{"kind":"ws"},{"kind":"%"},{"kind":"ws"},{"kind":"++"},{"kind":"ws"},{"kind":"--"},{"kind":"ws"},{"kind":"**"},{"kind":"eof"}]') {
694
+ throw result;
695
+ }
696
+ },
697
+ () => {
698
+ const result = tokenizeString('= += -= *= /= %= **=');
699
+ if (result !== '[{"kind":"="},{"kind":"ws"},{"kind":"+="},{"kind":"ws"},{"kind":"-="},{"kind":"ws"},{"kind":"*="},{"kind":"ws"},{"kind":"/="},{"kind":"ws"},{"kind":"%="},{"kind":"ws"},{"kind":"**="},{"kind":"eof"}]') {
700
+ throw result;
701
+ }
702
+ },
703
+ () => {
704
+ const result = tokenizeString('& | ^ ~ << >> >>>');
705
+ if (result !== '[{"kind":"&"},{"kind":"ws"},{"kind":"|"},{"kind":"ws"},{"kind":"^"},{"kind":"ws"},{"kind":"~"},{"kind":"ws"},{"kind":"<<"},{"kind":"ws"},{"kind":">>"},{"kind":"ws"},{"kind":">>>"},{"kind":"eof"}]') {
706
+ throw result;
707
+ }
708
+ },
709
+ () => {
710
+ const result = tokenizeString('&= |= ^= <<= >>= >>>=');
711
+ if (result !== '[{"kind":"&="},{"kind":"ws"},{"kind":"|="},{"kind":"ws"},{"kind":"^="},{"kind":"ws"},{"kind":"<<="},{"kind":"ws"},{"kind":">>="},{"kind":"ws"},{"kind":">>>="},{"kind":"eof"}]') {
712
+ throw result;
713
+ }
714
+ },
715
+ () => {
716
+ const result = tokenizeString('&& || ! ??');
717
+ if (result !== '[{"kind":"&&"},{"kind":"ws"},{"kind":"||"},{"kind":"ws"},{"kind":"!"},{"kind":"ws"},{"kind":"??"},{"kind":"eof"}]') {
718
+ throw result;
719
+ }
720
+ },
721
+ () => {
722
+ const result = tokenizeString('&&= ||= ??=');
723
+ if (result !== '[{"kind":"&&="},{"kind":"ws"},{"kind":"||="},{"kind":"ws"},{"kind":"??="},{"kind":"eof"}]') {
724
+ throw result;
725
+ }
726
+ },
727
+ () => {
728
+ const result = tokenizeString('? ?. . =>');
729
+ if (result !== '[{"kind":"?"},{"kind":"ws"},{"kind":"?."},{"kind":"ws"},{"kind":"."},{"kind":"ws"},{"kind":"=>"},{"kind":"eof"}]') {
730
+ throw result;
731
+ }
732
+ },
733
+ ],
734
+ ws: [
735
+ () => {
736
+ const result = tokenizeString(' ');
737
+ if (result !== '[{"kind":"ws"},{"kind":"eof"}]') {
738
+ throw result;
739
+ }
740
+ },
741
+ () => {
742
+ const result = tokenizeString('\t');
743
+ if (result !== '[{"kind":"ws"},{"kind":"eof"}]') {
744
+ throw result;
745
+ }
746
+ },
747
+ () => {
748
+ const result = tokenizeString(' \t');
749
+ if (result !== '[{"kind":"ws"},{"kind":"eof"}]') {
750
+ throw result;
751
+ }
752
+ },
753
+ () => {
754
+ const result = tokenizeString('\n');
755
+ if (result !== '[{"kind":"nl"},{"kind":"eof"}]') {
756
+ throw result;
757
+ }
758
+ },
759
+ () => {
760
+ const result = tokenizeString('\r');
761
+ if (result !== '[{"kind":"nl"},{"kind":"eof"}]') {
762
+ throw result;
763
+ }
764
+ },
765
+ () => {
766
+ const result = tokenizeString(' \t\n\r ');
767
+ if (result !== '[{"kind":"nl"},{"kind":"eof"}]') {
768
+ throw result;
769
+ }
770
+ },
737
771
  ],
738
772
  // id: [
739
773
  // () => {
@@ -9,7 +9,7 @@ const run = (root) => (path) => {
9
9
  };
10
10
  export const proof = {
11
11
  parse: () => {
12
- const result = run({ a: utf8('export default 1') })('a');
12
+ const result = run({ a: [utf8('export default 1')] })('a');
13
13
  if (result[0] === 'error') {
14
14
  throw result[1];
15
15
  }
@@ -19,7 +19,7 @@ export const proof = {
19
19
  }
20
20
  },
21
21
  parseWithSubModule: () => {
22
- const result = run({ a: { b: utf8('import c from "c"\nexport default c'), c: utf8('export default 2') } })('a/b');
22
+ const result = run({ a: { b: [utf8('import c from "c"\nexport default c')], c: [utf8('export default 2')] } })('a/b');
23
23
  if (result[0] === 'error') {
24
24
  throw result[1];
25
25
  }
@@ -30,10 +30,10 @@ export const proof = {
30
30
  },
31
31
  parseWithSubModules: () => {
32
32
  const result = run({
33
- a: utf8('import b from "b"\nimport c from "c"\nexport default [b,c,b]'),
34
- b: utf8('import d from "d"\nexport default [0,d]'),
35
- c: utf8('import d from "d"\nexport default [1,d]'),
36
- d: utf8('export default 2'),
33
+ a: [utf8('import b from "b"\nimport c from "c"\nexport default [b,c,b]')],
34
+ b: [utf8('import d from "d"\nexport default [0,d]')],
35
+ c: [utf8('import d from "d"\nexport default [1,d]')],
36
+ d: [utf8('export default 2')],
37
37
  })('a');
38
38
  if (result[0] === 'error') {
39
39
  throw result[1];
@@ -44,7 +44,7 @@ export const proof = {
44
44
  }
45
45
  },
46
46
  parseWithFileNotFoundError: () => {
47
- const result = run({ a: utf8('import b from "b"\nexport default b') })('a');
47
+ const result = run({ a: [utf8('import b from "b"\nexport default b')] })('a');
48
48
  if (result[0] !== 'error') {
49
49
  throw result;
50
50
  }
@@ -54,9 +54,9 @@ export const proof = {
54
54
  },
55
55
  parseWithCycleError: () => {
56
56
  const result = run({
57
- a: utf8('import b from "b"\nimport c from "c"\nexport default [b,c,b]'),
58
- b: utf8('import c from "c"\nexport default c'),
59
- c: utf8('import b from "b"\nexport default b'),
57
+ a: [utf8('import b from "b"\nimport c from "c"\nexport default [b,c,b]')],
58
+ b: [utf8('import c from "c"\nexport default c')],
59
+ c: [utf8('import b from "b"\nexport default b')],
60
60
  })('a');
61
61
  if (result[0] !== 'error') {
62
62
  throw result;
@@ -67,6 +67,12 @@ export declare const writeFile: Func<WriteFile>;
67
67
  export declare const writeUtf8File: (path: string, content: string) => Effect<WriteFile, IoResult<void>>;
68
68
  export type Rm = readonly ['rm', (path: string) => IoResult<void>];
69
69
  export declare const rm: Func<Rm>;
70
+ export type Rename = readonly ['rename', (src: string, dst: string) => IoResult<void>];
71
+ export declare const rename: Func<Rename>;
72
+ export type ReadBytes = readonly ['readBytes', (path: string, offset: number, size: number) => IoResult<Vec>];
73
+ export declare const readBytes: Func<ReadBytes>;
74
+ export type RandomInt = readonly ['randomInt', () => number];
75
+ export declare const randomInt: Func<RandomInt>;
70
76
  export type ExecResult = {
71
77
  readonly stdout: string;
72
78
  readonly stderr: string;
@@ -75,7 +81,7 @@ export type Exec = readonly ['exec', (command: string, stdin?: string) => IoResu
75
81
  export declare const exec: Func<Exec>;
76
82
  export type Access = readonly ['access', (path: string) => IoResult<void>];
77
83
  export declare const access: Func<Access>;
78
- export type Fs = Mkdir | ReadFile | Readdir | WriteFile | Rm | Exec | Access;
84
+ export type Fs = Mkdir | ReadFile | ReadBytes | Readdir | WriteFile | Rm | Rename | Exec | Access;
79
85
  export type Server = Nominal<'server', `160855c4f69310fece3273c1853ac32de43dee1eb41bf59d821917f8eebe9272`, unknown>;
80
86
  export type Headers = StringMap<string, string>;
81
87
  export type IncomingMessage = {
@@ -210,7 +216,7 @@ export type TestContext = {
210
216
  /** Effect operation that registers a named test with the active `TestContext`. */
211
217
  export type Test = readonly ['test', (ctx: TestContext, name: string, expectFailure: boolean, test: (t: TestContext) => Effect<Test | All | Await, void>) => void];
212
218
  export declare const test: Func<Test>;
213
- export type NodeOp = All | Await | Fetch | Fs | Http | Forever | Import | MemOp | Now | Read | Sandbox | Write | Test;
219
+ export type NodeOp = All | Await | Fetch | Fs | Http | Forever | Import | MemOp | Now | RandomInt | Read | Sandbox | Write | Test;
214
220
  export type NodeEffect<T> = Effect<NodeOp, T>;
215
221
  /**
216
222
  * Writes an error line to `stderr` and yields exit code `1`. The canonical
@@ -48,6 +48,9 @@ export const writeFile = do_('writeFile');
48
48
  /** Writes a string to `path` as UTF-8 bytes. */
49
49
  export const writeUtf8File = (path, content) => writeFile(path, utf8(content));
50
50
  export const rm = do_('rm');
51
+ export const rename = do_('rename');
52
+ export const readBytes = do_('readBytes');
53
+ export const randomInt = do_('randomInt');
51
54
  export const exec = do_('exec');
52
55
  export const access = do_('access');
53
56
  export const createServer = do_('createServer');