@scriptc/compiler 0.3.5 → 0.3.6
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/ambient/scriptc-node-fallback.d.ts +278 -32
- package/dist/backend/llvm/dyn.js +31 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +45 -1
- package/dist/backend/llvm/emitter.js +412 -104
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +1 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +25 -1
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +11 -0
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +28 -1
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +61 -1
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +21 -3
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +10 -0
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +43 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-test.js +16 -3
- package/dist/backend/llvm/lib-test.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.d.ts +6 -3
- package/dist/backend/llvm/nullable-unions.js +2 -0
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +1 -1
- package/dist/backend/llvm/record-results.js +2 -2
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-writes.js +1 -0
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +3 -0
- package/dist/backend/llvm/shapes.js +5 -0
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +74 -0
- package/dist/backend/llvm/speculative-integers.js +571 -0
- package/dist/backend/llvm/speculative-integers.js.map +1 -0
- package/dist/backend/llvm/speculative-integers.test.d.ts +1 -0
- package/dist/backend/llvm/speculative-integers.test.js +148 -0
- package/dist/backend/llvm/speculative-integers.test.js.map +1 -0
- package/dist/backend/may-throw.js +2 -0
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/executable.js +3 -0
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +7 -3
- package/dist/backend/runtime-pack.js +12 -6
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +15 -6
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/contracts/check.js +1 -0
- package/dist/contracts/check.js.map +1 -1
- package/dist/coverage/surface-manifest.js +3 -3
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +1 -1
- package/dist/diagnostics/diagnostic.js +6 -2
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/builtin-calls.js +10 -0
- package/dist/frontend/lowering/builtin-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/callable-aliases.js +31 -3
- package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
- package/dist/frontend/lowering/builtins/compression.d.ts +9 -0
- package/dist/frontend/lowering/builtins/compression.js +145 -30
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.js +12 -1
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +5 -3
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +4 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +11 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.d.ts +8 -0
- package/dist/frontend/lowering/builtins/filesystem.js +139 -2
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/hash-stream.d.ts +12 -0
- package/dist/frontend/lowering/builtins/hash-stream.js +80 -0
- package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-calls.js +13 -3
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.js +9 -2
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +45 -13
- package/dist/frontend/lowering/builtins/readline.js +812 -47
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/workers.d.ts +4 -0
- package/dist/frontend/lowering/builtins/workers.js +58 -0
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +55 -0
- package/dist/frontend/lowering/class-protocols.js +735 -0
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/containers/array-from-async.d.ts +18 -0
- package/dist/frontend/lowering/containers/array-from-async.js +282 -0
- package/dist/frontend/lowering/containers/array-from-async.js.map +1 -0
- package/dist/frontend/lowering/containers/collection-grouping.js +2 -1
- package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +27 -23
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/divergences.js +188 -15
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +71 -22
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +39 -1
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.js +10 -1
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +107 -13
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +23 -3
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mock.d.ts +11 -1
- package/dist/frontend/lowering/lower-mock.js +377 -61
- package/dist/frontend/lowering/lower-mock.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +1 -0
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +161 -16
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +48 -7
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +1 -3
- package/dist/frontend/lowering/lower-stream.js +317 -20
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.js +147 -48
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +10 -0
- package/dist/frontend/lowering/lowerer.js +8 -0
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/null-prototype.d.ts +13 -0
- package/dist/frontend/lowering/null-prototype.js +33 -0
- package/dist/frontend/lowering/null-prototype.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +3 -3
- package/dist/frontend/lowering/surfaces.js +27 -5
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/mock-shapes.d.ts +5 -0
- package/dist/frontend/mock-shapes.js +27 -2
- package/dist/frontend/mock-shapes.js.map +1 -1
- package/dist/frontend/program.js +5 -4
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/type-mapper.js +95 -4
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +18 -8
- package/dist/index.js.map +1 -1
- package/dist/ir/builtin-effects.js +36 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +167 -6
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/function-references.test.js +1 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/int32-slots.js +22 -0
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +28 -0
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loop-facts.d.ts +14 -6
- package/dist/ir/integer-loop-facts.js +119 -35
- package/dist/ir/integer-loop-facts.js.map +1 -1
- package/dist/ir/integer-ranges.js +1 -5
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +60 -0
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/ir.d.ts +13 -0
- package/dist/ir/ir.js +4 -0
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +3 -1
- package/dist/ir/runtime-features.js +96 -6
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/runtime-features.test.js +62 -0
- package/dist/ir/runtime-features.test.js.map +1 -1
- package/dist/ir/traverse.js +4 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +45 -3
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +38 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/ir-policy.js +5 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +31 -19
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as ts from "../ts7/adapter.js";
|
|
2
2
|
import type { Lowerer } from "./lowerer.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type ClassInfo } from "./lower-classes.js";
|
|
4
4
|
import { type IrExpr, type IrStmt, type IrType, type SrcLoc } from "../../ir/ir.js";
|
|
5
5
|
/** The stream sides of a receiver class: the nearest stream-class
|
|
6
6
|
* ancestor's, or null off the stream hierarchy. */
|
|
@@ -86,8 +86,6 @@ export declare function lowerStreamModuleCall(lowerer: Lowerer, call: ts.CallExp
|
|
|
86
86
|
}, loc: SrcLoc): IrExpr | null;
|
|
87
87
|
/** The Readable operators (scr_stream_ops.c — Node's operators.js). */
|
|
88
88
|
export declare const STREAM_OPERATORS: ReadonlySet<string>;
|
|
89
|
-
/** `recv.<member>(...)` over a stream-rooted receiver. Returns null only
|
|
90
|
-
* for members this spoke does not own. */
|
|
91
89
|
export declare function lowerStreamMethodCall(lowerer: Lowerer, call: ts.CallExpression, access: ts.PropertyAccessExpression, info: ClassInfo): IrExpr | null;
|
|
92
90
|
export declare function lowerStreamStateProperty(lowerer: Lowerer, expr: ts.PropertyAccessExpression): IrExpr | null;
|
|
93
91
|
/** Property reads on stream-rooted receivers (`r.readableEnded`,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nodeThrowExpr, boolLit, numLit, strLit } from "../../ir/build.js";
|
|
2
|
+
import { hashStreamOf, isHashValueType } from "./builtins/hash-stream.js";
|
|
2
3
|
import { InternalCompilerError } from "../../errors.js";
|
|
3
4
|
/* The node:stream lowering (the spoke-module pattern, like
|
|
4
5
|
* lower-event-emitter.ts): construction of the five runtime stream classes
|
|
@@ -30,6 +31,7 @@ import { InternalCompilerError } from "../../errors.js";
|
|
|
30
31
|
* its Node signature (the emitter listener rule). */
|
|
31
32
|
import * as ts from "../ts7/adapter.js";
|
|
32
33
|
import { dynFallbackType } from "./lowerer.js";
|
|
34
|
+
import { accessorCall, classIteratorNextCall, classIteratorOf, classIteratorOpenCall, } from "./lower-classes.js";
|
|
33
35
|
import { isJsSourceFile, locOf } from "../program.js";
|
|
34
36
|
import { newFnCtx, own } from "./lowerer.js";
|
|
35
37
|
import { appendImplicitUndefinedReturn } from "./function-returns.js";
|
|
@@ -161,6 +163,7 @@ export const STREAM_FORCED_EVENT_NAMES = new Set([
|
|
|
161
163
|
"unpipe",
|
|
162
164
|
"open",
|
|
163
165
|
"ready",
|
|
166
|
+
"keypress",
|
|
164
167
|
]);
|
|
165
168
|
/** The per-base FORCED event tuples (runtime-emitted payloads): consulted
|
|
166
169
|
* by the emitter spoke BEFORE the program-global table, so a stream's
|
|
@@ -181,6 +184,8 @@ export function streamForcedTuple(lowerer, info, name) {
|
|
|
181
184
|
resume: [],
|
|
182
185
|
open: [F64],
|
|
183
186
|
ready: [],
|
|
187
|
+
// readline.emitKeypressEvents' (str, key), as checked-dynamic values
|
|
188
|
+
keypress: [DYN, DYN],
|
|
184
189
|
};
|
|
185
190
|
const writable = {
|
|
186
191
|
open: [F64],
|
|
@@ -1191,21 +1196,66 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1191
1196
|
const single = typedElem(srcT);
|
|
1192
1197
|
const elem = srcT?.kind === "array" ? typedElem(srcT.elem) : null;
|
|
1193
1198
|
const opts = optsNode ? fromOptions(lowerer, optsNode) : { flags: 0, hwm: null };
|
|
1194
|
-
|
|
1199
|
+
// A class whose [Symbol.iterator]() or [Symbol.asyncIterator]() is a
|
|
1200
|
+
// generator method: from.js calls the method when the stream is built,
|
|
1201
|
+
// then reads the generator like any other.
|
|
1202
|
+
const genMethod = srcT?.kind === "object" ? classGeneratorMethodOf(lowerer, srcT) : null;
|
|
1203
|
+
const genT = srcT?.kind === "generator" ? srcT : (genMethod?.gen ?? null);
|
|
1204
|
+
if (srcNode && genT && opts && fromGenChunk(lowerer, genT.yieldT)) {
|
|
1195
1205
|
// A compiled generator: the runtime pulls it through interned helpers.
|
|
1196
|
-
const
|
|
1197
|
-
const
|
|
1206
|
+
const recv = lowerer.lowerExpr(srcNode);
|
|
1207
|
+
const gen = genMethod && srcT?.kind === "object"
|
|
1208
|
+
? accessorCall(lowerer, srcT.className, genMethod.method, recv, [], genT, loc)
|
|
1209
|
+
: recv;
|
|
1210
|
+
const helpers = fromGenHelpers(lowerer, genT, loc);
|
|
1198
1211
|
if (helpers) {
|
|
1199
1212
|
const hwm = opts.hwm ? lowerer.lowerExprExpecting(opts.hwm, F64) : numLit(0, loc);
|
|
1200
1213
|
return {
|
|
1201
1214
|
kind: "libCall",
|
|
1202
|
-
fn:
|
|
1215
|
+
fn: genT.async ? "readable.fromAsyncGen" : "readable.fromGen",
|
|
1203
1216
|
args: [gen, ...helpers, numLit(opts.flags, loc), hwm],
|
|
1204
1217
|
type,
|
|
1205
1218
|
loc,
|
|
1206
1219
|
};
|
|
1207
1220
|
}
|
|
1208
1221
|
}
|
|
1222
|
+
// from.js prefers Symbol.asyncIterator: a class declaring one takes the
|
|
1223
|
+
// async route.
|
|
1224
|
+
const asyncOpen = srcT?.kind === "object" &&
|
|
1225
|
+
lowerer.classes.has(srcT.className) &&
|
|
1226
|
+
lowerer.findMethodOn(lowerer.classes.get(srcT.className), "sym:asyncIterator") !== null;
|
|
1227
|
+
const cit = srcT?.kind === "object" && !asyncOpen ? classIteratorOf(lowerer, srcT) : null;
|
|
1228
|
+
if (srcNode && cit && opts && fromGenChunk(lowerer, cit.valueT)) {
|
|
1229
|
+
// A class iterable: from.js takes the iterator when the stream is
|
|
1230
|
+
// built (the typed [Symbol.iterator]() call here), and the runtime
|
|
1231
|
+
// pulls it through a checked-dynamic { next } object. Class iterators
|
|
1232
|
+
// declare no return() or throw(), so destroy calls neither.
|
|
1233
|
+
const recv = lowerer.lowerExpr(srcNode);
|
|
1234
|
+
const hwm = opts.hwm ? lowerer.lowerExprExpecting(opts.hwm, F64) : numLit(0, loc);
|
|
1235
|
+
return {
|
|
1236
|
+
kind: "libCall",
|
|
1237
|
+
fn: "readable.fromIter",
|
|
1238
|
+
args: [
|
|
1239
|
+
classIteratorObject(lowerer, cit, classIteratorOpenCall(lowerer, cit, recv, loc), loc),
|
|
1240
|
+
numLit(opts.flags, loc),
|
|
1241
|
+
hwm,
|
|
1242
|
+
],
|
|
1243
|
+
type,
|
|
1244
|
+
loc,
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
const acit = srcT?.kind === "object" && asyncOpen ? classAsyncIteratorOf(lowerer, srcT) : null;
|
|
1248
|
+
if (srcNode && acit && opts && fromGenChunk(lowerer, acit.valueT)) {
|
|
1249
|
+
const recv = lowerer.lowerExpr(srcNode);
|
|
1250
|
+
const hwm = opts.hwm ? lowerer.lowerExprExpecting(opts.hwm, F64) : numLit(0, loc);
|
|
1251
|
+
return {
|
|
1252
|
+
kind: "libCall",
|
|
1253
|
+
fn: "readable.fromAsyncIter",
|
|
1254
|
+
args: [classAsyncIteratorObject(lowerer, acit, recv, loc), numLit(opts.flags, loc), hwm],
|
|
1255
|
+
type,
|
|
1256
|
+
loc,
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1209
1259
|
if (srcNode && (single || elem) && opts) {
|
|
1210
1260
|
const v = lowerer.lowerExpr(srcNode);
|
|
1211
1261
|
const hwm = opts.hwm ? lowerer.lowerExprExpecting(opts.hwm, F64) : numLit(0, loc);
|
|
@@ -1222,6 +1272,7 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1222
1272
|
};
|
|
1223
1273
|
}
|
|
1224
1274
|
const anySrc = srcT?.kind === "dyn" ||
|
|
1275
|
+
(srcT?.kind === "set" && typedElem(srcT.elem) !== null) ||
|
|
1225
1276
|
(srcNode !== undefined &&
|
|
1226
1277
|
srcT === null &&
|
|
1227
1278
|
(lowerer.typeOf(srcNode).flags & ts.TypeFlags.Any) !== 0);
|
|
@@ -1235,7 +1286,7 @@ export function lowerStreamStaticCall(lowerer, call, access) {
|
|
|
1235
1286
|
if (srcNode && (single || elem)) {
|
|
1236
1287
|
lowerer.noLowering("Readable.from with these options", optsNode, "an object literal with 'objectMode' (true or false) and a number 'highWaterMark' is supported");
|
|
1237
1288
|
}
|
|
1238
|
-
lowerer.noLowering(`Readable.from over a '${srcT ? lowerer.fmt(srcT) : "?"}' source`, srcNode ?? call, "
|
|
1289
|
+
lowerer.noLowering(`Readable.from over a '${srcT ? lowerer.fmt(srcT) : "?"}' source`, srcNode ?? call, "the supported sources are a string or Buffer, and arrays, Sets, generators and class iterables of strings or Buffers");
|
|
1239
1290
|
}
|
|
1240
1291
|
/** Whether a generator's yields are stream chunks: strings, Buffers, a
|
|
1241
1292
|
* union of them (null included: the runtime destroys the stream with
|
|
@@ -1363,6 +1414,210 @@ function fromGenHelpers(lowerer, gen, loc) {
|
|
|
1363
1414
|
define("throw", [g, e], DYN, viaRecord("throw"), [r]),
|
|
1364
1415
|
];
|
|
1365
1416
|
}
|
|
1417
|
+
/** `{ next() { const r = it.next(); return { value: r.value, done: r.done }; } }`
|
|
1418
|
+
* over a class iterator `it`, as a checked-dynamic object: an interned
|
|
1419
|
+
* lifted function per iterator class takes the iterator and answers the
|
|
1420
|
+
* object, whose `next` closure captures it. */
|
|
1421
|
+
function classIteratorObject(lowerer, cit, iter, loc) {
|
|
1422
|
+
const key = `streamFromIter:${cit.iterT.className}`;
|
|
1423
|
+
let name = lowerer.valueHelpers.get(key);
|
|
1424
|
+
if (!name) {
|
|
1425
|
+
name = `%stream.fromIter.${lowerer.valueHelpers.size}`;
|
|
1426
|
+
lowerer.valueHelpers.set(key, name);
|
|
1427
|
+
const nextName = `${name}.next`;
|
|
1428
|
+
const nextT = funcOf([], DYN);
|
|
1429
|
+
const it = { id: "it.0", name: "it", type: cit.iterT, mutable: false, boxed: true };
|
|
1430
|
+
const r = { id: "res.0", name: "res", type: cit.resultT, mutable: false };
|
|
1431
|
+
const field = (f, t) => ({
|
|
1432
|
+
kind: "recordGet",
|
|
1433
|
+
obj: varRef(r.id, cit.resultT, loc),
|
|
1434
|
+
shapeId: cit.resultT.shapeId,
|
|
1435
|
+
field: f,
|
|
1436
|
+
type: t,
|
|
1437
|
+
loc,
|
|
1438
|
+
});
|
|
1439
|
+
const str = (value) => ({ kind: "strLit", value, type: STRING, loc });
|
|
1440
|
+
lowerer.liftedFns.push({
|
|
1441
|
+
name: nextName,
|
|
1442
|
+
params: [],
|
|
1443
|
+
returnType: DYN,
|
|
1444
|
+
captures: [{ localId: it.id, name: it.name, type: it.type }],
|
|
1445
|
+
locals: [it, r],
|
|
1446
|
+
body: [
|
|
1447
|
+
{
|
|
1448
|
+
kind: "varDecl",
|
|
1449
|
+
localId: r.id,
|
|
1450
|
+
init: classIteratorNextCall(lowerer, cit, varRef(it.id, cit.iterT, loc), loc),
|
|
1451
|
+
loc,
|
|
1452
|
+
},
|
|
1453
|
+
{
|
|
1454
|
+
kind: "return",
|
|
1455
|
+
value: {
|
|
1456
|
+
kind: "dynObjLit",
|
|
1457
|
+
fields: [
|
|
1458
|
+
{
|
|
1459
|
+
key: str("value"),
|
|
1460
|
+
value: lowerer.coerceToExpected(field("value", cit.valueT), DYN),
|
|
1461
|
+
},
|
|
1462
|
+
{
|
|
1463
|
+
key: str("done"),
|
|
1464
|
+
value: {
|
|
1465
|
+
kind: "dynFrom",
|
|
1466
|
+
value: cit.hasDone ? field("done", BOOL) : boolLit(false, loc),
|
|
1467
|
+
type: DYN,
|
|
1468
|
+
loc,
|
|
1469
|
+
},
|
|
1470
|
+
},
|
|
1471
|
+
],
|
|
1472
|
+
type: DYN,
|
|
1473
|
+
loc,
|
|
1474
|
+
},
|
|
1475
|
+
loc,
|
|
1476
|
+
},
|
|
1477
|
+
],
|
|
1478
|
+
loc,
|
|
1479
|
+
});
|
|
1480
|
+
lowerer.liftedFns.push({
|
|
1481
|
+
name,
|
|
1482
|
+
params: [{ localId: it.id, name: it.name, type: it.type }],
|
|
1483
|
+
returnType: DYN,
|
|
1484
|
+
locals: [it],
|
|
1485
|
+
body: [
|
|
1486
|
+
{
|
|
1487
|
+
kind: "return",
|
|
1488
|
+
value: {
|
|
1489
|
+
kind: "dynObjLit",
|
|
1490
|
+
fields: [
|
|
1491
|
+
{
|
|
1492
|
+
key: str("next"),
|
|
1493
|
+
value: {
|
|
1494
|
+
kind: "dynFrom",
|
|
1495
|
+
value: { kind: "closure", fnName: nextName, captures: [it.id], type: nextT, loc },
|
|
1496
|
+
type: DYN,
|
|
1497
|
+
loc,
|
|
1498
|
+
},
|
|
1499
|
+
},
|
|
1500
|
+
],
|
|
1501
|
+
type: DYN,
|
|
1502
|
+
loc,
|
|
1503
|
+
},
|
|
1504
|
+
loc,
|
|
1505
|
+
},
|
|
1506
|
+
],
|
|
1507
|
+
loc,
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
return { kind: "call", callee: name, args: [iter], type: DYN, loc };
|
|
1511
|
+
}
|
|
1512
|
+
/** A class's zero-parameter `[Symbol.asyncIterator]()` (checked first, as
|
|
1513
|
+
* from.js does) or `[Symbol.iterator]()` method that returns a generator,
|
|
1514
|
+
* with its method slot. */
|
|
1515
|
+
function classGeneratorMethodOf(lowerer, t) {
|
|
1516
|
+
const info = lowerer.classes.get(t.className);
|
|
1517
|
+
if (!info)
|
|
1518
|
+
return null;
|
|
1519
|
+
for (const method of ["sym:asyncIterator", "sym:iterator"]) {
|
|
1520
|
+
const m = lowerer.findMethodOn(info, method);
|
|
1521
|
+
if (!m)
|
|
1522
|
+
continue;
|
|
1523
|
+
const ret = m.sig.ret;
|
|
1524
|
+
if (m.sig.abstract === true || m.sig.params.length !== 0 || ret.kind !== "generator")
|
|
1525
|
+
return null;
|
|
1526
|
+
return { method, gen: ret };
|
|
1527
|
+
}
|
|
1528
|
+
return null;
|
|
1529
|
+
}
|
|
1530
|
+
function classAsyncIteratorOf(lowerer, t) {
|
|
1531
|
+
const info = lowerer.classes.get(t.className);
|
|
1532
|
+
const open = info ? lowerer.findMethodOn(info, "sym:asyncIterator") : null;
|
|
1533
|
+
if (!open || open.sig.abstract === true || open.sig.params.length !== 0)
|
|
1534
|
+
return null;
|
|
1535
|
+
const iterT = open.sig.ret;
|
|
1536
|
+
if (iterT.kind !== "object")
|
|
1537
|
+
return null;
|
|
1538
|
+
const itInfo = lowerer.classes.get(iterT.className);
|
|
1539
|
+
if (!itInfo || lowerer.findMethodOn(itInfo, "throw"))
|
|
1540
|
+
return null;
|
|
1541
|
+
const record = (name) => {
|
|
1542
|
+
const m = lowerer.findMethodOn(itInfo, name);
|
|
1543
|
+
if (!m || m.sig.abstract === true || m.sig.params.length !== 0)
|
|
1544
|
+
return null;
|
|
1545
|
+
const ret = m.sig.ret;
|
|
1546
|
+
return ret.kind === "promise" && ret.inner.kind === "record" ? ret.inner : null;
|
|
1547
|
+
};
|
|
1548
|
+
const resultT = record("next");
|
|
1549
|
+
if (!resultT)
|
|
1550
|
+
return null;
|
|
1551
|
+
const shape = lowerer.shapes.get(resultT.shapeId);
|
|
1552
|
+
const value = shape?.fields.find((f) => f.name === "value");
|
|
1553
|
+
const done = shape?.fields.find((f) => f.name === "done");
|
|
1554
|
+
if (!value || (done && done.type.kind !== "bool"))
|
|
1555
|
+
return null;
|
|
1556
|
+
const hasReturn = lowerer.findMethodOn(itInfo, "return") !== null;
|
|
1557
|
+
if (hasReturn && !record("return"))
|
|
1558
|
+
return null;
|
|
1559
|
+
return { className: t.className, iterT, resultT, valueT: value.type, hasReturn };
|
|
1560
|
+
}
|
|
1561
|
+
/** The checked-dynamic iterator object over an async class iterable:
|
|
1562
|
+
* `recv[Symbol.asyncIterator]()` runs when the stream is built, and the
|
|
1563
|
+
* object's `next` (and `return`, when the class declares one) answer the
|
|
1564
|
+
* iterator's own promises boxed. */
|
|
1565
|
+
function classAsyncIteratorObject(lowerer, cit, recv, loc) {
|
|
1566
|
+
const key = `streamFromAsyncIter:${cit.className}`;
|
|
1567
|
+
let name = lowerer.valueHelpers.get(key);
|
|
1568
|
+
if (!name) {
|
|
1569
|
+
name = `%stream.fromAsyncIter.${lowerer.valueHelpers.size}`;
|
|
1570
|
+
lowerer.valueHelpers.set(key, name);
|
|
1571
|
+
const it = { id: "it.0", name: "it", type: cit.iterT, mutable: false, boxed: true };
|
|
1572
|
+
const src = {
|
|
1573
|
+
id: "src.0",
|
|
1574
|
+
name: "src",
|
|
1575
|
+
type: { kind: "object", className: cit.className },
|
|
1576
|
+
mutable: false,
|
|
1577
|
+
};
|
|
1578
|
+
const str = (value) => ({ kind: "strLit", value, type: STRING, loc });
|
|
1579
|
+
const method = (m) => {
|
|
1580
|
+
const fnName = `${name}.${m}`;
|
|
1581
|
+
const call = accessorCall(lowerer, cit.iterT.className, m, varRef(it.id, cit.iterT, loc), [], { kind: "promise", inner: cit.resultT }, loc);
|
|
1582
|
+
lowerer.liftedFns.push({
|
|
1583
|
+
name: fnName,
|
|
1584
|
+
params: [],
|
|
1585
|
+
returnType: DYN,
|
|
1586
|
+
captures: [{ localId: it.id, name: it.name, type: it.type }],
|
|
1587
|
+
locals: [it],
|
|
1588
|
+
body: [{ kind: "return", value: { kind: "dynFrom", value: call, type: DYN, loc }, loc }],
|
|
1589
|
+
loc,
|
|
1590
|
+
});
|
|
1591
|
+
return {
|
|
1592
|
+
key: str(m),
|
|
1593
|
+
value: {
|
|
1594
|
+
kind: "dynFrom",
|
|
1595
|
+
value: { kind: "closure", fnName, captures: [it.id], type: funcOf([], DYN), loc },
|
|
1596
|
+
type: DYN,
|
|
1597
|
+
loc,
|
|
1598
|
+
},
|
|
1599
|
+
};
|
|
1600
|
+
};
|
|
1601
|
+
const fields = [method("next"), ...(cit.hasReturn ? [method("return")] : [])];
|
|
1602
|
+
lowerer.liftedFns.push({
|
|
1603
|
+
name,
|
|
1604
|
+
params: [{ localId: src.id, name: src.name, type: src.type }],
|
|
1605
|
+
returnType: DYN,
|
|
1606
|
+
locals: [src, it],
|
|
1607
|
+
body: [
|
|
1608
|
+
{
|
|
1609
|
+
kind: "varDecl",
|
|
1610
|
+
localId: it.id,
|
|
1611
|
+
init: accessorCall(lowerer, cit.className, "sym:asyncIterator", varRef(src.id, src.type, loc), [], cit.iterT, loc),
|
|
1612
|
+
loc,
|
|
1613
|
+
},
|
|
1614
|
+
{ kind: "return", value: { kind: "dynObjLit", fields, type: DYN, loc }, loc },
|
|
1615
|
+
],
|
|
1616
|
+
loc,
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
return { kind: "call", callee: name, args: [recv], type: DYN, loc };
|
|
1620
|
+
}
|
|
1366
1621
|
/** Readable.from's typed options: an object literal of `objectMode`
|
|
1367
1622
|
* (a boolean literal) and `highWaterMark` (a number), as SCR_FROM_* flag
|
|
1368
1623
|
* bits and the hwm expression; null for any other shape. */
|
|
@@ -1429,7 +1684,12 @@ const PIPELINE_STAGE_EXPECTED = "of type function or an instance of Blob, Readab
|
|
|
1429
1684
|
* { readable, writable } pairs — those shapes fence instead of throwing
|
|
1430
1685
|
* a ladder Node never throws. */
|
|
1431
1686
|
function lowerStreamArg(lowerer, node, what) {
|
|
1432
|
-
const
|
|
1687
|
+
const lowered = lowerer.lowerExpr(node);
|
|
1688
|
+
// A Hash or Hmac stage is its Transform; pipeline and compose stages
|
|
1689
|
+
// keep the value alive until the stream settles.
|
|
1690
|
+
const v = isHashValueType(lowered.type)
|
|
1691
|
+
? hashStreamOf(lowered, what === "pipeline" || what === "compose")
|
|
1692
|
+
: lowered;
|
|
1433
1693
|
const info = v.type.kind === "object" ? lowerer.classes.get(v.type.className) : undefined;
|
|
1434
1694
|
if (!streamSidesOf(lowerer, info)) {
|
|
1435
1695
|
// A provably-non-stream value in a JS source (the invalid-input
|
|
@@ -2420,6 +2680,22 @@ function checkUtf8Encoding(lowerer, member, arg) {
|
|
|
2420
2680
|
}
|
|
2421
2681
|
/** `recv.<member>(...)` over a stream-rooted receiver. Returns null only
|
|
2422
2682
|
* for members this spoke does not own. */
|
|
2683
|
+
/** pipe()'s `{ end }` option: true when absent. */
|
|
2684
|
+
function pipeEndOption(lowerer, options, loc) {
|
|
2685
|
+
let end = boolLit(true, loc);
|
|
2686
|
+
if (options === undefined)
|
|
2687
|
+
return end;
|
|
2688
|
+
if (!ts.isObjectLiteralExpression(options)) {
|
|
2689
|
+
lowerer.noLowering("pipe with a non-literal options argument", options, "{ end: <bool> } inline is the supported form");
|
|
2690
|
+
}
|
|
2691
|
+
for (const prop of options.properties) {
|
|
2692
|
+
if (!ts.isPropertyAssignment(prop) || !ts.isIdentifier(prop.name) || prop.name.text !== "end") {
|
|
2693
|
+
lowerer.noLowering("a pipe option other than 'end'", prop);
|
|
2694
|
+
}
|
|
2695
|
+
end = lowerer.lowerExprExpecting(prop.initializer, BOOL);
|
|
2696
|
+
}
|
|
2697
|
+
return end;
|
|
2698
|
+
}
|
|
2423
2699
|
export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
2424
2700
|
const member = access.name.text;
|
|
2425
2701
|
if (STREAM_OPERATORS.has(member)) {
|
|
@@ -2604,26 +2880,47 @@ export function lowerStreamMethodCall(lowerer, call, access, info) {
|
|
|
2604
2880
|
if (args.length === 0 || args.length > 2) {
|
|
2605
2881
|
lowerer.noLowering(`pipe with ${args.length} arguments`, call, "the supported forms are (destination) and (destination, { end })");
|
|
2606
2882
|
}
|
|
2883
|
+
// A Hash or Hmac destination pipes into its Transform, and pipe()
|
|
2884
|
+
// answers the Hash itself (the receiver evaluates first, as in JS).
|
|
2885
|
+
if (isHashValueType(lowerer.mapTypeOf(lowerer.typeOf(args[0])))) {
|
|
2886
|
+
const receiverValue = lowerer.lowerExpr(access.expression);
|
|
2887
|
+
const source = lowerer.declareHiddenLocal("%pipeSource", receiverValue.type);
|
|
2888
|
+
const hashValue = lowerer.lowerExpr(args[0]);
|
|
2889
|
+
const hash = lowerer.declareHiddenLocal("%pipeHash", hashValue.type);
|
|
2890
|
+
const end = pipeEndOption(lowerer, args[1], loc);
|
|
2891
|
+
return {
|
|
2892
|
+
kind: "seqExpr",
|
|
2893
|
+
stmts: [
|
|
2894
|
+
{ kind: "varDecl", localId: source.id, init: receiverValue, loc },
|
|
2895
|
+
{ kind: "varDecl", localId: hash.id, init: hashValue, loc },
|
|
2896
|
+
{
|
|
2897
|
+
kind: "exprStmt",
|
|
2898
|
+
expr: {
|
|
2899
|
+
kind: "libCall",
|
|
2900
|
+
fn: "readable.pipe",
|
|
2901
|
+
args: [
|
|
2902
|
+
{ kind: "varRef", localId: source.id, type: receiverValue.type, loc },
|
|
2903
|
+
hashStreamOf({ kind: "varRef", localId: hash.id, type: hashValue.type, loc }, true),
|
|
2904
|
+
end,
|
|
2905
|
+
],
|
|
2906
|
+
type: { kind: "object", className: "%Transform" },
|
|
2907
|
+
loc,
|
|
2908
|
+
},
|
|
2909
|
+
loc,
|
|
2910
|
+
},
|
|
2911
|
+
],
|
|
2912
|
+
result: { kind: "varRef", localId: hash.id, type: hashValue.type, loc },
|
|
2913
|
+
type: hashValue.type,
|
|
2914
|
+
loc,
|
|
2915
|
+
};
|
|
2916
|
+
}
|
|
2607
2917
|
const dst = lowerer.lowerExpr(args[0]);
|
|
2608
2918
|
const dstInfo = dst.type.kind === "object" ? lowerer.classes.get(dst.type.className) : undefined;
|
|
2609
2919
|
const dstSides = streamSidesOf(lowerer, dstInfo);
|
|
2610
2920
|
if (dstSides !== "w" && dstSides !== "rw") {
|
|
2611
2921
|
lowerer.noLowering(`pipe into a '${lowerer.fmt(dst.type)}'`, args[0], "the destination must be a stream Writable/Duplex (process streams and sockets are not pipe destinations yet)");
|
|
2612
2922
|
}
|
|
2613
|
-
|
|
2614
|
-
if (args[1] !== undefined) {
|
|
2615
|
-
if (!ts.isObjectLiteralExpression(args[1])) {
|
|
2616
|
-
lowerer.noLowering("pipe with a non-literal options argument", args[1], "{ end: <bool> } inline is the supported form");
|
|
2617
|
-
}
|
|
2618
|
-
for (const prop of args[1].properties) {
|
|
2619
|
-
if (!ts.isPropertyAssignment(prop) ||
|
|
2620
|
-
!ts.isIdentifier(prop.name) ||
|
|
2621
|
-
prop.name.text !== "end") {
|
|
2622
|
-
lowerer.noLowering("a pipe option other than 'end'", prop);
|
|
2623
|
-
}
|
|
2624
|
-
end = lowerer.lowerExprExpecting(prop.initializer, BOOL);
|
|
2625
|
-
}
|
|
2626
|
-
}
|
|
2923
|
+
const end = pipeEndOption(lowerer, args[1], loc);
|
|
2627
2924
|
const receiver = lowerer.lowerExpr(access.expression);
|
|
2628
2925
|
return {
|
|
2629
2926
|
kind: "libCall",
|