@barnum/barnum 0.0.0-main-54c41bbb → 0.0.0-main-57736a4e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/artifacts/linux-arm64/barnum +0 -0
  2. package/artifacts/linux-x64/barnum +0 -0
  3. package/artifacts/macos-arm64/barnum +0 -0
  4. package/artifacts/macos-x64/barnum +0 -0
  5. package/artifacts/win-x64/barnum.exe +0 -0
  6. package/dist/all.d.ts +1 -0
  7. package/dist/all.d.ts.map +1 -0
  8. package/dist/all.js +1 -1
  9. package/dist/ast.d.ts +148 -61
  10. package/dist/ast.d.ts.map +1 -0
  11. package/dist/ast.js +225 -42
  12. package/dist/bind.d.ts +7 -10
  13. package/dist/bind.d.ts.map +1 -0
  14. package/dist/bind.js +8 -8
  15. package/dist/builtins/array.d.ts +28 -0
  16. package/dist/builtins/array.d.ts.map +1 -0
  17. package/dist/builtins/array.js +74 -0
  18. package/dist/builtins/index.d.ts +6 -0
  19. package/dist/builtins/index.d.ts.map +1 -0
  20. package/dist/builtins/index.js +5 -0
  21. package/dist/builtins/scalar.d.ts +12 -0
  22. package/dist/builtins/scalar.d.ts.map +1 -0
  23. package/dist/builtins/scalar.js +41 -0
  24. package/dist/builtins/struct.d.ts +25 -0
  25. package/dist/builtins/struct.d.ts.map +1 -0
  26. package/dist/builtins/struct.js +67 -0
  27. package/dist/builtins/tagged-union.d.ts +54 -0
  28. package/dist/builtins/tagged-union.d.ts.map +1 -0
  29. package/dist/builtins/tagged-union.js +81 -0
  30. package/dist/builtins/with-resource.d.ts +23 -0
  31. package/dist/builtins/with-resource.d.ts.map +1 -0
  32. package/dist/builtins/with-resource.js +35 -0
  33. package/dist/chain.d.ts +1 -0
  34. package/dist/chain.d.ts.map +1 -0
  35. package/dist/chain.js +3 -3
  36. package/dist/effect-id.d.ts +1 -0
  37. package/dist/effect-id.d.ts.map +1 -0
  38. package/dist/handler.d.ts +7 -6
  39. package/dist/handler.d.ts.map +1 -0
  40. package/dist/handler.js +3 -3
  41. package/dist/index.d.ts +9 -5
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +4 -2
  44. package/dist/iterator.d.ts +18 -0
  45. package/dist/iterator.d.ts.map +1 -0
  46. package/dist/iterator.js +71 -0
  47. package/dist/option.d.ts +74 -0
  48. package/dist/option.d.ts.map +1 -0
  49. package/dist/option.js +141 -0
  50. package/dist/pipe.d.ts +2 -1
  51. package/dist/pipe.d.ts.map +1 -0
  52. package/dist/pipe.js +3 -2
  53. package/dist/race.d.ts +4 -3
  54. package/dist/race.d.ts.map +1 -0
  55. package/dist/race.js +10 -9
  56. package/dist/recursive.d.ts +9 -3
  57. package/dist/recursive.d.ts.map +1 -0
  58. package/dist/recursive.js +16 -10
  59. package/dist/result.d.ts +50 -0
  60. package/dist/result.d.ts.map +1 -0
  61. package/dist/result.js +117 -0
  62. package/dist/run.d.ts +2 -1
  63. package/dist/run.d.ts.map +1 -0
  64. package/dist/run.js +9 -5
  65. package/dist/runtime.d.ts +6 -0
  66. package/dist/runtime.d.ts.map +1 -0
  67. package/dist/runtime.js +7 -0
  68. package/dist/schema.d.ts +1 -0
  69. package/dist/schema.d.ts.map +1 -0
  70. package/dist/schemas.d.ts +5 -0
  71. package/dist/schemas.d.ts.map +1 -0
  72. package/dist/schemas.js +13 -0
  73. package/dist/try-catch.d.ts +1 -0
  74. package/dist/try-catch.d.ts.map +1 -0
  75. package/dist/try-catch.js +6 -6
  76. package/dist/values.d.ts +6 -0
  77. package/dist/values.d.ts.map +1 -0
  78. package/dist/values.js +12 -0
  79. package/dist/worker.d.ts +1 -0
  80. package/dist/worker.d.ts.map +1 -0
  81. package/package.json +7 -3
  82. package/src/all.ts +1 -1
  83. package/src/ast.ts +608 -132
  84. package/src/bind.ts +24 -23
  85. package/src/builtins/array.ts +96 -0
  86. package/src/builtins/index.ts +10 -0
  87. package/src/builtins/scalar.ts +49 -0
  88. package/src/builtins/struct.ts +111 -0
  89. package/src/builtins/tagged-union.ts +142 -0
  90. package/src/builtins/with-resource.ts +69 -0
  91. package/src/chain.ts +4 -4
  92. package/src/handler.ts +10 -13
  93. package/src/index.ts +18 -15
  94. package/src/iterator.ts +125 -0
  95. package/src/option.ts +199 -0
  96. package/src/pipe.ts +10 -4
  97. package/src/race.ts +32 -22
  98. package/src/recursive.ts +46 -22
  99. package/src/result.ts +168 -0
  100. package/src/run.ts +14 -6
  101. package/src/runtime.ts +16 -0
  102. package/src/schemas.ts +21 -0
  103. package/src/try-catch.ts +8 -9
  104. package/src/values.ts +21 -0
  105. package/dist/builtins.d.ts +0 -229
  106. package/dist/builtins.js +0 -486
  107. package/src/builtins.ts +0 -703
