@barnum/barnum 0.0.0-main-ef57b8fd → 0.0.0-main-39525152

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.
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/ast.d.ts CHANGED
@@ -68,16 +68,20 @@ export type BuiltinKind = {
68
68
  } | {
69
69
  kind: "Flatten";
70
70
  } | {
71
- kind: "ExtractField";
71
+ kind: "GetField";
72
72
  value: string;
73
73
  } | {
74
- kind: "ExtractIndex";
74
+ kind: "GetIndex";
75
75
  value: number;
76
76
  } | {
77
77
  kind: "Pick";
78
78
  value: string[];
79
79
  } | {
80
80
  kind: "CollectSome";
81
+ } | {
82
+ kind: "SplitFirst";
83
+ } | {
84
+ kind: "SplitLast";
81
85
  } | {
82
86
  kind: "WrapInField";
83
87
  value: string;
@@ -130,14 +134,20 @@ export type TypedAction<In = unknown, Out = unknown, Refs extends string = never
130
134
  drop(): TypedAction<In, never, Refs>;
131
135
  /** Wrap output as a tagged union member. Requires full variant map TDef so __def is carried. */
132
136
  tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>, Refs>;
133
- /** Extract a field from the output object. `a.get("name")` ≡ `pipe(a, extractField("name"))`. */
134
- get<TField extends keyof Out & string>(field: TField): TypedAction<In, Out[TField], Refs>;
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>;
135
141
  /** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
136
142
  wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>, Refs>;
137
143
  /** Merge a tuple of objects into a single object. `a.merge()` ≡ `pipe(a, merge())`. */
138
144
  merge(): TypedAction<In, MergeTuple<Out>, Refs>;
139
145
  /** Select fields from the output. `a.pick("x", "y")` ≡ `pipe(a, pick("x", "y"))`. */
140
146
  pick<TKeys extends (keyof Out & string)[]>(...keys: TKeys): TypedAction<In, Pick<Out, TKeys[number]>, Refs>;
147
+ /** Head/tail decomposition. Only callable when Out is TElement[]. */
148
+ splitFirst<TIn, TElement, TRefs extends string>(this: TypedAction<TIn, TElement[], TRefs>): TypedAction<TIn, Option<[TElement, TElement[]]>, TRefs>;
149
+ /** Init/last decomposition. Only callable when Out is TElement[]. */
150
+ splitLast<TIn, TElement, TRefs extends string>(this: TypedAction<TIn, TElement[], TRefs>): TypedAction<TIn, Option<[TElement[], TElement]>, TRefs>;
141
151
  /**
142
152
  * Transform the Some value inside an Option output. Only callable when
143
153
  * Out is Option<T>. Uses `this` parameter constraint to gate availability.
@@ -331,7 +341,7 @@ export declare const IDENTITY: Action;
331
341
  * If the body completes normally → output is TOut.
332
342
  * If restart fires → body re-executes with the restarted value.
333
343
  *
334
- * Compiled form: `RestartHandle(id, ExtractIndex(0), body)`
344
+ * Compiled form: `RestartHandle(id, GetIndex(0), body)`
335
345
  */
336
346
  export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>): TypedAction<PipeIn<TIn>, TOut>;
