@opencode/codemode 0.0.0-dev-19631 → 0.0.0-dev-19633

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 (62) hide show
  1. package/dist/codemode.js +1 -1
  2. package/dist/data.d.ts +3 -3
  3. package/dist/data.js +37 -31
  4. package/dist/interpreter/callback.d.ts +20 -0
  5. package/dist/interpreter/{runner.js → callback.js} +10 -10
  6. package/dist/interpreter/errors.d.ts +5 -5
  7. package/dist/interpreter/errors.js +21 -22
  8. package/dist/interpreter/execute.d.ts +2 -2
  9. package/dist/interpreter/execute.js +11 -11
  10. package/dist/interpreter/extensions.d.ts +2 -2
  11. package/dist/interpreter/extensions.js +42 -36
  12. package/dist/interpreter/generators.d.ts +2 -3
  13. package/dist/interpreter/generators.js +8 -8
  14. package/dist/interpreter/globals.d.ts +2 -12
  15. package/dist/interpreter/globals.js +41 -37
  16. package/dist/interpreter/interpreter.d.ts +31 -0
  17. package/dist/interpreter/{runtime.js → interpreter.js} +118 -117
  18. package/dist/interpreter/intrinsics.d.ts +5 -5
  19. package/dist/interpreter/intrinsics.js +16 -10
  20. package/dist/interpreter/model.d.ts +3 -3
  21. package/dist/interpreter/model.js +1 -1
  22. package/dist/interpreter/native.d.ts +9 -9
  23. package/dist/interpreter/native.js +9 -9
  24. package/dist/interpreter/objects.d.ts +51 -46
  25. package/dist/interpreter/objects.js +57 -40
  26. package/dist/interpreter/promises.d.ts +13 -13
  27. package/dist/interpreter/promises.js +70 -70
  28. package/dist/interpreter/references.js +17 -15
  29. package/dist/openapi/types.d.ts +1 -1
  30. package/dist/stdlib/array.d.ts +3 -3
  31. package/dist/stdlib/array.js +31 -31
  32. package/dist/stdlib/bytes.d.ts +10 -0
  33. package/dist/stdlib/bytes.js +228 -0
  34. package/dist/stdlib/collections.d.ts +4 -4
  35. package/dist/stdlib/collections.js +55 -55
  36. package/dist/stdlib/console.d.ts +3 -3
  37. package/dist/stdlib/console.js +24 -22
  38. package/dist/stdlib/date.d.ts +2 -2
  39. package/dist/stdlib/date.js +19 -19
  40. package/dist/stdlib/json.d.ts +3 -3
  41. package/dist/stdlib/json.js +24 -24
  42. package/dist/stdlib/math.d.ts +3 -3
  43. package/dist/stdlib/math.js +7 -7
  44. package/dist/stdlib/number.d.ts +3 -3
  45. package/dist/stdlib/number.js +11 -11
  46. package/dist/stdlib/object.d.ts +5 -5
  47. package/dist/stdlib/object.js +41 -39
  48. package/dist/stdlib/regexp.d.ts +6 -6
  49. package/dist/stdlib/regexp.js +24 -24
  50. package/dist/stdlib/string.d.ts +2 -2
  51. package/dist/stdlib/string.js +24 -24
  52. package/dist/stdlib/url.d.ts +6 -6
  53. package/dist/stdlib/url.js +39 -39
  54. package/dist/stdlib/value.d.ts +3 -3
  55. package/dist/stdlib/value.js +18 -14
  56. package/dist/stdlib/web.d.ts +4 -4
  57. package/dist/stdlib/web.js +19 -5
  58. package/dist/tool-runtime.d.ts +2 -2
  59. package/dist/tool-runtime.js +2 -2
  60. package/package.json +1 -1
  61. package/dist/interpreter/runner.d.ts +0 -27
  62. package/dist/interpreter/runtime.d.ts +0 -19
@@ -1,13 +1,13 @@
1
1
  import { Cause, Deferred, Effect, Exit } from "effect";
2
2
  import { toProgram } from "../data.js";
3
3
  import { ToolReference } from "../tool-runtime.js";
4
- import { AsyncIteratorSymbol, CallSite, GeneratorReturn, IteratorSymbol, OptionalShortCircuit, invalidData, ProgramThrow, rangeError, typeError, unsupportedSyntax, } from "./model.js";
4
+ import { AsyncIteratorSymbol, CallSite, GeneratorReturn, IteratorSymbol, OptionalShortCircuit, invalidData, Throw, rangeError, typeError, unsupportedSyntax, } from "./model.js";
5
5
  import { checkStringLength } from "./limits.js";
6
6
  import { locate, materialize } from "./errors.js";
7
7
  import { globals } from "./globals.js";
8
- import { assign, Callable, define, get, has, hasPrototype, keys, NativeFunction, parseArrayIndex, ProgramArray, ProgramDate, ProgramFunction, ProgramGenerator, ProgramMap, ProgramObject, ProgramPromise, ProgramSet, ProgramURLSearchParams, record, remove, set, } from "./objects.js";
9
- import { preserveConsumerError } from "./runner.js";
10
- import { PromiseRuntime, resolvePromise, resolvePromiseValue } from "./promises.js";
8
+ import { assign, Callable, define, get, has, hasPrototype, keys, Native, parseArrayIndex, Arr, Bytes, DateObj, Fn, GeneratorObj, MapObj, Obj, PromiseObj, SetObj, URLSearchParamsObj, record, remove, set, } from "./objects.js";
9
+ import { preserveConsumerError } from "./callback.js";
10
+ import { Pending, resolvePromise, resolvePromiseValue } from "./promises.js";
11
11
  import { containsOpaqueReference, describeValue, rejectCircularInsertion, typeofValue } from "./references.js";
