@barnum/barnum 0.0.0-main-3c07d795 → 0.0.0-main-54c41bbb

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/all.d.ts CHANGED
@@ -1,12 +1,42 @@
1
1
  import { type Pipeable, type TypedAction } from "./ast.js";
2
2
  export declare function all(): TypedAction<any, []>;
3
- export declare function all<In, O1>(a1: Pipeable<In, O1>): TypedAction<In, [O1]>;
4
- export declare function all<In, O1, O2>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>): TypedAction<In, [O1, O2]>;
5
- export declare function all<In, O1, O2, O3>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>): TypedAction<In, [O1, O2, O3]>;
6
- export declare function all<In, O1, O2, O3, O4>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>): TypedAction<In, [O1, O2, O3, O4]>;
7
- export declare function all<In, O1, O2, O3, O4, O5>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>): TypedAction<In, [O1, O2, O3, O4, O5]>;
8
- export declare function all<In, O1, O2, O3, O4, O5, O6>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>): TypedAction<In, [O1, O2, O3, O4, O5, O6]>;
9
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7]>;
10
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7, O8>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>, a8: Pipeable<In, O8>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7, O8]>;
11
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7, O8, O9>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>, a8: Pipeable<In, O8>, a9: Pipeable<In, O9>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7, O8, O9]>;
12
- export declare function all<In, O1, O2, O3, O4, O5, O6, O7, O8, O9, O10>(a1: Pipeable<In, O1>, a2: Pipeable<In, O2>, a3: Pipeable<In, O3>, a4: Pipeable<In, O4>, a5: Pipeable<In, O5>, a6: Pipeable<In, O6>, a7: Pipeable<In, O7>, a8: Pipeable<In, O8>, a9: Pipeable<In, O9>, a10: Pipeable<In, O10>): TypedAction<In, [O1, O2, O3, O4, O5, O6, O7, O8, O9, O10]>;
3
+ export declare function all<TInput, TOut1>(a1: Pipeable<TInput, TOut1>): TypedAction<TInput, [TOut1]>;
4
+ export declare function all<TInput, TOut1, TOut2>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>): TypedAction<TInput, [TOut1, TOut2]>;
5
+ export declare function all<TInput, TOut1, TOut2, TOut3>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>): TypedAction<TInput, [TOut1, TOut2, TOut3]>;
6
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4]>;
7
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4, TOut5]>;
8
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4, TOut5, TOut6]>;
9
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>): TypedAction<TInput, [TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7]>;
10
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7, TOut8>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>, a8: Pipeable<TInput, TOut8>): TypedAction<TInput, [
11
+ TOut1,
12
+ TOut2,
13
+ TOut3,
14
+ TOut4,
15
+ TOut5,
16
+ TOut6,
17
+ TOut7,
18
+ TOut8
19
+ ]>;
20
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7, TOut8, TOut9>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>, a8: Pipeable<TInput, TOut8>, a9: Pipeable<TInput, TOut9>): TypedAction<TInput, [
21
+ TOut1,
22
+ TOut2,
23
+ TOut3,
24
+ TOut4,
25
+ TOut5,
26
+ TOut6,
27
+ TOut7,
28
+ TOut8,
29
+ TOut9
30
+ ]>;
31
+ export declare function all<TInput, TOut1, TOut2, TOut3, TOut4, TOut5, TOut6, TOut7, TOut8, TOut9, TOut10>(a1: Pipeable<TInput, TOut1>, a2: Pipeable<TInput, TOut2>, a3: Pipeable<TInput, TOut3>, a4: Pipeable<TInput, TOut4>, a5: Pipeable<TInput, TOut5>, a6: Pipeable<TInput, TOut6>, a7: Pipeable<TInput, TOut7>, a8: Pipeable<TInput, TOut8>, a9: Pipeable<TInput, TOut9>, a10: Pipeable<TInput, TOut10>): TypedAction<TInput, [
32
+ TOut1,
33
+ TOut2,
34
+ TOut3,
35
+ TOut4,
36
+ TOut5,
37
+ TOut6,
38
+ TOut7,
39
+ TOut8,
40
+ TOut9,
41
+ TOut10
42
+ ]>;
package/dist/ast.d.ts CHANGED
@@ -60,22 +60,16 @@ export type BuiltinKind = {
60
60
  kind: "Identity";
61
61
  } | {
62
62
  kind: "Drop";
63
- } | {
64
- kind: "Tag";
65
- value: string;
66
63
  } | {
67
64
  kind: "Merge";
68
65
  } | {
69
66
  kind: "Flatten";
70
67
  } | {
71
68
  kind: "GetField";
72
- value: string;
69
+ field: string;
73
70
  } | {
74
71
  kind: "GetIndex";
75
- value: number;
76
- } | {
77
- kind: "Pick";
78
- value: string[];
72
+ index: number;
79
73
  } | {
80
74
  kind: "CollectSome";
81
75
  } | {
@@ -84,10 +78,10 @@ export type BuiltinKind = {
84
78
  kind: "SplitLast";
85
79
  } | {
86
80
  kind: "WrapInField";
87
- value: string;
81
+ field: string;
88
82
  } | {
89
83
  kind: "Sleep";
90
- value: number;
84
+ ms: number;
91
85
  };
92
86
  /**
93
87
  * When TIn is `never` (handler ignores input), produce `any` so the
@@ -112,54 +106,51 @@ export type MergeTuple<TTuple> = TTuple extends unknown[] ? UnionToIntersection<
112
106
  * Data crosses serialization boundaries to handlers in arbitrary languages
113
107
  * (Rust, Python, etc.), so extra/missing fields are runtime errors.
114
108
  */
115
- export type TypedAction<In = unknown, Out = unknown, Refs extends string = never> = Action & {
109
+ export type TypedAction<In = unknown, Out = unknown> = Action & {
116
110
  __in?: (input: In) => void;
117
111
  __in_co?: In;
118
112
  __out?: () => Out;
119
113
  __out_contra?: (output: Out) => void;
120
- __refs?: {
121
- _brand: Refs;
122
- };
123
114
  /** Chain this action with another. `a.then(b)` ≡ `chain(a, b)`. */
124
- then<TNext>(next: Pipeable<Out, TNext>): TypedAction<In, TNext, Refs>;
115
+ then<TNext>(next: Pipeable<Out, TNext>): TypedAction<In, TNext>;
125
116
  /** Apply an action to each element of an array output. `a.forEach(b)` ≡ `a.then(forEach(b))`. */
126
- forEach<TIn, TElement, TNext, TRefs extends string>(this: TypedAction<TIn, TElement[], TRefs>, action: Pipeable<TElement, TNext>): TypedAction<TIn, TNext[], TRefs>;
117
+ forEach<TIn, TElement, TNext>(this: TypedAction<TIn, TElement[]>, action: Pipeable<TElement, TNext>): TypedAction<TIn, TNext[]>;
127
118
  /** Dispatch on a tagged union output. Auto-unwraps `value` before each case handler. */
128
119
  branch<TCases extends {
129
120
  [K in BranchKeys<Out>]: CaseHandler<BranchPayload<Out, K>, unknown>;
130
- }>(cases: [BranchKeys<Out>] extends [never] ? never : TCases): TypedAction<In, ExtractOutput<TCases[keyof TCases & string]>, Refs>;
121
+ }>(cases: [BranchKeys<Out>] extends [never] ? never : TCases): TypedAction<In, ExtractOutput<TCases[keyof TCases & string]>>;
131
122
  /** Flatten a nested array output. `a.flatten()` ≡ `pipe(a, flatten())`. */
132
- flatten(): TypedAction<In, Out extends (infer TElement)[][] ? TElement[] : Out, Refs>;
123
+ flatten(): TypedAction<In, Out extends (infer TElement)[][] ? TElement[] : Out>;
133
124
  /** Discard output. `a.drop()` ≡ `pipe(a, drop)`. */
134
- drop(): TypedAction<In, never, Refs>;
125
+ drop(): TypedAction<In, never>;
135
126
  /** Wrap output as a tagged union member. Requires full variant map TDef so __def is carried. */
136
- tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>, Refs>;
127
+ tag<TDef extends Record<string, unknown>, TKind extends keyof TDef & string>(kind: TKind): TypedAction<In, TaggedUnion<TDef>>;
137
128
  /** 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>;
129
+ getField<TField extends keyof Out & string>(field: TField): TypedAction<In, Out[TField]>;
139
130
  /** 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>;
131
+ getIndex<TIn, TTuple extends unknown[], TIndex extends number>(this: TypedAction<TIn, TTuple>, index: TIndex): TypedAction<TIn, TTuple[TIndex]>;
141
132
  /** Wrap output in an object under a field name. `a.wrapInField("foo")` ≡ `pipe(a, wrapInField("foo"))`. */
142
- wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>, Refs>;
133
+ wrapInField<TField extends string>(field: TField): TypedAction<In, Record<TField, Out>>;
143
134
  /** Merge a tuple of objects into a single object. `a.merge()` ≡ `pipe(a, merge())`. */
144
- merge(): TypedAction<In, MergeTuple<Out>, Refs>;
135
+ merge(): TypedAction<In, MergeTuple<Out>>;
145
136
  /** Select fields from the output. `a.pick("x", "y")` ≡ `pipe(a, pick("x", "y"))`. */
146
- pick<TKeys extends (keyof Out & string)[]>(...keys: TKeys): TypedAction<In, Pick<Out, TKeys[number]>, Refs>;
137
+ pick<TKeys extends (keyof Out & string)[]>(...keys: TKeys): TypedAction<In, Pick<Out, TKeys[number]>>;
147
138
  /** 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>;
139
+ splitFirst<TIn, TElement>(this: TypedAction<TIn, TElement[]>): TypedAction<TIn, Option<[TElement, TElement[]]>>;
149
140
  /** 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
+ splitLast<TIn, TElement>(this: TypedAction<TIn, TElement[]>): TypedAction<TIn, Option<[TElement[], TElement]>>;
151
142
  /**
152
143
  * Transform the Some value inside an Option output. Only callable when
153
144
  * Out is Option<T>. Uses `this` parameter constraint to gate availability.
154
145
  */
155
- mapOption<TIn, T, U, TRefs extends string>(this: TypedAction<TIn, Option<T>, TRefs>, action: Pipeable<T, U>): TypedAction<TIn, Option<U>, TRefs>;
146
+ mapOption<TIn, T, U>(this: TypedAction<TIn, Option<T>>, action: Pipeable<T, U>): TypedAction<TIn, Option<U>>;
156
147
  /**
157
148
  * Transform the Err value of a Result output.
158
149
  * `Result<TValue, TError> → Result<TValue, TErrorOut>`
159
150
  *
160
151
  * Only callable when Out is Result<TValue, TError>.
161
152
  */
162
- mapErr<TIn, TValue, TError, TErrorOut>(this: TypedAction<TIn, Result<TValue, TError>, any>, action: Pipeable<TError, TErrorOut>): TypedAction<TIn, Result<TValue, TErrorOut>, Refs>;
153
+ mapErr<TIn, TValue, TError, TErrorOut>(this: TypedAction<TIn, Result<TValue, TError>>, action: Pipeable<TError, TErrorOut>): TypedAction<TIn, Result<TValue, TErrorOut>>;
163
154
  /**
164
155
  * Unwrap a Result output. If Ok, pass through the value. If Err, apply
165
156
  * the default action. Only callable when Out is Result<TValue, TError>.
@@ -170,12 +161,8 @@ export type TypedAction<In = unknown, Out = unknown, Refs extends string = never
170
161
  *
171
162
  * Uses CaseHandler for defaultAction (covariant output only) so that
172
163
  * `TypedAction<TError, never>` is assignable to `CaseHandler<TError, TValue>`.
173
- *
174
- * Refs position uses `any` in the `this` constraint to avoid TS
175
- * falling back to the constraint bound `string` when Refs = never.
176
- * The return type uses the enclosing TypedAction's `Refs` directly.
177
164
  */
178
- unwrapOr<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>, any>, defaultAction: CaseHandler<TError, TValue>): TypedAction<TIn, TValue, Refs>;
165
+ unwrapOr<TIn, TValue, TError>(this: TypedAction<TIn, Result<TValue, TError>>, defaultAction: CaseHandler<TError, TValue>): TypedAction<TIn, TValue>;
179
166
  };