337
347
  /**
@@ -349,7 +359,7 @@ export declare function recur<TIn = never, TOut = any>(bodyFn: (restart: TypedAc
349
359
  export declare function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(bodyFn: (earlyReturn: TypedAction<TEarlyReturn, never>) => Pipeable<TIn, TOut>): TypedAction<TIn, TEarlyReturn | TOut>;
350
360
  /**
351
361
  * Build the restart+branch compiled form:
352
- * `Chain(Tag("Continue"), RestartHandle(id, ExtractIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
362
+ * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
353
363
  *
354
364
  * Input is tagged Continue so the Branch enters the continueArm on first execution.
355
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 getMethod(field) {
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: "ExtractField", value: field },
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
  });
@@ -95,6 +108,26 @@ function pickMethod(...keys) {
95
108
  },
96
109
  });
97
110
  }
111
+ function splitFirstMethod() {
112
+ return typedAction({
113
+ kind: "Chain",
114
+ first: this,
115
+ rest: {
116
+ kind: "Invoke",
117
+ handler: { kind: "Builtin", builtin: { kind: "SplitFirst" } },
118
+ },
119
+ });
120
+ }
121
+ function splitLastMethod() {
122
+ return typedAction({
123
+ kind: "Chain",
124
+ first: this,
125
+ rest: {
126
+ kind: "Invoke",
127
+ handler: { kind: "Builtin", builtin: { kind: "SplitLast" } },
128
+ },
129
+ });
130
+ }
98
131
  function mapOptionMethod(action) {
99
132
  // Desugars to: self.then(branch({ Some: pipe(action, tag("Some")), None: tag("None") }))
100
133
  // But branch auto-unwraps value, so:
@@ -182,10 +215,13 @@ export function typedAction(action) {
182
215
  flatten: { value: flattenMethod, configurable: true },
183
216
  drop: { value: dropMethod, configurable: true },
184
217
  tag: { value: tagMethod, configurable: true },
185
- get: { value: getMethod, configurable: true },
218
+ getField: { value: getFieldMethod, configurable: true },
219
+ getIndex: { value: getIndexMethod, configurable: true },
186
220
  wrapInField: { value: wrapInFieldMethod, configurable: true },
187
221
  merge: { value: mergeMethod, configurable: true },
188
222
  pick: { value: pickMethod, configurable: true },
223
+ splitFirst: { value: splitFirstMethod, configurable: true },
224
+ splitLast: { value: splitLastMethod, configurable: true },
189
225
  mapOption: { value: mapOptionMethod, configurable: true },
190
226
  mapErr: { value: mapErrMethod, configurable: true },
191
227
  unwrapOr: { value: unwrapOrMethod, configurable: true },
@@ -209,7 +245,7 @@ export function forEach(action) {
209
245
  return typedAction({ kind: "ForEach", action: action });
210
246
  }
211
247
  /**
212
- * Insert ExtractField("value") before each case handler in a branch.
248
+ * Insert GetField("value") before each case handler in a branch.
213
249
  * This implements auto-unwrapping: the engine dispatches on `kind`, then
214
250
  * extracts `value` before passing to the handler. Case handlers receive
215
251
  * the payload directly, not the full `{ kind, value }` variant.
@@ -223,7 +259,7 @@ function unwrapBranchCases(cases) {
223
259
  kind: "Invoke",
224
260
  handler: {
225
261
  kind: "Builtin",
226
- builtin: { kind: "ExtractField", value: "value" },
262
+ builtin: { kind: "GetField", value: "value" },
227
263
  },
228
264
  },
229
265
  rest: cases[key],
@@ -240,7 +276,7 @@ export function branch(cases) {
240
276
  // ---------------------------------------------------------------------------
241
277
  const EXTRACT_PAYLOAD = {
242
278
  kind: "Invoke",
243
- handler: { kind: "Builtin", builtin: { kind: "ExtractIndex", value: 0 } },
279
+ handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
244
280
  };
245
281
  const TAG_CONTINUE = {
246
282
  kind: "Invoke",
@@ -264,7 +300,7 @@ export const IDENTITY = {
264
300
  * If the body completes normally → output is TOut.
265
301
  * If restart fires → body re-executes with the restarted value.
266
302
  *
267
- * Compiled form: `RestartHandle(id, ExtractIndex(0), body)`
303
+ * Compiled form: `RestartHandle(id, GetIndex(0), body)`
268
304
  */