12
12
  import { ScopeStack } from "./scope.js";
13
13
  import { constructRegExp } from "../stdlib/regexp.js";
@@ -49,7 +49,7 @@ const instanceofValue = (lhs, rhs, node) => {
49
49
  throw typeError("The right-hand side of 'instanceof' is not callable.", node);
50
50
  }
51
51
  const prototype = get(rhs, "prototype");
52
- if (!(prototype instanceof ProgramObject)) {
52
+ if (!(prototype instanceof Obj)) {
53
53
  throw typeError("The right-hand side of 'instanceof' has no 'prototype' object.", node);
54
54
  }
55
55
  return hasPrototype(lhs, prototype);
@@ -143,51 +143,49 @@ const loopDeclaration = (left, statement) => {
143
143
  };
144
144
  };
145
145
  /** One program execution: the tool bridge, promise scheduler, captured logs, and the global scope built once. */
146
- export class Runtime {
147
- executeTool;
148
- search;
149
- toolKeys;
150
- promises;
151
- prototypes;
146
+ export class Interpreter {
147
+ tools;
148
+ pending;
149
+ builtins;
152
150
  logs;
153
- runner;
154
151
  root;
155
- constructor(executeTool, search, toolKeys, promises, prototypes, logs = [], extraGlobals = () => []) {
156
- this.executeTool = executeTool;
157
- this.search = search;
158
- this.toolKeys = toolKeys;
159
- this.promises = promises;
160
- this.prototypes = prototypes;
161
- this.logs = logs;
152
+ constructor(options) {
153
+ this.tools = options.tools;
154
+ this.pending = options.pending;
155
+ this.builtins = options.builtins;
156
+ this.logs = options.logs ?? [];
162
157
  const globalScope = new Map();
163
158
  // Calling back into the program never reads frame state, so any frame serves; the root is always alive.
164
159
  this.root = new Frame(this, new ScopeStack([globalScope]));
165
- this.runner = {
166
- invokeCallable: (callable, thisValue, args) => this.root.invokeCallable(callable, thisValue, args),
167
- settlePromise: (promise) => this.root.settlePromise(promise),
168
- syncIterator: (value) => this.root.syncIterator(value),
169
- prototypes,
170
- };
171
- for (const [name, value] of [...globals(this), ...extraGlobals(this)]) {
160
+ for (const [name, value] of [...globals(this), ...(options.globals?.(this) ?? [])]) {
172
161
  globalScope.set(name, { mutable: false, value });
173
162
  }
174
163
  }
175
164
  run(program) {
176
165
  return this.root.run(program);
177
166
  }
167
+ call(callable, thisValue, args) {
168
+ return this.root.call(callable, thisValue, args);
169
+ }
170
+ await(promise) {
171
+ return this.root.await(promise);
172
+ }
173
+ iterate(value) {
174
+ return this.root.iterate(value);
175
+ }
178
176
  }
179
177
  const MAX_CALL_DEPTH = 10_000;
180
178
  /** One activation: the top-level program or a single function call, evaluating against its own scope chain. */
181
179
  class Frame {
182
- runtime;
180
+ ctx;
183
181
  scopes;
184
182
  depth;
185
183
  generatorState;
186
184
  generatorAsync = false;
187
- constructor(runtime, scopes,
185
+ constructor(ctx, scopes,
188
186
  /** Nested call depth; resets when an await resumes, since the continuation runs from the job queue. */
189
187
  depth = 0) {
190
- this.runtime = runtime;
188
+ this.ctx = ctx;
191
189
  this.scopes = scopes;
192
190
  this.depth = depth;
193
191
  }
@@ -215,20 +213,20 @@ class Frame {
215
213
  }
216
214
  }
217
215
  // The implicit async body adopts returned promises before copy-out.
218
- value = yield* resolvePromiseValue(self.runtime.runner, value);
216
+ value = yield* resolvePromiseValue(self.ctx, value);
219
217
  return value;
220
218
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
221
219
  }
222
220
  // Fork at the call site so admission and hooks occur when the call is made.
223
221
  createToolCallPromise(path, args) {
224
- return this.runtime.promises.create(Effect.suspend(() => this.runtime.executeTool(path, args)));
222
+ return this.ctx.pending.create(Effect.suspend(() => this.ctx.tools.execute(path, args)));
225
223
  }
226
224
  // Fiber exits make settlement idempotent; yielding prevents inline continuation.
227
- settlePromise(promise) {
228
- const promises = this.runtime.promises;
225
+ await(promise) {
226
+ const pending = this.ctx.pending;
229
227
  return Effect.suspend(() => {
230
- promises.markObserved(promise);
231
- return Effect.flatMap(promises.await(promise), (exit) => Effect.andThen(Effect.yieldNow, exit));
228
+ pending.markObserved(promise);
229
+ return Effect.flatMap(pending.await(promise), (exit) => Effect.andThen(Effect.yieldNow, exit));
232
230
  });
233
231
  }
234
232
  evaluateStatement(node) {
@@ -294,7 +292,7 @@ class Frame {
294
292
  }).pipe(Effect.ensuring(Effect.sync(() => self.scopes.pop())));
295
293
  }
296
294
  createFunction(node, name = node.type === "ArrowFunctionExpression" ? "" : (node.id?.name ?? "")) {
297
- return new ProgramFunction(this.runtime.prototypes.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
295
+ return new Fn(this.ctx.builtins.Function, name, node.params, node.body, this.scopes.capture(), node.async, node.generator);
298
296
  }
299
297
  // NamedEvaluation: an anonymous function definition takes the name of what it is assigned to.
300
298
  evaluateNamed(node, name) {
@@ -472,7 +470,7 @@ class Frame {
472
470
  self.predeclarePattern(declared.pattern, declared.mutable, left);
473
471
  const right = yield* self.evaluateExpression(node.right);
474
472
  const iterator = yield* self.customIterator(right, node, awaiting);
475
- const cursor = iterator === undefined ? yield* self.syncIterator(right, node) : undefined;
473
+ const cursor = iterator === undefined ? yield* self.iterate(right, node) : undefined;
476
474
  if (iterator === undefined && cursor === undefined) {
477
475
  throw invalidData(`${awaiting ? "for await...of" : "for...of"} requires an array, string, Map, Set, or URLSearchParams, or custom iterator value.`, node);
478
476
  }
@@ -529,7 +527,7 @@ class Frame {
529
527
  })));
530
528
  }
531
529
  awaitValue(value) {
532
- return Effect.flatMap(resolvePromise(this.runtime.runner, this.runtime.promises, value), (promise) => Effect.ensuring(this.settlePromise(promise), Effect.sync(() => (this.depth = 0))));
530
+ return Effect.flatMap(resolvePromise(this.ctx, value), (promise) => Effect.ensuring(this.await(promise), Effect.sync(() => (this.depth = 0))));
533
531
  }
534
532
  awaitAsyncFromSyncValue(iterator, value, node, closeOnRejection) {
535
533
  const self = this;
@@ -543,26 +541,28 @@ class Frame {
543
541
  return yield* Effect.failCause(settled.cause);
544
542
  });
545
543
  }
546
- syncIterator(value, node) {
547
- const iterator = value instanceof ProgramArray
544
+ iterate(value, node) {
545
+ const iterator = value instanceof Arr
548
546
  ? value.items[Symbol.iterator]()
549
547
  : typeof value === "string"
550
548
  ? value[Symbol.iterator]()
551
- : value instanceof ProgramMap
549
+ : value instanceof MapObj
552
550
  ? value.map.entries()
553
- : value instanceof ProgramSet
551
+ : value instanceof SetObj
554
552
  ? value.set.values()
555
- : value instanceof ProgramURLSearchParams
553
+ : value instanceof URLSearchParamsObj
556
554
  ? value.params.entries()
557
- : undefined;
555
+ : value instanceof Bytes
556
+ ? value.bytes.values()
557
+ : undefined;
558
558
  if (iterator !== undefined) {
559
- const proto = this.runtime.prototypes.Array;
559
+ const proto = this.ctx.builtins.Array;
560
560
  return Effect.succeed({
561
561
  next: Effect.sync(() => {
562
562
  const step = iterator.next();
563
563
  return {
564
564
  done: Boolean(step.done),
565
- value: Array.isArray(step.value) ? new ProgramArray(proto, step.value) : step.value,
565
+ value: Array.isArray(step.value) ? new Arr(proto, step.value) : step.value,
566
566
  };
567
567
  }),
568
568
  close: Effect.void,
@@ -577,14 +577,14 @@ class Frame {
577
577
  });
578
578
  }
579
579
  customIterator(value, node, allowAsync = true) {
580
- if (!(value instanceof ProgramObject))
580
+ if (!(value instanceof Obj))
581
581
  return Effect.undefined;
582
582
  const asyncMethod = allowAsync ? get(value, AsyncIteratorSymbol) : undefined;
583
583
  const method = asyncMethod ?? get(value, IteratorSymbol);
584
584
  if (method === undefined || method === null)
585
585
  return Effect.undefined;
586
586
  const self = this;
587
- return Effect.map(this.invokeCallable(this.requireIteratorMethod(method, "Iterator method", node), value, [], node), (iterator) => {
587
+ return Effect.map(this.call(this.requireIteratorMethod(method, "Iterator method", node), value, [], node), (iterator) => {
588
588
  const object = self.requireIteratorObject(iterator, "Iterator method result", node);
589
589
  return {
590
590
  iterator: object,
@@ -597,10 +597,10 @@ class Frame {
597
597
  const self = this;
598
598
  return Effect.gen(function* () {
599
599
  if (iterator.asynchronous) {
600
- const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(iterator.next, iterator.iterator, [], node)), "Iterator next() result", node);
600
+ const object = self.requireIteratorObject(yield* self.awaitValue(yield* self.call(iterator.next, iterator.iterator, [], node)), "Iterator next() result", node);
601
601
  return { done: Boolean(get(object, "done")), value: get(object, "value") };
602
602
  }
603
- const called = yield* Effect.exit(self.invokeCallable(iterator.next, iterator.iterator, [], node));
603
+ const called = yield* Effect.exit(self.call(iterator.next, iterator.iterator, [], node));
604
604
  if (!Exit.isSuccess(called)) {
605
605
  if (awaiting)
606
606
  yield* Effect.yieldNow;
@@ -631,10 +631,10 @@ class Frame {
631
631
  return Effect.gen(function* () {
632
632
  const method = self.requireIteratorMethod(close, "Iterator return", node);
633
633
  if (iterator.asynchronous) {
634
- self.requireIteratorObject(yield* self.awaitValue(yield* self.invokeCallable(method, iterator.iterator, [], node)), "Iterator return() result", node);
634
+ self.requireIteratorObject(yield* self.awaitValue(yield* self.call(method, iterator.iterator, [], node)), "Iterator return() result", node);
635
635
  return;
636
636
  }
637
- const called = yield* Effect.exit(self.invokeCallable(method, iterator.iterator, [], node));
637
+ const called = yield* Effect.exit(self.call(method, iterator.iterator, [], node));
638
638
  if (!Exit.isSuccess(called)) {
639
639
  if (awaiting)
640
640
  yield* Effect.yieldNow;
@@ -651,7 +651,7 @@ class Frame {
651
651
  });
652
652
  }
653
653
  requireIteratorObject(value, context, node) {
654
- if (value instanceof ProgramObject)
654
+ if (value instanceof Obj)
655
655
  return value;
656
656
  throw typeError(`${context} must be an object.`, node);
657
657
  }
@@ -663,10 +663,10 @@ class Frame {
663
663
  // for...in over null/undefined iterates nothing, like JS.
664
664
  enumerableKeys(value, node) {
665
665
  if (value instanceof ToolReference)
666
- return [...this.runtime.toolKeys(value.path)];
666
+ return [...this.ctx.tools.keys(value.path)];
667
667
  if (value === null || value === undefined)
668
668
  return [];
669
- return keys(enumerableSource(this.runtime.runner, "for...in", value, node));
669
+ return keys(enumerableSource(this.ctx, "for...in", value, node));
670
670
  }
671
671
  evaluateForInStatement(node, labels) {
672
672
  const left = node.left;
@@ -742,7 +742,7 @@ class Frame {
742
742
  : result);
743
743
  }
744
744
  evaluateThrowStatement(node) {
745
- return Effect.flatMap(this.evaluateExpression(node.argument), (value) => Effect.fail(new ProgramThrow(value)));
745
+ return Effect.flatMap(this.evaluateExpression(node.argument), (value) => Effect.fail(new Throw(value)));
746
746
  }
747
747
  evaluateTryStatement(node) {
748
748
  const body = node.block;
@@ -754,7 +754,7 @@ class Frame {
754
754
  if (cause.reasons.some(Cause.isInterruptReason) || Cause.squash(cause) instanceof GeneratorReturn || !handler) {
755
755
  return Effect.failCause(cause);
756
756
  }
757
- const caught = materialize(self.runtime.runner, Cause.squash(cause));
757
+ const caught = materialize(self.ctx, Cause.squash(cause));
758
758
  const parameter = handler.param;
759
759
  self.scopes.push();
760
760
  return Effect.gen(function* () {
@@ -814,13 +814,13 @@ class Frame {
814
814
  return;
815
815
  }
816
816
  if (pattern.type === "ObjectPattern") {
817
- if (!(value instanceof ProgramObject)) {
817
+ if (!(value instanceof Obj)) {
818
818
  throw typeError(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern);
819
819
  }
820
820
  const consumed = new Set();
821
821
  for (const property of pattern.properties) {
822
822
  if (property.type === "RestElement") {
823
- const rest = new ProgramObject(self.runtime.prototypes.Object);
823
+ const rest = new Obj(self.ctx.builtins.Object);
824
824
  assign(rest, value, consumed);
825
825
  yield* self.declarePattern(property.argument, rest, mutable, property, initialize);
826
826
  continue;
@@ -854,13 +854,13 @@ class Frame {
854
854
  return;
855
855
  }
856
856
  if (pattern.type === "ObjectPattern") {
857
- if (!(value instanceof ProgramObject)) {
857
+ if (!(value instanceof Obj)) {
858
858
  throw invalidData(`Object destructuring requires a data object or array value, received ${describeValue(value)}.`, pattern);
859
859
  }
860
860
  const consumed = new Set();
861
861
  for (const property of pattern.properties) {
862
862
  if (property.type === "RestElement") {
863
- const rest = new ProgramObject(self.runtime.prototypes.Object);
863
+ const rest = new Obj(self.ctx.builtins.Object);
864
864
  assign(rest, value, consumed);
865
865
  yield* self.assignPattern(property.argument, rest, property);
866
866
  continue;
@@ -885,7 +885,7 @@ class Frame {
885
885
  destructureArrayPattern(pattern, value, consume) {
886
886
  const self = this;
887
887
  return Effect.gen(function* () {
888
- const cursor = yield* self.syncIterator(value, pattern);
888
+ const cursor = yield* self.iterate(value, pattern);
889
889
  if (cursor === undefined) {
890
890
  throw typeError("Array destructuring requires a supported iterable value.", pattern);
891
891
  }
@@ -894,7 +894,7 @@ class Frame {
894
894
  if (done) {
895
895
  if (element === null)
896
896
  continue;
897
- yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new ProgramArray(self.runtime.prototypes.Array) : undefined, element);
897
+ yield* consume(element.type === "RestElement" ? element.argument : element, element.type === "RestElement" ? new Arr(self.ctx.builtins.Array) : undefined, element);
898
898
  if (element.type === "RestElement")
899
899
  return;
900
900
  continue;
@@ -913,7 +913,7 @@ class Frame {
913
913
  if (!done)
914
914
  rest.push(next.value);
915
915
  }
916
- yield* consume(element.argument, new ProgramArray(self.runtime.prototypes.Array, rest), element);
916
+ yield* consume(element.argument, new Arr(self.ctx.builtins.Array, rest), element);
917
917
  return;
918
918
  }
919
919
  const consumed = consume(element, step.done ? undefined : step.value, pattern);
@@ -942,8 +942,8 @@ class Frame {
942
942
  case "Literal": {
943
943
  const regex = node.regex;
944
944
  if (regex)
945
- return Effect.sync(() => constructRegExp(this.runtime.prototypes, [regex.pattern, regex.flags]));
946
- return Effect.sync(() => toProgram(this.runtime.prototypes, node.value, "Literal"));
945
+ return Effect.sync(() => constructRegExp(this.ctx.builtins, [regex.pattern, regex.flags]));
946
+ return Effect.sync(() => toProgram(this.ctx.builtins, node.value, "Literal"));
947
947
  }
948
948
  case "Identifier":
949
949
  return Effect.sync(() => this.scopes.get(node.name, node));
@@ -1001,15 +1001,15 @@ class Frame {
1001
1001
  return Effect.gen(function* () {
1002
1002
  const callee = yield* self.evaluateExpression(node.callee);
1003
1003
  // Globals are built with this interpreter's R; `instanceof` cannot recover the type argument.
1004
- const construct = callee instanceof NativeFunction ? callee.construct : undefined;
1004
+ const construct = callee instanceof Native ? callee.construct : undefined;
1005
1005
  if (construct === undefined) {
1006
1006
  // `new` itself is supported, so a non-constructible callee is a TypeError like JS rather than
1007
1007
  // unsupported syntax. Built-ins like Number are real constructors in JS, so do not claim
1008
1008
  // otherwise; say `new` is unsupported for them and point at the plain call.
1009
1009
  const name = calleeDescription(node.callee);
1010
- const message = callee instanceof ProgramFunction
1010
+ const message = callee instanceof Fn
1011
1011
  ? `${name} cannot be constructed: user-defined constructors and classes are not supported. Call it as a function that returns a plain object instead.`
1012
- : callee instanceof NativeFunction
1012
+ : callee instanceof Native
1013
1013
  ? `new ${name}(...) is not supported; call ${name}(...) without new instead.`
1014
1014
  : `${name} is not a constructor.`;
1015
1015
  throw typeError(message, node);
@@ -1029,7 +1029,7 @@ class Frame {
1029
1029
  const rhs = yield* self.evaluateExpression(node.right);
1030
1030
  if (operator === "instanceof")
1031
1031
  return instanceofValue(lhs, rhs, node);
1032
- return toProgram(self.runtime.prototypes, self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result");
1032
+ return toProgram(self.ctx.builtins, self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result");
1033
1033
  });
1034
1034
  }
1035
1035
  applyBinaryOperator(operator, lhs, rhs, node) {
@@ -1037,7 +1037,7 @@ class Frame {
1037
1037
  return lhs === rhs;
1038
1038
  if (operator === "!==")
1039
1039
  return lhs !== rhs;
1040
- if (operator === "in" && rhs instanceof ProgramObject && !containsOpaqueReference(lhs)) {
1040
+ if (operator === "in" && rhs instanceof Obj && !containsOpaqueReference(lhs)) {
1041
1041
  return has(rhs, lhs !== null && typeof lhs === "object" ? coerceToString(lhs) : lhs);
1042
1042
  }
1043
1043
  if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) {
@@ -1046,7 +1046,7 @@ class Frame {
1046
1046
  // Null-prototype data needs explicit primitive coercion; identity and `in` retain raw objects.
1047
1047
  // Dates use their default string hint for addition and loose equality, and epoch time elsewhere.
1048
1048
  const coerceOperand = (operand) => {
1049
- if (operand instanceof ProgramDate) {
1049
+ if (operand instanceof DateObj) {
1050
1050
  return operator === "+" || operator === "==" || operator === "!=" ? coerceToString(operand) : operand.time;
1051
1051
  }
1052
1052
  return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand;
@@ -1096,7 +1096,7 @@ class Frame {
1096
1096
  case ">>>":
1097
1097
  return l >>> r;
1098
1098
  case "in":
1099
- if (!(rhs instanceof ProgramObject)) {
1099
+ if (!(rhs instanceof Obj)) {
1100
1100
  throw typeError("The 'in' operator requires a data object on the right-hand side.", node);
1101
1101
  }
1102
1102
  return has(rhs, coerceOperand(lhs));
@@ -1135,7 +1135,7 @@ class Frame {
1135
1135
  if (containsOpaqueReference(value)) {
1136
1136
  throw invalidData("Unary operators require data values.", node);
1137
1137
  }
1138
- const operand = value instanceof ProgramDate
1138
+ const operand = value instanceof DateObj
1139
1139
  ? value.time
1140
1140
  : value !== null && typeof value === "object"
1141
1141
  ? coerceToString(value)
@@ -1154,7 +1154,7 @@ class Frame {
1154
1154
  default:
1155
1155
  throw typeError(`Unsupported unary operator '${operator}'.`, node);
1156
1156
  }
1157
- return toProgram(this.runtime.prototypes, result, "Unary expression result");
1157
+ return toProgram(this.ctx.builtins, result, "Unary expression result");
1158
1158
  });
1159
1159
  }
1160
1160
  evaluateAssignmentExpression(node) {
@@ -1175,7 +1175,7 @@ class Frame {
1175
1175
  if (operator !== "=") {
1176
1176
  const current = self.scopes.get(name, left);
1177
1177
  const rightValue = yield* self.evaluateExpression(node.right);
1178
- const next = toProgram(self.runtime.prototypes, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1178
+ const next = toProgram(self.ctx.builtins, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1179
1179
  return self.scopes.set(name, next, left);
1180
1180
  }
1181
1181
  const rightValue = yield* self.evaluateNamed(node.right, name);
@@ -1185,7 +1185,7 @@ class Frame {
1185
1185
  return yield* self.modifyMember(left, (current) => Effect.map(self.evaluateExpression(node.right), (rightValue) => {
1186
1186
  if (operator === "=")
1187
1187
  return { write: true, next: rightValue, result: rightValue };
1188
- const next = toProgram(self.runtime.prototypes, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1188
+ const next = toProgram(self.ctx.builtins, self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result");
1189
1189
  return { write: true, next, result: next };
1190
1190
  }));
1191
1191
  }
@@ -1265,7 +1265,7 @@ class Frame {
1265
1265
  if ((callable === null || callable === undefined) && node.optional)
1266
1266
  return OptionalShortCircuit;
1267
1267
  const args = yield* self.evaluateCallArguments(node.arguments);
1268
- return yield* self.invokeCallable(callable, thisValue, args, node, callee);
1268
+ return yield* self.call(callable, thisValue, args, node, callee);
1269
1269
  });
1270
1270
  }
1271
1271
  readMethod(node) {
@@ -1280,7 +1280,7 @@ class Frame {
1280
1280
  });
1281
1281
  }
1282
1282
  // The single dispatch for every invocation: call expressions and callbacks share it.
1283
- invokeCallable(callable, thisValue, args, node, callee) {
1283
+ call(callable, thisValue, args, node, callee) {
1284
1284
  const self = this;
1285
1285
  return Effect.gen(function* () {
1286
1286
  if (callable instanceof ToolReference) {
@@ -1289,9 +1289,9 @@ class Frame {
1289
1289
  }
1290
1290
  return yield* self.createToolCallPromise(callable.path, args);
1291
1291
  }
1292
- if (callable instanceof ProgramFunction)
1292
+ if (callable instanceof Fn)
1293
1293
  return yield* self.invokeFunction(callable, args, node);
1294
- if (callable instanceof NativeFunction) {
1294
+ if (callable instanceof Native) {
1295
1295
  return yield* self.native(() => callable.call(thisValue, args), node);
1296
1296
  }
1297
1297
  throw typeError(`${calleeDescription(callee)} is not a function.`, callee ?? node);
@@ -1308,7 +1308,7 @@ class Frame {
1308
1308
  for (const argNode of argNodes) {
1309
1309
  if (argNode.type === "SpreadElement") {
1310
1310
  const spread = yield* self.evaluateExpression(argNode.argument);
1311
- const cursor = yield* self.syncIterator(spread, argNode);
1311
+ const cursor = yield* self.iterate(spread, argNode);
1312
1312
  if (cursor === undefined)
1313
1313
  throw typeError("Spread arguments require a synchronous iterable.", argNode);
1314
1314
  while (true) {
@@ -1332,7 +1332,7 @@ class Frame {
1332
1332
  const depth = Math.max(self.depth, site.depth) + 1;
1333
1333
  if (depth > MAX_CALL_DEPTH)
1334
1334
  throw rangeError("Maximum call stack size exceeded", node);
1335
- const invocation = new Frame(this.runtime, new ScopeStack([...fn.capturedScopes, new Map()]), depth);
1335
+ const invocation = new Frame(this.ctx, new ScopeStack([...fn.capturedScopes, new Map()]), depth);
1336
1336
  const run = Effect.gen(function* () {
1337
1337
  // Seed all parameters first so defaults cannot fall through to same-named outer bindings.
1338
1338
  const paramScope = invocation.scopes.current();
@@ -1343,7 +1343,7 @@ class Frame {
1343
1343
  }
1344
1344
  for (const [index, parameter] of fn.parameters.entries()) {
1345
1345
  if (parameter.type === "RestElement") {
1346
- yield* invocation.declarePattern(parameter.argument, new ProgramArray(self.runtime.prototypes.Array, args.slice(index)), true, parameter, true);
1346
+ yield* invocation.declarePattern(parameter.argument, new Arr(self.ctx.builtins.Array, args.slice(index)), true, parameter, true);
1347
1347
  break;
1348
1348
  }
1349
1349
  yield* invocation.declarePattern(parameter, args[index], true, parameter, true);
@@ -1360,15 +1360,15 @@ class Frame {
1360
1360
  return Effect.succeed(this.createGenerator(invocation, run, fn.async));
1361
1361
  if (!fn.async)
1362
1362
  return run;
1363
- return this.runtime.promises.createWithSelf((self) => Effect.flatMap(run, (value) => resolvePromiseValue(invocation.runtime.runner, value, self)));
1363
+ return this.ctx.pending.createWithSelf((self) => Effect.flatMap(run, (value) => resolvePromiseValue(invocation.ctx, value, self)));
1364
1364
  });
1365
1365
  }
1366
1366
  createGenerator(invocation, run, asynchronous) {
1367
1367
  const state = { started: false, completed: false, draining: false, pending: [], pendingIndex: 0 };
1368
1368
  invocation.generatorState = state;
1369
1369
  invocation.generatorAsync = asynchronous;
1370
- const protos = this.runtime.prototypes;
1371
- const result = (value, done) => record(protos.Object, { value, done });
1370
+ const builtins = this.ctx.builtins;
1371
+ const result = (value, done) => record(builtins.Object, { value, done });
1372
1372
  const request = (kind, value) => {
1373
1373
  const request = { kind, value, response: Deferred.makeUnsafe() };
1374
1374
  if (!asynchronous && state.active)
@@ -1380,19 +1380,19 @@ class Frame {
1380
1380
  if (state.draining)
1381
1381
  return Deferred.await(request.response);
1382
1382
  state.draining = true;
1383
- return Effect.andThen(this.runtime.promises.fork(invocation
1383
+ return Effect.andThen(this.ctx.pending.fork(invocation
1384
1384
  .completeGeneratorRequests(state, true)
1385
1385
  .pipe(Effect.ensuring(Effect.sync(() => (state.draining = false))))), Deferred.await(request.response));
1386
1386
  }
1387
1387
  if (state.completed) {
1388
1388
  if (kind === "throw")
1389
- return Effect.fail(new ProgramThrow(value));
1389
+ return Effect.fail(new Throw(value));
1390
1390
  return Effect.succeed(result(kind === "return" ? value : undefined, true));
1391
1391
  }
1392
1392
  if (!state.started && kind !== "next") {
1393
1393
  state.completed = true;
1394
1394
  if (kind === "throw")
1395
- return Effect.fail(new ProgramThrow(value));
1395
+ return Effect.fail(new Throw(value));
1396
1396
  return Effect.succeed(result(value, true));
1397
1397
  }
1398
1398
  state.pending.push(request);
@@ -1418,23 +1418,23 @@ class Frame {
1418
1418
  yield* invocation.completeGeneratorRequests(state, asynchronous);
1419
1419
  state.completed = true;
1420
1420
  });
1421
- return Effect.andThen(this.runtime.promises.fork(body), Deferred.await(request.response));
1421
+ return Effect.andThen(this.ctx.pending.fork(body), Deferred.await(request.response));
1422
1422
  }
1423
1423
  return Deferred.await(request.response);
1424
1424
  };
1425
- const generator = new ProgramGenerator(asynchronous ? protos.AsyncGenerator : protos.Generator, asynchronous, request);
1425
+ const generator = new GeneratorObj(asynchronous ? builtins.AsyncGenerator : builtins.Generator, asynchronous, request);
1426
1426
  return generator;
1427
1427
  }
1428
1428
  completeGeneratorRequests(state, asynchronous) {
1429
1429
  const self = this;
1430
- const result = (value, done) => record(self.runtime.prototypes.Object, { value, done });
1430
+ const result = (value, done) => record(self.ctx.builtins.Object, { value, done });
1431
1431
  return Effect.gen(function* () {
1432
1432
  while (true) {
1433
1433
  const pending = self.dequeueGeneratorRequest(state);
1434
1434
  if (!pending)
1435
1435
  return;
1436
1436
  if (pending.kind === "throw") {
1437
- Deferred.doneUnsafe(pending.response, Exit.fail(new ProgramThrow(pending.value)));
1437
+ Deferred.doneUnsafe(pending.response, Exit.fail(new Throw(pending.value)));
1438
1438
  continue;
1439
1439
  }
1440
1440
  if (asynchronous && pending.kind === "return") {
@@ -1483,14 +1483,14 @@ class Frame {
1483
1483
  const state = this.generatorState;
1484
1484
  if (!state?.active)
1485
1485
  throw typeError("Generator has no active request.", node);
1486
- Deferred.doneUnsafe(state.active.response, Exit.succeed(record(this.runtime.prototypes.Object, { value, done: false })));
1486
+ Deferred.doneUnsafe(state.active.response, Exit.succeed(record(this.ctx.builtins.Object, { value, done: false })));
1487
1487
  state.active = undefined;
1488
1488
  return Effect.flatMap(this.takeGeneratorRequest(state), (request) => {
1489
1489
  state.active = request;
1490
1490
  if (request.kind === "next")
1491
1491
  return Effect.succeed(request.value);
1492
1492
  if (request.kind === "throw")
1493
- return Effect.fail(new ProgramThrow(request.value));
1493
+ return Effect.fail(new Throw(request.value));
1494
1494
  return this.generatorAsync
1495
1495
  ? Effect.flatMap(this.awaitValue(request.value), (value) => Effect.fail(new GeneratorReturn(value)))
1496
1496
  : Effect.fail(new GeneratorReturn(request.value));
@@ -1499,12 +1499,13 @@ class Frame {
1499
1499
  delegateYield(value, node) {
1500
1500
  const self = this;
1501
1501
  return Effect.gen(function* () {
1502
- if (value instanceof ProgramArray ||
1502
+ if (value instanceof Arr ||
1503
1503
  typeof value === "string" ||
1504
- value instanceof ProgramMap ||
1505
- value instanceof ProgramSet ||
1506
- value instanceof ProgramURLSearchParams) {
1507
- const cursor = yield* self.syncIterator(value, node);
1504
+ value instanceof MapObj ||
1505
+ value instanceof SetObj ||
1506
+ value instanceof URLSearchParamsObj ||
1507
+ value instanceof Bytes) {
1508
+ const cursor = yield* self.iterate(value, node);
1508
1509
  if (!cursor)
1509
1510
  throw typeError("Built-in iterator is unavailable.", node);
1510
1511
  while (true) {
@@ -1519,7 +1520,7 @@ class Frame {
1519
1520
  yield* cursor.close;
1520
1521
  return yield* Effect.fail(error);
1521
1522
  }
1522
- if (error instanceof ProgramThrow) {
1523
+ if (error instanceof Throw) {
1523
1524
  yield* cursor.close;
1524
1525
  throw typeError("The delegated iterator does not provide a throw() method.", node);
1525
1526
  }
@@ -1539,7 +1540,7 @@ class Frame {
1539
1540
  yield* self.closeIterator(iterator, node, self.generatorAsync);
1540
1541
  throw typeError("The delegated iterator does not provide a throw() method.", node);
1541
1542
  }
1542
- const called = yield* self.invokeCallable(self.requireIteratorMethod(method, `Iterator ${kind}`, node), iterator.iterator, [input], node);
1543
+ const called = yield* self.call(self.requireIteratorMethod(method, `Iterator ${kind}`, node), iterator.iterator, [input], node);
1543
1544
  const result = self.requireIteratorObject(iterator.asynchronous ? yield* self.awaitValue(called) : called, `Iterator ${kind}() result`, node);
1544
1545
  const done = Boolean(get(result, "done"));
1545
1546
  const resultValue = self.generatorAsync && !iterator.asynchronous
@@ -1557,7 +1558,7 @@ class Frame {
1557
1558
  continue;
1558
1559
  }
1559
1560
  const error = Cause.squash(resumed.cause);
1560
- if (!(error instanceof GeneratorReturn) && !(error instanceof ProgramThrow)) {
1561
+ if (!(error instanceof GeneratorReturn) && !(error instanceof Throw)) {
1561
1562
  return yield* Effect.failCause(resumed.cause);
1562
1563
  }
1563
1564
  kind = error instanceof GeneratorReturn ? "return" : "throw";
@@ -1566,7 +1567,7 @@ class Frame {
1566
1567
  });
1567
1568
  }
1568
1569
  evaluateObjectExpression(node) {
1569
- const objectValue = new ProgramObject(this.runtime.prototypes.Object);
1570
+ const objectValue = new Obj(this.ctx.builtins.Object);
1570
1571
  const self = this;
1571
1572
  return Effect.gen(function* () {
1572
1573
  for (const property of node.properties) {
@@ -1574,7 +1575,7 @@ class Frame {
1574
1575
  const spread = yield* self.evaluateExpression(property.argument);
1575
1576
  if (spread === null || spread === undefined)
1576
1577
  continue;
1577
- assign(objectValue, enumerableSource(self.runtime.runner, "Object spread", spread, property));
1578
+ assign(objectValue, enumerableSource(self.ctx, "Object spread", spread, property));
1578
1579
  continue;
1579
1580
  }
1580
1581
  if (property.kind !== "init") {
@@ -1616,7 +1617,7 @@ class Frame {
1616
1617
  }
1617
1618
  if (element.type === "SpreadElement") {
1618
1619
  const spread = yield* self.evaluateExpression(element.argument);
1619
- const cursor = yield* self.syncIterator(spread, element);
1620
+ const cursor = yield* self.iterate(spread, element);
1620
1621
  if (cursor === undefined)
1621
1622
  throw typeError("Array spread requires a synchronous iterable.", element);
1622
1623
  while (true) {
@@ -1630,7 +1631,7 @@ class Frame {
1630
1631
  values.push(yield* self.evaluateExpression(element));
1631
1632
  }
1632
1633
  }
1633
- return new ProgramArray(self.runtime.prototypes.Array, values);
1634
+ return new Arr(self.ctx.builtins.Array, values);
1634
1635
  });
1635
1636
  }
1636
1637
  evaluateTemplateLiteral(node) {
@@ -1649,7 +1650,7 @@ class Frame {
1649
1650
  checkStringLength(output.length);
1650
1651
  if (index < expressions.length) {
1651
1652
  const raw = yield* self.evaluateExpression(expressions[index]);
1652
- output += coerceToString(toProgram(self.runtime.prototypes, raw, "Template interpolation"));
1653
+ output += coerceToString(toProgram(self.ctx.builtins, raw, "Template interpolation"));
1653
1654
  checkStringLength(output.length);
1654
1655
  }
1655
1656
  }
@@ -1690,22 +1691,22 @@ class Frame {
1690
1691
  }
1691
1692
  return new ToolReference([...objectValue.path, key]);
1692
1693
  }
1693
- if (objectValue instanceof ProgramObject)
1694
+ if (objectValue instanceof Obj)
1694
1695
  return { target: objectValue, key, receiver: objectValue };
1695
1696
  // Primitives read through their wrapper prototype without being boxed; strings own length and indexes.
1696
- const protos = self.runtime.prototypes;
1697
+ const builtins = self.ctx.builtins;
1697
1698
  if (typeof objectValue === "string") {
1698
1699
  if (key === "length")
1699
1700
  return { value: objectValue.length };
1700
1701
  const index = typeof key === "symbol" ? undefined : parseArrayIndex(key);
1701
1702
  if (index !== undefined)
1702
1703
  return { value: objectValue[index] };
1703
- return { target: protos.String, key, receiver: objectValue };
1704
+ return { target: builtins.String, key, receiver: objectValue };
1704
1705
  }
1705
1706
  if (typeof objectValue === "number")
1706
- return { target: protos.Number, key, receiver: objectValue };
1707
+ return { target: builtins.Number, key, receiver: objectValue };
1707
1708
  if (typeof objectValue === "boolean")
1708
- return { target: protos.Boolean, key, receiver: objectValue };
1709
+ return { target: builtins.Boolean, key, receiver: objectValue };
1709
1710
  if (objectValue === null || objectValue === undefined) {
1710
1711
  throw typeError(`Cannot read properties of ${objectValue} (reading '${String(key)}').`, objectNode);
1711
1712
  }
@@ -1714,7 +1715,7 @@ class Frame {
1714
1715
  }
1715
1716
  readReference(reference, node) {
1716
1717
  // Reject unknown promise properties so a missing await cannot hide.
1717
- if (reference.target instanceof ProgramPromise && !has(reference.target, reference.key)) {
1718
+ if (reference.target instanceof PromiseObj && !has(reference.target, reference.key)) {
1718
1719
  throw invalidData("This value is an un-awaited Promise; await it first - e.g. `const result = await tools.ns.tool(...)`.", node.object);
1719
1720
  }
1720
1721
  return this.readProperty(reference.target, reference.key, node, reference.receiver);
@@ -1779,7 +1780,7 @@ class Frame {
1779
1780
  assignToReference(target, key, next, node) {
1780
1781
  const written = (() => {
1781
1782
  try {
1782
- rejectCircularInsertion(target, next, target instanceof ProgramArray ? "Array assignment result" : "Object assignment result");
1783
+ rejectCircularInsertion(target, next, target instanceof Arr ? "Array assignment result" : "Object assignment result");
1783
1784
  return set(target, key, next);
1784
1785
  }
1785
1786
  catch (error) {
@@ -1788,7 +1789,7 @@ class Frame {
1788
1789
  })();
1789
1790
  if (written)
1790
1791
  return;
1791
- if (target instanceof ProgramArray && key === "length")
1792
+ if (target instanceof Arr && key === "length")
1792
1793
  throw rangeError("Invalid array length", node);
1793
1794
  throw typeError(`Cannot assign to read only property '${String(key)}'.`, node);
1794
1795
  }