@opencode/codemode 0.0.0-dev-19530 → 2.0.0

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/data.d.ts +5 -6
  2. package/dist/data.js +44 -47
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +1 -0
  5. package/dist/interpreter/errors.d.ts +3 -5
  6. package/dist/interpreter/errors.js +22 -51
  7. package/dist/interpreter/execute.js +3 -5
  8. package/dist/interpreter/globals.js +47 -69
  9. package/dist/interpreter/host.d.ts +41 -0
  10. package/dist/interpreter/host.js +44 -0
  11. package/dist/interpreter/methods.d.ts +4 -0
  12. package/dist/interpreter/methods.js +837 -0
  13. package/dist/interpreter/model.d.ts +36 -13
  14. package/dist/interpreter/model.js +45 -15
  15. package/dist/interpreter/objects.d.ts +13 -106
  16. package/dist/interpreter/objects.js +65 -192
  17. package/dist/interpreter/promises.d.ts +13 -12
  18. package/dist/interpreter/promises.js +54 -59
  19. package/dist/interpreter/references.d.ts +0 -1
  20. package/dist/interpreter/references.js +33 -20
  21. package/dist/interpreter/runner.d.ts +11 -15
  22. package/dist/interpreter/runner.js +21 -21
  23. package/dist/interpreter/runtime.d.ts +3 -3
  24. package/dist/interpreter/runtime.js +327 -165
  25. package/dist/interpreter/scope.js +6 -6
  26. package/dist/stdlib/array.d.ts +2 -4
  27. package/dist/stdlib/array.js +32 -424
  28. package/dist/stdlib/collections.d.ts +7 -3
  29. package/dist/stdlib/collections.js +119 -291
  30. package/dist/stdlib/console.d.ts +2 -3
  31. package/dist/stdlib/console.js +30 -35
  32. package/dist/stdlib/date.d.ts +7 -1
  33. package/dist/stdlib/date.js +188 -93
  34. package/dist/stdlib/json.d.ts +2 -2
  35. package/dist/stdlib/json.js +27 -27
  36. package/dist/stdlib/math.d.ts +2 -2
  37. package/dist/stdlib/math.js +76 -96
  38. package/dist/stdlib/number.d.ts +4 -3
  39. package/dist/stdlib/number.js +60 -95
  40. package/dist/stdlib/object.d.ts +4 -4
  41. package/dist/stdlib/object.js +54 -128
  42. package/dist/stdlib/regexp.d.ts +8 -6
  43. package/dist/stdlib/regexp.js +68 -76
  44. package/dist/stdlib/string.d.ts +2 -2
  45. package/dist/stdlib/string.js +50 -213
  46. package/dist/stdlib/url.d.ts +13 -5
  47. package/dist/stdlib/url.js +102 -202
  48. package/dist/stdlib/value.d.ts +9 -5
  49. package/dist/stdlib/value.js +38 -16
  50. package/dist/stdlib/web.d.ts +4 -4
  51. package/dist/stdlib/web.js +10 -12
  52. package/dist/tool-runtime.d.ts +1 -2
  53. package/dist/tool-runtime.js +2 -2
  54. package/dist/values.d.ts +37 -0
  55. package/dist/values.js +56 -0
  56. package/package.json +1 -1
  57. package/dist/interpreter/generators.d.ts +0 -4
  58. package/dist/interpreter/generators.js +0 -25
  59. package/dist/interpreter/intrinsics.d.ts +0 -13
  60. package/dist/interpreter/intrinsics.js +0 -82
  61. package/dist/interpreter/native.d.ts +0 -19
  62. package/dist/interpreter/native.js +0 -40
