99
const params: Array<Place | SpreadPattern> = [];
100
func.get("params").forEach((param) => {
101
if (param.isIdentifier()) {
102
- const identifier = builder.resolveIdentifier(param);
103
- if (identifier === null) {
102
+ const binding = builder.resolveIdentifier(param);
103
+ if (binding.kind !== "Identifier") {
104
builder.errors.push({
105
reason: `(BuildHIR::lower) Could not find binding for param \`${param.node.name}\``,
106
severity: ErrorSeverity.Invariant,
111
}
112
const place: Place = {
113
kind: "Identifier",
114
- identifier,
114
+ identifier: binding.identifier,
115
effect: Effect.Unknown,
116
reactive: false,
117
loc: param.node.loc ?? GeneratedSource,
449
});
450
continue;
451
}
452
- const identifier = builder.resolveIdentifier(id)!;
452
+ const identifier = builder.resolveIdentifier(id);
453
+ CompilerError.invariant(identifier.kind === "Identifier", {
454
+ reason:
455
+ "Expected hoisted binding to be a local identifier, not a global",
456
+ loc: id.node.loc ?? GeneratedSource,
457
+ });
458
const place: Place = {
459
effect: Effect.Unknown,
455
- identifier,
460
+ identifier: identifier.identifier,
461
kind: "Identifier",
462
reactive: false,
463
loc: id.node.loc ?? GeneratedSource,
841
: "Assignment"
842
);
843
} else if (id.isIdentifier()) {
839
- const identifier = builder.resolveIdentifier(id);
840
- if (identifier == null) {
844
+ const binding = builder.resolveIdentifier(id);
845
+ if (binding.kind !== "Identifier") {
846
builder.errors.push({
847
reason: `(BuildHIR::lowerAssignment) Could not find binding for declaration.`,
848
severity: ErrorSeverity.Invariant,
852
} else {
853
const place: Place = {
854
effect: Effect.Unknown,
850
- identifier,
855
+ identifier: binding.identifier,
856
kind: "Identifier",
857
reactive: false,
858
loc: id.node.loc ?? GeneratedSource,
2099
const tagIdentifier = openingIdentifier.isJSXIdentifier()
2100
? builder.resolveIdentifier(openingIdentifier)
2101
: null;
2097
- if (tagIdentifier != null) {
2102
+ if (tagIdentifier != null && tagIdentifier.kind === "Identifier") {
2103
CompilerError.throwTodo({
2104
reason: `Support <${tagName}> tags where '${tagName}' is a local variable instead of a global`,
2105
loc: openingIdentifier.node.loc ?? GeneratedSource,
2727
): boolean {
2728
switch (expr.node.type) {
2729
case "Identifier": {
2725
- const identifier = builder.resolveIdentifier(
2726
- expr as NodePath<t.Identifier>
2727
- );
2728
- if (identifier === null) {
2730
+ const binding = builder.resolveIdentifier(expr as NodePath<t.Identifier>);
2731
+ if (binding.kind === "Identifier") {
2732
+ return allowLocalIdentifiers;
2733
+ } else {
2734
// global, definitely safe
2735
return true;
2731
- } else {
2732
- return allowLocalIdentifiers;
2736
}
2737
}
2738
case "RegExpLiteral":
2824
}
2825
if (
2826
innerObject.isIdentifier() &&
2824
- builder.resolveIdentifier(innerObject) === null // null means global
2827
+ builder.resolveIdentifier(innerObject).kind !== "Identifier"
2828
) {
2829
// This is a property/computed load from a global, that's safe to reorder
2830
return true;
3266
): Place {
3267
const exprNode = exprPath.node;
3268
const exprLoc = exprNode.loc ?? GeneratedSource;
3266
- const identifier = builder.resolveIdentifier(exprPath);
3267
- if (identifier === null) {
3268
- const global = builder.resolveGlobal(exprPath);
3269
- let value: InstructionValue;
3270
- if (global !== null) {
3271
- value = { kind: "LoadGlobal", name: global.name, loc: exprLoc };
3272
- } else {
3273
- value = { kind: "UnsupportedNode", node: exprPath.node, loc: exprLoc };
3269
+ const binding = builder.resolveIdentifier(exprPath);
3270
+ switch (binding.kind) {
3271
+ case "Identifier": {
3272
+ const place: Place = {
3273
+ kind: "Identifier",
3274
+ identifier: binding.identifier,
3275
+ effect: Effect.Unknown,
3276
+ reactive: false,
3277
+ loc: exprLoc,
3278
+ };
3279
+ return place;
3280
+ }
3281
+ default: {
3282
+ return lowerValueToTemporary(builder, {
3283
+ kind: "LoadGlobal",
3284
+ binding,
3285
+ loc: exprLoc,
3286
+ });
3287
}
3275
- return lowerValueToTemporary(builder, value);
3288
}
3277
- const place: Place = {
3278
- kind: "Identifier",
3279
- identifier: identifier,
3280
- effect: Effect.Unknown,
3281
- reactive: false,
3282
- loc: exprLoc,
3283
- };
3284
- return place;
3289
}
3290
3291
// Creates a temporary Identifier and Place referencing that identifier.
3322
kind: InstructionKind,
3323
path: NodePath<t.Identifier>
3324
): Place | { kind: "Global"; name: string } | null {
3321
- const identifier = builder.resolveIdentifier(path);
3322
- if (identifier == null) {
3325
+ const binding = builder.resolveIdentifier(path);
3326
+ if (binding.kind !== "Identifier") {
3327
if (kind === InstructionKind.Reassign) {
3328
return { kind: "Global", name: path.node.name };
3329
} else {
3340
3341
const place: Place = {
3342
kind: "Identifier",
3339
- identifier: identifier,
3343
+ identifier: binding.identifier,
3344
effect: Effect.Unknown,
3345
reactive: false,
3346
loc,
3500
(element) =>
3501
element.isIdentifier() &&
3502
(getStoreKind(builder, element) !== "StoreLocal" ||
3499
- builder.resolveIdentifier(element) == null)
3503
+ builder.resolveIdentifier(element).kind !== "Identifier")
3504
));
3505
for (let i = 0; i < elements.length; i++) {
3506
const element = elements[i];
3631
(!property.get("value").isIdentifier() ||
3632
builder.resolveIdentifier(
3633
property.get("value") as NodePath<t.Identifier>
3630
- ) == null))
3634
+ ).kind !== "Identifier"))
3635
);
3636
for (let i = 0; i < propertiesPaths.length; i++) {
3637
const property = propertiesPaths[i];