@opencode/codemode 2.0.1 → 2.0.2
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.
- package/dist/data.d.ts +6 -5
- package/dist/data.js +44 -46
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/interpreter/errors.d.ts +3 -4
- package/dist/interpreter/errors.js +40 -17
- package/dist/interpreter/execute.js +5 -3
- package/dist/interpreter/generators.d.ts +4 -0
- package/dist/interpreter/generators.js +25 -0
- package/dist/interpreter/globals.js +67 -46
- package/dist/interpreter/intrinsics.d.ts +8 -5
- package/dist/interpreter/intrinsics.js +59 -18
- package/dist/interpreter/model.d.ts +2 -32
- package/dist/interpreter/model.js +4 -38
- package/dist/interpreter/native.d.ts +19 -0
- package/dist/interpreter/native.js +40 -0
- package/dist/interpreter/objects.d.ts +105 -12
- package/dist/interpreter/objects.js +190 -66
- package/dist/interpreter/promises.d.ts +12 -13
- package/dist/interpreter/promises.js +52 -46
- package/dist/interpreter/references.d.ts +1 -0
- package/dist/interpreter/references.js +20 -33
- package/dist/interpreter/runner.d.ts +15 -13
- package/dist/interpreter/runner.js +19 -19
- package/dist/interpreter/runtime.d.ts +3 -3
- package/dist/interpreter/runtime.js +150 -314
- package/dist/stdlib/array.d.ts +4 -2
- package/dist/stdlib/array.js +423 -31
- package/dist/stdlib/collections.d.ts +3 -7
- package/dist/stdlib/collections.js +286 -114
- package/dist/stdlib/console.d.ts +3 -2
- package/dist/stdlib/console.js +35 -30
- package/dist/stdlib/date.d.ts +1 -7
- package/dist/stdlib/date.js +93 -188
- package/dist/stdlib/json.d.ts +2 -2
- package/dist/stdlib/json.js +24 -24
- package/dist/stdlib/math.d.ts +2 -2
- package/dist/stdlib/math.js +96 -76
- package/dist/stdlib/number.d.ts +3 -4
- package/dist/stdlib/number.js +94 -59
- package/dist/stdlib/object.d.ts +4 -4
- package/dist/stdlib/object.js +123 -49
- package/dist/stdlib/regexp.d.ts +6 -8
- package/dist/stdlib/regexp.js +71 -63
- package/dist/stdlib/string.d.ts +2 -2
- package/dist/stdlib/string.js +213 -50
- package/dist/stdlib/url.d.ts +5 -13
- package/dist/stdlib/url.js +196 -96
- package/dist/stdlib/value.d.ts +5 -4
- package/dist/stdlib/value.js +16 -16
- package/dist/stdlib/web.d.ts +4 -4
- package/dist/stdlib/web.js +8 -7
- package/dist/tool-runtime.d.ts +2 -1
- package/dist/tool-runtime.js +2 -2
- package/package.json +1 -1
- package/dist/interpreter/host.d.ts +0 -41
- package/dist/interpreter/host.js +0 -44
- package/dist/interpreter/methods.d.ts +0 -4
- package/dist/interpreter/methods.js +0 -837
- package/dist/values.d.ts +0 -37
- package/dist/values.js +0 -56
package/dist/stdlib/date.js
CHANGED
|
@@ -1,36 +1,24 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { constructor, methods, prototypeFrom, receiver } from "../interpreter/native.js";
|
|
3
|
+
import { rangeError } from "../interpreter/model.js";
|
|
4
|
+
import { ProgramDate, ProgramObject } from "../interpreter/objects.js";
|
|
5
|
+
import { toPrimitive, toPrimitiveNumber } from "../interpreter/runner.js";
|
|
6
6
|
import { coerceToNumber, coerceToString } from "./value.js";
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
["setUTCFullYear", 3],
|
|
23
|
-
]);
|
|
24
|
-
export const dateMethods = new Set([
|
|
25
|
-
"getTime",
|
|
26
|
-
"valueOf",
|
|
27
|
-
"toISOString",
|
|
28
|
-
"toJSON",
|
|
29
|
-
"toString",
|
|
30
|
-
"toDateString",
|
|
31
|
-
"toTimeString",
|
|
32
|
-
"toUTCString",
|
|
33
|
-
"toGMTString",
|
|
7
|
+
const constructDate = (runner, args, proto, node) => {
|
|
8
|
+
if (args.length === 0)
|
|
9
|
+
return Effect.succeed(new ProgramDate(proto, Date.now()));
|
|
10
|
+
if (args.length === 1) {
|
|
11
|
+
const arg = args[0];
|
|
12
|
+
if (arg instanceof ProgramDate)
|
|
13
|
+
return Effect.succeed(new ProgramDate(proto, arg.time));
|
|
14
|
+
return Effect.map(toPrimitive(runner, arg, "default", node), (value) => typeof value === "string"
|
|
15
|
+
? new ProgramDate(proto, Date.parse(value))
|
|
16
|
+
: new ProgramDate(proto, new Date(coerceToNumber(value)).getTime()));
|
|
17
|
+
}
|
|
18
|
+
const parts = args.map((arg) => coerceToNumber(arg));
|
|
19
|
+
return Effect.succeed(new ProgramDate(proto, new Date(...parts).getTime()));
|
|
20
|
+
};
|
|
21
|
+
const getters = [
|
|
34
22
|
"getFullYear",
|
|
35
23
|
"getMonth",
|
|
36
24
|
"getDate",
|
|
@@ -48,161 +36,78 @@ export const dateMethods = new Set([
|
|
|
48
36
|
"getUTCSeconds",
|
|
49
37
|
"getUTCMilliseconds",
|
|
50
38
|
"getTimezoneOffset",
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
case "getUTCHours":
|
|
126
|
-
return hosted.getUTCHours();
|
|
127
|
-
case "getUTCMinutes":
|
|
128
|
-
return hosted.getUTCMinutes();
|
|
129
|
-
case "getUTCSeconds":
|
|
130
|
-
return hosted.getUTCSeconds();
|
|
131
|
-
case "getUTCMilliseconds":
|
|
132
|
-
return hosted.getUTCMilliseconds();
|
|
133
|
-
case "getTimezoneOffset":
|
|
134
|
-
return hosted.getTimezoneOffset();
|
|
135
|
-
case "setTime":
|
|
136
|
-
return updateDate(value, hosted.setTime(args[0]));
|
|
137
|
-
case "setMilliseconds":
|
|
138
|
-
return updateDate(value, hosted.setMilliseconds(args[0]));
|
|
139
|
-
case "setUTCMilliseconds":
|
|
140
|
-
return updateDate(value, hosted.setUTCMilliseconds(args[0]));
|
|
141
|
-
case "setSeconds":
|
|
142
|
-
if (args.length < 2)
|
|
143
|
-
return updateDate(value, hosted.setSeconds(args[0]));
|
|
144
|
-
return updateDate(value, hosted.setSeconds(args[0], args[1]));
|
|
145
|
-
case "setUTCSeconds":
|
|
146
|
-
if (args.length < 2)
|
|
147
|
-
return updateDate(value, hosted.setUTCSeconds(args[0]));
|
|
148
|
-
return updateDate(value, hosted.setUTCSeconds(args[0], args[1]));
|
|
149
|
-
case "setMinutes":
|
|
150
|
-
if (args.length < 2)
|
|
151
|
-
return updateDate(value, hosted.setMinutes(args[0]));
|
|
152
|
-
if (args.length < 3)
|
|
153
|
-
return updateDate(value, hosted.setMinutes(args[0], args[1]));
|
|
154
|
-
return updateDate(value, hosted.setMinutes(args[0], args[1], args[2]));
|
|
155
|
-
case "setUTCMinutes":
|
|
156
|
-
if (args.length < 2)
|
|
157
|
-
return updateDate(value, hosted.setUTCMinutes(args[0]));
|
|
158
|
-
if (args.length < 3)
|
|
159
|
-
return updateDate(value, hosted.setUTCMinutes(args[0], args[1]));
|
|
160
|
-
return updateDate(value, hosted.setUTCMinutes(args[0], args[1], args[2]));
|
|
161
|
-
case "setHours":
|
|
162
|
-
if (args.length < 2)
|
|
163
|
-
return updateDate(value, hosted.setHours(args[0]));
|
|
164
|
-
if (args.length < 3)
|
|
165
|
-
return updateDate(value, hosted.setHours(args[0], args[1]));
|
|
166
|
-
if (args.length < 4)
|
|
167
|
-
return updateDate(value, hosted.setHours(args[0], args[1], args[2]));
|
|
168
|
-
return updateDate(value, hosted.setHours(args[0], args[1], args[2], args[3]));
|
|
169
|
-
case "setUTCHours":
|
|
170
|
-
if (args.length < 2)
|
|
171
|
-
return updateDate(value, hosted.setUTCHours(args[0]));
|
|
172
|
-
if (args.length < 3)
|
|
173
|
-
return updateDate(value, hosted.setUTCHours(args[0], args[1]));
|
|
174
|
-
if (args.length < 4)
|
|
175
|
-
return updateDate(value, hosted.setUTCHours(args[0], args[1], args[2]));
|
|
176
|
-
return updateDate(value, hosted.setUTCHours(args[0], args[1], args[2], args[3]));
|
|
177
|
-
case "setDate":
|
|
178
|
-
return updateDate(value, hosted.setDate(args[0]));
|
|
179
|
-
case "setUTCDate":
|
|
180
|
-
return updateDate(value, hosted.setUTCDate(args[0]));
|
|
181
|
-
case "setMonth":
|
|
182
|
-
if (args.length < 2)
|
|
183
|
-
return updateDate(value, hosted.setMonth(args[0]));
|
|
184
|
-
return updateDate(value, hosted.setMonth(args[0], args[1]));
|
|
185
|
-
case "setUTCMonth":
|
|
186
|
-
if (args.length < 2)
|
|
187
|
-
return updateDate(value, hosted.setUTCMonth(args[0]));
|
|
188
|
-
return updateDate(value, hosted.setUTCMonth(args[0], args[1]));
|
|
189
|
-
case "setFullYear":
|
|
190
|
-
if (args.length < 2)
|
|
191
|
-
return updateDate(value, hosted.setFullYear(args[0]));
|
|
192
|
-
if (args.length < 3)
|
|
193
|
-
return updateDate(value, hosted.setFullYear(args[0], args[1]));
|
|
194
|
-
return updateDate(value, hosted.setFullYear(args[0], args[1], args[2]));
|
|
195
|
-
case "setUTCFullYear":
|
|
196
|
-
if (args.length < 2)
|
|
197
|
-
return updateDate(value, hosted.setUTCFullYear(args[0]));
|
|
198
|
-
if (args.length < 3)
|
|
199
|
-
return updateDate(value, hosted.setUTCFullYear(args[0], args[1]));
|
|
200
|
-
return updateDate(value, hosted.setUTCFullYear(args[0], args[1], args[2]));
|
|
201
|
-
default:
|
|
202
|
-
throw new InterpreterRuntimeError(`Date method '${name}' is not available.`, node);
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
const updateDate = (value, time) => {
|
|
206
|
-
value.time = time;
|
|
207
|
-
return time;
|
|
39
|
+
];
|
|
40
|
+
const setters = [
|
|
41
|
+
["setTime", 1],
|
|
42
|
+
["setMilliseconds", 1],
|
|
43
|
+
["setUTCMilliseconds", 1],
|
|
44
|
+
["setSeconds", 2],
|
|
45
|
+
["setUTCSeconds", 2],
|
|
46
|
+
["setMinutes", 3],
|
|
47
|
+
["setUTCMinutes", 3],
|
|
48
|
+
["setHours", 4],
|
|
49
|
+
["setUTCHours", 4],
|
|
50
|
+
["setDate", 1],
|
|
51
|
+
["setUTCDate", 1],
|
|
52
|
+
["setMonth", 2],
|
|
53
|
+
["setUTCMonth", 2],
|
|
54
|
+
["setFullYear", 3],
|
|
55
|
+
["setUTCFullYear", 3],
|
|
56
|
+
];
|
|
57
|
+
export const dateGlobal = (runner) => {
|
|
58
|
+
const protos = runner.prototypes;
|
|
59
|
+
const proto = protos.Date;
|
|
60
|
+
const date = constructor(protos, proto, {
|
|
61
|
+
name: "Date",
|
|
62
|
+
length: 7,
|
|
63
|
+
// ISO instead of the host's locale string: date strings are deterministic and must not leak the host timezone.
|
|
64
|
+
call: () => Effect.sync(() => new Date().toISOString()),
|
|
65
|
+
construct: (args, newTarget, node) => constructDate(runner, args, prototypeFrom(newTarget, proto), node),
|
|
66
|
+
});
|
|
67
|
+
methods(protos, date, [
|
|
68
|
+
["now", 0, () => Date.now()],
|
|
69
|
+
["parse", 1, (_, args) => Date.parse(coerceToString(args[0]))],
|
|
70
|
+
["UTC", 7, (_, args) => Date.UTC(...args.map((arg) => coerceToNumber(arg)))],
|
|
71
|
+
]);
|
|
72
|
+
const self = (thisValue, name, node) => receiver(ProgramDate, thisValue, `Date.prototype.${name}`, node);
|
|
73
|
+
const iso = (value, node) => {
|
|
74
|
+
if (!Number.isFinite(value.time))
|
|
75
|
+
throw rangeError("Invalid time value.", node);
|
|
76
|
+
return new Date(value.time).toISOString();
|
|
77
|
+
};
|
|
78
|
+
methods(protos, proto, [
|
|
79
|
+
["getTime", 0, (thisValue, _, node) => self(thisValue, "getTime", node).time],
|
|
80
|
+
["valueOf", 0, (thisValue, _, node) => self(thisValue, "valueOf", node).time],
|
|
81
|
+
["toISOString", 0, (thisValue, _, node) => iso(self(thisValue, "toISOString", node), node)],
|
|
82
|
+
[
|
|
83
|
+
"toJSON",
|
|
84
|
+
1,
|
|
85
|
+
(thisValue, _, node) => {
|
|
86
|
+
const value = self(thisValue, "toJSON", node);
|
|
87
|
+
return Number.isFinite(value.time) ? iso(value, node) : null;
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
["toString", 0, (thisValue, _, node) => coerceToString(self(thisValue, "toString", node))],
|
|
91
|
+
["toDateString", 0, (thisValue, _, node) => new Date(self(thisValue, "toDateString", node).time).toDateString()],
|
|
92
|
+
["toTimeString", 0, (thisValue, _, node) => new Date(self(thisValue, "toTimeString", node).time).toTimeString()],
|
|
93
|
+
["toUTCString", 0, (thisValue, _, node) => new Date(self(thisValue, "toUTCString", node).time).toUTCString()],
|
|
94
|
+
["toGMTString", 0, (thisValue, _, node) => new Date(self(thisValue, "toGMTString", node).time).toUTCString()],
|
|
95
|
+
...getters.map((name) => [name, 0, (thisValue, _, node) => new Date(self(thisValue, name, node).time)[name]()]),
|
|
96
|
+
...setters.map(([name, length]) => [
|
|
97
|
+
name,
|
|
98
|
+
length,
|
|
99
|
+
(thisValue, args, node) => {
|
|
100
|
+
const target = self(thisValue, name, node);
|
|
101
|
+
// Native setters read the current time before argument coercion, whose callbacks may mutate the Date.
|
|
102
|
+
const hosted = new Date(target.time);
|
|
103
|
+
return Effect.map(Effect.forEach(args.slice(0, length), (arg) => toPrimitiveNumber(runner, arg, node), {
|
|
104
|
+
concurrency: 1,
|
|
105
|
+
}), (values) => {
|
|
106
|
+
target.time = hosted[name](...values);
|
|
107
|
+
return target.time;
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
]),
|
|
111
|
+
]);
|
|
112
|
+
return date;
|
|
208
113
|
};
|
package/dist/stdlib/json.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { HostNamespace } from "../interpreter/host.js";
|
|
2
1
|
import { type Runner } from "../interpreter/runner.js";
|
|
3
|
-
|
|
2
|
+
import { ProgramObject } from "../interpreter/objects.js";
|
|
3
|
+
export declare const jsonGlobal: <R>(runner: Runner<R>) => ProgramObject;
|
package/dist/stdlib/json.js
CHANGED
|
@@ -1,22 +1,25 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { methods } from "../interpreter/native.js";
|
|
3
3
|
import { applyCollectionCallback } from "../interpreter/runner.js";
|
|
4
4
|
import { InterpreterRuntimeError, syntaxError } from "../interpreter/model.js";
|
|
5
5
|
import { typeofValue } from "../interpreter/references.js";
|
|
6
6
|
import { fromData, toData, toProgram } from "../data.js";
|
|
7
|
-
import { get,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
import { Callable, get, keys, ProgramArray, ProgramObject, record, remove, set } from "../interpreter/objects.js";
|
|
8
|
+
export const jsonGlobal = (runner) => {
|
|
9
|
+
const json = new ProgramObject(runner.prototypes.Object);
|
|
10
|
+
methods(runner.prototypes, json, [
|
|
11
|
+
["parse", 2, (_, args, node) => parse(runner, args, node)],
|
|
12
|
+
["stringify", 3, (_, args, node) => stringify(runner, args, node)],
|
|
13
|
+
]);
|
|
14
|
+
return json;
|
|
15
|
+
};
|
|
13
16
|
const parse = (runner, args, node) => {
|
|
14
17
|
const text = args[0];
|
|
15
18
|
if (typeof text !== "string")
|
|
16
19
|
throw new InterpreterRuntimeError("JSON.parse expects a string.", node);
|
|
17
20
|
const parsed = (() => {
|
|
18
21
|
try {
|
|
19
|
-
return fromData(JSON.parse(text), "JSON.parse result");
|
|
22
|
+
return fromData(runner.prototypes, JSON.parse(text), "JSON.parse result");
|
|
20
23
|
}
|
|
21
24
|
catch (error) {
|
|
22
25
|
throw syntaxError(`JSON.parse received invalid JSON: ${error instanceof Error ? error.message : String(error)}`, node);
|
|
@@ -28,7 +31,7 @@ const parse = (runner, args, node) => {
|
|
|
28
31
|
const visit = (holder, key) => Effect.gen(function* () {
|
|
29
32
|
const value = get(holder, key);
|
|
30
33
|
if (value instanceof ProgramObject) {
|
|
31
|
-
for (const name of
|
|
34
|
+
for (const name of keys(value)) {
|
|
32
35
|
const revived = yield* visit(value, name);
|
|
33
36
|
if (revived === undefined)
|
|
34
37
|
remove(value, name);
|
|
@@ -38,7 +41,7 @@ const parse = (runner, args, node) => {
|
|
|
38
41
|
}
|
|
39
42
|
return yield* apply([key, value]);
|
|
40
43
|
});
|
|
41
|
-
return visit(record({ "": parsed }), "");
|
|
44
|
+
return visit(record(runner.prototypes.Object, { "": parsed }), "");
|
|
42
45
|
};
|
|
43
46
|
const stringify = (runner, args, node) => {
|
|
44
47
|
const space = args[2];
|
|
@@ -53,14 +56,14 @@ const stringify = (runner, args, node) => {
|
|
|
53
56
|
return Effect.succeed(JSON.stringify(toData(args[0], "JSON.stringify value"), properties, indent));
|
|
54
57
|
}
|
|
55
58
|
// Validate up front; the replacer walk below reads the original value.
|
|
56
|
-
toProgram(args[0], "JSON.stringify value");
|
|
59
|
+
toProgram(runner.prototypes, args[0], "JSON.stringify value");
|
|
57
60
|
const apply = applyCollectionCallback(runner, replacer, "JSON.stringify", node);
|
|
58
61
|
const stack = new Set();
|
|
59
62
|
const visit = (holder, key) => Effect.gen(function* () {
|
|
60
|
-
const value = yield* apply([key, toJSONValue(get(holder, key))]);
|
|
63
|
+
const value = yield* apply([key, yield* toJSONValue(runner, get(holder, key), key, node)]);
|
|
61
64
|
if (value === undefined || typeofValue(value) === "function")
|
|
62
65
|
return undefined;
|
|
63
|
-
toProgram(value, "JSON.stringify replacer result");
|
|
66
|
+
toProgram(runner.prototypes, value, "JSON.stringify replacer result");
|
|
64
67
|
if (typeof value === "number")
|
|
65
68
|
return Number.isFinite(value) ? value : null;
|
|
66
69
|
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
@@ -79,9 +82,7 @@ const stringify = (runner, args, node) => {
|
|
|
79
82
|
return result;
|
|
80
83
|
}
|
|
81
84
|
const result = Object.create(null);
|
|
82
|
-
for (const name of
|
|
83
|
-
if (typeof name !== "string")
|
|
84
|
-
continue;
|
|
85
|
+
for (const name of keys(value)) {
|
|
85
86
|
const item = yield* visit(value, name);
|
|
86
87
|
if (item !== undefined)
|
|
87
88
|
result[name] = item;
|
|
@@ -89,13 +90,12 @@ const stringify = (runner, args, node) => {
|
|
|
89
90
|
stack.delete(value);
|
|
90
91
|
return result;
|
|
91
92
|
});
|
|
92
|
-
return Effect.map(visit(record({ "": args[0] }), ""), (value) => JSON.stringify(value, null, indent));
|
|
93
|
+
return Effect.map(visit(record(runner.prototypes.Object, { "": args[0] }), ""), (value) => JSON.stringify(value, null, indent));
|
|
93
94
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return value;
|
|
95
|
+
// SerializeJSONProperty step 2: a callable `toJSON` decides the value, as Date and URL define.
|
|
96
|
+
const toJSONValue = (runner, value, key, node) => {
|
|
97
|
+
if (!(value instanceof ProgramObject))
|
|
98
|
+
return Effect.succeed(value);
|
|
99
|
+
const toJSON = get(value, "toJSON");
|
|
100
|
+
return toJSON instanceof Callable ? runner.invokeCallable(toJSON, value, [key], node) : Effect.succeed(value);
|
|
101
101
|
};
|
package/dist/stdlib/math.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProgramObject } from "../interpreter/objects.js";
|
|
2
2
|
import { type Runner } from "../interpreter/runner.js";
|
|
3
3
|
declare global {
|
|
4
4
|
interface Math {
|
|
5
5
|
sumPrecise(values: Iterable<number>): number;
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
export declare const mathGlobal: <R>(runner: Runner<R>) =>
|
|
8
|
+
export declare const mathGlobal: <R>(runner: Runner<R>) => ProgramObject;
|
package/dist/stdlib/math.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import {
|
|
3
|
-
import { preserveConsumerError } from "../interpreter/runner.js";
|
|
2
|
+
import { constants, methods } from "../interpreter/native.js";
|
|
4
3
|
import { InterpreterRuntimeError } from "../interpreter/model.js";
|
|
4
|
+
import { ProgramObject } from "../interpreter/objects.js";
|
|
5
|
+
import { preserveConsumerError } from "../interpreter/runner.js";
|
|
5
6
|
// Validate only the arguments a method consumes; like JS, extras are ignored
|
|
6
7
|
// (so built-ins work as callbacks receiving (element, index, array)).
|
|
7
8
|
const number = (name, args, index, node) => {
|
|
@@ -12,78 +13,97 @@ const number = (name, args, index, node) => {
|
|
|
12
13
|
throw new InterpreterRuntimeError(`Math.${name} expects number arguments.`, node);
|
|
13
14
|
return arg;
|
|
14
15
|
};
|
|
15
|
-
const unary = (name, op) =>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
name
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
16
|
+
const unary = (name, op) => [
|
|
17
|
+
name,
|
|
18
|
+
1,
|
|
19
|
+
(_, args, node) => op(number(name, args, 0, node)),
|
|
20
|
+
];
|
|
21
|
+
const binary = (name, op) => [
|
|
22
|
+
name,
|
|
23
|
+
2,
|
|
24
|
+
(_, args, node) => op(number(name, args, 0, node), number(name, args, 1, node)),
|
|
25
|
+
];
|
|
26
|
+
const variadic = (name, op) => [
|
|
27
|
+
name,
|
|
28
|
+
2,
|
|
29
|
+
(_, args, node) => op(...args.map((arg) => {
|
|
30
|
+
if (typeof arg !== "number")
|
|
31
|
+
throw new InterpreterRuntimeError(`Math.${name} expects number arguments.`, node);
|
|
32
|
+
return arg;
|
|
33
|
+
})),
|
|
34
|
+
];
|
|
35
|
+
export const mathGlobal = (runner) => {
|
|
36
|
+
const protos = runner.prototypes;
|
|
37
|
+
const math = new ProgramObject(protos.Object);
|
|
38
|
+
constants(math, {
|
|
39
|
+
PI: Math.PI,
|
|
40
|
+
E: Math.E,
|
|
41
|
+
LN2: Math.LN2,
|
|
42
|
+
LN10: Math.LN10,
|
|
43
|
+
LOG2E: Math.LOG2E,
|
|
44
|
+
LOG10E: Math.LOG10E,
|
|
45
|
+
SQRT2: Math.SQRT2,
|
|
46
|
+
SQRT1_2: Math.SQRT1_2,
|
|
47
|
+
});
|
|
48
|
+
methods(protos, math, [
|
|
49
|
+
["random", 0, () => Math.random()],
|
|
50
|
+
variadic("max", Math.max),
|
|
51
|
+
variadic("min", Math.min),
|
|
52
|
+
variadic("hypot", Math.hypot),
|
|
53
|
+
unary("abs", Math.abs),
|
|
54
|
+
unary("acos", Math.acos),
|
|
55
|
+
unary("acosh", Math.acosh),
|
|
56
|
+
unary("asin", Math.asin),
|
|
57
|
+
unary("asinh", Math.asinh),
|
|
58
|
+
unary("atan", Math.atan),
|
|
59
|
+
binary("atan2", Math.atan2),
|
|
60
|
+
unary("atanh", Math.atanh),
|
|
61
|
+
unary("floor", Math.floor),
|
|
62
|
+
unary("ceil", Math.ceil),
|
|
63
|
+
unary("round", Math.round),
|
|
64
|
+
unary("trunc", Math.trunc),
|
|
65
|
+
unary("sign", Math.sign),
|
|
66
|
+
unary("sqrt", Math.sqrt),
|
|
67
|
+
unary("cbrt", Math.cbrt),
|
|
68
|
+
binary("pow", Math.pow),
|
|
69
|
+
unary("cos", Math.cos),
|
|
70
|
+
unary("cosh", Math.cosh),
|
|
71
|
+
unary("sin", Math.sin),
|
|
72
|
+
unary("sinh", Math.sinh),
|
|
73
|
+
unary("tan", Math.tan),
|
|
74
|
+
unary("tanh", Math.tanh),
|
|
75
|
+
unary("log", Math.log),
|
|
76
|
+
unary("log2", Math.log2),
|
|
77
|
+
unary("log10", Math.log10),
|
|
78
|
+
unary("log1p", Math.log1p),
|
|
79
|
+
unary("exp", Math.exp),
|
|
80
|
+
unary("expm1", Math.expm1),
|
|
81
|
+
unary("f16round", Math.f16round),
|
|
82
|
+
unary("fround", Math.fround),
|
|
83
|
+
unary("clz32", Math.clz32),
|
|
84
|
+
binary("imul", Math.imul),
|
|
85
|
+
[
|
|
86
|
+
"sumPrecise",
|
|
87
|
+
1,
|
|
88
|
+
(_, args, node) => Effect.gen(function* () {
|
|
89
|
+
const cursor = yield* runner.syncIterator(args[0], node);
|
|
90
|
+
if (cursor === undefined) {
|
|
91
|
+
throw new InterpreterRuntimeError("Math.sumPrecise expects a synchronous iterable.", node);
|
|
92
|
+
}
|
|
93
|
+
const numbers = [];
|
|
94
|
+
while (true) {
|
|
95
|
+
const step = yield* cursor.next;
|
|
96
|
+
if (step.done)
|
|
97
|
+
return Math.sumPrecise(numbers);
|
|
98
|
+
yield* preserveConsumerError(cursor, Effect.sync(() => {
|
|
99
|
+
if (typeof step.value !== "number") {
|
|
100
|
+
throw new InterpreterRuntimeError("Math.sumPrecise expects an iterable of numbers.", node);
|
|
101
|
+
}
|
|
102
|
+
numbers.push(step.value);
|
|
103
|
+
}));
|
|
37
104
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
export const mathGlobal = (runner) => new HostNamespace("Math", {
|
|
44
|
-
PI: Math.PI,
|
|
45
|
-
E: Math.E,
|
|
46
|
-
LN2: Math.LN2,
|
|
47
|
-
LN10: Math.LN10,
|
|
48
|
-
LOG2E: Math.LOG2E,
|
|
49
|
-
LOG10E: Math.LOG10E,
|
|
50
|
-
SQRT2: Math.SQRT2,
|
|
51
|
-
SQRT1_2: Math.SQRT1_2,
|
|
52
|
-
random: sync("Math.random", () => Math.random()),
|
|
53
|
-
max: variadic("max", Math.max),
|
|
54
|
-
min: variadic("min", Math.min),
|
|
55
|
-
hypot: variadic("hypot", Math.hypot),
|
|
56
|
-
abs: unary("abs", Math.abs),
|
|
57
|
-
acos: unary("acos", Math.acos),
|
|
58
|
-
acosh: unary("acosh", Math.acosh),
|
|
59
|
-
asin: unary("asin", Math.asin),
|
|
60
|
-
asinh: unary("asinh", Math.asinh),
|
|
61
|
-
atan: unary("atan", Math.atan),
|
|
62
|
-
atan2: binary("atan2", Math.atan2),
|
|
63
|
-
atanh: unary("atanh", Math.atanh),
|
|
64
|
-
floor: unary("floor", Math.floor),
|
|
65
|
-
ceil: unary("ceil", Math.ceil),
|
|
66
|
-
round: unary("round", Math.round),
|
|
67
|
-
trunc: unary("trunc", Math.trunc),
|
|
68
|
-
sign: unary("sign", Math.sign),
|
|
69
|
-
sqrt: unary("sqrt", Math.sqrt),
|
|
70
|
-
cbrt: unary("cbrt", Math.cbrt),
|
|
71
|
-
pow: binary("pow", Math.pow),
|
|
72
|
-
cos: unary("cos", Math.cos),
|
|
73
|
-
cosh: unary("cosh", Math.cosh),
|
|
74
|
-
sin: unary("sin", Math.sin),
|
|
75
|
-
sinh: unary("sinh", Math.sinh),
|
|
76
|
-
tan: unary("tan", Math.tan),
|
|
77
|
-
tanh: unary("tanh", Math.tanh),
|
|
78
|
-
log: unary("log", Math.log),
|
|
79
|
-
log2: unary("log2", Math.log2),
|
|
80
|
-
log10: unary("log10", Math.log10),
|
|
81
|
-
log1p: unary("log1p", Math.log1p),
|
|
82
|
-
exp: unary("exp", Math.exp),
|
|
83
|
-
expm1: unary("expm1", Math.expm1),
|
|
84
|
-
f16round: unary("f16round", Math.f16round),
|
|
85
|
-
fround: unary("fround", Math.fround),
|
|
86
|
-
clz32: unary("clz32", Math.clz32),
|
|
87
|
-
imul: binary("imul", Math.imul),
|
|
88
|
-
sumPrecise: sumPrecise(runner),
|
|
89
|
-
});
|
|
105
|
+
}),
|
|
106
|
+
],
|
|
107
|
+
]);
|
|
108
|
+
return math;
|
|
109
|
+
};
|
package/dist/stdlib/number.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const
|
|
3
|
-
export declare const
|
|
4
|
-
export declare const numberGlobal: import("../interpreter/host.js").HostFunction<never>;
|
|
1
|
+
import type { Runner } from "../interpreter/runner.js";
|
|
2
|
+
export declare const numberGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
|
|
3
|
+
export declare const booleanGlobal: <R>(runner: Runner<R>) => import("../interpreter/objects.js").NativeFunction<R>;
|