@@ -1,4 +1,4 @@
1
- import { InterpreterRuntimeError, referenceError } from "./model.js";
1
+ import { InterpreterRuntimeError } from "./model.js";
2
2
  export class ScopeStack {
3
3
  scopes;
4
4
  constructor(scopes) {
@@ -29,23 +29,23 @@ export class ScopeStack {
29
29
  get(name, node) {
30
30
  const binding = this.resolve(name);
31
31
  if (!binding) {
32
- throw referenceError(`Unknown identifier '${name}'.`, node);
32
+ throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError");
33
33
  }
34
34
  if (binding.initialized === false) {
35
- throw referenceError(`Cannot access '${name}' before initialization.`, node);
35
+ throw new InterpreterRuntimeError(`Cannot access '${name}' before initialization.`, node).as("ReferenceError");
36
36
  }
37
37
  return binding.value;
38
38
  }
39
39
  set(name, value, node) {
40
40
  const binding = this.resolve(name);
41
41
  if (!binding) {
42
- throw referenceError(`Unknown identifier '${name}'.`, node);
42
+ throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError");
43
43
  }
44
44
  if (binding.initialized === false) {
45
- throw referenceError(`Cannot access '${name}' before initialization.`, node);
45
+ throw new InterpreterRuntimeError(`Cannot access '${name}' before initialization.`, node).as("ReferenceError");
46
46
  }
47
47
  if (!binding.mutable) {
48
- throw new InterpreterRuntimeError(`Cannot assign to constant '${name}'.`, node);
48
+ throw new InterpreterRuntimeError(`Cannot assign to constant '${name}'.`, node).as("TypeError");
49
49
  }
50
50
  binding.value = value;
51
51
  return value;
@@ -1,5 +1,3 @@
1
- import { Effect } from "effect";
2
- import { type AstNode } from "../interpreter/model.js";
1
+ import { HostFunction } from "../interpreter/host.js";
3
2
  import { type Runner } from "../interpreter/runner.js";
4
- export declare const sortArray: <R>(runner: Runner<R>, target: Array<unknown>, comparator: unknown, name: string, node: AstNode) => Effect.Effect<Array<unknown>, unknown, R>;
5
- export declare const arrayGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
3
+ export declare const arrayGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
@@ -1,17 +1,26 @@
1
1
  import { Effect } from "effect";
2
- import { constructor, methods, prototypeFrom, receiver } from "../interpreter/native.js";
3
- import { InterpreterRuntimeError, rangeError } from "../interpreter/model.js";
4
- import { get, ProgramArray, ProgramGenerator, ProgramObject } from "../interpreter/objects.js";
5
- import { describeValue, rejectCircularInsertion } from "../interpreter/references.js";
2
+ import { HostFunction, sync, syncCall } from "../interpreter/host.js";
3
+ import { CodeModeGenerator, InterpreterRuntimeError } from "../interpreter/model.js";
4
+ import { get, ProgramArray, ProgramObject } from "../interpreter/objects.js";
5
+ import { describeValue } from "../interpreter/references.js";
6
6
  import { applyCollectionCallback, preserveConsumerError } from "../interpreter/runner.js";
7
- import { compareText } from "../tool-runtime.js";
8
- import { coerceToNumber, coerceToString } from "./value.js";
9
- const MAX_LENGTH = 4_294_967_295;
7
+ const constructArray = (args, node) => {
8
+ if (args.length !== 1)
9
+ return new ProgramArray([...args]);
10
+ const first = args[0];
11
+ if (typeof first !== "number")
12
+ return new ProgramArray([first]);
13
+ if (!Number.isInteger(first) || first < 0 || first > 4294967295) {
14
+ throw new InterpreterRuntimeError("Invalid array length.", node).as("RangeError");
15
+ }
16
+ // Sparse like JS: Array(3) has holes, and combinator loops already skip them.
17
+ return new ProgramArray(new Array(first));
18
+ };
10
19
  const arrayLikeSource = (source, node) => {
11
20
  if (source instanceof ProgramObject && typeof get(source, "length") === "number") {
12
21
  const length = get(source, "length");
13
22
  const normalized = Number.isNaN(length) || length <= 0 ? 0 : Math.trunc(length);
14
- if (normalized > MAX_LENGTH)
23
+ if (normalized > 4_294_967_295)
15
24
  throw new RangeError("Invalid array length");
16
25
  return { length: normalized, source };
17
26
  }
@@ -19,13 +28,12 @@ const arrayLikeSource = (source, node) => {
19
28
  };
20
29
  const arrayFrom = (runner, args, node) => {
21
30
  const source = args[0];
22
- const proto = runner.prototypes.Array;
23
31
  const apply = args.length < 2 || args[1] === undefined ? undefined : applyCollectionCallback(runner, args[1], "Array.from", node);
24
32
  return Effect.gen(function* () {
25
33
  const cursor = yield* runner.syncIterator(source, node);
26
34
  if (cursor === undefined) {
27
- if (source instanceof ProgramGenerator) {
28
- throw new InterpreterRuntimeError("Array.from expects a synchronous iterable or array-like value.", node);
35
+ if (source instanceof CodeModeGenerator) {
36
+ throw new InterpreterRuntimeError("Array.from expects a synchronous iterable or array-like value.", node).as("TypeError");
29
37
  }
30
38
  const arrayLike = arrayLikeSource(source, node);
31
39
  const values = [];
@@ -33,428 +41,28 @@ const arrayFrom = (runner, args, node) => {
33
41
  const item = get(arrayLike.source, index);
34
42
  values.push(apply === undefined ? item : yield* apply([item, index]));
35
43
  }
36
- return new ProgramArray(proto, values);
44
+ return new ProgramArray(values);
37
45
  }
38
46
  const values = [];
39
47
  let index = 0;
40
48
  while (true) {
41
49
  const step = yield* cursor.next;
42
50
  if (step.done)
43
- return new ProgramArray(proto, values);
51
+ return new ProgramArray(values);
44
52
  values.push(apply === undefined ? step.value : yield* preserveConsumerError(cursor, apply([step.value, index])));
45
53
  index += 1;
46
54
  }
47
55
  });
48
56
  };
49
- export const sortArray = (runner, target, comparator, name, node) => {
50
- if (comparator === undefined) {
51
- return Effect.sync(() => [...target].sort((a, b) => compareText(coerceToString(a), coerceToString(b))));
52
- }
53
- const apply = applyCollectionCallback(runner, comparator, name, node);
54
- const mergeSort = (items) => {
55
- if (items.length <= 1)
56
- return Effect.succeed(items);
57
- const midpoint = Math.floor(items.length / 2);
58
- return Effect.gen(function* () {
59
- const left = yield* mergeSort(items.slice(0, midpoint));
60
- const right = yield* mergeSort(items.slice(midpoint));
61
- const merged = [];
62
- let leftIndex = 0;
63
- let rightIndex = 0;
64
- while (leftIndex < left.length && rightIndex < right.length) {
65
- // Treat a NaN comparator result as equal to preserve stable ordering.
66
- const order = coerceToNumber(yield* apply([left[leftIndex], right[rightIndex]]));
67
- if (Number.isNaN(order) || order <= 0)
68
- merged.push(left[leftIndex++]);
69
- else
70
- merged.push(right[rightIndex++]);
71
- }
72
- return [...merged, ...left.slice(leftIndex), ...right.slice(rightIndex)];
73
- });
74
- };
75
- const defined = target.filter((item) => item !== undefined);
76
- const undefinedCount = target.length - defined.length;
77
- return Effect.map(mergeSort(defined), (items) => [...items, ...Array(undefinedCount).fill(undefined)]);
78
- };
79
57
  // Array constructs identically with or without new, like JS.
80
- export const arrayGlobal = (runner) => {
81
- const protos = runner.prototypes;
82
- const proto = protos.Array;
83
- const wrap = (items) => new ProgramArray(proto, items);
84
- const construct = (args, into, node) => {
85
- if (args.length !== 1)
86
- return new ProgramArray(into, [...args]);
87
- const first = args[0];
88
- if (typeof first !== "number")
89
- return new ProgramArray(into, [first]);
90
- if (!Number.isInteger(first) || first < 0 || first > MAX_LENGTH)
91
- throw rangeError("Invalid array length.", node);
92
- // Sparse like JS: Array(3) has holes, and combinator loops already skip them.
93
- return new ProgramArray(into, new Array(first));
94
- };
95
- const array = constructor(protos, proto, {
96
- name: "Array",
97
- length: 1,
98
- call: (_, args, node) => Effect.sync(() => construct(args, proto, node)),
99
- construct: (args, newTarget, node) => Effect.sync(() => construct(args, prototypeFrom(newTarget, proto), node)),
100
- });
101
- methods(protos, array, [
102
- ["isArray", 1, (_, args) => args[0] instanceof ProgramArray],
103
- ["of", 0, (_, args) => wrap([...args])],
104
- ["from", 1, (_, args, node) => arrayFrom(runner, args, node)],
105
- ]);
106
- const self = (thisValue, name, node) => receiver(ProgramArray, thisValue, `Array.prototype.${name}`, node);
107
- const optNumber = (name, value, label, node) => {
108
- if (value === undefined)
109
- return undefined;
110
- if (typeof value !== "number") {
111
- throw new InterpreterRuntimeError(`Array.${name} expects ${label} to be a number.`, node);
112
- }
113
- return value;
114
- };
115
- // Callback methods fix the iteration length while reading existing elements live.
116
- const iterate = (name, length, body) => [
117
- name,
118
- length,
119
- (thisValue, args, node) => {
120
- const target = self(thisValue, name, node);
121
- return body(target.items, target, applyCollectionCallback(runner, args[0], `Array.${name}`, node), args, node);
122
- },
123
- ];
124
- methods(protos, proto, [
125
- [
126
- "join",
127
- 1,
128
- (thisValue, args, node) => {
129
- const target = self(thisValue, "join", node).items;
130
- if (args.length > 1 || (args.length === 1 && typeof args[0] !== "string")) {
131
- throw new InterpreterRuntimeError("Array.join expects zero arguments or one string separator.", node);
132
- }
133
- return target.map((item) => coerceToString(item ?? "")).join(args.length === 0 ? "," : args[0]);
134
- },
135
- ],
136
- [
137
- "toString",
138
- 0,
139
- (thisValue, _, node) => self(thisValue, "toString", node)
140
- .items.map((item) => coerceToString(item ?? ""))
141
- .join(","),
142
- ],
143
- [
144
- "includes",
145
- 1,
146
- (thisValue, args, node) => {
147
- const target = self(thisValue, "includes", node).items;
148
- if (args.length === 0 || args.length > 2) {
149
- throw new InterpreterRuntimeError("Array.includes expects a value and optional start index.", node);
150
- }
151
- return target.includes(args[0], optNumber("includes", args[1], "start index", node));
152
- },
153
- ],
154
- [
155
- "indexOf",
156
- 1,
157
- (thisValue, args, node) => self(thisValue, "indexOf", node).items.indexOf(args[0], optNumber("indexOf", args[1], "start index", node)),
158
- ],
159
- [
160
- "lastIndexOf",
161
- 1,
162
- (thisValue, args, node) => {
163
- const target = self(thisValue, "lastIndexOf", node).items;
164
- return args[1] === undefined
165
- ? target.lastIndexOf(args[0])
166
- : target.lastIndexOf(args[0], optNumber("lastIndexOf", args[1], "start index", node));
167
- },
168
- ],
169
- [
170
- "at",
171
- 1,
172
- (thisValue, args, node) => self(thisValue, "at", node).items.at(optNumber("at", args[0], "index", node) ?? 0),
173
- ],
174
- [
175
- "slice",
176
- 2,
177
- (thisValue, args, node) => wrap(self(thisValue, "slice", node).items.slice(optNumber("slice", args[0], "start", node), optNumber("slice", args[1], "end", node))),
178
- ],
179
- [
180
- "concat",
181
- 1,
182
- (thisValue, args, node) => wrap(self(thisValue, "concat", node).items.concat(...args.map((item) => (item instanceof ProgramArray ? item.items : item)))),
183
- ],
184
- [
185
- "flat",
186
- 0,
187
- (thisValue, args, node) => {
188
- const flatten = (items, depth) => items.flatMap((item) => (item instanceof ProgramArray && depth > 0 ? flatten(item.items, depth - 1) : [item]));
189
- return wrap(flatten(self(thisValue, "flat", node).items, optNumber("flat", args[0], "depth", node) ?? 1));
190
- },
191
- ],
192
- [
193
- "reverse",
194
- 0,
195
- (thisValue, _, node) => {
196
- const target = self(thisValue, "reverse", node);
197
- target.items.reverse();
198
- return target;
199
- },
200
- ],
201
- [
202
- "sort",
203
- 1,
204
- (thisValue, args, node) => {
205
- const target = self(thisValue, "sort", node);
206
- const items = target.items;
207
- const length = items.length;
208
- const holeCount = Array.from({ length }, (_, index) => Object.hasOwn(items, index)).filter((o) => !o).length;
209
- const itemCount = length - holeCount;
210
- return Effect.map(sortArray(runner, items, args[0], "Array.sort", node), (sorted) => {
211
- sorted.slice(0, itemCount).forEach((item, index) => {
212
- items[index] = item;
213
- });
214
- Array.from({ length: holeCount }, (_, index) => itemCount + index).forEach((index) => {
215
- Reflect.deleteProperty(items, index);
216
- });
217
- return target;
218
- });
219
- },
220
- ],
221
- [
222
- "toSorted",
223
- 1,
224
- (thisValue, args, node) => Effect.map(sortArray(runner, self(thisValue, "toSorted", node).items, args[0], "Array.toSorted", node), wrap),
225
- ],
226
- ["toReversed", 0, (thisValue, _, node) => wrap([...self(thisValue, "toReversed", node).items].reverse())],
227
- [
228
- "with",
229
- 2,
230
- (thisValue, args, node) => {
231
- const target = self(thisValue, "with", node).items;
232
- const index = optNumber("with", args[0], "index", node) ?? 0;
233
- const resolved = index < 0 ? target.length + index : index;
234
- if (resolved < 0 || resolved >= target.length)
235
- throw rangeError("Array.with index is out of range.", node);
236
- const copied = [...target];
237
- copied[resolved] = args[1];
238
- return wrap(copied);
239
- },
240
- ],
241
- [
242
- "push",
243
- 1,
244
- (thisValue, args, node) => {
245
- const target = self(thisValue, "push", node);
246
- // Validate all insertions before mutating to avoid partial cyclic updates.
247
- for (const item of args)
248
- rejectCircularInsertion(target, item, "Array.push result", node);
249
- return target.items.push(...args);
250
- },
251
- ],
252
- [
253
- "unshift",
254
- 1,
255
- (thisValue, args, node) => {
256
- const target = self(thisValue, "unshift", node);
257
- for (const item of args)
258
- rejectCircularInsertion(target, item, "Array.unshift result", node);
259
- return target.items.unshift(...args);
260
- },
261
- ],
262
- ["pop", 0, (thisValue, _, node) => self(thisValue, "pop", node).items.pop()],
263
- ["shift", 0, (thisValue, _, node) => self(thisValue, "shift", node).items.shift()],
264
- [
265
- "splice",
266
- 2,
267
- (thisValue, args, node) => {
268
- const target = self(thisValue, "splice", node);
269
- if (args.length === 0)
270
- return wrap(target.items.splice(0, 0));
271
- const start = optNumber("splice", args[0], "start", node) ?? 0;
272
- if (args.length === 1)
273
- return wrap(target.items.splice(start));
274
- const deleteCount = optNumber("splice", args[1], "delete count", node) ?? 0;
275
- const inserted = args.slice(2);
276
- for (const item of inserted)
277
- rejectCircularInsertion(target, item, "Array.splice result", node);
278
- return wrap(target.items.splice(start, deleteCount, ...inserted));
279
- },
280
- ],
281
- [
282
- "toSpliced",
283
- 2,
284
- (thisValue, args, node) => {
285
- const copied = [...self(thisValue, "toSpliced", node).items];
286
- if (args.length === 0)
287
- return wrap(copied);
288
- const start = optNumber("toSpliced", args[0], "start", node) ?? 0;
289
- if (args.length === 1)
290
- copied.splice(start);
291
- else
292
- copied.splice(start, optNumber("toSpliced", args[1], "delete count", node) ?? 0, ...args.slice(2));
293
- return wrap(copied);
294
- },
295
- ],
296
- [
297
- "fill",
298
- 1,
299
- (thisValue, args, node) => {
300
- const target = self(thisValue, "fill", node);
301
- rejectCircularInsertion(target, args[0], "Array.fill result", node);
302
- target.items.fill(args[0], optNumber("fill", args[1], "start", node), optNumber("fill", args[2], "end", node));
303
- return target;
304
- },
305
- ],
306
- [
307
- "copyWithin",
308
- 2,
309
- (thisValue, args, node) => {
310
- const target = self(thisValue, "copyWithin", node);
311
- target.items.copyWithin(optNumber("copyWithin", args[0], "target index", node) ?? 0, optNumber("copyWithin", args[1], "start", node) ?? 0, optNumber("copyWithin", args[2], "end", node));
312
- return target;
313
- },
314
- ],
315
- ["keys", 0, (thisValue, _, node) => wrap(Array.from(self(thisValue, "keys", node).items.keys()))],
316
- ["values", 0, (thisValue, _, node) => wrap([...self(thisValue, "values", node).items])],
317
- [
318
- "entries",
319
- 0,
320
- (thisValue, _, node) => wrap(Array.from(self(thisValue, "entries", node).items.entries(), ([index, item]) => wrap([index, item]))),
321
- ],
322
- iterate("map", 1, (target, receiver, apply) => Effect.gen(function* () {
323
- const length = target.length;
324
- const values = [];
325
- values.length = length;
326
- for (let index = 0; index < length; index += 1) {
327
- if (!(index in target))
328
- continue;
329
- values[index] = yield* apply([target[index], index, receiver]);
330
- }
331
- return wrap(values);
332
- })),
333
- iterate("flatMap", 1, (target, receiver, apply) => Effect.gen(function* () {
334
- const length = target.length;
335
- const values = [];
336
- for (let index = 0; index < length; index += 1) {
337
- if (!(index in target))
338
- continue;
339
- const mapped = yield* apply([target[index], index, receiver]);
340
- if (mapped instanceof ProgramArray)
341
- values.push(...mapped.items);
342
- else
343
- values.push(mapped);
344
- }
345
- return wrap(values);
346
- })),
347
- iterate("filter", 1, (target, receiver, apply) => Effect.gen(function* () {
348
- const length = target.length;
349
- const values = [];
350
- for (let index = 0; index < length; index += 1) {
351
- if (!(index in target))
352
- continue;
353
- const item = target[index];
354
- if (yield* apply([item, index, receiver]))
355
- values.push(item);
356
- }
357
- return wrap(values);
358
- })),
359
- iterate("find", 1, (target, receiver, apply) => Effect.gen(function* () {
360
- const length = target.length;
361
- for (let index = 0; index < length; index += 1) {
362
- const item = target[index];
363
- if (yield* apply([item, index, receiver]))
364
- return item;
365
- }
366
- return undefined;
367
- })),
368
- iterate("findIndex", 1, (target, receiver, apply) => Effect.gen(function* () {
369
- const length = target.length;
370
- for (let index = 0; index < length; index += 1) {
371
- if (yield* apply([target[index], index, receiver]))
372
- return index;
373
- }
374
- return -1;
375
- })),
376
- iterate("findLast", 1, (target, receiver, apply) => Effect.gen(function* () {
377
- for (let index = target.length - 1; index >= 0; index -= 1) {
378
- const item = target[index];
379
- if (yield* apply([item, index, receiver]))
380
- return item;
381
- }
382
- return undefined;
383
- })),
384
- iterate("findLastIndex", 1, (target, receiver, apply) => Effect.gen(function* () {
385
- for (let index = target.length - 1; index >= 0; index -= 1) {
386
- if (yield* apply([target[index], index, receiver]))
387
- return index;
388
- }
389
- return -1;
390
- })),
391
- iterate("some", 1, (target, receiver, apply) => Effect.gen(function* () {
392
- const length = target.length;
393
- for (let index = 0; index < length; index += 1) {
394
- if (!(index in target))
395
- continue;
396
- if (yield* apply([target[index], index, receiver]))
397
- return true;
398
- }
399
- return false;
400
- })),
401
- iterate("every", 1, (target, receiver, apply) => Effect.gen(function* () {
402
- const length = target.length;
403
- for (let index = 0; index < length; index += 1) {
404
- if (!(index in target))
405
- continue;
406
- if (!(yield* apply([target[index], index, receiver])))
407
- return false;
408
- }
409
- return true;
410
- })),
411
- iterate("forEach", 1, (target, receiver, apply) => Effect.gen(function* () {
412
- const length = target.length;
413
- for (let index = 0; index < length; index += 1) {
414
- if (index in target)
415
- yield* apply([target[index], index, receiver]);
416
- }
417
- return undefined;
418
- })),
419
- iterate("reduce", 1, (target, receiver, apply, args, node) => Effect.gen(function* () {
420
- const length = target.length;
421
- let start = 0;
422
- let accumulator = args[1];
423
- if (args.length < 2) {
424
- while (start < length && !(start in target))
425
- start += 1;
426
- if (start === length) {
427
- throw new InterpreterRuntimeError("Array.reduce of an empty array with no initial value.", node);
428
- }
429
- accumulator = target[start];
430
- start += 1;
431
- }
432
- for (let index = start; index < length; index += 1) {
433
- if (!(index in target))
434
- continue;
435
- accumulator = yield* apply([accumulator, target[index], index, receiver]);
436
- }
437
- return accumulator;
438
- })),
439
- iterate("reduceRight", 1, (target, receiver, apply, args, node) => Effect.gen(function* () {
440
- let start = target.length - 1;
441
- let accumulator = args[1];
442
- if (args.length < 2) {
443
- while (start >= 0 && !(start in target))
444
- start -= 1;
445
- if (start < 0) {
446
- throw new InterpreterRuntimeError("Array.reduceRight of an empty array with no initial value.", node);
447
- }
448
- accumulator = target[start];
449
- start -= 1;
450
- }
451
- for (let index = start; index >= 0; index -= 1) {
452
- if (!(index in target))
453
- continue;
454
- accumulator = yield* apply([accumulator, target[index], index, receiver]);
455
- }
456
- return accumulator;
457
- })),
458
- ]);
459
- return array;
460
- };
58
+ export const arrayGlobal = (runner) => new HostFunction({
59
+ name: "Array",
60
+ call: syncCall(constructArray),
61
+ construct: syncCall(constructArray),
62
+ instanceOf: (value) => value instanceof ProgramArray,
63
+ members: {
64
+ isArray: sync("Array.isArray", (args) => args[0] instanceof ProgramArray),
65
+ of: sync("Array.of", (args) => new ProgramArray([...args])),
66
+ from: new HostFunction({ name: "Array.from", call: (args, node) => arrayFrom(runner, args, node) }),
67
+ },
68
+ });
@@ -1,5 +1,9 @@
1
+ import { HostFunction } from "../interpreter/host.js";
1
2
  import { type Runner } from "../interpreter/runner.js";
3
+ export declare const arrayMethods: Set<string>;
4
+ export declare const mapMethods: Set<string>;
5
+ export declare const setMethods: Set<string>;
2
6
  /** `Map.groupBy` and `Object.groupBy`: the same iteration, keyed into a Map or a data object. */
3
- export declare const groupBy: <R>(runner: Runner<R>, namespace: "Map" | "Object") => import("../interpreter/objects.js").NativeFunction<R>;
4
- export declare const mapGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
5
- export declare const setGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
7
+ export declare const groupBy: <R>(runner: Runner<R>, namespace: "Map" | "Object") => HostFunction<R>;
8
+ export declare const mapGlobal: <R>(runner: Runner<R>) => HostFunction<R>;
9
+ export declare const setGlobal: <R>(runner: Runner<R>) => HostFunction<R>;