269
305
  export function recur(bodyFn) {
270
306
  const restartHandlerId = allocateRestartHandlerId();
@@ -310,7 +346,7 @@ export function earlyReturn(bodyFn) {
310
346
  // ---------------------------------------------------------------------------
311
347
  /**
312
348
  * Build the restart+branch compiled form:
313
- * `Chain(Tag("Continue"), RestartHandle(id, ExtractIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
349
+ * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
314
350
  *
315
351
  * Input is tagged Continue so the Branch enters the continueArm on first execution.
316
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 `extractField` — pipe overloads can't infer
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(ExtractIndex(N), body)
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(ExtractIndex(1), ExtractIndex(n)), ExtractIndex(1))
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: "ExtractIndex", value: 1 },
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: "ExtractIndex", value: n },
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: "ExtractIndex", value: 1 },
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: "ExtractIndex", value: pipelineInputIndex },
70
+ builtin: { kind: "GetIndex", value: pipelineInputIndex },
71
71
  },
72
72
  },
73
73
  rest: bodyAction,
@@ -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 extractField<TObj extends Record<string, unknown>, TField extends keyof TObj & string>(field: TField): TypedAction<TObj, TObj[TField]>;
22
- export declare function extractIndex<TTuple extends unknown[], TIndex extends number>(index: TIndex): TypedAction<TTuple, TTuple[TIndex]>;
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
  /**
@@ -57,6 +57,29 @@ export declare function withResource<TIn extends Record<string, unknown>, TResou
57
57
  export declare function tap<TInput extends Record<string, unknown>>(action: Pipeable<TInput, any>): TypedAction<TInput, TInput>;
58
58
  export declare function wrapInField<TField extends string, TValue>(field: TField): TypedAction<TValue, Record<TField, TValue>>;
59
59
  export declare function range(start: number, end: number): TypedAction<any, number[]>;
60
+ /**
61
+ * Deconstruct an array into its first element and the remaining elements.
62
+ * `TElement[] → Option<[TElement, TElement[]]>`
63
+ *
64
+ * Returns `Some([first, rest])` for non-empty arrays, `None` for empty arrays.
65
+ * This is the array equivalent of cons/uncons — enables recursive iteration
66
+ * patterns via `loop` + `splitFirst` + `branch`.
67
+ *
68
+ * This is a builtin (SplitFirst) because it requires array-length branching
69
+ * that can't be composed from existing AST nodes.
70
+ */
71
+ export declare function splitFirst<TElement>(): TypedAction<TElement[], OptionT<[TElement, TElement[]]>>;
72
+ /**
73
+ * Deconstruct an array into the leading elements and the last element.
74
+ * `TElement[] → Option<[TElement[], TElement]>`
75
+ *
76
+ * Returns `Some([init, last])` for non-empty arrays, `None` for empty arrays.
77
+ * Mirror of `splitFirst` — enables processing from the tail end.
78
+ *
79
+ * This is a builtin (SplitLast) because it requires array-length branching
80
+ * that can't be composed from existing AST nodes.
81
+ */
82
+ export declare function splitLast<TElement>(): TypedAction<TElement[], OptionT<[TElement[], TElement]>>;
60
83
  /**
61
84
  * Option namespace. All combinators produce TypedAction AST nodes that
62
85
  * desugar to branch + existing builtins, except collect which uses the
package/dist/builtins.js CHANGED
@@ -64,26 +64,26 @@ export function flatten() {
64
64
  });
65
65
  }
66
66
  // ---------------------------------------------------------------------------
67
- // ExtractField — extract a single field from an object
67
+ // GetField — extract a single field from an object
68
68
  // ---------------------------------------------------------------------------
69
- export function extractField(field) {
69
+ export function getField(field) {
70
70
  return typedAction({
71
71
  kind: "Invoke",
72
72
  handler: {
73
73
  kind: "Builtin",
74
- builtin: { kind: "ExtractField", value: field },
74
+ builtin: { kind: "GetField", value: field },
75
75
  },
76
76
  });
77
77
  }
78
78
  // ---------------------------------------------------------------------------
79
- // ExtractIndex — extract a single element from an array by index
79
+ // GetIndex — extract a single element from an array by index
80
80
  // ---------------------------------------------------------------------------
81
- export function extractIndex(index) {
81
+ export function getIndex(index) {
82
82
  return typedAction({
83
83
  kind: "Invoke",
84
84
  handler: {
85
85
  kind: "Builtin",
86
- builtin: { kind: "ExtractIndex", value: index },
86
+ builtin: { kind: "GetIndex", value: index },
87
87
  },
88
88
  });
89
89
  }
@@ -146,16 +146,16 @@ export function withResource({ create, action, dispose, }) {
146
146
  kind: "All",
147
147
  actions: [action, identity],
148
148
  });
149
- // Step 3: all(extractIndex(0), chain(extractIndex(1), dispose)) → [TOut, unknown]
149
+ // Step 3: all(getIndex(0), chain(getIndex(1), dispose)) → [TOut, unknown]
150
150
  const disposeAndKeepResult = typedAction({
151
151
  kind: "All",
152
152
  actions: [
153
- extractIndex(0),
154
- chain(extractIndex(1), dispose),
153
+ getIndex(0),
154
+ chain(getIndex(1), dispose),
155
155
  ],
156
156
  });
157
- // Step 4: extractIndex(0) → TOut
158
- return chain(chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult), extractIndex(0));
157
+ // Step 4: getIndex(0) → TOut
158
+ return chain(chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult), getIndex(0));
159
159
  }
160
160
  // ---------------------------------------------------------------------------
161
161
  // Tap — run an action for side effects, preserve original input
@@ -227,6 +227,45 @@ export function range(start, end) {
227
227
  });
228
228
  }
229
229
  // ---------------------------------------------------------------------------
230
+ // SplitFirst — head/tail decomposition of an array
231
+ // ---------------------------------------------------------------------------
232
+ /**
233
+ * Deconstruct an array into its first element and the remaining elements.
234
+ * `TElement[] → Option<[TElement, TElement[]]>`
235
+ *
236
+ * Returns `Some([first, rest])` for non-empty arrays, `None` for empty arrays.
237
+ * This is the array equivalent of cons/uncons — enables recursive iteration
238
+ * patterns via `loop` + `splitFirst` + `branch`.
239
+ *
240
+ * This is a builtin (SplitFirst) because it requires array-length branching
241
+ * that can't be composed from existing AST nodes.
242
+ */
243
+ export function splitFirst() {
244
+ return typedAction({
245
+ kind: "Invoke",
246
+ handler: { kind: "Builtin", builtin: { kind: "SplitFirst" } },
247
+ });
248
+ }
249
+ // ---------------------------------------------------------------------------
250
+ // SplitLast — init/last decomposition of an array
251
+ // ---------------------------------------------------------------------------
252
+ /**
253
+ * Deconstruct an array into the leading elements and the last element.
254
+ * `TElement[] → Option<[TElement[], TElement]>`
255
+ *
256
+ * Returns `Some([init, last])` for non-empty arrays, `None` for empty arrays.
257
+ * Mirror of `splitFirst` — enables processing from the tail end.
258
+ *
259
+ * This is a builtin (SplitLast) because it requires array-length branching
260
+ * that can't be composed from existing AST nodes.
261
+ */
262
+ export function splitLast() {
263
+ return typedAction({
264
+ kind: "Invoke",
265
+ handler: { kind: "Builtin", builtin: { kind: "SplitLast" } },
266
+ });
267
+ }
268
+ // ---------------------------------------------------------------------------
230
269
  // Option namespace — combinators for Option<T> tagged unions
231
270
  // ---------------------------------------------------------------------------
232
271
  // Shared AST fragments for Option desugaring
@@ -242,7 +281,7 @@ const EXTRACT_VALUE = {
242
281
  kind: "Invoke",
243
282
  handler: {
244
283
  kind: "Builtin",
245
- builtin: { kind: "ExtractField", value: "value" },
284
+ builtin: { kind: "GetField", value: "value" },
246
285
  },
247
286
  };
248
287
  const DROP = {
@@ -253,7 +292,7 @@ const IDENTITY = {
253
292
  kind: "Invoke",
254
293
  handler: { kind: "Builtin", builtin: { kind: "Identity" } },
255
294
  };
256
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
295
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
257
296
  function optionBranch(someCaseBody, noneCaseBody) {
258
297
  return {
259
298
  kind: "Branch",
@@ -416,7 +455,7 @@ const TAG_ERR = {
416
455
  kind: "Invoke",
417
456
  handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Err" } },
418
457
  };
419
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
458
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
420
459
  function resultBranch(okCaseBody, errCaseBody) {
421
460
  return {
422
461
  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, extractField, extractIndex, pick, dropResult, withResource, tap, range, wrapInField, Option, Result, } from "./builtins.js";
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, extractField, extractIndex, pick, dropResult, withResource, tap, range, wrapInField, Option, Result, } from "./builtins.js";
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/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, ExtractIndex(0),`
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, ExtractIndex(0),`
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, extractField, extractIndex, tag, } from "./builtins.js";
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,10 +35,10 @@ 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 → ExtractField("value") → bodyN
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(extractField("value"), bodyActions[i]);
41
+ cases[`Call${i}`] = chain(getField("value"), bodyActions[i]);
42
42
  }
43
43
  // Return curried entry-point combinator
44
44
  return (entryFn) => {
@@ -46,8 +46,8 @@ export function defineRecursiveFunctions(bodiesFn) {
46
46
  return typedAction(chain(all(identity, constant(UNUSED_STATE)), {
47
47
  kind: "ResumeHandle",
48
48
  resume_handler_id: resumeHandlerId,
49
- body: chain(extractIndex(0), userBody),
50
- handler: all(chain(extractIndex(0), branch(cases)), constant(UNUSED_STATE)),
49
+ body: chain(getIndex(0), userBody),
50
+ handler: all(chain(getIndex(0), branch(cases)), constant(UNUSED_STATE)),
51
51
  }));
52
52
  };
53
53
  }
@@ -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, ExtractIndex(0),`
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, ExtractIndex(0),`
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@barnum/barnum",
3
- "version": "0.0.0-main-ef57b8fd",
3
+ "version": "0.0.0-main-39525152",
4
4
  "description": "Barnum workflow engine",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/ast.ts CHANGED
@@ -91,10 +91,12 @@ export type BuiltinKind =
91
91
  | { kind: "Tag"; value: string }
92
92
  | { kind: "Merge" }
93
93
  | { kind: "Flatten" }
94
- | { kind: "ExtractField"; value: string }
95
- | { kind: "ExtractIndex"; value: number }
94
+ | { kind: "GetField"; value: string }
95
+ | { kind: "GetIndex"; value: number }
96
96
  | { kind: "Pick"; value: string[] }
97
97
  | { kind: "CollectSome" }
98
+ | { kind: "SplitFirst" }
99
+ | { kind: "SplitLast" }
98
100
  | { kind: "WrapInField"; value: string }
99
101
  | { kind: "Sleep"; value: number };
100
102
 
@@ -181,10 +183,20 @@ export type TypedAction<
181
183
  tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(
182
184
  kind: TKind,
183
185
  ): TypedAction<In, TaggedUnion<TDef>, Refs>;
184
- /** Extract a field from the output object. `a.get("name")` ≡ `pipe(a, extractField("name"))`. */
185
- get<TField extends keyof Out & string>(
186
+ /** Extract a field from the output object. `a.getField("name")` ≡ `pipe(a, getField("name"))`. */
187
+ getField<TField extends keyof Out & string>(
186
188
  field: TField,
187
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>;
188
200
  /** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
189
201
  wrapInField<TField extends string>(
190
202
  field: TField,
@@ -195,6 +207,14 @@ export type TypedAction<
195
207
  pick<TKeys extends (keyof Out & string)[]>(
196
208
  ...keys: TKeys
197
209
  ): TypedAction<In, Pick<Out, TKeys[number]>, Refs>;
210
+ /** Head/tail decomposition. Only callable when Out is TElement[]. */
211
+ splitFirst<TIn, TElement, TRefs extends string>(
212
+ this: TypedAction<TIn, TElement[], TRefs>,
213
+ ): TypedAction<TIn, Option<[TElement, TElement[]]>, TRefs>;
214
+ /** Init/last decomposition. Only callable when Out is TElement[]. */
215
+ splitLast<TIn, TElement, TRefs extends string>(
216
+ this: TypedAction<TIn, TElement[], TRefs>,
217
+ ): TypedAction<TIn, Option<[TElement[], TElement]>, TRefs>;
198
218
  /**
199
219
  * Transform the Some value inside an Option output. Only callable when
200
220
  * Out is Option<T>. Uses `this` parameter constraint to gate availability.
@@ -418,7 +438,7 @@ function tagMethod(this: TypedAction, kind: string): TypedAction {
418
438
  });
419
439
  }
420
440
 
421
- function getMethod(this: TypedAction, field: string): TypedAction {
441
+ function getFieldMethod(this: TypedAction, field: string): TypedAction {
422
442
  return typedAction({
423
443
  kind: "Chain",
424
444
  first: this,
@@ -426,7 +446,21 @@ function getMethod(this: TypedAction, field: string): TypedAction {
426
446
  kind: "Invoke",
427
447
  handler: {
428
448
  kind: "Builtin",
429
- builtin: { kind: "ExtractField", value: field },
449
+ builtin: { kind: "GetField", value: field },
450
+ },
451
+ },
452
+ });
453
+ }
454
+
455
+ function getIndexMethod(this: TypedAction, index: number): TypedAction {
456
+ return typedAction({
457
+ kind: "Chain",
458
+ first: this,
459
+ rest: {
460
+ kind: "Invoke",
461
+ handler: {
462
+ kind: "Builtin",
463
+ builtin: { kind: "GetIndex", value: index },
430
464
  },
431
465
  },
432
466
  });
@@ -468,6 +502,28 @@ function pickMethod(this: TypedAction, ...keys: string[]): TypedAction {
468
502
  });
469
503
  }
470
504
 
505
+ function splitFirstMethod(this: TypedAction): TypedAction {
506
+ return typedAction({
507
+ kind: "Chain",
508
+ first: this,
509
+ rest: {
510
+ kind: "Invoke",
511
+ handler: { kind: "Builtin", builtin: { kind: "SplitFirst" } },
512
+ },
513
+ });
514
+ }
515
+
516
+ function splitLastMethod(this: TypedAction): TypedAction {
517
+ return typedAction({
518
+ kind: "Chain",
519
+ first: this,
520
+ rest: {
521
+ kind: "Invoke",
522
+ handler: { kind: "Builtin", builtin: { kind: "SplitLast" } },
523
+ },
524
+ });
525
+ }
526
+
471
527
  function mapOptionMethod(this: TypedAction, action: Action): TypedAction {
472
528
  // Desugars to: self.then(branch({ Some: pipe(action, tag("Some")), None: tag("None") }))
473
529
  // But branch auto-unwraps value, so:
@@ -562,10 +618,13 @@ export function typedAction<
562
618
  flatten: { value: flattenMethod, configurable: true },
563
619
  drop: { value: dropMethod, configurable: true },
564
620
  tag: { value: tagMethod, configurable: true },
565
- get: { value: getMethod, configurable: true },
621
+ getField: { value: getFieldMethod, configurable: true },
622
+ getIndex: { value: getIndexMethod, configurable: true },
566
623
  wrapInField: { value: wrapInFieldMethod, configurable: true },
567
624
  merge: { value: mergeMethod, configurable: true },
568
625
  pick: { value: pickMethod, configurable: true },
626
+ splitFirst: { value: splitFirstMethod, configurable: true },
627
+ splitLast: { value: splitLastMethod, configurable: true },
569
628
  mapOption: { value: mapOptionMethod, configurable: true },
570
629
  mapErr: { value: mapErrMethod, configurable: true },
571
630
  unwrapOr: { value: unwrapOrMethod, configurable: true },
@@ -625,7 +684,7 @@ export function forEach<In, Out>(
625
684
  }
626
685
 
627
686
  /**
628
- * Insert ExtractField("value") before each case handler in a branch.
687
+ * Insert GetField("value") before each case handler in a branch.
629
688
  * This implements auto-unwrapping: the engine dispatches on `kind`, then
630
689
  * extracts `value` before passing to the handler. Case handlers receive
631
690
  * the payload directly, not the full `{ kind, value }` variant.
@@ -641,7 +700,7 @@ function unwrapBranchCases(
641
700
  kind: "Invoke",
642
701
  handler: {
643
702
  kind: "Builtin",
644
- builtin: { kind: "ExtractField", value: "value" },
703
+ builtin: { kind: "GetField", value: "value" },
645
704
  },
646
705
  },
647
706
  rest: cases[key],
@@ -691,7 +750,7 @@ export type LoopResult<TContinue, TBreak> = TaggedUnion<
691
750
 
692
751
  const EXTRACT_PAYLOAD: Action = {
693
752
  kind: "Invoke",
694
- handler: { kind: "Builtin", builtin: { kind: "ExtractIndex", value: 0 } },
753
+ handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
695
754
  };
696
755
 
697
756
  const TAG_CONTINUE: Action = {
@@ -720,7 +779,7 @@ export const IDENTITY: Action = {
720
779
  * If the body completes normally → output is TOut.
721
780
  * If restart fires → body re-executes with the restarted value.
722
781
  *
723
- * Compiled form: `RestartHandle(id, ExtractIndex(0), body)`
782
+ * Compiled form: `RestartHandle(id, GetIndex(0), body)`
724
783
  */
725
784
  export function recur<TIn = never, TOut = any>(
726
785
  bodyFn: (restart: TypedAction<TIn, never>) => Pipeable<TIn, TOut>,
@@ -784,7 +843,7 @@ export function earlyReturn<TEarlyReturn = never, TIn = any, TOut = any>(
784
843
 
785
844
  /**
786
845
  * Build the restart+branch compiled form:
787
- * `Chain(Tag("Continue"), RestartHandle(id, ExtractIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
846
+ * `Chain(Tag("Continue"), RestartHandle(id, GetIndex(0), Branch({ Continue: continueArm, Break: breakArm })))`
788
847
  *
789
848
  * Input is tagged Continue so the Branch enters the continueArm on first execution.
790
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 `extractField` — pipe overloads can't infer
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(ExtractIndex(1), ExtractIndex(n)), ExtractIndex(1))
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: "ExtractIndex", value: 1 },
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: "ExtractIndex", value: n },
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: "ExtractIndex", value: 1 },
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(ExtractIndex(N), body)
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: "ExtractIndex", value: pipelineInputIndex },
151
+ builtin: { kind: "GetIndex", value: pipelineInputIndex },
152
152
  },
153
153
  },
154
154
  rest: bodyAction,
package/src/builtins.ts CHANGED
@@ -93,10 +93,10 @@ export function flatten<TElement>(): TypedAction<TElement[][], TElement[]> {
93
93
  }
94
94
 
95
95
  // ---------------------------------------------------------------------------
96
- // ExtractField — extract a single field from an object
96
+ // GetField — extract a single field from an object
97
97
  // ---------------------------------------------------------------------------
98
98
 
99
- export function extractField<
99
+ export function getField<
100
100
  TObj extends Record<string, unknown>,
101
101
  TField extends keyof TObj & string,
102
102
  >(field: TField): TypedAction<TObj, TObj[TField]> {
@@ -104,23 +104,23 @@ export function extractField<
104
104
  kind: "Invoke",
105
105
  handler: {
106
106
  kind: "Builtin",
107
- builtin: { kind: "ExtractField", value: field },
107
+ builtin: { kind: "GetField", value: field },
108
108
  },
109
109
  });
110
110
  }
111
111
 
112
112
  // ---------------------------------------------------------------------------
113
- // ExtractIndex — extract a single element from an array by index
113
+ // GetIndex — extract a single element from an array by index
114
114
  // ---------------------------------------------------------------------------
115
115
 
116
- export function extractIndex<TTuple extends unknown[], TIndex extends number>(
116
+ export function getIndex<TTuple extends unknown[], TIndex extends number>(
117
117
  index: TIndex,
118
118
  ): TypedAction<TTuple, TTuple[TIndex]> {
119
119
  return typedAction({
120
120
  kind: "Invoke",
121
121
  handler: {
122
122
  kind: "Builtin",
123
- builtin: { kind: "ExtractIndex", value: index },
123
+ builtin: { kind: "GetIndex", value: index },
124
124
  },
125
125
  });
126
126
  }
@@ -216,25 +216,25 @@ export function withResource<
216
216
  actions: [action as Action, identity as Action],
217
217
  });
218
218
 
219
- // Step 3: all(extractIndex(0), chain(extractIndex(1), dispose)) → [TOut, unknown]
219
+ // Step 3: all(getIndex(0), chain(getIndex(1), dispose)) → [TOut, unknown]
220
220
  const disposeAndKeepResult = typedAction<
221
221
  [TOut, TResource & TIn],
222
222
  [TOut, unknown]
223
223
  >({
224
224
  kind: "All",
225
225
  actions: [
226
- extractIndex<[TOut, TResource & TIn], 0>(0) as Action,
226
+ getIndex<[TOut, TResource & TIn], 0>(0) as Action,
227
227
  chain(
228
- extractIndex<[TOut, TResource & TIn], 1>(1),
228
+ getIndex<[TOut, TResource & TIn], 1>(1),
229
229
  dispose as Pipeable<TResource & TIn, unknown>,
230
230
  ) as Action,
231
231
  ],
232
232
  });
233
233
 
234
- // Step 4: extractIndex(0) → TOut
234
+ // Step 4: getIndex(0) → TOut
235
235
  return chain(
236
236
  chain(chain(acquireAndMerge, actionAndKeepMerged), disposeAndKeepResult),
237
- extractIndex<[TOut, unknown], 0>(0),
237
+ getIndex<[TOut, unknown], 0>(0),
238
238
  ) as TypedAction<TIn, TOut>;
239
239
  }
240
240
 
@@ -317,6 +317,55 @@ export function range(start: number, end: number): TypedAction<any, number[]> {
317
317
  });
318
318
  }
319
319
 
320
+ // ---------------------------------------------------------------------------
321
+ // SplitFirst — head/tail decomposition of an array
322
+ // ---------------------------------------------------------------------------
323
+
324
+ /**
325
+ * Deconstruct an array into its first element and the remaining elements.
326
+ * `TElement[] → Option<[TElement, TElement[]]>`
327
+ *
328
+ * Returns `Some([first, rest])` for non-empty arrays, `None` for empty arrays.
329
+ * This is the array equivalent of cons/uncons — enables recursive iteration
330
+ * patterns via `loop` + `splitFirst` + `branch`.
331
+ *
332
+ * This is a builtin (SplitFirst) because it requires array-length branching
333
+ * that can't be composed from existing AST nodes.
334
+ */
335
+ export function splitFirst<TElement>(): TypedAction<
336
+ TElement[],
337
+ OptionT<[TElement, TElement[]]>
338
+ > {
339
+ return typedAction({
340
+ kind: "Invoke",
341
+ handler: { kind: "Builtin", builtin: { kind: "SplitFirst" } },
342
+ });
343
+ }
344
+
345
+ // ---------------------------------------------------------------------------
346
+ // SplitLast — init/last decomposition of an array
347
+ // ---------------------------------------------------------------------------
348
+
349
+ /**
350
+ * Deconstruct an array into the leading elements and the last element.
351
+ * `TElement[] → Option<[TElement[], TElement]>`
352
+ *
353
+ * Returns `Some([init, last])` for non-empty arrays, `None` for empty arrays.
354
+ * Mirror of `splitFirst` — enables processing from the tail end.
355
+ *
356
+ * This is a builtin (SplitLast) because it requires array-length branching
357
+ * that can't be composed from existing AST nodes.
358
+ */
359
+ export function splitLast<TElement>(): TypedAction<
360
+ TElement[],
361
+ OptionT<[TElement[], TElement]>
362
+ > {
363
+ return typedAction({
364
+ kind: "Invoke",
365
+ handler: { kind: "Builtin", builtin: { kind: "SplitLast" } },
366
+ });
367
+ }
368
+
320
369
  // ---------------------------------------------------------------------------
321
370
  // Option namespace — combinators for Option<T> tagged unions
322
371
  // ---------------------------------------------------------------------------
@@ -334,7 +383,7 @@ const EXTRACT_VALUE: Action = {
334
383
  kind: "Invoke",
335
384
  handler: {
336
385
  kind: "Builtin",
337
- builtin: { kind: "ExtractField", value: "value" },
386
+ builtin: { kind: "GetField", value: "value" },
338
387
  },
339
388
  };
340
389
  const DROP: Action = {
@@ -346,7 +395,7 @@ const IDENTITY: Action = {
346
395
  handler: { kind: "Builtin", builtin: { kind: "Identity" } },
347
396
  };
348
397
 
349
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
398
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
350
399
  function optionBranch(someCaseBody: Action, noneCaseBody: Action): Action {
351
400
  return {
352
401
  kind: "Branch",
@@ -541,7 +590,7 @@ const TAG_ERR: Action = {
541
590
  handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Err" } },
542
591
  };
543
592
 
544
- /** Wrap branch cases with ExtractField("value") auto-unwrapping. */
593
+ /** Wrap branch cases with GetField("value") auto-unwrapping. */
545
594
  function resultBranch(okCaseBody: Action, errCaseBody: Action): Action {
546
595
  return {
547
596
  kind: "Branch",
package/src/index.ts CHANGED
@@ -8,13 +8,15 @@ export {
8
8
  tag,
9
9
  merge,
10
10
  flatten,
11
- extractField,
12
- extractIndex,
11
+ getField,
12
+ getIndex,
13
13
  pick,
14
14
  dropResult,
15
15
  withResource,
16
16
  tap,
17
17
  range,
18
+ splitFirst,
19
+ splitLast,
18
20
  wrapInField,
19
21
  Option,
20
22
  Result,
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, ExtractIndex(0),`
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 → ExtractField("value") → bodyN
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
- extractField("value"),
85
+ getField("value"),
92
86
  bodyActions[i] as any,
93
87
  ) as Action;
94
88
  }
@@ -101,9 +95,9 @@ export function defineRecursiveFunctions<TDefs extends FunctionDef[]>(
101
95
  chain(all(identity, constant(UNUSED_STATE)), {
102
96
  kind: "ResumeHandle",
103
97
  resume_handler_id: resumeHandlerId,
104
- body: chain(extractIndex(0), userBody as any) as Action,
98
+ body: chain(getIndex(0), userBody as any) as Action,
105
99
  handler: all(
106
- chain(extractIndex(0), branch(cases) as any),
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, ExtractIndex(0),`
28
+ * `RestartHandle(id, GetIndex(0),`
29
29
  * `Branch({ Continue: body, Break: recovery })))`
30
30
  *
31
31
  * throwError = `Chain(Tag("Break"), RestartPerform(id))`