Foundation for IndexStore/IndexLoad (no lowering)

Adds new types for IndexLoad/IndexStore (renamed later in the stack to 
ComputedLoad/ComputedStore) which will be used to represent computed property 
access/update. The actual lowering to use these is later in the stack.
This commit is contained in:
Joe Savona
2023-01-03 16:59:35 -08:00
parent c2b2df0d17
commit 45b3bd4899
7 changed files with 99 additions and 0 deletions
+20
View File
@@ -473,6 +473,26 @@ export function codegenInstructionValue(
);
break;
}
case "IndexStore": {
value = t.assignmentExpression(
"=",
t.memberExpression(
codegenPlace(temp, instrValue.object),
codegenPlace(temp, instrValue.property),
true
),
codegenPlace(temp, instrValue.value)
);
break;
}
case "IndexLoad": {
value = t.memberExpression(
codegenPlace(temp, instrValue.object),
codegenPlace(temp, instrValue.property),
true
);
break;
}
case "Identifier": {
value = codegenPlace(temp, instrValue);
break;
+5
View File
@@ -298,6 +298,11 @@ export type InstructionData =
// load `object.property`
| { kind: "PropertyLoad"; object: Place; property: string }
// store `object[index] = value` - like PropertyStore but with a dynamic property
| { kind: "IndexStore"; object: Place; property: Place; value: Place }
// load `object[index]` - like PropertyLoad but with a dynamic property
| { kind: "IndexLoad"; object: Place; property: Place }
/**
* Catch-all for statements such as type imports, nested class declarations, etc
* which are not directly represented, but included for completeness and to allow
@@ -607,6 +607,42 @@ function inferBlock(env: Environment, block: BasicBlock) {
}
continue;
}
case "IndexStore": {
const effect = isObjectType(instrValue.object.identifier)
? Effect.Store
: Effect.Mutate;
env.reference(instrValue.value, Effect.Read);
env.reference(instrValue.property, Effect.Read);
env.reference(instrValue.object, effect);
const lvalue = instr.lvalue;
if (lvalue !== null) {
env.alias(lvalue.place, instrValue.value);
lvalue.place.effect = Effect.Store;
}
continue;
}
case "IndexLoad": {
if (!env.isDefined(instrValue.object)) {
// TODO @josephsavona: improve handling of globals
const value: InstructionValue = {
kind: "Primitive",
loc: instrValue.loc,
value: undefined,
};
env.initialize(value, ValueKind.Frozen);
env.define(instrValue.object, value);
}
env.reference(instrValue.object, Effect.Read);
env.reference(instrValue.property, Effect.Read);
const lvalue = instr.lvalue;
if (lvalue !== null) {
env.initialize(instrValue, env.kind(instrValue.object));
env.define(lvalue.place, instrValue);
}
continue;
}
case "Identifier": {
env.reference(instrValue, Effect.Read);
const lvalue = instr.lvalue;
+12
View File
@@ -277,6 +277,18 @@ export function printInstructionValue(instrValue: InstructionValue): string {
} = ${printPlace(instrValue.value)}`;
break;
}
case "IndexLoad": {
value = `IndexLoad ${printPlace(instrValue.object)}[${printPlace(
instrValue.property
)}]`;
break;
}
case "IndexStore": {
value = `IndexStore ${printPlace(instrValue.object)}[${printPlace(
instrValue.property
)}] = ${printPlace(instrValue.value)}`;
break;
}
default: {
assertExhaustive(
instrValue,
+22
View File
@@ -50,6 +50,17 @@ export function* eachInstructionValueOperand(
yield instrValue.value;
break;
}
case "IndexLoad": {
yield instrValue.object;
yield instrValue.property;
break;
}
case "IndexStore": {
yield instrValue.object;
yield instrValue.property;
yield instrValue.value;
break;
}
case "UnaryExpression": {
yield instrValue.value;
break;
@@ -110,6 +121,17 @@ export function mapInstructionOperands(
instrValue.value = fn(instrValue.value);
break;
}
case "IndexLoad": {
instrValue.object = fn(instrValue.object);
instrValue.property = fn(instrValue.property);
break;
}
case "IndexStore": {
instrValue.object = fn(instrValue.object);
instrValue.property = fn(instrValue.property);
instrValue.value = fn(instrValue.value);
break;
}
case "Identifier": {
instr.value = fn(instrValue);
break;
@@ -161,11 +161,13 @@ function mayAllocate(value: InstructionValue): boolean {
case "BinaryExpression":
case "Identifier":
case "PropertyLoad":
case "IndexLoad":
case "JSXText":
case "Primitive": {
return false;
}
case "PropertyStore":
case "IndexStore":
case "ArrayExpression":
case "CallExpression":
case "JsxExpression":
@@ -302,6 +302,8 @@ function valueKind(value: InstructionValue): DeclKind {
case "Primitive": {
return DeclKind.Const;
}
case "IndexLoad":
case "IndexStore":
case "PropertyStore":
case "PropertyLoad":
case "Identifier":