@scriptc/compiler 0.0.32 → 0.0.33
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/backend/cc-cache.test.js +308 -1
- package/dist/backend/cc-cache.test.js.map +1 -1
- package/dist/backend/cc.d.ts +6 -0
- package/dist/backend/cc.js +707 -68
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +53 -2
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +12 -5
- package/dist/backend/emission/emitter.js +160 -22
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +7 -4
- package/dist/backend/emission/may-throw.js.map +1 -1
- package/dist/backend/ffi-callbacks.d.ts +38 -1
- package/dist/backend/ffi-callbacks.js +76 -3
- package/dist/backend/ffi-callbacks.js.map +1 -1
- package/dist/backend/llvm/emitter.js +243 -12
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/diagnostics/diagnostic.js +2 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/ffi/profile.d.ts +17 -5
- package/dist/ffi/profile.js +169 -22
- package/dist/ffi/profile.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +1 -0
- package/dist/frontend/lowering/lower-calls.js +89 -23
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.js +65 -19
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +12 -0
- package/dist/frontend/lowering/lowerer.js +20 -1
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +2 -0
- package/dist/frontend/ts7/checker.js +20 -3
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/types.d.ts +8 -0
- package/dist/frontend/types.js +33 -5
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +22 -9
- package/dist/ir/nodes.js +7 -1
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/validate.js +74 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/profile.d.ts +3 -0
- package/dist/library/profile.js +9 -1
- package/dist/library/profile.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* generic instantiation (bounded by MAX_GENERIC_INSTANCES). */
|
|
5
5
|
import * as ts from "../ts7/adapter.js";
|
|
6
6
|
import { lowerGenMethodCall } from "./lower-generators.js";
|
|
7
|
-
import { BOOL, CAUGHT, DYN, F64, JSVAL, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isFfiCallbackParam, isFfiContextParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/nodes.js";
|
|
7
|
+
import { BOOL, CAUGHT, DYN, F64, JSVAL, STRING, SYMBOL_T, UNDEFINED_T, VOID, arrayOf, canBoxFuncIntoDyn, canConvertToDyn, canDynCheckTo, canMarshalTypedFuncIntoIsland, ffiClassType, ffiSourceParamTypes, funcOf, isFfiCallbackParam, isFfiContextParam, isFfiReleaseParam, isUnitType, shapeHasAccessorSlots, typeEquals } from "../../ir/nodes.js";
|
|
8
8
|
import { isJsSourceFile, locOf } from "../program.js";
|
|
9
9
|
import { isGenericCallableMemberType, typeKey } from "../types.js";
|
|
10
10
|
import { PoisonError, dynFallbackType, dynUndefinedExpr, importCallHandleType, jsFuncNameOf, newFnCtx, nodeThrowExpr } from "./lowerer.js";
|
|
@@ -2276,7 +2276,11 @@ function ffiSourceParams(binding) {
|
|
|
2276
2276
|
return binding.params.filter((param) => !isFfiContextParam(param));
|
|
2277
2277
|
}
|
|
2278
2278
|
function ffiParamDisplay(param) {
|
|
2279
|
-
return isFfiCallbackParam(param)
|
|
2279
|
+
return isFfiCallbackParam(param)
|
|
2280
|
+
? `callback '${param.callback.id}'`
|
|
2281
|
+
: isFfiReleaseParam(param)
|
|
2282
|
+
? `release callback '${param.callback.release}'`
|
|
2283
|
+
: `class '${param}'`;
|
|
2280
2284
|
}
|
|
2281
2285
|
/** Callback arguments flow from native code into TypeScript. Their source
|
|
2282
2286
|
* declarations therefore need to cover the whole scalar domain represented
|
|
@@ -2302,12 +2306,23 @@ function ffiCallbackInputDiagnostic(L, descriptor, callbackType) {
|
|
|
2302
2306
|
!typeEquals(mapped, ffiClassType(nativeClass))) {
|
|
2303
2307
|
continue;
|
|
2304
2308
|
}
|
|
2305
|
-
|
|
2309
|
+
if (nativeClass === "bytes")
|
|
2310
|
+
continue;
|
|
2311
|
+
const domain = nativeClass === "bool"
|
|
2312
|
+
? "boolean"
|
|
2313
|
+
: nativeClass === "cstring" || nativeClass === "string"
|
|
2314
|
+
? "string"
|
|
2315
|
+
: "number";
|
|
2306
2316
|
const coversDomain = nativeClass === "bool"
|
|
2307
2317
|
? (paramType.flags & ts.TypeFlags.Boolean) !== 0
|
|
2308
|
-
:
|
|
2318
|
+
: nativeClass === "cstring" || nativeClass === "string"
|
|
2319
|
+
? (paramType.flags & ts.TypeFlags.String) !== 0
|
|
2320
|
+
: (paramType.flags & ts.TypeFlags.Number) !== 0;
|
|
2309
2321
|
if (!coversDomain) {
|
|
2310
|
-
|
|
2322
|
+
const descriptorName = isFfiCallbackParam(descriptor)
|
|
2323
|
+
? descriptor.callback.id
|
|
2324
|
+
: descriptor.callback.release;
|
|
2325
|
+
return (`callback '${descriptorName}' parameter ${i + 1} is '${L.checker.typeToString(paramType)}', ` +
|
|
2311
2326
|
`but native class '${nativeClass}' may supply any ${domain}; declare it as '${domain}'`);
|
|
2312
2327
|
}
|
|
2313
2328
|
}
|
|
@@ -2379,7 +2394,7 @@ function ffiDeclarationDiagnostic(L, binding, symbol, loc) {
|
|
|
2379
2394
|
if ((paramType.flags & ts.TypeFlags.Never) !== 0) {
|
|
2380
2395
|
return signatureDiag(binding.name, `parameter ${i + 1} is 'never', an uninhabited TypeScript type that cannot describe a native ABI parameter`, loc);
|
|
2381
2396
|
}
|
|
2382
|
-
if (isFfiCallbackParam(sourceParam)) {
|
|
2397
|
+
if (isFfiCallbackParam(sourceParam) || isFfiReleaseParam(sourceParam)) {
|
|
2383
2398
|
const callbackDiagnostic = ffiCallbackInputDiagnostic(L, sourceParam, paramType);
|
|
2384
2399
|
if (callbackDiagnostic !== null) {
|
|
2385
2400
|
return signatureDiag(binding.name, callbackDiagnostic, loc);
|
|
@@ -2602,7 +2617,45 @@ export function lowerFfiCall(L, expr) {
|
|
|
2602
2617
|
signatureError(`this call passes ${expr.arguments.length} argument(s), but the native binding requires exactly ${expectedParams.length}`);
|
|
2603
2618
|
}
|
|
2604
2619
|
const expectedReturn = ffiClassType(binding.returns);
|
|
2605
|
-
const
|
|
2620
|
+
const sourceParams = ffiSourceParams(binding);
|
|
2621
|
+
const args = expr.arguments.map((arg, i) => {
|
|
2622
|
+
const sourceParam = sourceParams[i];
|
|
2623
|
+
const expected = expectedParams[i];
|
|
2624
|
+
const lowered = L.lowerExprExpecting(arg, expected);
|
|
2625
|
+
// Retained identity is the runtime closure pointer. A coercion adapter
|
|
2626
|
+
// would be freshly allocated at registration and release sites, so an
|
|
2627
|
+
// assignable-but-different function shape (notably `() => number` into
|
|
2628
|
+
// `() => void`) cannot honestly participate in explicit release. The
|
|
2629
|
+
// adapter set comes from the mint sites themselves (Lowerer's
|
|
2630
|
+
// freshClosureAdapters), not name-prefix matching, so a new coercion
|
|
2631
|
+
// helper cannot silently slip past this guard.
|
|
2632
|
+
if (isFfiReleaseParam(sourceParam) ||
|
|
2633
|
+
(isFfiCallbackParam(sourceParam) && sourceParam.callback.lifetime === "retained")) {
|
|
2634
|
+
if (lowered.kind === "dynCheck" ||
|
|
2635
|
+
(lowered.kind === "call" && L.freshClosureAdapters.has(lowered.callee))) {
|
|
2636
|
+
signatureError(`retained callback argument ${i + 1} must have the exact manifest function type; ` +
|
|
2637
|
+
`an implicit function adapter would change its release identity`);
|
|
2638
|
+
}
|
|
2639
|
+
// An inline function value at a RELEASE site can never match:
|
|
2640
|
+
// lifted lambdas always carry a captures list (even an empty one),
|
|
2641
|
+
// so both backends mint a fresh closure per evaluation of the
|
|
2642
|
+
// expression — the release argument is a pointer no registration
|
|
2643
|
+
// holds, a guaranteed runtime trap. Declared functions stay valid
|
|
2644
|
+
// here — their value is the interned immortal closure (captures
|
|
2645
|
+
// undefined), one pointer for every mention. Registration sites
|
|
2646
|
+
// still accept literals: an unnameable registration is simply
|
|
2647
|
+
// permanent, released by the exit teardown (the live-at-exit
|
|
2648
|
+
// fixture shape), and hides no matching failure.
|
|
2649
|
+
if (isFfiReleaseParam(sourceParam) &&
|
|
2650
|
+
lowered.kind === "closure" &&
|
|
2651
|
+
L.liftedFns.some((f) => f.name === lowered.fnName && f.captures !== undefined)) {
|
|
2652
|
+
signatureError(`retained callback argument ${i + 1} cannot be an inline function value; ` +
|
|
2653
|
+
`each evaluation creates a fresh closure no registration holds — ` +
|
|
2654
|
+
`pass the same named value used to register`);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
return lowered;
|
|
2658
|
+
});
|
|
2606
2659
|
return {
|
|
2607
2660
|
kind: "ffiCall",
|
|
2608
2661
|
import: binding.name,
|
|
@@ -4155,7 +4208,8 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
4155
4208
|
// take the ordinary typed paths, but there is no static home for an
|
|
4156
4209
|
// any-elemented array). Typed receivers keep their own lowerings.
|
|
4157
4210
|
const recvTs = L.typeOf(access.expression);
|
|
4158
|
-
const
|
|
4211
|
+
const arrayReceiver = L.checker.isArrayType(recvTs);
|
|
4212
|
+
const anyArray = arrayReceiver &&
|
|
4159
4213
|
((L.checker.getTypeArguments(recvTs)[0]?.flags ?? 0) &
|
|
4160
4214
|
(ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0;
|
|
4161
4215
|
let recv;
|
|
@@ -4234,21 +4288,9 @@ function lowerDynReceiverMethodCall(L, call, access) {
|
|
|
4234
4288
|
// unimplemented methods throw a LOUD not-supported Error; names the
|
|
4235
4289
|
// kind's prototype lacks throw Node's "x.y is not a function"; OBJ
|
|
4236
4290
|
// receivers call the own member.
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
}
|
|
4241
|
-
const args = call.arguments.map((a) => L.lowerExprExpecting(a, DYN));
|
|
4242
|
-
return {
|
|
4243
|
-
kind: "dynInvoke",
|
|
4244
|
-
recv,
|
|
4245
|
-
method: access.name.text,
|
|
4246
|
-
calleeName: access.getText(),
|
|
4247
|
-
args,
|
|
4248
|
-
type: DYN,
|
|
4249
|
-
loc: locOf(call),
|
|
4250
|
-
};
|
|
4251
|
-
}
|
|
4291
|
+
const dispatched = lowerDynDispatchMethodCall(L, call, access, recv, arrayReceiver);
|
|
4292
|
+
if (dispatched)
|
|
4293
|
+
return dispatched;
|
|
4252
4294
|
// Names NO dyn-representable prototype declares: the member can only
|
|
4253
4295
|
// be an OWN property, so "read the member, call it" IS Node's
|
|
4254
4296
|
// semantics for every possible dyn value — `handlers.onDone(x)` on a
|
|
@@ -4359,6 +4401,30 @@ export const DYN_DISPATCH_METHODS = new Set([
|
|
|
4359
4401
|
"request", "sendTrailers", "priority", "settings", "goaway", "ping",
|
|
4360
4402
|
"additionalHeaders", "altsvc", "origin",
|
|
4361
4403
|
]);
|
|
4404
|
+
export function lowerDynDispatchMethodCall(L, call, access, recv, arrayReceiver) {
|
|
4405
|
+
const method = access.name.text;
|
|
4406
|
+
if (!DYN_DISPATCH_METHODS.has(method) || call.questionDotToken || access.questionDotToken)
|
|
4407
|
+
return null;
|
|
4408
|
+
if (call.arguments.some((arg) => ts.isSpreadElement(arg))) {
|
|
4409
|
+
L.unsupported("SC1090", call, "spread arguments in calls through 'unknown' values");
|
|
4410
|
+
}
|
|
4411
|
+
const predicate = method === "filter" && call.arguments[0]
|
|
4412
|
+
? L.lowerExpr(call.arguments[0])
|
|
4413
|
+
: null;
|
|
4414
|
+
if (arrayReceiver && predicate?.type.kind === "func" && predicate.type.ret.kind === "void") {
|
|
4415
|
+
L.unsupported("SC1090", call.arguments[0], "'.filter()' with a void-returning predicate (the callback return value is erased before its truthiness can be tested)");
|
|
4416
|
+
}
|
|
4417
|
+
const args = call.arguments.map((arg, i) => i === 0 && predicate ? L.coerceInto(arg, predicate, DYN) : L.lowerExprExpecting(arg, DYN));
|
|
4418
|
+
return {
|
|
4419
|
+
kind: "dynInvoke",
|
|
4420
|
+
recv,
|
|
4421
|
+
method,
|
|
4422
|
+
calleeName: access.getText(),
|
|
4423
|
+
args,
|
|
4424
|
+
type: DYN,
|
|
4425
|
+
loc: locOf(call),
|
|
4426
|
+
};
|
|
4427
|
+
}
|
|
4362
4428
|
/** STR_METHODS ∪ the regex-form names, MINUS everything Array (or any
|
|
4363
4429
|
* other dyn kind's prototype) also declares. */
|
|
4364
4430
|
const DYN_STRING_ONLY_METHODS = new Set([
|