@scriptc/compiler 0.1.5 → 0.1.7
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 +0 -1
- package/ambient/scriptc.d.ts +13 -5
- package/dist/backend/c/c-emitter.d.ts +5 -0
- package/dist/backend/c/c-emitter.js +15 -0
- package/dist/backend/c/c-emitter.js.map +1 -1
- package/dist/backend/c/exprs.js +81 -9
- package/dist/backend/c/exprs.js.map +1 -1
- package/dist/backend/c/stmts.js +25 -1
- package/dist/backend/c/stmts.js.map +1 -1
- package/dist/backend/c/walkers.js +2 -3
- package/dist/backend/c/walkers.js.map +1 -1
- package/dist/backend/debug-symbols.d.ts +8 -0
- package/dist/backend/debug-symbols.js +52 -0
- package/dist/backend/debug-symbols.js.map +1 -0
- package/dist/backend/link-plan.d.ts +1 -0
- package/dist/backend/link-plan.js +2 -0
- package/dist/backend/link-plan.js.map +1 -1
- package/dist/backend/linker.js +8 -0
- package/dist/backend/linker.js.map +1 -1
- package/dist/backend/llvm/blocks.d.ts +2 -0
- package/dist/backend/llvm/blocks.js +18 -2
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/debug-info.d.ts +32 -0
- package/dist/backend/llvm/debug-info.js +203 -0
- package/dist/backend/llvm/debug-info.js.map +1 -0
- package/dist/backend/llvm/dyn.js +4 -10
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +2 -0
- package/dist/backend/llvm/emitter.js +49 -4
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +28 -2
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +10 -0
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +37 -0
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +4 -3
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +9 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/split.js +4 -1
- package/dist/backend/llvm/split.js.map +1 -1
- package/dist/backend/llvm/split.test.js +26 -1
- package/dist/backend/llvm/split.test.js.map +1 -1
- package/dist/backend/native-toolchain.js +58 -8
- package/dist/backend/native-toolchain.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +10 -0
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/source-locations.d.ts +12 -0
- package/dist/backend/source-locations.js +32 -0
- package/dist/backend/source-locations.js.map +1 -0
- package/dist/backend/source-locations.test.d.ts +1 -0
- package/dist/backend/source-locations.test.js +16 -0
- package/dist/backend/source-locations.test.js.map +1 -0
- package/dist/coverage/surface-manifest.js +6 -1
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +4 -0
- package/dist/diagnostics/diagnostic.js +12 -0
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.js +28 -4
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +23 -0
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/frontend/arguments-usage.d.ts +6 -0
- package/dist/frontend/arguments-usage.js +40 -0
- package/dist/frontend/arguments-usage.js.map +1 -0
- package/dist/frontend/binding-source.d.ts +4 -0
- package/dist/frontend/binding-source.js +18 -0
- package/dist/frontend/binding-source.js.map +1 -0
- package/dist/frontend/lowering/array-indexed-mutation.d.ts +8 -0
- package/dist/frontend/lowering/array-indexed-mutation.js +176 -0
- package/dist/frontend/lowering/array-indexed-mutation.js.map +1 -0
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +7 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js +190 -13
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +13 -8
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +5 -6
- package/dist/frontend/lowering/expressions/optional-chains.js +7 -6
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/indexed-comparison.d.ts +6 -0
- package/dist/frontend/lowering/indexed-comparison.js +30 -0
- package/dist/frontend/lowering/indexed-comparison.js.map +1 -0
- package/dist/frontend/lowering/lower-builtins.d.ts +1 -1
- package/dist/frontend/lowering/lower-builtins.js +21 -10
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +2 -9
- package/dist/frontend/lowering/lower-calls.js +406 -40
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +3 -27
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +8 -2
- package/dist/frontend/lowering/lower-containers.js +454 -104
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.js +134 -18
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +1 -1
- package/dist/frontend/lowering/lower-island.js +1 -1
- package/dist/frontend/lowering/lower-modules.js +19 -8
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +4 -37
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.js +14 -3
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +3 -1
- package/dist/frontend/lowering/surfaces.js +50 -7
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.d.ts +5 -0
- package/dist/frontend/program.js +216 -32
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.d.ts +1 -0
- package/dist/frontend/program.test.js +117 -0
- package/dist/frontend/program.test.js.map +1 -0
- package/dist/frontend/type-mapper.d.ts +4 -2
- package/dist/frontend/type-mapper.js +249 -186
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-mapper.test.d.ts +1 -0
- package/dist/frontend/type-mapper.test.js +86 -0
- package/dist/frontend/type-mapper.test.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +4 -2
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/ir.d.ts +33 -14
- package/dist/ir/ir.js +5 -1
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/validate.js +57 -31
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +17 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/compiler-self-identity.d.ts +1 -1
- package/dist/library/compiler-self-identity.js +31 -15
- package/dist/library/compiler-self-identity.js.map +1 -1
- package/dist/library/compiler-self-identity.test.d.ts +1 -0
- package/dist/library/compiler-self-identity.test.js +93 -0
- package/dist/library/compiler-self-identity.test.js.map +1 -0
- package/package.json +17 -17
- package/surface-manifest.json +155 -4
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import * as ts from "./ts7/adapter.js";
|
|
2
|
+
/** Whether an identifier in a function body reads the runtime arguments object. */
|
|
3
|
+
function isArgumentsRead(id) {
|
|
4
|
+
const parent = id.parent;
|
|
5
|
+
// A shorthand object property reads its value, but other `name` positions
|
|
6
|
+
// declare a binding or spell a property (including `o.arguments`).
|
|
7
|
+
if (ts.isShorthandPropertyAssignment(parent))
|
|
8
|
+
return true;
|
|
9
|
+
if (parent.name === id)
|
|
10
|
+
return false;
|
|
11
|
+
if (ts.isBindingElement(parent) && parent.propertyName === id)
|
|
12
|
+
return false;
|
|
13
|
+
if (ts.isLabeledStatement(parent) && parent.label === id)
|
|
14
|
+
return false;
|
|
15
|
+
if ((ts.isBreakStatement(parent) || ts.isContinueStatement(parent)) && parent.label === id)
|
|
16
|
+
return false;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
/** Does this function's own body read `arguments`? Nested plain functions and
|
|
20
|
+
* methods own theirs; arrows inherit the enclosing one. */
|
|
21
|
+
export function bodyReadsArguments(fn) {
|
|
22
|
+
if (fn.body === undefined)
|
|
23
|
+
return false;
|
|
24
|
+
let found = false;
|
|
25
|
+
// Iterative walking preserves the frontend's nesting fence on deep trees.
|
|
26
|
+
ts.walkPreorder(fn.body, (node) => {
|
|
27
|
+
if (ts.isTypeNode(node))
|
|
28
|
+
return "skip";
|
|
29
|
+
if (ts.isIdentifier(node) && node.text === "arguments" && isArgumentsRead(node)) {
|
|
30
|
+
found = true;
|
|
31
|
+
return "stop";
|
|
32
|
+
}
|
|
33
|
+
if (ts.isFunctionLike(node) && !ts.isArrowFunction(node) && node !== fn) {
|
|
34
|
+
return "skip";
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
});
|
|
38
|
+
return found;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=arguments-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arguments-usage.js","sourceRoot":"","sources":["../../src/frontend/arguments-usage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,mFAAmF;AACnF,SAAS,eAAe,CAAC,EAAiB;IACxC,MAAM,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC;IACzB,0EAA0E;IAC1E,mEAAmE;IACnE,IAAI,EAAE,CAAC,6BAA6B,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1D,IAAK,MAAuC,CAAC,IAAI,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACvE,IAAI,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,YAAY,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAC5E,IAAI,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACvE,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACzG,OAAO,IAAI,CAAC;AACd,CAAC;AAED;2DAC2D;AAC3D,MAAM,UAAU,kBAAkB,CAAC,EAAkC;IACnE,IAAI,EAAE,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,0EAA0E;IAC1E,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;QAChC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,MAAM,CAAC;QACvC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;YAChF,KAAK,GAAG,IAAI,CAAC;YACb,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;YACxE,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as ts from "./ts7/adapter.js";
|
|
2
|
+
import { locOf } from "./program.js";
|
|
3
|
+
/** Preserve source scopes before lowering flattens bindings and control flow. */
|
|
4
|
+
export function bindingSource(name) {
|
|
5
|
+
let functionScoped = false;
|
|
6
|
+
for (let node = name.parent; node; node = node.parent) {
|
|
7
|
+
if (ts.isVariableDeclarationList(node)) {
|
|
8
|
+
functionScoped = (node.flags & ts.NodeFlags.BlockScoped) === 0;
|
|
9
|
+
}
|
|
10
|
+
if (ts.isFunctionLike(node) || ts.isSourceFile(node) ||
|
|
11
|
+
(!functionScoped && (ts.isBlock(node) || ts.isCaseBlock(node) ||
|
|
12
|
+
ts.isForStatement(node) || ts.isForOfStatement(node) || ts.isForInStatement(node) || ts.isCatchClause(node)))) {
|
|
13
|
+
return { loc: locOf(name), scope: locOf(node) };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return { loc: locOf(name), scope: locOf(name) };
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=binding-source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binding-source.js","sourceRoot":"","sources":["../../src/frontend/binding-source.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAErC,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,IAAa;IACzC,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,KAAK,IAAI,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QACtD,IAAI,EAAE,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,cAAc,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC;YAClD,CAAC,CAAC,cAAc,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC;gBAC3D,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAClH,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type IrExpr, type IrType, type SrcLoc } from "../../ir/ir.js";
|
|
2
|
+
import type { Lowerer } from "./lowerer.js";
|
|
3
|
+
export declare function lowerArrayFill(lowerer: Lowerer, receiver: IrExpr, value: IrExpr | null, writeUndefined: boolean, start: IrExpr, end: IrExpr, arrType: IrType & {
|
|
4
|
+
kind: "array";
|
|
5
|
+
}, loc: SrcLoc): IrExpr;
|
|
6
|
+
export declare function lowerArrayCopyWithin(lowerer: Lowerer, receiver: IrExpr, target: IrExpr, start: IrExpr, end: IrExpr, arrType: IrType & {
|
|
7
|
+
kind: "array";
|
|
8
|
+
}, loc: SrcLoc): IrExpr;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { BOOL, F64 } from "../../ir/ir.js";
|
|
2
|
+
import { numLit, varRef } from "../../ir/build.js";
|
|
3
|
+
import { typeKey } from "../type-mapper.js";
|
|
4
|
+
import { arrayValueStore } from "./array-values.js";
|
|
5
|
+
const add = (left, right, loc) => ({ kind: "bin", op: "+", left, right, type: F64, loc });
|
|
6
|
+
const sub = (left, right, loc) => ({ kind: "bin", op: "-", left, right, type: F64, loc });
|
|
7
|
+
const lt = (left, right, loc) => ({ kind: "bin", op: "<", left, right, type: BOOL, loc });
|
|
8
|
+
const eq = (left, right, loc) => ({ kind: "bin", op: "===", left, right, type: BOOL, loc });
|
|
9
|
+
const math = (fn, args, loc) => ({ kind: "libCall", fn: `math.${fn}`, args, type: F64, loc });
|
|
10
|
+
const lengthOf = (arr, loc) => ({ kind: "arrIntrinsic", method: "length", receiver: arr, args: [], type: F64, loc });
|
|
11
|
+
function relativeIndex(position, length, loc) {
|
|
12
|
+
const integer = {
|
|
13
|
+
kind: "ternary",
|
|
14
|
+
cond: { kind: "libCall", fn: "num.isNaN", args: [position], type: BOOL, loc },
|
|
15
|
+
then: numLit(0, loc),
|
|
16
|
+
else_: math("trunc", [position], loc),
|
|
17
|
+
type: F64,
|
|
18
|
+
loc,
|
|
19
|
+
};
|
|
20
|
+
return {
|
|
21
|
+
kind: "ternary",
|
|
22
|
+
cond: lt(integer, numLit(0, loc), loc),
|
|
23
|
+
then: math("max", [add(length, integer, loc), numLit(0, loc)], loc),
|
|
24
|
+
else_: math("min", [integer, length], loc),
|
|
25
|
+
type: F64,
|
|
26
|
+
loc,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function lowerArrayFill(lowerer, receiver, value, writeUndefined, start, end, arrType, loc) {
|
|
30
|
+
const valueType = writeUndefined ? F64 : value.type;
|
|
31
|
+
const key = "indexed:fill:" + typeKey(arrType.elem) + ":" + typeKey(valueType) + ":" + writeUndefined;
|
|
32
|
+
let name = lowerer.arrHofHelpers.get(key);
|
|
33
|
+
if (!name) {
|
|
34
|
+
name = "%arr.fill." + lowerer.arrHofHelpers.size;
|
|
35
|
+
lowerer.arrHofHelpers.set(key, name);
|
|
36
|
+
const a = varRef("a.0", arrType, loc);
|
|
37
|
+
const n = varRef("n.0", F64, loc);
|
|
38
|
+
const i = varRef("i.0", F64, loc);
|
|
39
|
+
const body = writeUndefined
|
|
40
|
+
? [{ kind: "arraySetUndefined", arr: a, index: i, loc }]
|
|
41
|
+
: [arrayValueStore(lowerer, a, i, varRef("v.0", valueType, loc), arrType.elem, loc)];
|
|
42
|
+
lowerer.liftedFns.push({
|
|
43
|
+
name,
|
|
44
|
+
params: [
|
|
45
|
+
{ localId: "a.0", name: "a", type: arrType },
|
|
46
|
+
{ localId: "v.0", name: "v", type: valueType },
|
|
47
|
+
{ localId: "start.0", name: "start", type: F64 },
|
|
48
|
+
{ localId: "end.0", name: "end", type: F64 },
|
|
49
|
+
],
|
|
50
|
+
returnType: arrType,
|
|
51
|
+
locals: [
|
|
52
|
+
{ id: "a.0", name: "a", type: arrType, mutable: true },
|
|
53
|
+
{ id: "v.0", name: "v", type: valueType, mutable: false },
|
|
54
|
+
{ id: "start.0", name: "start", type: F64, mutable: false },
|
|
55
|
+
{ id: "end.0", name: "end", type: F64, mutable: false },
|
|
56
|
+
{ id: "n.0", name: "n", type: F64, mutable: false },
|
|
57
|
+
{ id: "from.0", name: "from", type: F64, mutable: false },
|
|
58
|
+
{ id: "until.0", name: "until", type: F64, mutable: false },
|
|
59
|
+
{ id: "i.0", name: "i", type: F64, mutable: true },
|
|
60
|
+
],
|
|
61
|
+
body: [
|
|
62
|
+
{ kind: "varDecl", localId: "n.0", init: lengthOf(a, loc), loc },
|
|
63
|
+
{ kind: "varDecl", localId: "from.0", init: relativeIndex(varRef("start.0", F64, loc), n, loc), loc },
|
|
64
|
+
{ kind: "varDecl", localId: "until.0", init: relativeIndex(varRef("end.0", F64, loc), n, loc), loc },
|
|
65
|
+
{
|
|
66
|
+
kind: "for",
|
|
67
|
+
init: { kind: "varDecl", localId: "i.0", init: varRef("from.0", F64, loc), loc },
|
|
68
|
+
cond: lt(i, varRef("until.0", F64, loc), loc),
|
|
69
|
+
update: { kind: "assign", localId: "i.0", value: add(i, numLit(1, loc), loc), loc },
|
|
70
|
+
body,
|
|
71
|
+
loc,
|
|
72
|
+
},
|
|
73
|
+
{ kind: "return", value: a, loc },
|
|
74
|
+
],
|
|
75
|
+
loc,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const valueArg = value && writeUndefined
|
|
79
|
+
? { kind: "seqExpr", stmts: [{ kind: "exprStmt", expr: value, loc }], result: numLit(0, loc), type: F64, loc }
|
|
80
|
+
: value ?? numLit(0, loc);
|
|
81
|
+
return { kind: "call", callee: name, args: [receiver, valueArg, start, end], type: arrType, loc };
|
|
82
|
+
}
|
|
83
|
+
export function lowerArrayCopyWithin(lowerer, receiver, target, start, end, arrType, loc) {
|
|
84
|
+
const key = "indexed:copyWithin:" + typeKey(arrType.elem);
|
|
85
|
+
let name = lowerer.arrHofHelpers.get(key);
|
|
86
|
+
if (!name) {
|
|
87
|
+
name = "%arr.copyWithin." + lowerer.arrHofHelpers.size;
|
|
88
|
+
lowerer.arrHofHelpers.set(key, name);
|
|
89
|
+
const a = varRef("a.0", arrType, loc);
|
|
90
|
+
const n = varRef("n.0", F64, loc);
|
|
91
|
+
const dst = varRef("targetIndex.0", F64, loc);
|
|
92
|
+
const src = varRef("startIndex.0", F64, loc);
|
|
93
|
+
const last = varRef("endIndex.0", F64, loc);
|
|
94
|
+
const remaining = varRef("count.0", F64, loc);
|
|
95
|
+
const step = varRef("direction.0", F64, loc);
|
|
96
|
+
const from = varRef("from.0", F64, loc);
|
|
97
|
+
const to = varRef("to.0", F64, loc);
|
|
98
|
+
const state = varRef("state.0", F64, loc);
|
|
99
|
+
const backwards = {
|
|
100
|
+
kind: "logical", op: "&&", left: lt(src, dst, loc),
|
|
101
|
+
right: lt(dst, add(src, remaining, loc), loc), type: BOOL, loc,
|
|
102
|
+
};
|
|
103
|
+
const offset = {
|
|
104
|
+
kind: "ternary", cond: lt(step, numLit(0, loc), loc),
|
|
105
|
+
then: sub(remaining, numLit(1, loc), loc), else_: numLit(0, loc), type: F64, loc,
|
|
106
|
+
};
|
|
107
|
+
lowerer.liftedFns.push({
|
|
108
|
+
name,
|
|
109
|
+
params: [
|
|
110
|
+
{ localId: "a.0", name: "a", type: arrType },
|
|
111
|
+
{ localId: "target.0", name: "target", type: F64 },
|
|
112
|
+
{ localId: "start.0", name: "start", type: F64 },
|
|
113
|
+
{ localId: "end.0", name: "end", type: F64 },
|
|
114
|
+
],
|
|
115
|
+
returnType: arrType,
|
|
116
|
+
locals: [
|
|
117
|
+
{ id: "a.0", name: "a", type: arrType, mutable: true },
|
|
118
|
+
{ id: "target.0", name: "target", type: F64, mutable: false },
|
|
119
|
+
{ id: "start.0", name: "start", type: F64, mutable: false },
|
|
120
|
+
{ id: "end.0", name: "end", type: F64, mutable: false },
|
|
121
|
+
{ id: "n.0", name: "n", type: F64, mutable: false },
|
|
122
|
+
{ id: "targetIndex.0", name: "targetIndex", type: F64, mutable: false },
|
|
123
|
+
{ id: "startIndex.0", name: "startIndex", type: F64, mutable: false },
|
|
124
|
+
{ id: "endIndex.0", name: "endIndex", type: F64, mutable: false },
|
|
125
|
+
{ id: "count.0", name: "count", type: F64, mutable: true },
|
|
126
|
+
{ id: "direction.0", name: "direction", type: F64, mutable: false },
|
|
127
|
+
{ id: "from.0", name: "from", type: F64, mutable: true },
|
|
128
|
+
{ id: "to.0", name: "to", type: F64, mutable: true },
|
|
129
|
+
{ id: "state.0", name: "state", type: F64, mutable: false },
|
|
130
|
+
{ id: "value.0", name: "value", type: arrType.elem, mutable: false },
|
|
131
|
+
],
|
|
132
|
+
body: [
|
|
133
|
+
{ kind: "varDecl", localId: "n.0", init: lengthOf(a, loc), loc },
|
|
134
|
+
{ kind: "varDecl", localId: "targetIndex.0", init: relativeIndex(varRef("target.0", F64, loc), n, loc), loc },
|
|
135
|
+
{ kind: "varDecl", localId: "startIndex.0", init: relativeIndex(varRef("start.0", F64, loc), n, loc), loc },
|
|
136
|
+
{ kind: "varDecl", localId: "endIndex.0", init: relativeIndex(varRef("end.0", F64, loc), n, loc), loc },
|
|
137
|
+
{
|
|
138
|
+
kind: "varDecl", localId: "count.0",
|
|
139
|
+
init: {
|
|
140
|
+
kind: "ternary", cond: eq(src, dst, loc), then: numLit(0, loc),
|
|
141
|
+
else_: math("min", [math("max", [sub(last, src, loc), numLit(0, loc)], loc), sub(n, dst, loc)], loc),
|
|
142
|
+
type: F64, loc,
|
|
143
|
+
}, loc,
|
|
144
|
+
},
|
|
145
|
+
{ kind: "varDecl", localId: "direction.0", init: { kind: "ternary", cond: backwards, then: numLit(-1, loc), else_: numLit(1, loc), type: F64, loc }, loc },
|
|
146
|
+
{ kind: "varDecl", localId: "from.0", init: add(src, offset, loc), loc },
|
|
147
|
+
{ kind: "varDecl", localId: "to.0", init: add(dst, offset, loc), loc },
|
|
148
|
+
{
|
|
149
|
+
kind: "while", cond: lt(numLit(0, loc), remaining, loc),
|
|
150
|
+
body: [
|
|
151
|
+
{ kind: "varDecl", localId: "state.0", init: { kind: "arrayState", arr: a, index: from, type: F64, loc }, loc },
|
|
152
|
+
{
|
|
153
|
+
kind: "if", cond: eq(state, numLit(0, loc), loc),
|
|
154
|
+
then: [{ kind: "arrayDelete", arr: a, index: to, loc }],
|
|
155
|
+
else_: [{
|
|
156
|
+
kind: "if", cond: eq(state, numLit(2, loc), loc),
|
|
157
|
+
then: [{ kind: "arraySetUndefined", arr: a, index: to, loc }],
|
|
158
|
+
else_: [
|
|
159
|
+
{ kind: "varDecl", localId: "value.0", init: { kind: "arrayGet", arr: a, index: from, type: arrType.elem, loc }, loc },
|
|
160
|
+
{ kind: "arraySet", arr: a, index: to, value: varRef("value.0", arrType.elem, loc), loc },
|
|
161
|
+
], loc,
|
|
162
|
+
}], loc,
|
|
163
|
+
},
|
|
164
|
+
{ kind: "assign", localId: "from.0", value: add(from, step, loc), loc },
|
|
165
|
+
{ kind: "assign", localId: "to.0", value: add(to, step, loc), loc },
|
|
166
|
+
{ kind: "assign", localId: "count.0", value: sub(remaining, numLit(1, loc), loc), loc },
|
|
167
|
+
], loc,
|
|
168
|
+
},
|
|
169
|
+
{ kind: "return", value: a, loc },
|
|
170
|
+
],
|
|
171
|
+
loc,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return { kind: "call", callee: name, args: [receiver, target, start, end], type: arrType, loc };
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=array-indexed-mutation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array-indexed-mutation.js","sourceRoot":"","sources":["../../../src/frontend/lowering/array-indexed-mutation.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import * as ts from "../../ts7/adapter.js";
|
|
2
2
|
import { IrExpr } from "../../../ir/ir.js";
|
|
3
3
|
import type { Lowerer } from "../lowerer.js";
|
|
4
|
+
/** Split evaluates its arguments before converting the receiver, limit, and
|
|
5
|
+
* separator, in that order. An undefined separator returns the whole string
|
|
6
|
+
* unless ToUint32(limit) is zero; the string-separator intrinsic handles the
|
|
7
|
+
* remaining split loop. */
|
|
8
|
+
export declare function lowerStringSplitCall(lowerer: Lowerer, call: ts.CallExpression, receiver: IrExpr, receiverNode: ts.Node, argumentNodes: readonly ts.Expression[]): IrExpr;
|
|
9
|
+
/** Relative string indexing and code-point decoding over the UTF-16 intrinsics. */
|
|
10
|
+
export declare function lowerStringIndexCall(lowerer: Lowerer, call: ts.CallExpression, method: "at" | "codePointAt", receiver: IrExpr, receiverNode: ts.Node, argumentNodes: readonly ts.Expression[]): IrExpr;
|
|
4
11
|
/** Pad arguments are evaluated before receiver/length coercion, while fill
|
|
5
12
|
* conversion runs only if padding is needed. One helper keeps that order for
|
|
6
13
|
* member calls and direct String.prototype calls alike. */
|
|
@@ -1,15 +1,107 @@
|
|
|
1
1
|
import * as ts from "../../ts7/adapter.js";
|
|
2
|
-
import { BOOL, F64, STRING, arrayOf, isUnitType, typeEquals, typeKey } from "../../../ir/ir.js";
|
|
2
|
+
import { BOOL, DYN, F64, STRING, UNDEFINED_T, arrayOf, isUnitType, typeEquals, typeKey } from "../../../ir/ir.js";
|
|
3
3
|
import { numLit, strLit, varRef } from "../../../ir/build.js";
|
|
4
4
|
import { locOf } from "../../program.js";
|
|
5
5
|
import { nodeThrowExpr, own } from "../lowerer.js";
|
|
6
6
|
import { isRequireMainFilename } from "../expressions/optional-chains.js";
|
|
7
|
-
import { STR_METHODS } from "../surfaces.js";
|
|
7
|
+
import { STRING_INDEX_METHODS, STR_METHODS } from "../surfaces.js";
|
|
8
8
|
import { coerceStringSearchValue, defaultAfterUndefined, lowerOptionalArgument, lowerPositionArgument, lowerStaticallyUndefinedArgument, lowerStringSearchArgument, positionNumber } from "../optional-arguments.js";
|
|
9
9
|
function lowerSplitLimitArg(lowerer, node, loc) {
|
|
10
10
|
const defaultValue = { kind: "numLit", value: 4294967295, type: F64, loc };
|
|
11
11
|
return node ? lowerOptionalArgument(lowerer, node, F64, defaultValue) : defaultValue;
|
|
12
12
|
}
|
|
13
|
+
/** Split evaluates its arguments before converting the receiver, limit, and
|
|
14
|
+
* separator, in that order. An undefined separator returns the whole string
|
|
15
|
+
* unless ToUint32(limit) is zero; the string-separator intrinsic handles the
|
|
16
|
+
* remaining split loop. */
|
|
17
|
+
export function lowerStringSplitCall(lowerer, call, receiver, receiverNode, argumentNodes) {
|
|
18
|
+
const loc = locOf(call);
|
|
19
|
+
if (argumentNodes.length > 2 || argumentNodes.some(ts.isSpreadElement)) {
|
|
20
|
+
return lowerer.noLowering(`.split with ${argumentNodes.length} arguments`, call);
|
|
21
|
+
}
|
|
22
|
+
const separatorNode = argumentNodes[0];
|
|
23
|
+
const undefinedSeparator = separatorNode ? lowerStaticallyUndefinedArgument(lowerer, separatorNode) : null;
|
|
24
|
+
const absent = !separatorNode || undefinedSeparator !== null;
|
|
25
|
+
let separator = absent
|
|
26
|
+
? undefinedSeparator
|
|
27
|
+
? defaultAfterUndefined(undefinedSeparator, strLit("undefined", loc))
|
|
28
|
+
: strLit("undefined", loc)
|
|
29
|
+
: lowerer.lowerExpr(separatorNode);
|
|
30
|
+
if (separator.type.kind === "nullT")
|
|
31
|
+
separator = defaultAfterUndefined(separator, strLit("null", loc));
|
|
32
|
+
const scalar = separator.type.kind === "string" || separator.type.kind === "f64" ||
|
|
33
|
+
separator.type.kind === "bool" || separator.type.kind === "bigint" ||
|
|
34
|
+
(separator.type.kind === "union" && (lowerer.unions.get(separator.type.unionId)?.arms.every((arm) => arm.kind === "string" || arm.kind === "f64" || arm.kind === "bool" ||
|
|
35
|
+
arm.kind === "bigint" || arm.kind === "nullT" || arm.kind === "undefinedT") ?? false));
|
|
36
|
+
if (!scalar) {
|
|
37
|
+
lowerer.unsupported("SC1090", separatorNode ?? call, `'.split()' on a '${lowerer.fmt(separator.type)}' separator (pass a string, or a regex literal)`);
|
|
38
|
+
}
|
|
39
|
+
const defaultLimit = numLit(4294967295, loc);
|
|
40
|
+
const suppliedLimit = lowerPositionArgument(lowerer, argumentNodes[1], defaultLimit);
|
|
41
|
+
const limit = suppliedLimit.type.kind === "record" && argumentNodes[1]
|
|
42
|
+
? lowerer.coerceInto(argumentNodes[1], suppliedLimit, DYN) : suppliedLimit;
|
|
43
|
+
const resultType = arrayOf(STRING);
|
|
44
|
+
if (receiver.type.kind === "string" && separator.type.kind === "string" && limit.type.kind === "f64" && !absent) {
|
|
45
|
+
return { kind: "strIntrinsic", method: "split", receiver, args: [separator, limit], type: resultType, loc };
|
|
46
|
+
}
|
|
47
|
+
const key = `str.split:${receiver.type.kind === "union" ? typeKey(receiver.type) : receiver.type.kind}:${typeKey(separator.type)}:${typeKey(limit.type)}:${absent}`;
|
|
48
|
+
let helper = lowerer.widthHelpers.get(key);
|
|
49
|
+
if (!helper) {
|
|
50
|
+
helper = `%str.split.${lowerer.widthHelpers.size}`;
|
|
51
|
+
const values = [receiver, separator, limit];
|
|
52
|
+
const params = values.map((value, index) => ({ localId: `arg.${index}`, name: `arg${index}`, type: value.type }));
|
|
53
|
+
const rawReceiver = varRef("arg.0", receiver.type, loc);
|
|
54
|
+
const rawSeparator = varRef("arg.1", separator.type, loc);
|
|
55
|
+
const rawLimit = varRef("arg.2", limit.type, loc);
|
|
56
|
+
const stringReceiver = varRef("receiver.0", STRING, loc);
|
|
57
|
+
const numericLimit = varRef("limit.0", F64, loc);
|
|
58
|
+
const stringSeparator = varRef("separator.0", STRING, loc);
|
|
59
|
+
const undefinedTag = separator.type.kind === "union"
|
|
60
|
+
? lowerer.unions.get(separator.type.unionId).arms.findIndex((arm) => arm.kind === "undefinedT") : -1;
|
|
61
|
+
const separatorIsUndefined = absent
|
|
62
|
+
? { kind: "boolLit", value: true, type: BOOL, loc }
|
|
63
|
+
: undefinedTag >= 0 && separator.type.kind === "union"
|
|
64
|
+
? { kind: "unionIsTag", unionId: separator.type.unionId, tag: undefinedTag, value: rawSeparator, negated: false, type: BOOL, loc }
|
|
65
|
+
: { kind: "boolLit", value: false, type: BOOL, loc };
|
|
66
|
+
const split = {
|
|
67
|
+
kind: "strIntrinsic", method: "split", receiver: stringReceiver,
|
|
68
|
+
args: [stringSeparator, numericLimit], type: resultType, loc,
|
|
69
|
+
};
|
|
70
|
+
const result = {
|
|
71
|
+
kind: "ternary",
|
|
72
|
+
cond: {
|
|
73
|
+
kind: "bin", op: "===",
|
|
74
|
+
left: { kind: "bin", op: ">>>", left: numericLimit, right: numLit(0, loc), type: F64, loc },
|
|
75
|
+
right: numLit(0, loc), type: BOOL, loc,
|
|
76
|
+
},
|
|
77
|
+
then: { kind: "arrayLit", elems: [], type: resultType, loc },
|
|
78
|
+
else_: {
|
|
79
|
+
kind: "ternary", cond: separatorIsUndefined,
|
|
80
|
+
then: { kind: "arrayLit", elems: [stringReceiver], type: resultType, loc },
|
|
81
|
+
else_: split, type: resultType, loc,
|
|
82
|
+
},
|
|
83
|
+
type: resultType, loc,
|
|
84
|
+
};
|
|
85
|
+
lowerer.widthHelpers.set(key, helper);
|
|
86
|
+
lowerer.liftedFns.push({
|
|
87
|
+
name: helper, params, returnType: resultType,
|
|
88
|
+
locals: [
|
|
89
|
+
...params.map(param => ({ id: param.localId, name: param.name, type: param.type, mutable: false })),
|
|
90
|
+
{ id: "receiver.0", name: "receiver", type: STRING, mutable: false },
|
|
91
|
+
{ id: "limit.0", name: "limit", type: F64, mutable: false },
|
|
92
|
+
{ id: "separator.0", name: "separator", type: STRING, mutable: false },
|
|
93
|
+
],
|
|
94
|
+
body: [
|
|
95
|
+
{ kind: "varDecl", localId: "receiver.0", init: lowerer.ensureString(rawReceiver, receiverNode), loc },
|
|
96
|
+
{ kind: "varDecl", localId: "limit.0", init: positionNumber(lowerer, rawLimit, defaultLimit, argumentNodes[1] ?? call, "string split limit"), loc },
|
|
97
|
+
{ kind: "varDecl", localId: "separator.0", init: lowerer.ensureString(rawSeparator, separatorNode ?? call), loc },
|
|
98
|
+
{ kind: "return", value: result, loc },
|
|
99
|
+
],
|
|
100
|
+
loc,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return { kind: "call", callee: helper, args: [receiver, separator, limit], type: resultType, loc };
|
|
104
|
+
}
|
|
13
105
|
function lowerRegexSubject(lowerer, node, loc) {
|
|
14
106
|
const absent = { kind: "strLit", value: "undefined", type: STRING, loc };
|
|
15
107
|
if (!node)
|
|
@@ -35,6 +127,92 @@ function lowerMethodReceiver(lowerer, node, expected, member) {
|
|
|
35
127
|
return lowered;
|
|
36
128
|
return lowerer.coerceInto(node, lowered, expected);
|
|
37
129
|
}
|
|
130
|
+
/** Relative string indexing and code-point decoding over the UTF-16 intrinsics. */
|
|
131
|
+
export function lowerStringIndexCall(lowerer, call, method, receiver, receiverNode, argumentNodes) {
|
|
132
|
+
const loc = locOf(call);
|
|
133
|
+
if (argumentNodes.length > 1 || argumentNodes.some(ts.isSpreadElement)) {
|
|
134
|
+
return lowerer.noLowering(`String.prototype.${method} with ${argumentNodes.length} arguments`, call);
|
|
135
|
+
}
|
|
136
|
+
const indexNode = argumentNodes[0];
|
|
137
|
+
let index = lowerPositionArgument(lowerer, indexNode, numLit(0, loc));
|
|
138
|
+
if (indexNode && (index.type.kind === "record" || index.type.kind === "array" || index.type.kind === "func")) {
|
|
139
|
+
index = lowerer.coerceInto(indexNode, index, DYN);
|
|
140
|
+
}
|
|
141
|
+
const valueType = method === "at" ? STRING : F64;
|
|
142
|
+
const resultType = lowerer.withUndefinedArmOf(valueType);
|
|
143
|
+
if (!resultType || resultType.kind !== "union")
|
|
144
|
+
return lowerer.noLowering(`String.prototype.${method} result`, call);
|
|
145
|
+
const undefinedTag = lowerer.armTag(resultType.unionId, UNDEFINED_T);
|
|
146
|
+
const valueTag = lowerer.armTag(resultType.unionId, valueType);
|
|
147
|
+
const key = `str.index:${method}:${typeKey(receiver.type)}:${typeKey(index.type)}`;
|
|
148
|
+
let helper = lowerer.widthHelpers.get(key);
|
|
149
|
+
if (!helper) {
|
|
150
|
+
helper = `%str.index.${lowerer.widthHelpers.size}`;
|
|
151
|
+
lowerer.widthHelpers.set(key, helper);
|
|
152
|
+
const rawReceiver = varRef("arg.0", receiver.type, loc);
|
|
153
|
+
const rawIndex = varRef("arg.1", index.type, loc);
|
|
154
|
+
const stringReceiver = varRef("receiver.0", STRING, loc);
|
|
155
|
+
const length = varRef("length.0", F64, loc);
|
|
156
|
+
const position = varRef("position.0", F64, loc);
|
|
157
|
+
const first = varRef("first.0", F64, loc);
|
|
158
|
+
const second = varRef("second.0", F64, loc);
|
|
159
|
+
const bin = (op, left, right) => ({ kind: "bin", op, left, right, type: op === "<" || op === ">=" || op === ">" ? BOOL : F64, loc });
|
|
160
|
+
const either = (left, right) => ({ kind: "logical", op: "||", left, right, type: BOOL, loc });
|
|
161
|
+
const wrap = (value) => ({ kind: "unionWrap", unionId: resultType.unionId, tag: valueTag, value, type: resultType, loc });
|
|
162
|
+
const miss = {
|
|
163
|
+
kind: "unionWrap", unionId: resultType.unionId, tag: undefinedTag,
|
|
164
|
+
value: { kind: "unitLit", unit: "undefined", type: UNDEFINED_T, loc }, type: resultType, loc,
|
|
165
|
+
};
|
|
166
|
+
const numeric = positionNumber(lowerer, rawIndex, numLit(0, loc), indexNode ?? call, "string index");
|
|
167
|
+
const numericValue = varRef("numeric.0", F64, loc);
|
|
168
|
+
const body = [
|
|
169
|
+
{ kind: "varDecl", localId: "receiver.0", init: lowerer.ensureString(rawReceiver, receiverNode), loc },
|
|
170
|
+
{ kind: "varDecl", localId: "length.0", init: { kind: "strIntrinsic", method: "length", receiver: stringReceiver, args: [], type: F64, loc }, loc },
|
|
171
|
+
{ kind: "varDecl", localId: "numeric.0", init: numeric, loc },
|
|
172
|
+
{ kind: "varDecl", localId: "position.0", init: {
|
|
173
|
+
kind: "ternary", cond: { kind: "libCall", fn: "num.isNaN", args: [numericValue], type: BOOL, loc },
|
|
174
|
+
then: numLit(0, loc), else_: { kind: "libCall", fn: "math.trunc", args: [numericValue], type: F64, loc }, type: F64, loc,
|
|
175
|
+
}, loc },
|
|
176
|
+
];
|
|
177
|
+
if (method === "at") {
|
|
178
|
+
body.push({ kind: "if", cond: bin("<", position, numLit(0, loc)),
|
|
179
|
+
then: [{ kind: "assign", localId: "position.0", value: bin("+", position, length), loc }], else_: null, loc });
|
|
180
|
+
}
|
|
181
|
+
body.push({ kind: "if", cond: either(bin("<", position, numLit(0, loc)), bin(">=", position, length)),
|
|
182
|
+
then: [{ kind: "return", value: miss, loc }], else_: null, loc });
|
|
183
|
+
if (method === "at") {
|
|
184
|
+
body.push({ kind: "return", value: wrap({ kind: "strIntrinsic", method: "charAt", receiver: stringReceiver, args: [position], type: STRING, loc }), loc });
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
body.push({ kind: "varDecl", localId: "first.0", init: { kind: "strIntrinsic", method: "charCodeAt", receiver: stringReceiver, args: [position], type: F64, loc }, loc });
|
|
188
|
+
body.push({ kind: "if", cond: either(either(bin("<", first, numLit(0xd800, loc)), bin(">", first, numLit(0xdbff, loc))), bin(">=", bin("+", position, numLit(1, loc)), length)),
|
|
189
|
+
then: [{ kind: "return", value: wrap(first), loc }], else_: null, loc });
|
|
190
|
+
body.push({ kind: "varDecl", localId: "second.0", init: { kind: "strIntrinsic", method: "charCodeAt", receiver: stringReceiver, args: [bin("+", position, numLit(1, loc))], type: F64, loc }, loc });
|
|
191
|
+
body.push({ kind: "if", cond: either(bin("<", second, numLit(0xdc00, loc)), bin(">", second, numLit(0xdfff, loc))),
|
|
192
|
+
then: [{ kind: "return", value: wrap(first), loc }], else_: null, loc });
|
|
193
|
+
body.push({ kind: "return", value: wrap(bin("+", bin("+", bin("*", bin("-", first, numLit(0xd800, loc)), numLit(1024, loc)), bin("-", second, numLit(0xdc00, loc))), numLit(0x10000, loc))), loc });
|
|
194
|
+
}
|
|
195
|
+
lowerer.liftedFns.push({
|
|
196
|
+
name: helper,
|
|
197
|
+
params: [{ localId: "arg.0", name: "receiver", type: receiver.type }, { localId: "arg.1", name: "index", type: index.type }],
|
|
198
|
+
returnType: resultType,
|
|
199
|
+
locals: [
|
|
200
|
+
{ id: "arg.0", name: "receiver", type: receiver.type, mutable: false },
|
|
201
|
+
{ id: "arg.1", name: "index", type: index.type, mutable: false },
|
|
202
|
+
{ id: "receiver.0", name: "stringReceiver", type: STRING, mutable: false },
|
|
203
|
+
{ id: "length.0", name: "length", type: F64, mutable: false },
|
|
204
|
+
{ id: "numeric.0", name: "numeric", type: F64, mutable: false },
|
|
205
|
+
{ id: "position.0", name: "position", type: F64, mutable: method === "at" },
|
|
206
|
+
...(method === "codePointAt" ? [
|
|
207
|
+
{ id: "first.0", name: "first", type: F64, mutable: false },
|
|
208
|
+
{ id: "second.0", name: "second", type: F64, mutable: false },
|
|
209
|
+
] : []),
|
|
210
|
+
],
|
|
211
|
+
body, loc,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return { kind: "call", callee: helper, args: [receiver, index], type: resultType, loc };
|
|
215
|
+
}
|
|
38
216
|
function paddingFillString(lowerer, value, node) {
|
|
39
217
|
const loc = value.loc;
|
|
40
218
|
if (value.type.kind === "undefinedT" || value.type.kind === "void")
|
|
@@ -339,7 +517,8 @@ export function lowerStringMethodCall(lowerer, call, access, dynReceiver, argume
|
|
|
339
517
|
if (dynReceiver === undefined && access.name.text === "localeCompare")
|
|
340
518
|
return lowerLocaleCompareCall(lowerer, call, access);
|
|
341
519
|
const entry = own(STR_METHODS, access.name.text);
|
|
342
|
-
|
|
520
|
+
const indexMethod = STRING_INDEX_METHODS.has(access.name.text) ? access.name.text : null;
|
|
521
|
+
if (!entry && !indexMethod)
|
|
343
522
|
return null;
|
|
344
523
|
// A validated dyn receiver (`pkg.name.replace(...)` on a JSON.parse
|
|
345
524
|
// value) arrives pre-extracted through `dynReceiver`; its checker type
|
|
@@ -362,13 +541,19 @@ export function lowerStringMethodCall(lowerer, call, access, dynReceiver, argume
|
|
|
362
541
|
}
|
|
363
542
|
// The lib declares optional parameters beyond some lowered forms; fence
|
|
364
543
|
// those arities instead of passing arguments the runtime doesn't take.
|
|
365
|
-
if (argumentNodes.length < entry
|
|
544
|
+
if (argumentNodes.length < (entry?.minArgs ?? 0) || argumentNodes.length > (entry?.maxArgs ?? 1)) {
|
|
366
545
|
lowerer.noLowering(`.${access.name.text} with ${argumentNodes.length} argument${argumentNodes.length === 1 ? "" : "s"} on strings`, call);
|
|
367
546
|
}
|
|
368
547
|
const receiver = dynReceiver
|
|
369
548
|
? dynReceiver()
|
|
370
549
|
: lowerMethodReceiver(lowerer, access.expression, STRING, access.name.text);
|
|
371
550
|
const loc = locOf(call);
|
|
551
|
+
if (indexMethod)
|
|
552
|
+
return lowerStringIndexCall(lowerer, call, indexMethod, receiver, access.expression, argumentNodes);
|
|
553
|
+
if (!entry)
|
|
554
|
+
return null;
|
|
555
|
+
if (entry.method === "split")
|
|
556
|
+
return lowerStringSplitCall(lowerer, call, receiver, access.expression, argumentNodes);
|
|
372
557
|
if (entry.method === "padStart" || entry.method === "padEnd") {
|
|
373
558
|
return lowerStringPaddingCall(lowerer, call, entry.method, receiver, access.expression, argumentNodes);
|
|
374
559
|
}
|
|
@@ -467,15 +652,7 @@ export function lowerStringMethodCall(lowerer, call, access, dynReceiver, argume
|
|
|
467
652
|
}
|
|
468
653
|
return { kind: "call", callee: helper, args: [receiver, ...args], type: entry.result, loc };
|
|
469
654
|
}
|
|
470
|
-
const args =
|
|
471
|
-
? [lowerer.lowerExpr(argumentNodes[0]), lowerSplitLimitArg(lowerer, argumentNodes[1], locOf(call))]
|
|
472
|
-
: argumentNodes.map((a) => lowerer.lowerExpr(a));
|
|
473
|
-
// split's separator must BE a string here (a regex argument was
|
|
474
|
-
// claimed by lowerRegexMethodCall before this path) — the lib's
|
|
475
|
-
// `string | RegExp` union has no lowering as a VALUE.
|
|
476
|
-
if (entry.method === "split" && args[0].type.kind !== "string") {
|
|
477
|
-
lowerer.unsupported("SC1090", argumentNodes[0], `'.split()' on a '${lowerer.fmt(args[0].type)}' separator (pass a string, or a regex literal)`);
|
|
478
|
-
}
|
|
655
|
+
const args = argumentNodes.map((a) => lowerer.lowerExpr(a));
|
|
479
656
|
return {
|
|
480
657
|
kind: "strIntrinsic",
|
|
481
658
|
method: entry.method,
|