180
167
  /**
181
168
  * Parameter type for pipe and combinators. Contains the same phantom fields
@@ -231,6 +218,11 @@ type CaseHandler<TIn = unknown, TOut = unknown> = Action & {
231
218
  * field enables `.branch()` to decompose the union via simple indexing
232
219
  * (`keyof ExtractDef<Out>` and `ExtractDef<Out>[K]`) instead of
233
220
  * conditional types (`KindOf<Out>` and `Extract<Out, { kind: K }>`).
221
+ *
222
+ * **Void → null mapping:** Variants with `void` payload (e.g. `{ None: void }`)
223
+ * become `{ kind: "None"; value: null }` at runtime. This is handled by
224
+ * `VoidToNull` below — `void` has no runtime representation in JSON, so it
225
+ * serializes as `null`. Use `z.null()` in Zod schemas for void variants.
234
226
  */
235
227
  type VoidToNull<T> = 0 extends 1 & T ? T : [T] extends [never] ? never : [T] extends [void] ? null : T;
236
228
  export type TaggedUnion<TDef extends Record<string, unknown>> = {
@@ -279,12 +271,12 @@ type BranchPayload<Out, K extends string> = [ExtractDef<Out>] extends [never] ?
279
271
  * Attach `.then()` and `.forEach()` methods to a plain Action object.
280
272
  * Methods are non-enumerable: invisible to JSON.stringify and toEqual.
281
273
  */
282
- export declare function typedAction<In = unknown, Out = unknown, Refs extends string = never>(action: Action): TypedAction<In, Out, Refs>;
274
+ export declare function typedAction<In = unknown, Out = unknown>(action: Action): TypedAction<In, Out>;
283
275
  /**
284
276
  * Extract the input type from a TypedAction.
285
277
  *
286
278
  * Uses direct phantom field extraction (not full TypedAction matching) to
287
- * avoid the `TypedAction<any, any, any>` constraint which fails for In=never
279
+ * avoid a full `TypedAction<any, any>` constraint which fails for In=never
288
280
  * due to __in contravariance.
289
281
  */
290
282
  export type ExtractInput<T> = T extends {
@@ -332,8 +324,6 @@ type LoopResultDef<TContinue, TBreak> = {
332
324
  Break: TBreak;
333
325
  };
334
326
  export type LoopResult<TContinue, TBreak> = TaggedUnion<LoopResultDef<TContinue, TBreak>>;
335
- export declare const TAG_BREAK: Action;
336
- export declare const IDENTITY: Action;
337
327
  /**
338
328
  * Restartable scope. The body callback receives `restart`, a TypedAction that
339
329
  * re-executes the body from the beginning with a new input value.
package/dist/ast.js CHANGED
@@ -1,206 +1,56 @@
1
+ import { chain } from "./chain.js";
2
+ import { drop, flatten as flattenBuiltin, getField, getIndex, identity, merge, Option, pick, Result, splitFirst, splitLast, tag, wrapInField, } from "./builtins.js";
1
3
  // ---------------------------------------------------------------------------
2
4
  // typedAction — attach .then() and .forEach() as non-enumerable methods
3
5
  // ---------------------------------------------------------------------------
4
6
  // Shared implementations (one closure, not per-instance)
5
7
  function thenMethod(next) {
6
- return typedAction({ kind: "Chain", first: this, rest: next });
8
+ return chain(this, next);
7
9
  }
8
10
  function forEachMethod(action) {
9
- return typedAction({
10
- kind: "Chain",
11
- first: this,
12
- rest: { kind: "ForEach", action },
13
- });
11
+ return chain(this, forEach(action));
14
12
  }
15
13
  function branchMethod(cases) {
16
- return typedAction({
17
- kind: "Chain",
18
- first: this,
19
- rest: { kind: "Branch", cases: unwrapBranchCases(cases) },
20
- });
14
+ return chain(this, branch(cases));
21
15
  }
22
16
  function flattenMethod() {
23
- return typedAction({
24
- kind: "Chain",
25
- first: this,
26
- rest: {
27
- kind: "Invoke",
28
- handler: { kind: "Builtin", builtin: { kind: "Flatten" } },
29
- },
30
- });
17
+ return chain(this, flattenBuiltin());
31
18
  }
32
19
  function dropMethod() {
33
- return typedAction({
34
- kind: "Chain",
35
- first: this,
36
- rest: {
37
- kind: "Invoke",
38
- handler: { kind: "Builtin", builtin: { kind: "Drop" } },
39
- },
40
- });
20
+ return chain(this, drop);
41
21
  }
42
22
  function tagMethod(kind) {
43
- return typedAction({
44
- kind: "Chain",
45
- first: this,
46
- rest: {
47
- kind: "Invoke",
48
- handler: { kind: "Builtin", builtin: { kind: "Tag", value: kind } },
49
- },
50
- });
23
+ return chain(this, tag(kind));
51
24
  }
52
25
  function getFieldMethod(field) {
53
- return typedAction({
54
- kind: "Chain",
55
- first: this,
56
- rest: {
57
- kind: "Invoke",
58
- handler: {
59
- kind: "Builtin",
60
- builtin: { kind: "GetField", value: field },
61
- },
62
- },
63
- });
26
+ return chain(this, getField(field));
64
27
  }
65
28
  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 },
74
- },
75
- },
76
- });
29
+ return chain(this, getIndex(index));
77
30
  }
78
31
  function wrapInFieldMethod(field) {
79
- return typedAction({
80
- kind: "Chain",
81
- first: this,
82
- rest: {
83
- kind: "Invoke",
84
- handler: {
85
- kind: "Builtin",
86
- builtin: { kind: "WrapInField", value: field },
87
- },
88
- },
89
- });
32
+ return chain(this, wrapInField(field));
90
33
  }
91
34
  function mergeMethod() {
92
- return typedAction({
93
- kind: "Chain",
94
- first: this,
95
- rest: {
96
- kind: "Invoke",
97
- handler: { kind: "Builtin", builtin: { kind: "Merge" } },
98
- },
99
- });
35
+ return chain(this, merge());
100
36
  }
101
37
  function pickMethod(...keys) {
102
- return typedAction({
103
- kind: "Chain",
104
- first: this,
105
- rest: {
106
- kind: "Invoke",
107
- handler: { kind: "Builtin", builtin: { kind: "Pick", value: keys } },
108
- },
109
- });
38
+ return chain(this, pick(...keys));
110
39
  }
111
40
  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
- });
41
+ return chain(this, splitFirst());
120
42
  }
121
43
  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
- });
44
+ return chain(this, splitLast());
130
45
  }
131
46
  function mapOptionMethod(action) {
132
- // Desugars to: self.then(branch({ Some: pipe(action, tag("Some")), None: tag("None") }))
133
- // But branch auto-unwraps value, so:
134
- // Some case: receives T, runs action, wraps as Some
135
- // None case: receives void, wraps as None
136
- return typedAction({
137
- kind: "Chain",
138
- first: this,
139
- rest: {
140
- kind: "Branch",
141
- cases: unwrapBranchCases({
142
- Some: {
143
- kind: "Chain",
144
- first: action,
145
- rest: {
146
- kind: "Invoke",
147
- handler: {
148
- kind: "Builtin",
149
- builtin: { kind: "Tag", value: "Some" },
150
- },
151
- },
152
- },
153
- None: {
154
- kind: "Invoke",
155
- handler: { kind: "Builtin", builtin: { kind: "Tag", value: "None" } },
156
- },
157
- }),
158
- },
159
- });
47
+ return chain(this, Option.map(action));
160
48
  }
161
49
  function mapErrMethod(action) {
162
- // Desugars to: self.then(branch({ Ok: tag("Ok"), Err: pipe(action, tag("Err")) }))
163
- return typedAction({
164
- kind: "Chain",
165
- first: this,
166
- rest: {
167
- kind: "Branch",
168
- cases: unwrapBranchCases({
169
- Ok: {
170
- kind: "Invoke",
171
- handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Ok" } },
172
- },
173
- Err: {
174
- kind: "Chain",
175
- first: action,
176
- rest: {
177
- kind: "Invoke",
178
- handler: {
179
- kind: "Builtin",
180
- builtin: { kind: "Tag", value: "Err" },
181
- },
182
- },
183
- },
184
- }),
185
- },
186
- });
50
+ return chain(this, Result.mapErr(action));
187
51
  }
188
52
  function unwrapOrMethod(defaultAction) {
189
- // Desugars to: self.then(branch({ Ok: identity(), Err: defaultAction }))
190
- return typedAction({
191
- kind: "Chain",
192
- first: this,
193
- rest: {
194
- kind: "Branch",
195
- cases: unwrapBranchCases({
196
- Ok: {
197
- kind: "Invoke",
198
- handler: { kind: "Builtin", builtin: { kind: "Identity" } },
199
- },
200
- Err: defaultAction,
201
- }),
202
- },
203
- });
53
+ return chain(this, Result.unwrapOr(defaultAction));
204
54
  }
205
55
  /**
206
56
  * Attach `.then()` and `.forEach()` methods to a plain Action object.
@@ -253,17 +103,7 @@ export function forEach(action) {
253
103
  function unwrapBranchCases(cases) {
254
104
  const unwrapped = {};
255
105
  for (const key of Object.keys(cases)) {
256
- unwrapped[key] = {
257
- kind: "Chain",
258
- first: {
259
- kind: "Invoke",
260
- handler: {
261
- kind: "Builtin",
262
- builtin: { kind: "GetField", value: "value" },
263
- },
264
- },
265
- rest: cases[key],
266
- };
106
+ unwrapped[key] = chain(getField("value"), cases[key]);
267
107
  }
268
108
  return unwrapped;
269
109
  }
@@ -272,25 +112,6 @@ export function branch(cases) {
272
112
  return typedAction({ kind: "Branch", cases: unwrapBranchCases(cases) });
273
113
  }
274
114
  // ---------------------------------------------------------------------------
275
- // Shared AST constants for control flow compilation
276
- // ---------------------------------------------------------------------------
277
- const EXTRACT_PAYLOAD = {
278
- kind: "Invoke",
279
- handler: { kind: "Builtin", builtin: { kind: "GetIndex", value: 0 } },
280
- };
281
- const TAG_CONTINUE = {
282
- kind: "Invoke",
283
- handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Continue" } },
284
- };
285
- export const TAG_BREAK = {
286
- kind: "Invoke",
287
- handler: { kind: "Builtin", builtin: { kind: "Tag", value: "Break" } },
288
- };
289
- export const IDENTITY = {
290
- kind: "Invoke",
291
- handler: { kind: "Builtin", builtin: { kind: "Identity" } },
292
- };
293
- // ---------------------------------------------------------------------------
294
115
  // recur — restart body primitive
295
116
  // ---------------------------------------------------------------------------
296
117
  /**
@@ -313,7 +134,7 @@ export function recur(bodyFn) {
313
134
  kind: "RestartHandle",
314
135
  restart_handler_id: restartHandlerId,
315
136
  body,
316
- handler: EXTRACT_PAYLOAD,
137
+ handler: getIndex(0),
317
138
  });
318
139
  }
319
140
  // ---------------------------------------------------------------------------
@@ -333,13 +154,12 @@ export function recur(bodyFn) {
333
154
  */
334
155
  export function earlyReturn(bodyFn) {
335
156
  const restartHandlerId = allocateRestartHandlerId();
336
- const earlyReturnAction = typedAction({
337
- kind: "Chain",
338
- first: TAG_BREAK,
339
- rest: { kind: "RestartPerform", restart_handler_id: restartHandlerId },
340
- });
157
+ const earlyReturnAction = typedAction(chain(tag("Break"), {
158
+ kind: "RestartPerform",
159
+ restart_handler_id: restartHandlerId,
160
+ }));
341
161
  const body = bodyFn(earlyReturnAction);
342
- return typedAction(buildRestartBranchAction(restartHandlerId, body, IDENTITY));
162
+ return typedAction(buildRestartBranchAction(restartHandlerId, body, identity()));
343
163
  }
344
164
  // ---------------------------------------------------------------------------
345
165
  // loop — iterative restart with break
@@ -354,22 +174,12 @@ export function earlyReturn(bodyFn) {
354
174
  * Used by earlyReturn, loop, tryCatch, and race.
355
175
  */
356
176
  export function buildRestartBranchAction(restartHandlerId, continueArm, breakArm) {
357
- return {
358
- kind: "Chain",
359
- first: TAG_CONTINUE,
360
- rest: {
361
- kind: "RestartHandle",
362
- restart_handler_id: restartHandlerId,
363
- body: {
364
- kind: "Branch",
365
- cases: unwrapBranchCases({
366
- Continue: continueArm,
367
- Break: breakArm,
368
- }),
369
- },
370
- handler: EXTRACT_PAYLOAD,
371
- },
372
- };
177
+ return chain(tag("Continue"), {
178
+ kind: "RestartHandle",
179
+ restart_handler_id: restartHandlerId,
180
+ body: branch({ Continue: continueArm, Break: breakArm }),
181
+ handler: getIndex(0),
182
+ });
373
183
  }
374
184
  /**
375
185
  * Iterative loop. The body callback receives `recur` and `done`:
@@ -386,18 +196,10 @@ export function loop(bodyFn) {
386
196
  kind: "RestartPerform",
387
197
  restart_handler_id: restartHandlerId,
388
198
  };
389
- const recurAction = typedAction({
390
- kind: "Chain",
391
- first: TAG_CONTINUE,
392
- rest: perform,
393
- });
394
- const doneAction = typedAction({
395
- kind: "Chain",
396
- first: TAG_BREAK,
397
- rest: perform,
398
- });
199
+ const recurAction = typedAction(chain(tag("Continue"), perform));
200
+ const doneAction = typedAction(chain(tag("Break"), perform));
399
201
  const body = bodyFn(recurAction, doneAction);
400
- return typedAction(buildRestartBranchAction(restartHandlerId, body, IDENTITY));
202
+ return typedAction(buildRestartBranchAction(restartHandlerId, body, identity()));
401
203
  }
402
204
  // ---------------------------------------------------------------------------
403
205
  // Config builders
package/dist/bind.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import { typedAction, } from "./ast.js";
2
- import { identity, drop } from "./builtins.js";
2
+ import { chain } from "./chain.js";
3
+ import { all } from "./all.js";
4
+ import { identity, drop, getIndex } from "./builtins.js";
3
5
  import { allocateResumeHandlerId } from "./effect-id.js";
4
6
  import { pipe } from "./pipe.js";
5
7
  function createVarRef(resumeHandlerId) {
@@ -21,35 +23,7 @@ function createVarRef(resumeHandlerId) {
21
23
  * Expanded AST: All(Chain(GetIndex(1), GetIndex(n)), GetIndex(1))
22
24
  */
23
25
  function readVar(n) {
24
- return {
25
- kind: "All",
26
- actions: [
27
- {
28
- kind: "Chain",
29
- first: {
30
- kind: "Invoke",
31
- handler: {
32
- kind: "Builtin",
33
- builtin: { kind: "GetIndex", value: 1 },
34
- },
35
- },
36
- rest: {
37
- kind: "Invoke",
38
- handler: {
39
- kind: "Builtin",
40
- builtin: { kind: "GetIndex", value: n },
41
- },
42
- },
43
- },
44
- {
45
- kind: "Invoke",
46
- handler: {
47
- kind: "Builtin",
48
- builtin: { kind: "GetIndex", value: 1 },
49
- },
50
- },
51
- ],
52
- };
26
+ return all(chain(getIndex(1), getIndex(n)), getIndex(1));
53
27
  }
54
28
  export function bind(bindings, body) {
55
29
  // 1. Gensym one resumeHandlerId per binding.
@@ -61,17 +35,7 @@ export function bind(bindings, body) {
61
35
  // 4. Build nested Handles from inside out.
62
36
  // Innermost: extract pipeline_input (last All element) → user body
63
37
  const pipelineInputIndex = bindings.length;
64
- let inner = {
65
- kind: "Chain",
66
- first: {
67
- kind: "Invoke",
68
- handler: {
69
- kind: "Builtin",
70
- builtin: { kind: "GetIndex", value: pipelineInputIndex },
71
- },
72
- },
73
- rest: bodyAction,
74
- };
38
+ let inner = chain(getIndex(pipelineInputIndex), bodyAction);
75
39
  for (let i = resumeHandlerIds.length - 1; i >= 0; i--) {
76
40
  inner = {
77
41
  kind: "ResumeHandle",
@@ -81,15 +45,11 @@ export function bind(bindings, body) {
81
45
  };
82
46
  }
83
47
  // 5. All(...bindings, identity()) → nested Handles
84
- const allActions = [
85
- ...bindings.map((b) => b),
86
- identity(),
87
- ];
88
- return typedAction({
89
- kind: "Chain",
90
- first: { kind: "All", actions: allActions },
91
- rest: inner,
92
- });
48
+ const allAction = {
49
+ kind: "All",
50
+ actions: [...bindings.map((b) => b), identity()],
51
+ };
52
+ return typedAction(chain(allAction, inner));
93
53
  }
94
54
  // ---------------------------------------------------------------------------
95
55
  // bindInput — bind the pipeline input