package/dist/ast.js CHANGED
@@ -1,5 +1,23 @@
1
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";
2
+ import { constant, drop, extractPrefix, flatten as flattenBuiltin, getField, getIndex, identity, panic, pick, splitFirst, splitLast, tag, wrapInField, asOption as asOptionStandalone, } from "./builtins/index.js";
3
+ import { Option } from "./option.js";
4
+ import { Result } from "./result.js";
5
+ // Lazy import — iterator.ts imports from ast.ts, but these are only called inside
6
+ // methods (after all modules load), so the circular reference is safe at runtime.
7
+ import { Iterator as IteratorNs } from "./iterator.js";
8
+ // Lazy import — bind.ts imports from ast.ts, but these are only called inside
9
+ // methods (after all modules load), so the circular reference is safe at runtime.
10
+ import { bind as bindStandalone, bindInput as bindInputStandalone, } from "./bind.js";
11
+ /**
12
+ * Strip phantom types from a Pipeable, returning a plain Action.
13
+ *
14
+ * Replaces `x as Action` casts throughout the codebase. The constraint
15
+ * ensures the argument is structurally a Pipeable — unlike a bare cast,
16
+ * `toAction(123)` is a type error.
17
+ */
18
+ export function toAction(pipeable) {
19
+ return pipeable;
20
+ }
3
21
  // ---------------------------------------------------------------------------
4
22
  // typedAction — attach .then() and .forEach() as non-enumerable methods
5
23
  // ---------------------------------------------------------------------------
