Remove unused Place.memberPath

After the previous PR to change the scope dependency representation, 
`Place.memberPath` is now completely unused, this PR deletes that field and all 
references. Rejoice!
This commit is contained in:
Joe Savona
2023-01-03 15:34:42 -08:00
parent c69cba357f
commit c2b2df0d17
13 changed files with 30 additions and 175 deletions
+8 -41
View File
@@ -79,7 +79,6 @@ export function lower(
const place: Place = {
kind: "Identifier",
identifier,
memberPath: null,
effect: Effect.Unknown,
loc: param.loc ?? GeneratedSource,
};
@@ -624,6 +623,10 @@ function lowerStatement(
nodeKind === "let" ? InstructionKind.Let : InstructionKind.Const;
for (const declaration of stmt.get("declarations")) {
const id = declaration.get("id");
invariant(
id.isIdentifier(),
"Support non-identifier variable declarations"
);
const init = declaration.get("init");
let value: InstructionValue;
if (init.hasNode()) {
@@ -942,11 +945,12 @@ function lowerExpression(
const leftNode = left.node;
switch (leftNode.type) {
case "Identifier": {
const lvalue = left as NodePath<t.Identifier>;
return lowerAssignment(
builder,
leftNode.loc ?? GeneratedSource,
InstructionKind.Reassign,
left,
lvalue,
lowerExpression(builder, expr.get("right"))
);
}
@@ -1247,7 +1251,6 @@ function lowerJsxElementName(
const place: Place = {
kind: "Identifier",
identifier: identifier,
memberPath: null,
effect: Effect.Unknown,
loc: exprLoc,
};
@@ -1373,47 +1376,12 @@ function lowerIdentifier(
const place: Place = {
kind: "Identifier",
identifier: identifier,
memberPath: null,
effect: Effect.Unknown,
loc: exprLoc,
};
return place;
}
function lowerLVal(builder: HIRBuilder, exprPath: NodePath<t.LVal>): Place {
const exprNode = exprPath.node;
const exprLoc = exprNode.loc ?? GeneratedSource;
switch (exprNode.type) {
case "Identifier": {
const expr = exprPath as NodePath<t.Identifier>;
return lowerIdentifier(builder, expr);
}
case "MemberExpression": {
const expr = exprPath as NodePath<t.MemberExpression>;
const objectPath = expr.get("object");
todoInvariant(objectPath.isLVal(), "Support complex object assignment");
const object = lowerLVal(builder, objectPath);
const propertyPath = expr.get("property");
todoInvariant(
propertyPath.isIdentifier(),
"Support non-identifier properties"
);
const place: Place = {
kind: "Identifier",
identifier: object.identifier,
memberPath: [...(object.memberPath ?? []), propertyPath.node.name],
effect: Effect.Unknown,
loc: exprLoc,
};
return place;
}
default: {
todo(`lowerLVal(${exprNode.type})`);
// assertExhaustive(exprNode, "Unexpected lval kind");
}
}
}
/**
* Creates a temporary Identifier and Place referencing that identifier.
*/
@@ -1421,7 +1389,6 @@ function buildTemporaryPlace(builder: HIRBuilder, loc: SourceLocation): Place {
const place: Place = {
kind: "Identifier",
identifier: builder.makeTemporary(),
memberPath: null,
effect: Effect.Unknown,
loc,
};
@@ -1432,10 +1399,10 @@ function lowerAssignment(
builder: HIRBuilder,
loc: SourceLocation,
kind: InstructionKind,
lvalue: NodePath<t.LVal>,
lvalue: NodePath<t.Identifier>,
value: InstructionValue
): InstructionValue {
const id = lowerLVal(builder, lvalue);
const id = lowerIdentifier(builder, lvalue);
builder.push({
id: makeInstructionId(0),
lvalue: { place: id, kind },
+6 -25
View File
@@ -302,10 +302,7 @@ export function codegenInstruction(
if (instr.lvalue === null) {
return t.expressionStatement(value);
}
if (
instr.lvalue.place.memberPath === null &&
instr.lvalue.place.identifier.name === null
) {
if (instr.lvalue.place.identifier.name === null) {
// temporary
temp.set(instr.lvalue.place.identifier.id, value);
return t.emptyStatement();
@@ -511,15 +508,7 @@ function codegenJsxElement(
}
export function codegenLVal(lval: LValue): t.LVal {
const expr = convertIdentifier(lval.place.identifier);
const memberPath = lval.place.memberPath;
return memberPath == null
? expr
: memberPath.reduceRight(
(path: t.Identifier | t.MemberExpression, member) =>
t.memberExpression(path, t.identifier(member)),
expr
);
return convertIdentifier(lval.place.identifier);
}
function codegenValue(
@@ -543,19 +532,11 @@ function codegenValue(
export function codegenPlace(temp: Temporaries, place: Place): t.Expression {
todoInvariant(place.kind === "Identifier", "support scope values");
if (place.memberPath === null) {
let tmp = temp.get(place.identifier.id);
if (tmp != null) {
return tmp;
}
return convertIdentifier(place.identifier);
} else {
let object: t.Expression = convertIdentifier(place.identifier);
for (const path of place.memberPath) {
object = t.memberExpression(object, t.identifier(path));
}
return object;
let tmp = temp.get(place.identifier.id);
if (tmp != null) {
return tmp;
}
return convertIdentifier(place.identifier);
}
export function convertIdentifier(identifier: Identifier): t.Identifier {
-1
View File
@@ -316,7 +316,6 @@ export type InstructionData =
export type Place = {
kind: "Identifier";
identifier: Identifier;
memberPath: Array<string> | null;
effect: Effect;
loc: SourceLocation;
};
-5
View File
@@ -7,11 +7,6 @@ class AliasAnalyser {
aliases = new DisjointSet<Identifier>();
alias(lvalue: LValue, alias: Place) {
// This is handled by InferAliasForStores.
if (lvalue.place.memberPath !== null) {
return;
}
this.aliases.union([lvalue.place.identifier, alias.identifier]);
}
}
@@ -122,19 +122,15 @@ export function inferMutableLifetimes(
}
if (instr.lvalue !== null) {
if (instr.lvalue.place.memberPath === null) {
const lvalueId = instr.lvalue.place.identifier;
const lvalueId = instr.lvalue.place.identifier;
// lvalue start being mutable when they're initially assigned a
// value.
lvalueId.mutableRange.start = instr.id;
// lvalue start being mutable when they're initially assigned a
// value.
lvalueId.mutableRange.start = instr.id;
// Let's be optimistic and assume this lvalue is not mutable by
// default.
lvalueId.mutableRange.end = makeInstructionId(instr.id + 1);
} else {
inferPlace(instr.lvalue.place, instr, inferMutableRangeForStores);
}
// Let's be optimistic and assume this lvalue is not mutable by
// default.
lvalueId.mutableRange.end = makeInstructionId(instr.id + 1);
}
}
}
@@ -74,7 +74,6 @@ export default function inferReferenceEffects(fn: HIRFunction) {
const initialEnvironment = Environment.empty();
const id: Place = {
kind: "Identifier",
memberPath: null,
identifier: fn.id as any,
loc: fn.loc,
effect: Effect.Freeze,
@@ -172,7 +171,7 @@ class Environment {
*/
initialize(value: InstructionValue, kind: ValueKind) {
invariant(
value.kind !== "Identifier" || value.memberPath !== null,
value.kind !== "Identifier",
"Expected all top-level identifiers to be defined as variables, not values"
);
this.#values.set(value, kind);
@@ -218,10 +217,6 @@ class Environment {
* Defines (initializing or updating) a variable with a specific kind of value.
*/
define(place: Place, value: InstructionValue) {
invariant(
place.memberPath === null,
"Expected a top-level identifier, not a member path"
);
invariant(
this.#values.has(value),
`Expected value to be initialized at '${printSourceLocation(value.loc)}'`
@@ -587,10 +582,6 @@ function inferBlock(env: Environment, block: BasicBlock) {
const lvalue = instr.lvalue;
if (lvalue !== null) {
invariant(
lvalue.place.memberPath === null,
"PropertyLoad must always be saved to a temporary"
);
env.alias(lvalue.place, instrValue.value);
lvalue.place.effect = Effect.Store;
}
@@ -611,27 +602,15 @@ function inferBlock(env: Environment, block: BasicBlock) {
env.reference(instrValue.object, Effect.Read);
const lvalue = instr.lvalue;
if (lvalue !== null) {
invariant(
lvalue.place.memberPath === null,
"PropertyLoad must always be saved to a temporary"
);
env.initialize(instrValue, env.kind(instrValue.object));
env.define(lvalue.place, instrValue);
}
continue;
}
case "Identifier": {
invariant(
instrValue.memberPath === null,
"Expected RHS memberPath to be lowered to PropertyLoad"
);
env.reference(instrValue, Effect.Read);
const lvalue = instr.lvalue;
if (lvalue !== null) {
invariant(
lvalue.place.memberPath === null,
"Expected lvalue member path to be null"
);
lvalue.place.effect = Effect.Mutate;
// direct aliasing: `a = b`;
env.alias(lvalue.place, instrValue);
@@ -654,10 +633,6 @@ function inferBlock(env: Environment, block: BasicBlock) {
env.initialize(instrValue, valueKind);
if (instr.lvalue !== null) {
invariant(
instr.lvalue.place.memberPath === null,
"Expected lvalue member path to be null"
);
env.define(instr.lvalue.place, instrValue);
instr.lvalue.place.effect = lvalueEffect;
}
@@ -695,10 +670,6 @@ type HookKind = { kind: "State" } | { kind: "Ref" } | { kind: "Custom" };
type Hook = HookKind & { effectKind: Effect; valueKind: ValueKind };
function parseHookCall(place: Place): Hook | null {
if (place.memberPath !== null) {
// Hook calls must be statically resolved
return null;
}
const name = place.identifier.name;
if (name === null || !name.match(/^_?use/)) {
return null;
+1 -1
View File
@@ -132,7 +132,7 @@ function generateTypeEquation(
function assignType(place: Place | undefined): Type | null {
// We type only top level identifiers. Typing objects is not very useful
// when we have to be so conservative.
if (place?.memberPath !== null) {
if (place === undefined) {
return null;
}
+1 -8
View File
@@ -321,14 +321,7 @@ export function printLValue(lval: LValue): string {
export function printPlace(place: Place): string {
const items = [place.effect, " ", printIdentifier(place.identifier)];
if (place.memberPath !== null) {
for (const path of place.memberPath) {
items.push(".");
items.push(path);
}
} else {
items.push(printType(place.identifier.type));
}
items.push(printType(place.identifier.type));
return items.filter((x) => x != null).join("");
}
@@ -305,11 +305,7 @@ export function codegenInstructionNullable(
value: t.Expression
): t.Statement | null {
let statement;
if (
instr.lvalue !== null &&
instr.lvalue.place.memberPath === null &&
cx.declared(instr.lvalue.place.identifier)
) {
if (instr.lvalue !== null && cx.declared(instr.lvalue.place.identifier)) {
statement = codegenInstruction(
cx.temp,
{
@@ -80,11 +80,7 @@ export function inferReactiveScopeVariables(fn: HIRFunction) {
const operands: Array<Identifier> = [];
if (instr.lvalue !== null) {
const range = instr.lvalue.place.identifier.mutableRange;
if (
instr.lvalue.place.memberPath !== null ||
range.end > range.start + 1 ||
mayAllocate(instr.value)
) {
if (range.end > range.start + 1 || mayAllocate(instr.value)) {
operands.push(instr.lvalue!.place.identifier);
}
}
@@ -21,7 +21,6 @@ import {
ReactiveValueBlock,
} from "../HIR/HIR";
import { eachInstructionValueOperand } from "../HIR/visitors";
import { invariant } from "../Utils/CompilerError";
import { assertExhaustive } from "../Utils/utils";
/**
@@ -76,14 +75,6 @@ class Context {
}
declareProperty(lvalue: Place, object: Place, property: string): void {
invariant(
lvalue.memberPath === null,
"Expected property loads to be stored to a temporary (no member path)"
);
invariant(
object.memberPath === null,
"Expected operands to have null memberPath"
);
const objectDependency = this.#properties.get(object.identifier);
let nextDependency: ReactiveScopeDependency;
if (objectDependency === undefined) {
@@ -281,17 +272,7 @@ function visitInstructionValue(
): void {
for (const operand of eachInstructionValueOperand(value)) {
// check for method invocation, we want to depend on the callee, not the method
if (
value.kind === "CallExpression" &&
operand === value.callee &&
operand.memberPath !== null
) {
const callee = {
...operand,
memberPath: operand.memberPath.slice(0, -1),
};
context.visitOperand(callee);
} else if (value.kind === "PropertyLoad" && lvalue !== null) {
if (value.kind === "PropertyLoad" && lvalue !== null) {
context.declareProperty(lvalue.place, value.object, value.property);
} else {
context.visitOperand(operand);
@@ -302,11 +283,7 @@ function visitInstructionValue(
function visitInstruction(context: Context, instr: Instruction): void {
const { lvalue } = instr;
visitInstructionValue(context, instr.value, lvalue);
if (
lvalue !== null &&
lvalue.kind !== InstructionKind.Reassign &&
lvalue.place.memberPath === null
) {
if (lvalue !== null && lvalue.kind !== InstructionKind.Reassign) {
const range = lvalue.place.identifier.mutableRange;
// TODO: only assign Const if the value is never reassigned
const kind =
+2 -6
View File
@@ -199,12 +199,8 @@ export default function enterSSA(func: HIRFunction, env: Environment) {
if (instr.lvalue != null) {
const oldPlace = instr.lvalue.place;
let newPlace: Place;
if (oldPlace.memberPath !== null) {
newPlace = builder.getPlace(oldPlace);
} else {
newPlace = builder.definePlace(oldPlace);
instr.lvalue.kind = InstructionKind.Const;
}
newPlace = builder.definePlace(oldPlace);
instr.lvalue.kind = InstructionKind.Const;
instr.lvalue.place = newPlace;
}
}
-12
View File
@@ -136,13 +136,6 @@ export function leaveSSA(fn: HIRFunction) {
const update = fn.body.blocks.get(terminal.update)!;
rewritePhis.push(...update.phis);
update.phis.clear();
// find declarations in the for init
for (const instr of init.instructions) {
if (instr.lvalue !== null && instr.lvalue.place.memberPath === null) {
// hasDeclaration.add(instr.lvalue.place.identifier);
}
}
}
for (const phi of reassignmentPhis) {
@@ -197,7 +190,6 @@ export function leaveSSA(fn: HIRFunction) {
lvalue: {
place: {
kind: "Identifier",
memberPath: null,
identifier: canonicalId,
effect: Effect.Mutate,
loc: GeneratedSource,
@@ -208,7 +200,6 @@ export function leaveSSA(fn: HIRFunction) {
initOperand !== null
? {
kind: "Identifier",
memberPath: null,
identifier: initOperand,
effect: Effect.Read,
loc: GeneratedSource,
@@ -234,7 +225,6 @@ export function leaveSSA(fn: HIRFunction) {
lvalue: {
place: {
kind: "Identifier",
memberPath: null,
identifier: canonicalId,
effect: Effect.Mutate,
loc: GeneratedSource,
@@ -243,7 +233,6 @@ export function leaveSSA(fn: HIRFunction) {
},
value: {
kind: "Identifier",
memberPath: null,
identifier: operand,
effect: Effect.Read,
loc: GeneratedSource,
@@ -295,7 +284,6 @@ export function leaveSSA(fn: HIRFunction) {
if (lvalue !== null) {
if (
lvalue.kind === InstructionKind.Const &&
lvalue.place.memberPath === null &&
rewrites.has(lvalue.place.identifier)
) {
// For rewrites, the declaration of the canonical identifier has to be `let`,