@barnum/barnum 0.0.0-main-50effdfd → 0.0.0-main-3c07d795
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/artifacts/linux-arm64/barnum +0 -0
- package/artifacts/linux-x64/barnum +0 -0
- package/artifacts/macos-arm64/barnum +0 -0
- package/artifacts/macos-x64/barnum +0 -0
- package/artifacts/win-x64/barnum.exe +0 -0
- package/dist/ast.d.ts +8 -6
- package/dist/ast.js +22 -8
- package/dist/bind.d.ts +2 -2
- package/dist/bind.js +10 -7
- package/dist/builtins.d.ts +3 -3
- package/dist/builtins.js +22 -20
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/pipe.js +1 -1
- package/dist/race.d.ts +1 -1
- package/dist/race.js +1 -1
- package/dist/recursive.js +6 -6
- package/dist/try-catch.d.ts +1 -1
- package/dist/try-catch.js +1 -1
- package/package.json +1 -1
- package/src/ast.ts +37 -12
- package/src/bind.ts +12 -9
- package/src/builtins.ts +22 -20
- package/src/index.ts +2 -2
- package/src/pipe.ts +1 -1
- package/src/race.ts +1 -1
- package/src/recursive.ts +6 -12
- package/src/try-catch.ts +1 -1
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/ast.d.ts
CHANGED
|
@@ -68,10 +68,10 @@ export type BuiltinKind = {
|
|
|
68
68
|
} | {
|
|
69
69
|
kind: "Flatten";
|
|
70
70
|
} | {
|
|
71
|
-
kind: "
|
|
71
|
+
kind: "GetField";
|
|
72
72
|
value: string;
|
|
73
73
|
} | {
|
|
74
|
-
kind: "
|
|
74
|
+
kind: "GetIndex";
|
|
75
75
|
value: number;
|
|
76
76
|
} | {
|
|
77
77
|
kind: "Pick";
|
|
@@ -134,8 +134,10 @@ export type TypedAction<In = unknown, Out = unknown, Refs extends string = never
|
|
|
134
134
|
drop(): TypedAction<In, never, Refs>;
|
|
135
135
|
/** Wrap output as a tagged union member. Requires full variant map TDef so __def is carried. */
|
|
136
136
|
tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>, Refs>;
|
|
137
|
-
/** Extract a field from the output object. `a.
|
|
138
|
-
|
|
137
|
+
/** Extract a field from the output object. `a.getField("name")` ≡ `pipe(a, getField("name"))`. */
|
|
138
|
+
getField<TField extends keyof Out & string>(field: TField): TypedAction<In, Out[TField], Refs>;
|
|
139
|
+
/** Extract an element from the output tuple by index. `a.getIndex(0)` ≡ `pipe(a, getIndex(0))`. */
|
|
140
|
+
getIndex<TIn, TTuple extends unknown[], TIndex extends number, TRefs extends string>(this: TypedAction<TIn, TTuple, TRefs>, index: TIndex): TypedAction<TIn, TTuple[TIndex], TRefs>;
|
|
139
141
|
/** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
|
|
140
142
|
wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>, Refs>;
|
|
141
143
|
/** Merge a tuple of objects into a single object. `a.merge()` ≡ `pipe(a, merge())`. */
|
|
@@ -339,7 +341,7 @@ export declare const IDENTITY: Action;
|
|
|
339
341
|
* If the body completes normally → output is TOut.
|
|
340
342
|
* If restart fires → body re-executes with the restarted value.
|
|
341
343
|
*
|
|
342
|
-
* Compiled form: `RestartHandle(id,
|
|
344
|
+
* Compiled form: `RestartHandle(id, GetIndex(0), body)`
|
|
343
345
|
*/
|
|
344
346
|
export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>): TypedAction<PipeIn<TIn>, TOut>;
|
|
345
347
|
/**
|
|
@@ -357,7 +359,7 @@ export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAc
|
|
|
357
359
|
export declare function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(bodyFn: (earlyReturn: TypedAction<TEarlyReturn, never>) => Pipeable<TIn, TOut>): TypedAction<TIn, TEarlyReturn | TOut>;
|
|
358
360
|
/**
|
|
359
361
|
* Build the restart+branch compiled form:
|
|
360
|
-
* `Chain(Tag("Continue"), RestartHandle(id,
|
|
362
|
+
* `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
|
|
361
363
|
*
|
|
362
364
|
* Input is tagged Continue so the Branch enters the continueArm on first execution.
|
|
363
365
|
* Continue tag → restart → re-enters continueArm. Break tag → restart → runs breakArm, exits `RestartHandle`.
|
package/dist/ast.js
CHANGED
|
@@ -49,7 +49,7 @@ function tagMethod(kind) {
|
|
|
49
49
|
},
|
|
50
50
|
});
|
|
51
51
|
}
|
|
52
|
-
function
|
|
52
|
+
function getFieldMethod(field) {
|
|
53
53
|
return typedAction({
|
|
54
54
|
kind: "Chain",
|
|
55
55
|
first: this,
|
|
@@ -57,7 +57,20 @@ function getMethod(field) {
|
|
|
57
57
|
kind: "Invoke",
|
|
58
58
|
handler: {
|
|
59
59
|
kind: "Builtin",
|
|
60
|
-
builtin: { kind: "
|
|
60
|
+
builtin: { kind: "GetField", value: field },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function getIndexMethod(index) {
|
|
66
|
+
return typedAction({
|
|
67
|
+
kind: "Chain",
|
|
68
|
+
first: this,
|
|
69
|
+
rest: {
|
|
70
|
+
kind: "Invoke",
|
|
71
|
+
handler: {
|
|
72
|
+
kind: "Builtin",
|
|
73
|
+
builtin: { kind: "GetIndex", value: index },
|
|
61
74
|
},
|
|
62
75
|
},
|
|
63
76
|
});
|
|
@@ -202,7 +215,8 @@ export function typedAction(action) {
|
|
|
202
215
|
flatten: { value: flattenMethod, configurable: true },
|
|
203
216
|
drop: { value: dropMethod, configurable: true },
|
|
204
217
|
tag: { value: tagMethod, configurable: true },
|
|
205
|
-
|
|
218
|
+
getField: { value: getFieldMethod, configurable: true },
|
|
219
|
+
getIndex: { value: getIndexMethod, configurable: true },
|
|
206
220
|
wrapInField: { value: wrapInFieldMethod, configurable: true },
|
|
207
221
|
merge: { value: mergeMethod, configurable: true },
|
|
208
222
|
pick: { value: pickMethod, configurable: true },
|
|
@@ -231,7 +245,7 @@ export function forEach(action) {
|
|
|
231
245
|
return typedAction({ kind: "ForEach", action: action });
|
|
232
246
|
}
|
|
233
247
|
/**
|
|
234
|
-
* Insert
|
|
248
|
+
* Insert GetField("value") before each case handler in a branch.
|
|
235
249
|
* This implements auto-unwrapping: the engine dispatches on `kind`, then
|
|
236
250
|
* extracts `value` before passing to the handler. Case handlers receive
|
|
237
251
|
* the payload directly, not the full `{ kind, value }` variant.
|
|
@@ -245,7 +259,7 @@ function unwrapBranchCases(cases) {
|
|
|
245
259
|
kind: "Invoke",
|
|
246
260
|
handler: {
|
|
247
261
|
kind: "Builtin",
|
|
248
|
-
builtin: { kind: "
|
|
262
|
+
builtin: { kind: "GetField", value: "value" },
|
|
249
263
|
},
|
|
250
264
|
},
|
|
251
265
|
rest: cases[key],
|
|
@@ -262,7 +276,7 @@ export function branch(cases) {
|
|
|
262
276
|
// ---------------------------------------------------------------------------
|
|
263
277
|
const EXTRACT_PAYLOAD = {
|
|
264
278
|
kind: "Invoke",
|
|
265
|
-
handler: { kind: "Builtin", builtin: { kind: "
|
|
279
|
+
handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
|
|
266
280
|
};
|
|
267
281
|
const TAG_CONTINUE = {
|
|
268
282
|
kind: "Invoke",
|
|
@@ -286,7 +300,7 @@ export const IDENTITY = {
|
|
|
286
300
|
* If the body completes normally → output is TOut.
|
|
287
301
|
* If restart fires → body re-executes with the restarted value.
|
|
288
302
|
*
|
|
289
|
-
* Compiled form: `RestartHandle(id,
|
|
303
|
+
* Compiled form: `RestartHandle(id, GetIndex(0), body)`
|
|
290
304
|
*/
|
|
291
305
|
export function recur(bodyFn) {
|
|
292
306
|
const restartHandlerId = allocateRestartHandlerId();
|
|
@@ -332,7 +346,7 @@ export function earlyReturn(bodyFn) {
|
|
|
332
346
|
// ---------------------------------------------------------------------------
|
|
333
347
|
/**
|
|
334
348
|
* Build the restart+branch compiled form:
|
|
335
|
-
* `Chain(Tag("Continue"), RestartHandle(id,
|
|
349
|
+
* `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
|
|
336
350
|
*
|
|
337
351
|
* Input is tagged Continue so the Branch enters the continueArm on first execution.
|
|
338
352
|
* Continue tag → restart → re-enters continueArm. Break tag → restart → runs breakArm, exits `RestartHandle`.
|
package/dist/bind.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type Action, type ExtractInput, type ExtractOutput, type TypedAction }
|
|
|
3
3
|
* A typed reference to a bound value. Output is `TValue`.
|
|
4
4
|
*
|
|
5
5
|
* Use `.then()` (not `pipe()`) when chaining a VarRef into a generic
|
|
6
|
-
* action like `pick` or `
|
|
6
|
+
* action like `pick` or `getField` — pipe overloads can't infer
|
|
7
7
|
* the generic's type parameter from the VarRef's output.
|
|
8
8
|
*/
|
|
9
9
|
export type VarRef<TValue> = TypedAction<never, TValue>;
|
|
@@ -33,7 +33,7 @@ export type InferVarRefs<TBindings extends Action[]> = {
|
|
|
33
33
|
* All(...bindings, Identity),
|
|
34
34
|
* ResumeHandle(r0, readVar(0),
|
|
35
35
|
* ResumeHandle(r1, readVar(1),
|
|
36
|
-
* Chain(
|
|
36
|
+
* Chain(GetIndex(N), body)
|
|
37
37
|
* )
|
|
38
38
|
* )
|
|
39
39
|
* )
|
package/dist/bind.js
CHANGED
|
@@ -18,7 +18,7 @@ function createVarRef(resumeHandlerId) {
|
|
|
18
18
|
* `state` (index 1) is the full All output tuple. The handler produces
|
|
19
19
|
* `[state[n], state]` — value is state[n], new_state is state (unchanged).
|
|
20
20
|
*
|
|
21
|
-
* Expanded AST: All(Chain(
|
|
21
|
+
* Expanded AST: All(Chain(GetIndex(1), GetIndex(n)), GetIndex(1))
|
|
22
22
|
*/
|
|
23
23
|
function readVar(n) {
|
|
24
24
|
return {
|
|
@@ -30,14 +30,14 @@ function readVar(n) {
|
|
|
30
30
|
kind: "Invoke",
|
|
31
31
|
handler: {
|
|
32
32
|
kind: "Builtin",
|
|
33
|
-
builtin: { kind: "
|
|
33
|
+
builtin: { kind: "GetIndex", value: 1 },
|
|
34
34
|
},
|
|
35
35
|
},
|
|
36
36
|
rest: {
|
|
37
37
|
kind: "Invoke",
|
|
38
38
|
handler: {
|
|
39
39
|
kind: "Builtin",
|
|
40
|
-
builtin: { kind: "
|
|
40
|
+
builtin: { kind: "GetIndex", value: n },
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
},
|
|
@@ -45,7 +45,7 @@ function readVar(n) {
|
|
|
45
45
|
kind: "Invoke",
|
|
46
46
|
handler: {
|
|
47
47
|
kind: "Builtin",
|
|
48
|
-
builtin: { kind: "
|
|
48
|
+
builtin: { kind: "GetIndex", value: 1 },
|
|
49
49
|
},
|
|
50
50
|
},
|
|
51
51
|
],
|
|
@@ -67,7 +67,7 @@ export function bind(bindings, body) {
|
|
|
67
67
|
kind: "Invoke",
|
|
68
68
|
handler: {
|
|
69
69
|
kind: "Builtin",
|
|
70
|
-
builtin: { kind: "
|
|
70
|
+
builtin: { kind: "GetIndex", value: pipelineInputIndex },
|
|
71
71
|
},
|
|
72
72
|
},
|
|
73
73
|
rest: bodyAction,
|
|
@@ -81,7 +81,10 @@ export function bind(bindings, body) {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
// 5. All(...bindings, identity()) → nested Handles
|
|
84
|
-
const allActions = [
|
|
84
|
+
const allActions = [
|
|
85
|
+
...bindings.map((b) => b),
|
|
86
|
+
identity(),
|
|
87
|
+
];
|
|
85
88
|
return typedAction({
|
|
86
89
|
kind: "Chain",
|
|
87
90
|
first: { kind: "All", actions: allActions },
|
|
@@ -102,5 +105,5 @@ export function bind(bindings, body) {
|
|
|
102
105
|
* bindInput<FileEntry>((entry) => ...)
|
|
103
106
|
*/
|
|
104
107
|
export function bindInput(body) {
|
|
105
|
-
return bind([identity], ([input]) => pipe(drop, body(input)));
|
|
108
|
+
return bind([identity()], ([input]) => pipe(drop, body(input)));
|
|
106
109
|
}
|
package/dist/builtins.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { type Action, type MergeTuple, type Option as OptionT, type Pipeable, ty
|
|
|
6
6
|
* kinds. The Rust scheduler executes them inline (no subprocess).
|
|
7
7
|
*/
|
|
8
8
|
export declare function constant<TValue>(value: TValue): TypedAction<any, TValue>;
|
|
9
|
-
export declare
|
|
9
|
+
export declare function identity<TValue = any>(): TypedAction<TValue, TValue>;
|
|
10
10
|
export declare const drop: TypedAction<any, never>;
|
|
11
11
|
/**
|
|
12
12
|
* Wrap input as a tagged union member. Requires the full variant map TDef
|
|
@@ -18,8 +18,8 @@ export declare const drop: TypedAction<any, never>;
|
|
|
18
18
|
export declare function tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<TDef[TKind], TaggedUnion<TDef>>;
|
|
19
19
|
export declare function merge<TTuple extends Record<string, unknown>[]>(): TypedAction<TTuple, MergeTuple<TTuple>>;
|
|
20
20
|
export declare function flatten<TElement>(): TypedAction<TElement[][], TElement[]>;
|
|
21
|
-
export declare function
|
|
22
|
-
export declare function
|
|
21
|
+
export declare function getField<TObj extends Record<string, unknown>, TField extends keyof TObj & string>(field: TField): TypedAction<TObj, TObj[TField]>;
|
|
22
|
+
export declare function getIndex<TTuple extends unknown[], TIndex extends number>(index: TIndex): TypedAction<TTuple, TTuple[TIndex]>;
|
|
23
23
|
export declare function pick<TObj extends Record<string, unknown>, TKeys extends (keyof TObj & string)[]>(...keys: TKeys): TypedAction<TObj, Pick<TObj, TKeys[number]>>;
|
|
24
24
|
export declare function dropResult<TInput, TOutput>(action: Pipeable<TInput, TOutput>): TypedAction<TInput, never>;
|
|
25
25
|
/**
|
package/dist/builtins.js
CHANGED
|
@@ -18,10 +18,12 @@ export function constant(value) {
|
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
// Identity — pass input through unchanged
|
|
20
20
|
// ---------------------------------------------------------------------------
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
21
|
+
export function identity() {
|
|
22
|
+
return typedAction({
|
|
23
|
+
kind: "Invoke",
|
|
24
|
+
handler: { kind: "Builtin", builtin: { kind: "Identity" } },
|
|
25
|
+
});
|
|
26
|
+
}
|
|
25
27
|
// ---------------------------------------------------------------------------
|
|
26
28
|
// Drop — discard pipeline value
|
|
27
29
|
// ---------------------------------------------------------------------------
|
|
@@ -64,26 +66,26 @@ export function flatten() {
|
|
|
64
66
|
});
|
|
65
67
|
}
|
|
66
68
|
// ---------------------------------------------------------------------------
|
|
67
|
-
//
|
|
69
|
+
// GetField — extract a single field from an object
|
|
68
70
|
// ---------------------------------------------------------------------------
|
|
69
|
-
export function
|
|
71
|
+
export function getField(field) {
|
|
70
72
|
return typedAction({
|
|
71
73
|
kind: "Invoke",
|
|
72
74
|
handler: {
|
|
73
75
|
kind: "Builtin",
|
|
74
|
-
builtin: { kind: "
|
|
76
|
+
builtin: { kind: "GetField", value: field },
|
|
75
77
|
},
|
|
76
78
|
});
|
|
77
79
|
}
|
|
78
80
|
// ---------------------------------------------------------------------------
|
|
79
|
-
//
|
|
81
|
+
// GetIndex — extract a single element from an array by index
|
|
80
82
|
// ---------------------------------------------------------------------------
|
|
81
|
-
export function
|
|
83
|
+
export function getIndex(index) {
|
|
82
84
|
return typedAction({
|
|
83
85
|
kind: "Invoke",
|
|
84
86
|
handler: {
|
|
85
87
|
kind: "Builtin",
|
|
86
|
-
builtin: { kind: "
|
|
88
|
+
builtin: { kind: "GetIndex", value: index },
|
|
87
89
|
},
|
|
88
90
|
});
|
|
89
91
|
}
|
|
@@ -138,24 +140,24 @@ export function withResource({ create, action, dispose, }) {
|
|
|
138
140
|
// Step 1: all(create, identity) → [TResource, TIn] → merge → TResource & TIn
|
|
139
141
|
const acquireAndMerge = chain(typedAction({
|
|
140
142
|
kind: "All",
|
|
141
|
-
actions: [create, identity],
|
|
143
|
+
actions: [create, identity()],
|
|
142
144
|
}), typedAction(mergeBuiltin));
|
|
143
145
|
// Step 2: all(action, identity) → [TOut, TResource & TIn]
|
|
144
146
|
// Keep merged object so dispose can access resource fields.
|
|
145
147
|
const actionAndKeepMerged = typedAction({
|
|
146
148
|
kind: "All",
|
|
147
|
-
actions: [action, identity],
|
|
149
|
+
actions: [action, identity()],
|
|
148
150
|
});
|
|
149
|
-
// Step 3: all(
|
|
151
|
+
// Step 3: all(getIndex(0), chain(getIndex(1), dispose)) → [TOut, unknown]
|
|
150
152
|
const disposeAndKeepResult = typedAction({
|
|
151
153
|
kind: "All",
|
|
152
154
|
actions: [
|
|
153
|
-
|
|
154
|
-
chain(
|
|
155
|
+
getIndex(0),
|
|
156
|
+
chain(getIndex(1), dispose),
|
|
155
157
|
],
|
|
156
158
|
});
|
|
157
|
-
// Step 4:
|
|
158
|
-
return chain(chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult),
|
|
159
|
+
// Step 4: getIndex(0) → TOut
|
|
160
|
+
return chain(chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult), getIndex(0));
|
|
159
161
|
}
|
|
160
162
|
// ---------------------------------------------------------------------------
|
|
161
163
|
// Tap — run an action for side effects, preserve original input
|
|
@@ -281,7 +283,7 @@ const EXTRACT_VALUE = {
|
|
|
281
283
|
kind: "Invoke",
|
|
282
284
|
handler: {
|
|
283
285
|
kind: "Builtin",
|
|
284
|
-
builtin: { kind: "
|
|
286
|
+
builtin: { kind: "GetField", value: "value" },
|
|
285
287
|
},
|
|
286
288
|
};
|
|
287
289
|
const DROP = {
|
|
@@ -292,7 +294,7 @@ const IDENTITY = {
|
|
|
292
294
|
kind: "Invoke",
|
|
293
295
|
handler: { kind: "Builtin", builtin: { kind: "Identity" } },
|
|
294
296
|
};
|
|
295
|
-
/** Wrap branch cases with
|
|
297
|
+
/** Wrap branch cases with GetField("value") auto-unwrapping. */
|
|
296
298
|
function optionBranch(someCaseBody, noneCaseBody) {
|
|
297
299
|
return {
|
|
298
300
|
kind: "Branch",
|
|
@@ -455,7 +457,7 @@ const TAG_ERR = {
|
|
|
455
457
|
kind: "Invoke",
|
|
456
458
|
handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Err" } },
|
|
457
459
|
};
|
|
458
|
-
/** Wrap branch cases with
|
|
460
|
+
/** Wrap branch cases with GetField("value") auto-unwrapping. */
|
|
459
461
|
function resultBranch(okCaseBody, errCaseBody) {
|
|
460
462
|
return {
|
|
461
463
|
kind: "Branch",
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TaggedUnion, OptionDef, ResultDef } from "./ast.js";
|
|
2
2
|
export * from "./ast.js";
|
|
3
|
-
export { constant, identity, drop, tag, merge, flatten,
|
|
3
|
+
export { constant, identity, drop, tag, merge, flatten, getField, getIndex, pick, dropResult, withResource, tap, range, splitFirst, splitLast, wrapInField, Option, Result, } from "./builtins.js";
|
|
4
4
|
export * from "./handler.js";
|
|
5
5
|
export { runPipeline, type RunPipelineOptions, type LogLevel } from "./run.js";
|
|
6
6
|
export { zodToCheckedJsonSchema } from "./schema.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export * from "./ast.js";
|
|
2
|
-
export { constant, identity, drop, tag, merge, flatten,
|
|
2
|
+
export { constant, identity, drop, tag, merge, flatten, getField, getIndex, pick, dropResult, withResource, tap, range, splitFirst, splitLast, wrapInField, Option, Result, } from "./builtins.js";
|
|
3
3
|
export * from "./handler.js";
|
|
4
4
|
export { runPipeline } from "./run.js";
|
|
5
5
|
export { zodToCheckedJsonSchema } from "./schema.js";
|
package/dist/pipe.js
CHANGED
package/dist/race.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { type Pipeable, type Result, type TypedAction } from "./ast.js";
|
|
|
8
8
|
*
|
|
9
9
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
10
10
|
* `Chain(Tag("Continue"),`
|
|
11
|
-
* `RestartHandle(id,
|
|
11
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
12
12
|
* `Branch({`
|
|
13
13
|
* `Continue: All(Chain(a, breakPerform), Chain(b, breakPerform), ...),`
|
|
14
14
|
* `Break: identity,`
|
package/dist/race.js
CHANGED
|
@@ -35,7 +35,7 @@ function breakPerform(restartHandlerId) {
|
|
|
35
35
|
*
|
|
36
36
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
37
37
|
* `Chain(Tag("Continue"),`
|
|
38
|
-
* `RestartHandle(id,
|
|
38
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
39
39
|
* `Branch({`
|
|
40
40
|
* `Continue: All(Chain(a, breakPerform), Chain(b, breakPerform), ...),`
|
|
41
41
|
* `Break: identity,`
|
package/dist/recursive.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { typedAction, branch, } from "./ast.js";
|
|
2
2
|
import { all } from "./all.js";
|
|
3
3
|
import { chain } from "./chain.js";
|
|
4
|
-
import { constant, identity,
|
|
4
|
+
import { constant, identity, getField, getIndex, tag } from "./builtins.js";
|
|
5
5
|
import { allocateResumeHandlerId } from "./effect-id.js";
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
7
|
const UNUSED_STATE = undefined;
|
|
@@ -35,19 +35,19 @@ export function defineRecursiveFunctions(bodiesFn) {
|
|
|
35
35
|
const callTokens = Array.from({ length: fnCount }, (_, i) => typedAction(chain(tag(`Call${i}`), resumePerform)));
|
|
36
36
|
// Get function body ASTs
|
|
37
37
|
const bodyActions = bodiesFn(...callTokens);
|
|
38
|
-
// Branch cases: CallN →
|
|
38
|
+
// Branch cases: CallN → GetField("value") → bodyN
|
|
39
39
|
const cases = {};
|
|
40
40
|
for (let i = 0; i < bodyActions.length; i++) {
|
|
41
|
-
cases[`Call${i}`] = chain(
|
|
41
|
+
cases[`Call${i}`] = chain(getField("value"), bodyActions[i]);
|
|
42
42
|
}
|
|
43
43
|
// Return curried entry-point combinator
|
|
44
44
|
return (entryFn) => {
|
|
45
45
|
const userBody = entryFn(...callTokens);
|
|
46
|
-
return typedAction(chain(all(identity, constant(UNUSED_STATE)), {
|
|
46
|
+
return typedAction(chain(all(identity(), constant(UNUSED_STATE)), {
|
|
47
47
|
kind: "ResumeHandle",
|
|
48
48
|
resume_handler_id: resumeHandlerId,
|
|
49
|
-
body: chain(
|
|
50
|
-
handler: all(chain(
|
|
49
|
+
body: chain(getIndex(0), userBody),
|
|
50
|
+
handler: all(chain(getIndex(0), branch(cases)), constant(UNUSED_STATE)),
|
|
51
51
|
}));
|
|
52
52
|
};
|
|
53
53
|
}
|
package/dist/try-catch.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { type Pipeable, type TypedAction } from "./ast.js";
|
|
|
12
12
|
*
|
|
13
13
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
14
14
|
* `Chain(Tag("Continue"),`
|
|
15
|
-
* `RestartHandle(id,
|
|
15
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
16
16
|
* `Branch({ Continue: body, Break: recovery })))`
|
|
17
17
|
*
|
|
18
18
|
* throwError = `Chain(Tag("Break"), RestartPerform(id))`
|
package/dist/try-catch.js
CHANGED
|
@@ -16,7 +16,7 @@ import { allocateRestartHandlerId } from "./effect-id.js";
|
|
|
16
16
|
*
|
|
17
17
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
18
18
|
* `Chain(Tag("Continue"),`
|
|
19
|
-
* `RestartHandle(id,
|
|
19
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
20
20
|
* `Branch({ Continue: body, Break: recovery })))`
|
|
21
21
|
*
|
|
22
22
|
* throwError = `Chain(Tag("Break"), RestartPerform(id))`
|
package/package.json
CHANGED
package/src/ast.ts
CHANGED
|
@@ -91,8 +91,8 @@ export type BuiltinKind =
|
|
|
91
91
|
| { kind: "Tag"; value: string }
|
|
92
92
|
| { kind: "Merge" }
|
|
93
93
|
| { kind: "Flatten" }
|
|
94
|
-
| { kind: "
|
|
95
|
-
| { kind: "
|
|
94
|
+
| { kind: "GetField"; value: string }
|
|
95
|
+
| { kind: "GetIndex"; value: number }
|
|
96
96
|
| { kind: "Pick"; value: string[] }
|
|
97
97
|
| { kind: "CollectSome" }
|
|
98
98
|
| { kind: "SplitFirst" }
|
|
@@ -183,10 +183,20 @@ export type TypedAction<
|
|
|
183
183
|
tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(
|
|
184
184
|
kind: TKind,
|
|
185
185
|
): TypedAction<In, TaggedUnion<TDef>, Refs>;
|
|
186
|
-
/** Extract a field from the output object. `a.
|
|
187
|
-
|
|
186
|
+
/** Extract a field from the output object. `a.getField("name")` ≡ `pipe(a, getField("name"))`. */
|
|
187
|
+
getField<TField extends keyof Out & string>(
|
|
188
188
|
field: TField,
|
|
189
189
|
): TypedAction<In, Out[TField], Refs>;
|
|
190
|
+
/** Extract an element from the output tuple by index. `a.getIndex(0)` ≡ `pipe(a, getIndex(0))`. */
|
|
191
|
+
getIndex<
|
|
192
|
+
TIn,
|
|
193
|
+
TTuple extends unknown[],
|
|
194
|
+
TIndex extends number,
|
|
195
|
+
TRefs extends string,
|
|
196
|
+
>(
|
|
197
|
+
this: TypedAction<TIn, TTuple, TRefs>,
|
|
198
|
+
index: TIndex,
|
|
199
|
+
): TypedAction<TIn, TTuple[TIndex], TRefs>;
|
|
190
200
|
/** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
|
|
191
201
|
wrapInField<TField extends string>(
|
|
192
202
|
field: TField,
|
|
@@ -428,7 +438,21 @@ function tagMethod(this: TypedAction, kind: string): TypedAction {
|
|
|
428
438
|
});
|
|
429
439
|
}
|
|
430
440
|
|
|
431
|
-
function
|
|
441
|
+
function getFieldMethod(this: TypedAction, field: string): TypedAction {
|
|
442
|
+
return typedAction({
|
|
443
|
+
kind: "Chain",
|
|
444
|
+
first: this,
|
|
445
|
+
rest: {
|
|
446
|
+
kind: "Invoke",
|
|
447
|
+
handler: {
|
|
448
|
+
kind: "Builtin",
|
|
449
|
+
builtin: { kind: "GetField", value: field },
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function getIndexMethod(this: TypedAction, index: number): TypedAction {
|
|
432
456
|
return typedAction({
|
|
433
457
|
kind: "Chain",
|
|
434
458
|
first: this,
|
|
@@ -436,7 +460,7 @@ function getMethod(this: TypedAction, field: string): TypedAction {
|
|
|
436
460
|
kind: "Invoke",
|
|
437
461
|
handler: {
|
|
438
462
|
kind: "Builtin",
|
|
439
|
-
builtin: { kind: "
|
|
463
|
+
builtin: { kind: "GetIndex", value: index },
|
|
440
464
|
},
|
|
441
465
|
},
|
|
442
466
|
});
|
|
@@ -594,7 +618,8 @@ export function typedAction<
|
|
|
594
618
|
flatten: { value: flattenMethod, configurable: true },
|
|
595
619
|
drop: { value: dropMethod, configurable: true },
|
|
596
620
|
tag: { value: tagMethod, configurable: true },
|
|
597
|
-
|
|
621
|
+
getField: { value: getFieldMethod, configurable: true },
|
|
622
|
+
getIndex: { value: getIndexMethod, configurable: true },
|
|
598
623
|
wrapInField: { value: wrapInFieldMethod, configurable: true },
|
|
599
624
|
merge: { value: mergeMethod, configurable: true },
|
|
600
625
|
pick: { value: pickMethod, configurable: true },
|
|
@@ -659,7 +684,7 @@ export function forEach<In, Out>(
|
|
|
659
684
|
}
|
|
660
685
|
|
|
661
686
|
/**
|
|
662
|
-
* Insert
|
|
687
|
+
* Insert GetField("value") before each case handler in a branch.
|
|
663
688
|
* This implements auto-unwrapping: the engine dispatches on `kind`, then
|
|
664
689
|
* extracts `value` before passing to the handler. Case handlers receive
|
|
665
690
|
* the payload directly, not the full `{ kind, value }` variant.
|
|
@@ -675,7 +700,7 @@ function unwrapBranchCases(
|
|
|
675
700
|
kind: "Invoke",
|
|
676
701
|
handler: {
|
|
677
702
|
kind: "Builtin",
|
|
678
|
-
builtin: { kind: "
|
|
703
|
+
builtin: { kind: "GetField", value: "value" },
|
|
679
704
|
},
|
|
680
705
|
},
|
|
681
706
|
rest: cases[key],
|
|
@@ -725,7 +750,7 @@ export type LoopResult<TContinue, TBreak> = TaggedUnion<
|
|
|
725
750
|
|
|
726
751
|
const EXTRACT_PAYLOAD: Action = {
|
|
727
752
|
kind: "Invoke",
|
|
728
|
-
handler: { kind: "Builtin", builtin: { kind: "
|
|
753
|
+
handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
|
|
729
754
|
};
|
|
730
755
|
|
|
731
756
|
const TAG_CONTINUE: Action = {
|
|
@@ -754,7 +779,7 @@ export const IDENTITY: Action = {
|
|
|
754
779
|
* If the body completes normally → output is TOut.
|
|
755
780
|
* If restart fires → body re-executes with the restarted value.
|
|
756
781
|
*
|
|
757
|
-
* Compiled form: `RestartHandle(id,
|
|
782
|
+
* Compiled form: `RestartHandle(id, GetIndex(0), body)`
|
|
758
783
|
*/
|
|
759
784
|
export function recur<TIn = never, TOut = any>(
|
|
760
785
|
bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>,
|
|
@@ -818,7 +843,7 @@ export function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(
|
|
|
818
843
|
|
|
819
844
|
/**
|
|
820
845
|
* Build the restart+branch compiled form:
|
|
821
|
-
* `Chain(Tag("Continue"), RestartHandle(id,
|
|
846
|
+
* `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
|
|
822
847
|
*
|
|
823
848
|
* Input is tagged Continue so the Branch enters the continueArm on first execution.
|
|
824
849
|
* Continue tag → restart → re-enters continueArm. Break tag → restart → runs breakArm, exits `RestartHandle`.
|
package/src/bind.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { pipe } from "./pipe.js";
|
|
|
17
17
|
* A typed reference to a bound value. Output is `TValue`.
|
|
18
18
|
*
|
|
19
19
|
* Use `.then()` (not `pipe()`) when chaining a VarRef into a generic
|
|
20
|
-
* action like `pick` or `
|
|
20
|
+
* action like `pick` or `getField` — pipe overloads can't infer
|
|
21
21
|
* the generic's type parameter from the VarRef's output.
|
|
22
22
|
*/
|
|
23
23
|
export type VarRef<TValue> = TypedAction<never, TValue>;
|
|
@@ -61,7 +61,7 @@ export type InferVarRefs<TBindings extends Action[]> = {
|
|
|
61
61
|
* `state` (index 1) is the full All output tuple. The handler produces
|
|
62
62
|
* `[state[n], state]` — value is state[n], new_state is state (unchanged).
|
|
63
63
|
*
|
|
64
|
-
* Expanded AST: All(Chain(
|
|
64
|
+
* Expanded AST: All(Chain(GetIndex(1), GetIndex(n)), GetIndex(1))
|
|
65
65
|
*/
|
|
66
66
|
function readVar(n: number): Action {
|
|
67
67
|
return {
|
|
@@ -73,14 +73,14 @@ function readVar(n: number): Action {
|
|
|
73
73
|
kind: "Invoke",
|
|
74
74
|
handler: {
|
|
75
75
|
kind: "Builtin",
|
|
76
|
-
builtin: { kind: "
|
|
76
|
+
builtin: { kind: "GetIndex", value: 1 },
|
|
77
77
|
},
|
|
78
78
|
},
|
|
79
79
|
rest: {
|
|
80
80
|
kind: "Invoke",
|
|
81
81
|
handler: {
|
|
82
82
|
kind: "Builtin",
|
|
83
|
-
builtin: { kind: "
|
|
83
|
+
builtin: { kind: "GetIndex", value: n },
|
|
84
84
|
},
|
|
85
85
|
},
|
|
86
86
|
},
|
|
@@ -88,7 +88,7 @@ function readVar(n: number): Action {
|
|
|
88
88
|
kind: "Invoke",
|
|
89
89
|
handler: {
|
|
90
90
|
kind: "Builtin",
|
|
91
|
-
builtin: { kind: "
|
|
91
|
+
builtin: { kind: "GetIndex", value: 1 },
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
94
|
],
|
|
@@ -111,7 +111,7 @@ function readVar(n: number): Action {
|
|
|
111
111
|
* All(...bindings, Identity),
|
|
112
112
|
* ResumeHandle(r0, readVar(0),
|
|
113
113
|
* ResumeHandle(r1, readVar(1),
|
|
114
|
-
* Chain(
|
|
114
|
+
* Chain(GetIndex(N), body)
|
|
115
115
|
* )
|
|
116
116
|
* )
|
|
117
117
|
* )
|
|
@@ -148,7 +148,7 @@ export function bind<TBindings extends Action[], TOut>(
|
|
|
148
148
|
kind: "Invoke",
|
|
149
149
|
handler: {
|
|
150
150
|
kind: "Builtin",
|
|
151
|
-
builtin: { kind: "
|
|
151
|
+
builtin: { kind: "GetIndex", value: pipelineInputIndex },
|
|
152
152
|
},
|
|
153
153
|
},
|
|
154
154
|
rest: bodyAction,
|
|
@@ -163,7 +163,10 @@ export function bind<TBindings extends Action[], TOut>(
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
// 5. All(...bindings, identity()) → nested Handles
|
|
166
|
-
const allActions = [
|
|
166
|
+
const allActions = [
|
|
167
|
+
...bindings.map((b) => b as Action),
|
|
168
|
+
identity() as Action,
|
|
169
|
+
];
|
|
167
170
|
return typedAction({
|
|
168
171
|
kind: "Chain",
|
|
169
172
|
first: { kind: "All", actions: allActions },
|
|
@@ -188,5 +191,5 @@ export function bind<TBindings extends Action[], TOut>(
|
|
|
188
191
|
export function bindInput<TIn, TOut = any>(
|
|
189
192
|
body: (input: VarRef<TIn>) => BodyResult<TOut>,
|
|
190
193
|
): TypedAction<TIn, TOut> {
|
|
191
|
-
return bind([identity], ([input]) => pipe(drop, body(input)));
|
|
194
|
+
return bind([identity()], ([input]) => pipe(drop, body(input)));
|
|
192
195
|
}
|
package/src/builtins.ts
CHANGED
|
@@ -32,10 +32,12 @@ export function constant<TValue>(value: TValue): TypedAction<any, TValue> {
|
|
|
32
32
|
// Identity — pass input through unchanged
|
|
33
33
|
// ---------------------------------------------------------------------------
|
|
34
34
|
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
35
|
+
export function identity<TValue = any>(): TypedAction<TValue, TValue> {
|
|
36
|
+
return typedAction({
|
|
37
|
+
kind: "Invoke",
|
|
38
|
+
handler: { kind: "Builtin", builtin: { kind: "Identity" } },
|
|
39
|
+
});
|
|
40
|
+
}
|
|
39
41
|
|
|
40
42
|
// ---------------------------------------------------------------------------
|
|
41
43
|
// Drop — discard pipeline value
|
|
@@ -93,10 +95,10 @@ export function flatten<TElement>(): TypedAction<TElement[][], TElement[]> {
|
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
// ---------------------------------------------------------------------------
|
|
96
|
-
//
|
|
98
|
+
// GetField — extract a single field from an object
|
|
97
99
|
// ---------------------------------------------------------------------------
|
|
98
100
|
|
|
99
|
-
export function
|
|
101
|
+
export function getField<
|
|
100
102
|
TObj extends Record<string, unknown>,
|
|
101
103
|
TField extends keyof TObj & string,
|
|
102
104
|
>(field: TField): TypedAction<TObj, TObj[TField]> {
|
|
@@ -104,23 +106,23 @@ export function extractField<
|
|
|
104
106
|
kind: "Invoke",
|
|
105
107
|
handler: {
|
|
106
108
|
kind: "Builtin",
|
|
107
|
-
builtin: { kind: "
|
|
109
|
+
builtin: { kind: "GetField", value: field },
|
|
108
110
|
},
|
|
109
111
|
});
|
|
110
112
|
}
|
|
111
113
|
|
|
112
114
|
// ---------------------------------------------------------------------------
|
|
113
|
-
//
|
|
115
|
+
// GetIndex — extract a single element from an array by index
|
|
114
116
|
// ---------------------------------------------------------------------------
|
|
115
117
|
|
|
116
|
-
export function
|
|
118
|
+
export function getIndex<TTuple extends unknown[], TIndex extends number>(
|
|
117
119
|
index: TIndex,
|
|
118
120
|
): TypedAction<TTuple, TTuple[TIndex]> {
|
|
119
121
|
return typedAction({
|
|
120
122
|
kind: "Invoke",
|
|
121
123
|
handler: {
|
|
122
124
|
kind: "Builtin",
|
|
123
|
-
builtin: { kind: "
|
|
125
|
+
builtin: { kind: "GetIndex", value: index },
|
|
124
126
|
},
|
|
125
127
|
});
|
|
126
128
|
}
|
|
@@ -201,7 +203,7 @@ export function withResource<
|
|
|
201
203
|
const acquireAndMerge = chain(
|
|
202
204
|
typedAction<TIn, [TResource, TIn]>({
|
|
203
205
|
kind: "All",
|
|
204
|
-
actions: [create as Action, identity as Action],
|
|
206
|
+
actions: [create as Action, identity() as Action],
|
|
205
207
|
}),
|
|
206
208
|
typedAction<[TResource, TIn], TResource & TIn>(mergeBuiltin),
|
|
207
209
|
);
|
|
@@ -213,28 +215,28 @@ export function withResource<
|
|
|
213
215
|
[TOut, TResource & TIn]
|
|
214
216
|
>({
|
|
215
217
|
kind: "All",
|
|
216
|
-
actions: [action as Action, identity as Action],
|
|
218
|
+
actions: [action as Action, identity() as Action],
|
|
217
219
|
});
|
|
218
220
|
|
|
219
|
-
// Step 3: all(
|
|
221
|
+
// Step 3: all(getIndex(0), chain(getIndex(1), dispose)) → [TOut, unknown]
|
|
220
222
|
const disposeAndKeepResult = typedAction<
|
|
221
223
|
[TOut, TResource & TIn],
|
|
222
224
|
[TOut, unknown]
|
|
223
225
|
>({
|
|
224
226
|
kind: "All",
|
|
225
227
|
actions: [
|
|
226
|
-
|
|
228
|
+
getIndex<[TOut, TResource & TIn], 0>(0) as Action,
|
|
227
229
|
chain(
|
|
228
|
-
|
|
230
|
+
getIndex<[TOut, TResource & TIn], 1>(1),
|
|
229
231
|
dispose as Pipeable<TResource & TIn, unknown>,
|
|
230
232
|
) as Action,
|
|
231
233
|
],
|
|
232
234
|
});
|
|
233
235
|
|
|
234
|
-
// Step 4:
|
|
236
|
+
// Step 4: getIndex(0) → TOut
|
|
235
237
|
return chain(
|
|
236
238
|
chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult),
|
|
237
|
-
|
|
239
|
+
getIndex<[TOut, unknown], 0>(0),
|
|
238
240
|
) as TypedAction<TIn, TOut>;
|
|
239
241
|
}
|
|
240
242
|
|
|
@@ -383,7 +385,7 @@ const EXTRACT_VALUE: Action = {
|
|
|
383
385
|
kind: "Invoke",
|
|
384
386
|
handler: {
|
|
385
387
|
kind: "Builtin",
|
|
386
|
-
builtin: { kind: "
|
|
388
|
+
builtin: { kind: "GetField", value: "value" },
|
|
387
389
|
},
|
|
388
390
|
};
|
|
389
391
|
const DROP: Action = {
|
|
@@ -395,7 +397,7 @@ const IDENTITY: Action = {
|
|
|
395
397
|
handler: { kind: "Builtin", builtin: { kind: "Identity" } },
|
|
396
398
|
};
|
|
397
399
|
|
|
398
|
-
/** Wrap branch cases with
|
|
400
|
+
/** Wrap branch cases with GetField("value") auto-unwrapping. */
|
|
399
401
|
function optionBranch(someCaseBody: Action, noneCaseBody: Action): Action {
|
|
400
402
|
return {
|
|
401
403
|
kind: "Branch",
|
|
@@ -590,7 +592,7 @@ const TAG_ERR: Action = {
|
|
|
590
592
|
handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Err" } },
|
|
591
593
|
};
|
|
592
594
|
|
|
593
|
-
/** Wrap branch cases with
|
|
595
|
+
/** Wrap branch cases with GetField("value") auto-unwrapping. */
|
|
594
596
|
function resultBranch(okCaseBody: Action, errCaseBody: Action): Action {
|
|
595
597
|
return {
|
|
596
598
|
kind: "Branch",
|
package/src/index.ts
CHANGED
package/src/pipe.ts
CHANGED
|
@@ -82,7 +82,7 @@ export function pipe<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>(
|
|
|
82
82
|
): TypedAction<PipeIn<T1>, T11>;
|
|
83
83
|
export function pipe(...actions: Action[]): Action {
|
|
84
84
|
if (actions.length === 0) {
|
|
85
|
-
return identity;
|
|
85
|
+
return identity();
|
|
86
86
|
}
|
|
87
87
|
if (actions.length === 1) {
|
|
88
88
|
return actions[0];
|
package/src/race.ts
CHANGED
|
@@ -53,7 +53,7 @@ function breakPerform(restartHandlerId: RestartHandlerId): Action {
|
|
|
53
53
|
*
|
|
54
54
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
55
55
|
* `Chain(Tag("Continue"),`
|
|
56
|
-
* `RestartHandle(id,
|
|
56
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
57
57
|
* `Branch({`
|
|
58
58
|
* `Continue: All(Chain(a, breakPerform), Chain(b, breakPerform), ...),`
|
|
59
59
|
* `Break: identity,`
|
package/src/recursive.ts
CHANGED
|
@@ -7,13 +7,7 @@ import {
|
|
|
7
7
|
} from "./ast.js";
|
|
8
8
|
import { all } from "./all.js";
|
|
9
9
|
import { chain } from "./chain.js";
|
|
10
|
-
import {
|
|
11
|
-
constant,
|
|
12
|
-
identity,
|
|
13
|
-
extractField,
|
|
14
|
-
extractIndex,
|
|
15
|
-
tag,
|
|
16
|
-
} from "./builtins.js";
|
|
10
|
+
import { constant, identity, getField, getIndex, tag } from "./builtins.js";
|
|
17
11
|
import { allocateResumeHandlerId } from "./effect-id.js";
|
|
18
12
|
|
|
19
13
|
// ---------------------------------------------------------------------------
|
|
@@ -84,11 +78,11 @@ export function defineRecursiveFunctions<TDefs extends FunctionDef[]>(
|
|
|
84
78
|
...(callTokens as FunctionRefs<TDefs>),
|
|
85
79
|
) as Action[];
|
|
86
80
|
|
|
87
|
-
// Branch cases: CallN →
|
|
81
|
+
// Branch cases: CallN → GetField("value") → bodyN
|
|
88
82
|
const cases: Record<string, Action> = {};
|
|
89
83
|
for (let i = 0; i < bodyActions.length; i++) {
|
|
90
84
|
cases[`Call${i}`] = chain(
|
|
91
|
-
|
|
85
|
+
getField("value"),
|
|
92
86
|
bodyActions[i] as any,
|
|
93
87
|
) as Action;
|
|
94
88
|
}
|
|
@@ -98,12 +92,12 @@ export function defineRecursiveFunctions<TDefs extends FunctionDef[]>(
|
|
|
98
92
|
const userBody = entryFn(...(callTokens as FunctionRefs<TDefs>)) as Action;
|
|
99
93
|
|
|
100
94
|
return typedAction<any, TOut>(
|
|
101
|
-
chain(all(identity, constant(UNUSED_STATE)), {
|
|
95
|
+
chain(all(identity(), constant(UNUSED_STATE)), {
|
|
102
96
|
kind: "ResumeHandle",
|
|
103
97
|
resume_handler_id: resumeHandlerId,
|
|
104
|
-
body: chain(
|
|
98
|
+
body: chain(getIndex(0), userBody as any) as Action,
|
|
105
99
|
handler: all(
|
|
106
|
-
chain(
|
|
100
|
+
chain(getIndex(0), branch(cases) as any),
|
|
107
101
|
constant(UNUSED_STATE),
|
|
108
102
|
) as Action,
|
|
109
103
|
} as Action) as Action,
|
package/src/try-catch.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { allocateRestartHandlerId } from "./effect-id.js";
|
|
|
25
25
|
*
|
|
26
26
|
* Compiled form (restart+Branch, same substrate as loop/earlyReturn):
|
|
27
27
|
* `Chain(Tag("Continue"),`
|
|
28
|
-
* `RestartHandle(id,
|
|
28
|
+
* `RestartHandle(id, GetIndex(0),`
|
|
29
29
|
* `Branch({ Continue: body, Break: recovery })))`
|
|
30
30
|
*
|
|
31
31
|
* throwError = `Chain(Tag("Break"), RestartPerform(id))`
|