@@ -7,50 +25,182 @@ import { drop, flatten as flattenBuiltin, getField, getIndex, identity, merge, O
7
25
  function thenMethod(next) {
8
26
  return chain(this, next);
9
27
  }
10
- function forEachMethod(action) {
11
- return chain(this, forEach(action));
12
- }
13
28
  function branchMethod(cases) {
14
- return chain(this, branch(cases));
29
+ return chain(toAction(this), toAction(branch(cases)));
15
30
  }
16
31
  function flattenMethod() {
17
- return chain(this, flattenBuiltin());
32
+ return chain(toAction(this), toAction(flattenBuiltin()));
18
33
  }
19
34
  function dropMethod() {
20
- return chain(this, drop);
35
+ return chain(toAction(this), toAction(drop));
21
36
  }
22
- function tagMethod(kind) {
23
- return chain(this, tag(kind));
37
+ function tagMethod(kind, enumName) {
38
+ return chain(toAction(this), toAction(tag(kind, enumName)));
39
+ }
40
+ function someMethod() {
41
+ return chain(toAction(this), toAction(Option.some()));
42
+ }
43
+ function okMethod() {
44
+ return chain(toAction(this), toAction(Result.ok()));
45
+ }
46
+ function errMethod() {
47
+ return chain(toAction(this), toAction(Result.err()));
24
48
  }
25
49
  function getFieldMethod(field) {
26
- return chain(this, getField(field));
50
+ return chain(toAction(this), toAction(getField(field)));
27
51
  }
28
52
  function getIndexMethod(index) {
29
- return chain(this, getIndex(index));
53
+ return chain(toAction(this), toAction(getIndex(index)));
30
54
  }
31
55
  function wrapInFieldMethod(field) {
32
- return chain(this, wrapInField(field));
33
- }
34
- function mergeMethod() {
35
- return chain(this, merge());
56
+ return chain(toAction(this), toAction(wrapInField(field)));
36
57
  }
37
58
  function pickMethod(...keys) {
38
- return chain(this, pick(...keys));
59
+ return chain(toAction(this), toAction(pick(...keys)));
39
60
  }
40
61
  function splitFirstMethod() {
41
- return chain(this, splitFirst());
62
+ return chain(toAction(this), toAction(splitFirst()));
42
63
  }
43
64
  function splitLastMethod() {
44
- return chain(this, splitLast());
65
+ return chain(toAction(this), toAction(splitLast()));
45
66
  }
46
- function mapOptionMethod(action) {
47
- return chain(this, Option.map(action));
67
+ // --- Shared postfix methods (Option + Result) — dispatch via branchFamily ---
68
+ function mapMethod(action) {
69
+ return chain(toAction(this), toAction(branchFamily({
70
+ Result: branch({
71
+ Ok: chain(toAction(action), toAction(Result.ok())),
72
+ Err: Result.err(),
73
+ }),
74
+ Option: branch({
75
+ Some: chain(toAction(action), toAction(Option.some())),
76
+ None: Option.none(),
77
+ }),
78
+ Iterator: IteratorNs.map(action),
79
+ })));
48
80
  }
49
- function mapErrMethod(action) {
50
- return chain(this, Result.mapErr(action));
81
+ function unwrapMethod() {
82
+ return chain(toAction(this), toAction(branchFamily({
83
+ Result: branch({ Ok: identity(), Err: panic("called unwrap on Err") }),
84
+ Option: branch({
85
+ Some: identity(),
86
+ None: panic("called unwrap on None"),
87
+ }),
88
+ })));
51
89
  }
52
90
  function unwrapOrMethod(defaultAction) {
53
- return chain(this, Result.unwrapOr(defaultAction));
91
+ return chain(toAction(this), toAction(branchFamily({
92
+ Result: branch({ Ok: identity(), Err: defaultAction }),
93
+ Option: branch({ Some: identity(), None: defaultAction }),
94
+ })));
95
+ }
96
+ function andThenMethod(action) {
97
+ return chain(toAction(this), toAction(branchFamily({
98
+ Result: branch({ Ok: action, Err: Result.err() }),
99
+ Option: branch({ Some: action, None: Option.none() }),
100
+ })));
101
+ }
102
+ function transposeMethod() {
103
+ return chain(toAction(this), toAction(branchFamily({
104
+ Option: branch({
105
+ Some: branch({
106
+ Ok: chain(toAction(Option.some()), toAction(Result.ok())),
107
+ Err: Result.err(),
108
+ }),
109
+ None: chain(toAction(chain(toAction(drop), toAction(Option.none()))), toAction(Result.ok())),
110
+ }),
111
+ Result: branch({
112
+ Ok: branch({
113
+ Some: chain(toAction(Result.ok()), toAction(Option.some())),
114
+ None: chain(toAction(drop), toAction(Option.none())),
115
+ }),
116
+ Err: chain(toAction(Result.err()), toAction(Option.some())),
117
+ }),
118
+ })));
119
+ }
120
+ // --- Result-only postfix methods ---
121
+ function mapErrMethod(action) {
122
+ return chain(toAction(this), toAction(branch({
123
+ Ok: Result.ok(),
124
+ Err: chain(toAction(action), toAction(Result.err())),
125
+ })));
126
+ }
127
+ function orMethod(fallback) {
128
+ return chain(toAction(this), toAction(branch({
129
+ Ok: Result.ok(),
130
+ Err: fallback,
131
+ })));
132
+ }
133
+ function asOkOptionMethod() {
134
+ return chain(toAction(this), toAction(branch({
135
+ Ok: Option.some(),
136
+ Err: chain(toAction(drop), toAction(Option.none())),
137
+ })));
138
+ }
139
+ function asErrOptionMethod() {
140
+ return chain(toAction(this), toAction(branch({
141
+ Ok: chain(toAction(drop), toAction(Option.none())),
142
+ Err: Option.some(),
143
+ })));
144
+ }
145
+ function isOkMethod() {
146
+ return chain(toAction(this), toAction(branch({
147
+ Ok: constant(true),
148
+ Err: constant(false),
149
+ })));
150
+ }
151
+ function isErrMethod() {
152
+ return chain(toAction(this), toAction(branch({
153
+ Ok: constant(false),
154
+ Err: constant(true),
155
+ })));
156
+ }
157
+ // --- Option-only postfix methods ---
158
+ function filterMethod(predicate) {
159
+ return chain(toAction(this), toAction(branchFamily({
160
+ Option: branch({
161
+ Some: predicate,
162
+ None: Option.none(),
163
+ }),
164
+ Iterator: IteratorNs.filter(predicate),
165
+ })));
166
+ }
167
+ function isSomeMethod() {
168
+ return chain(toAction(this), toAction(branch({
169
+ Some: constant(true),
170
+ None: constant(false),
171
+ })));
172
+ }
173
+ function isNoneMethod() {
174
+ return chain(toAction(this), toAction(branch({
175
+ Some: constant(false),
176
+ None: constant(true),
177
+ })));
178
+ }
179
+ function asOptionMethod() {
180
+ return chain(toAction(this), toAction(asOptionStandalone()));
181
+ }
182
+ // --- Iterator postfix methods ---
183
+ function iterateMethod() {
184
+ return chain(toAction(this), toAction(branchFamily({
185
+ Option: IteratorNs.fromOption(),
186
+ Result: IteratorNs.fromResult(),
187
+ Array: IteratorNs.fromArray(),
188
+ })));
189
+ }
190
+ function flatMapMethod(action) {
191
+ return chain(toAction(this), toAction(IteratorNs.flatMap(action)));
192
+ }
193
+ function collectMethod() {
194
+ return chain(toAction(this), toAction(branchFamily({
195
+ Array: Option.collect(),
196
+ Iterator: IteratorNs.collect(),
197
+ })));
198
+ }
199
+ function bindMethod(bindings, body) {
200
+ return chain(toAction(this), toAction(bindStandalone(bindings, body)));
201
+ }
202
+ function bindInputMethod(body) {
203
+ return chain(toAction(this), toAction(bindInputStandalone(body)));
54
204
  }
55
205
  /**
56
206
  * Attach `.then()` and `.forEach()` methods to a plain Action object.
@@ -60,21 +210,39 @@ export function typedAction(action) {
60
210
  if (!("then" in action)) {
61
211
  Object.defineProperties(action, {
62
212
  then: { value: thenMethod, configurable: true },
63
- forEach: { value: forEachMethod, configurable: true },
64
213
  branch: { value: branchMethod, configurable: true },
65
214
  flatten: { value: flattenMethod, configurable: true },
66
215
  drop: { value: dropMethod, configurable: true },
67
216
  tag: { value: tagMethod, configurable: true },
217
+ some: { value: someMethod, configurable: true },
218
+ ok: { value: okMethod, configurable: true },
219
+ err: { value: errMethod, configurable: true },
68
220
  getField: { value: getFieldMethod, configurable: true },
69
221
  getIndex: { value: getIndexMethod, configurable: true },
70
222
  wrapInField: { value: wrapInFieldMethod, configurable: true },
71
- merge: { value: mergeMethod, configurable: true },
72
223
  pick: { value: pickMethod, configurable: true },
73
224
  splitFirst: { value: splitFirstMethod, configurable: true },
74
225
  splitLast: { value: splitLastMethod, configurable: true },
75
- mapOption: { value: mapOptionMethod, configurable: true },
226
+ map: { value: mapMethod, configurable: true },
76
227
  mapErr: { value: mapErrMethod, configurable: true },
228
+ unwrap: { value: unwrapMethod, configurable: true },
77
229
  unwrapOr: { value: unwrapOrMethod, configurable: true },
230
+ andThen: { value: andThenMethod, configurable: true },
231
+ filter: { value: filterMethod, configurable: true },
232
+ isSome: { value: isSomeMethod, configurable: true },
233
+ isNone: { value: isNoneMethod, configurable: true },
234
+ asOption: { value: asOptionMethod, configurable: true },
235
+ collect: { value: collectMethod, configurable: true },
236
+ or: { value: orMethod, configurable: true },
237
+ iterate: { value: iterateMethod, configurable: true },
238
+ flatMap: { value: flatMapMethod, configurable: true },
239
+ asOkOption: { value: asOkOptionMethod, configurable: true },
240
+ asErrOption: { value: asErrOptionMethod, configurable: true },
241
+ isOk: { value: isOkMethod, configurable: true },
242
+ isErr: { value: isErrMethod, configurable: true },
243
+ transpose: { value: transposeMethod, configurable: true },
244
+ bind: { value: bindMethod, configurable: true },
245
+ bindInput: { value: bindInputMethod, configurable: true },
78
246
  });
79
247
  }
80
248
  return action;
@@ -92,7 +260,7 @@ import { allocateRestartHandlerId, } from "./effect-id.js";
92
260
  export { tryCatch } from "./try-catch.js";
93
261
  export { race, sleep, withTimeout } from "./race.js";
94
262
  export function forEach(action) {
95
- return typedAction({ kind: "ForEach", action: action });
263
+ return typedAction({ kind: "ForEach", action: toAction(action) });
96
264
  }
97
265
  /**
98
266
  * Insert GetField("value") before each case handler in a branch.
@@ -103,7 +271,7 @@ export function forEach(action) {
103
271
  function unwrapBranchCases(cases) {
104
272
  const unwrapped = {};
105
273
  for (const key of Object.keys(cases)) {
106
- unwrapped[key] = chain(getField("value"), cases[key]);
274
+ unwrapped[key] = toAction(chain(toAction(getField("value")), toAction(cases[key])));
107
275
  }
108
276
  return unwrapped;
109
277
  }
@@ -111,6 +279,21 @@ function unwrapBranchCases(cases) {
111
279
  export function branch(cases) {
112
280
  return typedAction({ kind: "Branch", cases: unwrapBranchCases(cases) });
113
281
  }
282
+ /**
283
+ * Two-level dispatch: extract the enum prefix from a tagged value's `kind`,
284
+ * then branch on that prefix. Used by postfix methods (`.map()`, `.unwrapOr()`,
285
+ * etc.) to dispatch across union families (Option, Result) without runtime
286
+ * metadata.
287
+ *
288
+ * `branchFamily({ Result: ..., Option: ... })` ≡ `chain(extractPrefix(), branch(cases))`
289
+ */
290
+ export function branchFamily(cases) {
291
+ return typedAction({
292
+ kind: "Chain",
293
+ first: toAction(extractPrefix()),
294
+ rest: toAction(branch(cases)),
295
+ });
296
+ }
114
297
  // ---------------------------------------------------------------------------
115
298
  // recur — restart body primitive
116
299
  // ---------------------------------------------------------------------------
@@ -129,12 +312,12 @@ export function recur(bodyFn) {
129
312
  kind: "RestartPerform",
130
313
  restart_handler_id: restartHandlerId,
131
314
  });
132
- const body = bodyFn(restartAction);
315
+ const body = toAction(bodyFn(restartAction));
133
316
  return typedAction({
134
317
  kind: "RestartHandle",
135
318
  restart_handler_id: restartHandlerId,
136
319
  body,
137
- handler: getIndex(0),
320
+ handler: toAction(getIndex(0).unwrap()),
138
321
  });
139
322
  }
140
323
  // ---------------------------------------------------------------------------
@@ -154,12 +337,12 @@ export function recur(bodyFn) {
154
337
  */
155
338
  export function earlyReturn(bodyFn) {
156
339
  const restartHandlerId = allocateRestartHandlerId();
157
- const earlyReturnAction = typedAction(chain(tag("Break"), {
340
+ const earlyReturnAction = typedAction(toAction(chain(toAction(tag("Break", "LoopResult")), {
158
341
  kind: "RestartPerform",
159
342
  restart_handler_id: restartHandlerId,
160
- }));
161
- const body = bodyFn(earlyReturnAction);
162
- return typedAction(buildRestartBranchAction(restartHandlerId, body, identity()));
343
+ })));
344
+ const body = toAction(bodyFn(earlyReturnAction));
345
+ return typedAction(buildRestartBranchAction(restartHandlerId, body, toAction(identity())));
163
346
  }
164
347
  // ---------------------------------------------------------------------------
165
348
  // loop — iterative restart with break
@@ -174,12 +357,12 @@ export function earlyReturn(bodyFn) {
174
357
  * Used by earlyReturn, loop, tryCatch, and race.
175
358
  */
176
359
  export function buildRestartBranchAction(restartHandlerId, continueArm, breakArm) {
177
- return chain(tag("Continue"), {
360
+ return toAction(chain(toAction(tag("Continue", "LoopResult")), {
178
361
  kind: "RestartHandle",
179
362
  restart_handler_id: restartHandlerId,
180
- body: branch({ Continue: continueArm, Break: breakArm }),
181
- handler: getIndex(0),
182
- });
363
+ body: toAction(branch({ Continue: continueArm, Break: breakArm })),
364
+ handler: toAction(getIndex(0).unwrap()),
365
+ }));
183
366
  }
184
367
  /**
185
368
  * Iterative loop. The body callback receives `recur` and `done`:
@@ -196,10 +379,10 @@ export function loop(bodyFn) {
196
379
  kind: "RestartPerform",
197
380
  restart_handler_id: restartHandlerId,
198
381
  };
199
- const recurAction = typedAction(chain(tag("Continue"), perform));
200
- const doneAction = typedAction(chain(tag("Break"), perform));
201
- const body = bodyFn(recurAction, doneAction);
202
- return typedAction(buildRestartBranchAction(restartHandlerId, body, identity()));
382
+ const recurAction = typedAction(toAction(chain(toAction(tag("Continue", "LoopResult")), toAction(perform))));
383
+ const doneAction = typedAction(toAction(chain(toAction(tag("Break", "LoopResult")), toAction(perform))));
384
+ const body = toAction(bodyFn(recurAction, doneAction));
385
+ return typedAction(buildRestartBranchAction(restartHandlerId, body, toAction(identity())));
203
386
  }
204
387
  // ---------------------------------------------------------------------------
205
388
  // Config builders
package/dist/bind.d.ts CHANGED
@@ -6,17 +6,14 @@ import { type Action, type ExtractInput, type ExtractOutput, type TypedAction }
6
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
- export type VarRef<TValue> = TypedAction<never, TValue>;
9
+ export type VarRef<TValue> = TypedAction<any, TValue>;
10
10
  /**
11
11
  * Maps each binding's output type to a VarRef. TypeScript resolves
12
12
  * ExtractOutput from each binding expression.
13
13
  *
14
- * Constraint is `Action[]` (not `Pipeable<any, any>[]`) because
15
- * `TypedAction<never, X>` (e.g. from `constant()`) fails the invariant
16
- * `__in` check against `Pipeable<any, any>` on the 9-variant
17
- * Action union. Using raw `Action[]` avoids the phantom field
18
- * assignability issue while `ExtractOutput` still extracts the correct
19
- * output type from the phantom fields on the concrete types.
14
+ * Constraint is `Action[]` (not `Pipeable<any, any>[]`) so that
15
+ * `ExtractOutput` extracts the correct output type from the phantom
16
+ * fields on the concrete types without fighting invariant `__in` checks.
20
17
  */
21
18
  export type InferVarRefs<TBindings extends Action[]> = {
22
19
  [K in keyof TBindings]: VarRef<ExtractOutput<TBindings[K]>>;
@@ -40,12 +37,11 @@ export type InferVarRefs<TBindings extends Action[]> = {
40
37
  */
41
38
  /**
42
39
  * Constraint for the body callback return type. Only requires the output
43
- * phantom fields — omits `__in` and `__in_co` so that body actions with
44
- * `In = never` (e.g. pipelines starting from a VarRef) are assignable.
40
+ * phantom field — omits `__in` and `__in_co` so that body actions with
41
+ * any input type (e.g. pipelines starting from a VarRef) are assignable.
45
42
  */
46
43
  type BodyResult<TOut> = Action & {
47
44
  __out?: () => TOut;
48
- __out_contra?: (output: TOut) => void;
49
45
  };
50
46
  export declare function bind<TBindings extends Action[], TOut>(bindings: [...TBindings], body: (vars: InferVarRefs<TBindings>) => BodyResult<TOut>): TypedAction<ExtractInput<TBindings[number]>, TOut>;
51
47
  /**
@@ -60,3 +56,4 @@ export declare function bind<TBindings extends Action[], TOut>(bindings: [...TBi
60
56
  */
61
57
  export declare function bindInput<TIn, TOut = any>(body: (input: VarRef<TIn>) => BodyResult<TOut>): TypedAction<TIn, TOut>;
62
58
  export {};
59
+ //# sourceMappingURL=bind.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bind.d.ts","sourceRoot":"","sources":["../src/bind.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,WAAW,EAGjB,MAAM,UAAU,CAAC;AAWlB;;;;;;GAMG;AACH,MAAM,MAAM,MAAM,CAAC,MAAM,IAAI,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAetD;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,CAAC,SAAS,SAAS,MAAM,EAAE,IAAI;KACpD,CAAC,IAAI,MAAM,SAAS,GAAG,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5D,CAAC;AA4BF;;;;;;;;;;;;;;;;GAgBG;AACH;;;;GAIG;AACH,KAAK,UAAU,CAAC,IAAI,IAAI,MAAM,GAAG;IAC/B,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,wBAAgB,IAAI,CAAC,SAAS,SAAS,MAAM,EAAE,EAAE,IAAI,EACnD,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAC,EACxB,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,GACxD,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAkCpD;AAMD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,IAAI,GAAG,GAAG,EACvC,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,KAAK,UAAU,CAAC,IAAI,CAAC,GAC7C,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAExB"}
package/dist/bind.js CHANGED
@@ -1,7 +1,7 @@
1
- import { typedAction, } from "./ast.js";
1
+ import { toAction, typedAction, } from "./ast.js";
2
2
  import { chain } from "./chain.js";
3
3
  import { all } from "./all.js";
4
- import { identity, drop, getIndex } from "./builtins.js";
4
+ import { identity, drop, getIndex } from "./builtins/index.js";
5
5
  import { allocateResumeHandlerId } from "./effect-id.js";
6
6
  import { pipe } from "./pipe.js";
7
7
  function createVarRef(resumeHandlerId) {
@@ -20,10 +20,10 @@ function createVarRef(resumeHandlerId) {
20
20
  * `state` (index 1) is the full All output tuple. The handler produces
21
21
  * `[state[n], state]` — value is state[n], new_state is state (unchanged).
22
22
  *
23
- * Expanded AST: All(Chain(GetIndex(1), GetIndex(n)), GetIndex(1))
23
+ * Expanded AST: All(Chain(GetIndex(1).unwrap(), GetIndex(n).unwrap()), GetIndex(1).unwrap())
24
24
  */
25
25
  function readVar(n) {
26
- return all(chain(getIndex(1), getIndex(n)), getIndex(1));
26
+ return toAction(all(chain(toAction(getIndex(1).unwrap()), toAction(getIndex(n).unwrap())), toAction(getIndex(1).unwrap())));
27
27
  }
28
28
  export function bind(bindings, body) {
29
29
  // 1. Gensym one resumeHandlerId per binding.
@@ -31,11 +31,11 @@ export function bind(bindings, body) {
31
31
  // 2. Create VarRefs (ResumePerform nodes) for each binding.
32
32
  const varRefs = resumeHandlerIds.map((id) => createVarRef(id));
33
33
  // 3. Invoke the body callback with the VarRefs.
34
- const bodyAction = body(varRefs);
34
+ const bodyAction = toAction(body(varRefs));
35
35
  // 4. Build nested Handles from inside out.
36
36
  // Innermost: extract pipeline_input (last All element) → user body
37
37
  const pipelineInputIndex = bindings.length;
38
- let inner = chain(getIndex(pipelineInputIndex), bodyAction);
38
+ let inner = toAction(chain(toAction(getIndex(pipelineInputIndex).unwrap()), toAction(bodyAction)));
39
39
  for (let i = resumeHandlerIds.length - 1; i >= 0; i--) {
40
40
  inner = {
41
41
  kind: "ResumeHandle",
@@ -47,9 +47,9 @@ export function bind(bindings, body) {
47
47
  // 5. All(...bindings, identity()) → nested Handles
48
48
  const allAction = {
49
49
  kind: "All",
50
- actions: [...bindings.map((b) => b), identity()],
50
+ actions: [...bindings.map((b) => toAction(b)), toAction(identity())],
51
51
  };
52
- return typedAction(chain(allAction, inner));
52
+ return typedAction(toAction(chain(toAction(allAction), toAction(inner))));
53
53
  }
54
54
  // ---------------------------------------------------------------------------
55
55
  // bindInput — bind the pipeline input
@@ -0,0 +1,28 @@
1
+ import { type Option as OptionT, type TypedAction } from "../ast.js";
2
+ export declare function getIndex<TTuple extends unknown[], TIndex extends number>(index: TIndex): TypedAction<TTuple, OptionT<TTuple[TIndex]>>;
3
+ export declare function flatten<TElement>(): TypedAction<TElement[][], TElement[]>;
4
+ /**
5
+ * Deconstruct an array into its first element and the remaining elements.
6
+ * `TElement[] → Option<[TElement, TElement[]]>`
7
+ *
8
+ * Returns `Some([first, rest])` for non-empty arrays, `None` for empty arrays.
9
+ * This is the array equivalent of cons/uncons — enables recursive iteration
10
+ * patterns via `loop` + `splitFirst` + `branch`.
11
+ *
12
+ * This is a builtin (SplitFirst) because it requires array-length branching
13
+ * that can't be composed from existing AST nodes.
14
+ */
15
+ export declare function splitFirst<TElement>(): TypedAction<TElement[], OptionT<[TElement, TElement[]]>>;
16
+ /**
17
+ * Deconstruct an array into the leading elements and the last element.
18
+ * `TElement[] → Option<[TElement[], TElement]>`
19
+ *
20
+ * Returns `Some([init, last])` for non-empty arrays, `None` for empty arrays.
21
+ * Mirror of `splitFirst` — enables processing from the tail end.
22
+ *
23
+ * This is a builtin (SplitLast) because it requires array-length branching
24
+ * that can't be composed from existing AST nodes.
25
+ */
26
+ export declare function splitLast<TElement>(): TypedAction<TElement[], OptionT<[TElement[], TElement]>>;
27
+ export declare function range(start: number, end: number): TypedAction<any, number[]>;
28
+ //# sourceMappingURL=array.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/builtins/array.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,IAAI,OAAO,EACtB,KAAK,WAAW,EAEjB,MAAM,WAAW,CAAC;AAMnB,wBAAgB,QAAQ,CAAC,MAAM,SAAS,OAAO,EAAE,EAAE,MAAM,SAAS,MAAM,EACtE,KAAK,EAAE,MAAM,GACZ,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAQ9C;AAMD,wBAAgB,OAAO,CAAC,QAAQ,KAAK,WAAW,CAAC,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAKzE;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,QAAQ,KAAK,WAAW,CACjD,QAAQ,EAAE,EACV,OAAO,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,CAChC,CAKA;AAMD;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,QAAQ,KAAK,WAAW,CAChD,QAAQ,EAAE,EACV,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,CAChC,CAKA;AAMD,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,CAAC,CAS5E"}
@@ -0,0 +1,74 @@
1
+ import { typedAction, } from "../ast.js";
2
+ // ---------------------------------------------------------------------------
3
+ // GetIndex — extract a single element from an array by index
4
+ // ---------------------------------------------------------------------------
5
+ export function getIndex(index) {
6
+ return typedAction({
7
+ kind: "Invoke",
8
+ handler: {
9
+ kind: "Builtin",
10
+ builtin: { kind: "GetIndex", index },
11
+ },
12
+ });
13
+ }
14
+ // ---------------------------------------------------------------------------
15
+ // Flatten — flatten a nested array one level
16
+ // ---------------------------------------------------------------------------
17
+ export function flatten() {
18
+ return typedAction({
19
+ kind: "Invoke",
20
+ handler: { kind: "Builtin", builtin: { kind: "Flatten" } },
21
+ });
22
+ }
23
+ // ---------------------------------------------------------------------------
24
+ // SplitFirst — head/tail decomposition of an array
25
+ // ---------------------------------------------------------------------------
26
+ /**
27
+ * Deconstruct an array into its first element and the remaining elements.
28
+ * `TElement[] → Option<[TElement, TElement[]]>`
29
+ *
30
+ * Returns `Some([first, rest])` for non-empty arrays, `None` for empty arrays.
31
+ * This is the array equivalent of cons/uncons — enables recursive iteration
32
+ * patterns via `loop` + `splitFirst` + `branch`.
33
+ *
34
+ * This is a builtin (SplitFirst) because it requires array-length branching
35
+ * that can't be composed from existing AST nodes.
36
+ */
37
+ export function splitFirst() {
38
+ return typedAction({
39
+ kind: "Invoke",
40
+ handler: { kind: "Builtin", builtin: { kind: "SplitFirst" } },
41
+ });
42
+ }
43
+ // ---------------------------------------------------------------------------
44
+ // SplitLast — init/last decomposition of an array
45
+ // ---------------------------------------------------------------------------
46
+ /**
47
+ * Deconstruct an array into the leading elements and the last element.
48
+ * `TElement[] → Option<[TElement[], TElement]>`
49
+ *
50
+ * Returns `Some([init, last])` for non-empty arrays, `None` for empty arrays.
51
+ * Mirror of `splitFirst` — enables processing from the tail end.
52
+ *
53
+ * This is a builtin (SplitLast) because it requires array-length branching
54
+ * that can't be composed from existing AST nodes.
55
+ */
56
+ export function splitLast() {
57
+ return typedAction({
58
+ kind: "Invoke",
59
+ handler: { kind: "Builtin", builtin: { kind: "SplitLast" } },
60
+ });
61
+ }
62
+ // ---------------------------------------------------------------------------
63
+ // Range — produce an integer array [start, start+1, ..., end-1]
64
+ // ---------------------------------------------------------------------------
65
+ export function range(start, end) {
66
+ const result = [];
67
+ for (let i = start; i < end; i++) {
68
+ result.push(i);
69
+ }
70
+ return typedAction({
71
+ kind: "Invoke",
72
+ handler: { kind: "Builtin", builtin: { kind: "Constant", value: result } },
73
+ });
74
+ }
@@ -0,0 +1,6 @@
1
+ export { constant, identity, drop, panic } from "./scalar.js";
2
+ export { getField, wrapInField, merge, pick, allObject } from "./struct.js";
3
+ export { getIndex, flatten, splitFirst, splitLast, range } from "./array.js";
4
+ export { tag, extractPrefix, asOption, taggedUnionSchema, } from "./tagged-union.js";
5
+ export { withResource } from "./with-resource.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builtins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EACL,GAAG,EACH,aAAa,EACb,QAAQ,EACR,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { constant, identity, drop, panic } from "./scalar.js";
2
+ export { getField, wrapInField, merge, pick, allObject } from "./struct.js";
3
+ export { getIndex, flatten, splitFirst, splitLast, range } from "./array.js";
4
+ export { tag, extractPrefix, asOption, taggedUnionSchema, } from "./tagged-union.js";
5
+ export { withResource } from "./with-resource.js";
@@ -0,0 +1,12 @@
1
+ import { type TypedAction } from "../ast.js";
2
+ export declare function constant<TValue>(value: TValue): TypedAction<any, TValue>;
3
+ export declare function identity<TValue = any>(): TypedAction<TValue, TValue>;
4
+ export declare const drop: TypedAction<any, void>;
5
+ /**
6
+ * Halt execution with a fatal error. Not caught by tryCatch.
7
+ * Analogous to Rust's `panic!`.
8
+ *
9
+ * Output type is `never` — a panic never produces a value.
10
+ */
11
+ export declare function panic(message: string): TypedAction<any, never>;
12
+ //# sourceMappingURL=scalar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scalar.d.ts","sourceRoot":"","sources":["../../src/builtins/scalar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,WAAW,CAAC;AAM1D,wBAAgB,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,MAAM,CAAC,CAKxE;AAMD,wBAAgB,QAAQ,CAAC,MAAM,GAAG,GAAG,KAAK,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAKpE;AAMD,eAAO,MAAM,IAAI,EAAE,WAAW,CAAC,GAAG,EAAE,IAAI,CAGtC,CAAC;AAMH;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,KAAK,CAAC,CAK9D"}
@@ -0,0 +1,41 @@
1
+ import { typedAction } from "../ast.js";
2
+ // ---------------------------------------------------------------------------
3
+ // Constant — produce a fixed value (takes no pipeline input)
4
+ // ---------------------------------------------------------------------------
5
+ export function constant(value) {
6
+ return typedAction({
7
+ kind: "Invoke",
8
+ handler: { kind: "Builtin", builtin: { kind: "Constant", value } },
9
+ });
10
+ }
11
+ // ---------------------------------------------------------------------------
12
+ // Identity — pass input through unchanged
13
+ // ---------------------------------------------------------------------------
14
+ export function identity() {
15
+ return typedAction({
16
+ kind: "Invoke",
17
+ handler: { kind: "Builtin", builtin: { kind: "Identity" } },
18
+ });
19
+ }
20
+ // ---------------------------------------------------------------------------
21
+ // Drop — discard pipeline value
22
+ // ---------------------------------------------------------------------------
23
+ export const drop = typedAction({
24
+ kind: "Invoke",
25
+ handler: { kind: "Builtin", builtin: { kind: "Drop" } },
26
+ });
27
+ // ---------------------------------------------------------------------------
28
+ // Panic — halt execution with an error message
29
+ // ---------------------------------------------------------------------------
30
+ /**
31
+ * Halt execution with a fatal error. Not caught by tryCatch.
32
+ * Analogous to Rust's `panic!`.
33
+ *
34
+ * Output type is `never` — a panic never produces a value.
35
+ */
36
+ export function panic(message) {
37
+ return typedAction({
38
+ kind: "Invoke",
39
+ handler: { kind: "Builtin", builtin: { kind: "Panic", message } },
40
+ });
41
+ }