110
param.node.loc ?? GeneratedSource,
111
InstructionKind.Let,
112
param,
113
- { kind: "LoadLocal", place, loc: place.loc }
113
+ place
114
);
115
} else {
116
builder.errors.push({
590
}
591
case "VariableDeclaration": {
592
const stmt = stmtPath as NodePath<t.VariableDeclaration>;
593
- const nodeKind: string = stmt.node.kind;
593
+ const nodeKind: t.VariableDeclaration["kind"] = stmt.node.kind;
594
if (nodeKind === "var") {
595
builder.errors.push({
596
reason: `(BuildHIR::lowerStatement) Handle ${nodeKind} kinds in VariableDeclaration`,
604
for (const declaration of stmt.get("declarations")) {
605
const id = declaration.get("id");
606
const init = declaration.get("init");
607
- let value: InstructionValue;
607
+ let value: Place;
608
if (init.node != null) {
609
- value = lowerExpression(builder, init as NodePath<t.Expression>);
609
+ value = lowerExpressionToTemporary(
610
+ builder,
611
+ init as NodePath<t.Expression>
612
+ );
613
} else {
611
- value = {
612
- kind: "Primitive",
613
- value: undefined,
614
- loc: id.node.loc ?? GeneratedSource,
615
- };
614
+ value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource);
615
+ builder.push({
616
+ id: makeInstructionId(0),
617
+ lvalue: { place: { ...value }, kind: InstructionKind.Const },
618
+ value: {
619
+ kind: "Primitive",
620
+ value: undefined,
621
+ loc: id.node.loc ?? GeneratedSource,
622
+ },
623
+ loc: value.loc,
624
+ });
625
}
626
lowerAssignment(
627
builder,
1186
left.node.loc ?? GeneratedSource,
1187
InstructionKind.Reassign,
1188
left,
1180
- lowerExpression(builder, expr.get("right"))
1189
+ lowerExpressionToTemporary(builder, expr.get("right"))
1190
);
1191
}
1192
1218
switch (leftNode.type) {
1219
case "Identifier": {
1220
const leftExpr = left as NodePath<t.Identifier>;
1212
- const place = lowerIdentifier(builder, leftExpr);
1221
+ const identifier = lowerIdentifier(builder, leftExpr);
1222
+ const leftPlace = lowerExpressionToTemporary(builder, leftExpr);
1223
const right = lowerExpressionToTemporary(builder, expr.get("right"));
1224
+ const binaryPlace = buildTemporaryPlace(builder, exprLoc);
1225
builder.push({
1226
id: makeInstructionId(0),
1216
- lvalue: { place: { ...place }, kind: InstructionKind.Reassign },
1227
+ lvalue: {
1228
+ place: { ...binaryPlace },
1229
+ kind: InstructionKind.Const,
1230
+ },
1231
value: {
1232
kind: "BinaryExpression",
1233
operator: binaryOperator,
1220
- left: { ...place },
1234
+ left: leftPlace,
1235
right,
1236
loc: exprLoc,
1237
},
1238
loc: exprLoc,
1239
});
1226
- return { kind: "LoadLocal", place, loc: exprLoc };
1240
+ const result = buildTemporaryPlace(builder, exprLoc);
1241
+ builder.push({
1242
+ id: makeInstructionId(0),
1243
+ lvalue: { place: { ...result }, kind: InstructionKind.Const },
1244
+ value: {
1245
+ kind: "StoreLocal",
1246
+ lvalue: {
1247
+ place: { ...identifier },
1248
+ kind: InstructionKind.Reassign,
1249
+ },
1250
+ value: { ...binaryPlace },
1251
+ loc: exprLoc,
1252
+ },
1253
+ loc: exprLoc,
1254
+ });
1255
+ return { kind: "LoadLocal", place: identifier, loc: exprLoc };
1256
}
1257
case "MemberExpression": {
1258
// a.b.c += <right>
1575
});
1576
return { kind: "UnsupportedNode", node: exprNode, loc: exprLoc };
1577
}
1549
- const temp = buildTemporaryPlace(
1578
+ const primitiveTemp = buildTemporaryPlace(
1579
builder,
1580
expr.node.loc ?? GeneratedSource
1581
);
1582
builder.push({
1583
id: makeInstructionId(0),
1555
- lvalue: { place: { ...temp }, kind: InstructionKind.Const },
1584
+ lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const },
1585
value: {
1586
kind: "Primitive",
1587
value: 1,
1589
},
1590
loc: expr.node.loc ?? GeneratedSource,
1591
});
1592
+ const temp = buildTemporaryPlace(
1593
+ builder,
1594
+ expr.node.loc ?? GeneratedSource
1595
+ );
1596
const identifier = lowerIdentifier(
1597
builder,
1598
argument as NodePath<t.Identifier>
1599
);
1600
builder.push({
1601
id: makeInstructionId(0),
1569
- lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign },
1602
+ lvalue: { place: { ...temp }, kind: InstructionKind.Const },
1603
value: {
1604
kind: "BinaryExpression",
1605
operator: expr.node.operator === "++" ? "+" : "-",
1606
left: { ...identifier },
1574
- right: { ...temp },
1607
+ right: { ...primitiveTemp },
1608
+ loc: exprLoc,
1609
+ },
1610
+ loc: exprLoc,
1611
+ });
1612
+ builder.push({
1613
+ id: makeInstructionId(0),
1614
+ lvalue: {
1615
+ place: buildTemporaryPlace(builder, exprLoc),
1616
+ kind: InstructionKind.Const,
1617
+ },
1618
+ value: {
1619
+ kind: "StoreLocal",
1620
+ lvalue: {
1621
+ place: { ...identifier },
1622
+ kind: InstructionKind.Reassign,
1623
+ },
1624
+ value: { ...temp },
1625
loc: exprLoc,
1626
},
1627
loc: exprLoc,
1933
loc: SourceLocation,
1934
kind: InstructionKind,
1935
lvaluePath: NodePath<t.LVal>,
1886
- value: InstructionValue
1936
+ value: Place
1937
): InstructionValue {
1938
const lvalueNode = lvaluePath.node;
1939
switch (lvalueNode.type) {
1963
};
1964
}
1965
1966
+ const temporary = buildTemporaryPlace(builder, loc);
1967
const place: Place = {
1968
kind: "Identifier",
1969
identifier: identifier,
1972
};
1973
builder.push({
1974
id: makeInstructionId(0),
1924
- lvalue: { place: { ...place }, kind },
1925
- value,
1975
+ lvalue: { place: { ...temporary }, kind },
1976
+ value: {
1977
+ kind: "StoreLocal",
1978
+ lvalue: {
1979
+ place: { ...place },
1980
+ kind,
1981
+ },
1982
+ value,
1983
+ loc,
1984
+ },
1985
loc,
1986
});
1928
- return { kind: "LoadLocal", place, loc: place.loc };
1987
+ return { kind: "LoadLocal", place, loc: temporary.loc };
1988
}
1989
case "MemberExpression": {
1990
const lvalue = lvaluePath as NodePath<t.MemberExpression>;
1991
const property = lvalue.get("property");
1992
const object = lowerExpressionToTemporary(builder, lvalue.get("object"));
1934
- let valuePlace: Place;
1935
- if (value.kind === "LoadLocal") {
1936
- valuePlace = value.place;
1937
- } else {
1938
- valuePlace = buildTemporaryPlace(builder, loc);
1939
- builder.push({
1940
- id: makeInstructionId(0),
1941
- lvalue: { place: { ...valuePlace }, kind: InstructionKind.Const },
1942
- value,
1943
- loc,
1944
- });
1945
- }
1993
if (!lvalue.node.computed) {
1994
if (!property.isIdentifier()) {
1995
builder.errors.push({
2003
kind: "PropertyStore",
2004
object,
2005
property: property.node.name,
1959
- value: valuePlace,
2006
+ value,
2007
loc,
2008
};
2009
} else {
2021
kind: "ComputedStore",
2022
object,
2023
property: propertyPlace,
1977
- value: valuePlace,
2024
+ value,
2025
loc,
2026
};
2027
}
2028
}
2029
case "ArrayPattern": {
2030
const lvalue = lvaluePath as NodePath<t.ArrayPattern>;
1984
- const arrayPlace = buildTemporaryPlace(builder, loc);
1985
- builder.push({
1986
- id: makeInstructionId(0),
1987
- lvalue: { place: { ...arrayPlace }, kind: InstructionKind.Const },
1988
- value,
1989
- loc,
1990
- });
2031
const elements = lvalue.get("elements");
2032
let hasError = false;
2033
for (let i = 0; i < elements.length; i++) {
2058
},
2059
loc: element.node.loc ?? GeneratedSource,
2060
});
2021
- const value: InstructionValue = {
2022
- kind: "ComputedLoad",
2061
+ const propertyPlace = buildTemporaryPlace(builder, property.loc);
2062
+ builder.push({
2063
+ id: makeInstructionId(0),
2064
+ lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2065
+ value: {
2066
+ kind: "ComputedLoad",
2067
+ loc,
2068
+ object: { ...value },
2069
+ property,
2070
+ },
2071
loc,
2024
- object: { ...arrayPlace },
2025
- property,
2026
- };
2027
- lowerAssignment(builder, loc, kind, element as NodePath<t.LVal>, value);
2072
+ });
2073
+ lowerAssignment(
2074
+ builder,
2075
+ loc,
2076
+ kind,
2077
+ element as NodePath<t.LVal>,
2078
+ propertyPlace
2079
+ );
2080
}
2081
return hasError
2082
? { kind: "UnsupportedNode", node: lvalueNode, loc }
2031
- : { kind: "LoadLocal", place: arrayPlace, loc: arrayPlace.loc };
2083
+ : { kind: "LoadLocal", place: value, loc: value.loc };
2084
}
2085
case "ObjectPattern": {
2086
const lvalue = lvaluePath as NodePath<t.ObjectPattern>;
2035
- const objectPlace = buildTemporaryPlace(builder, loc);
2036
- builder.push({
2037
- id: makeInstructionId(0),
2038
- lvalue: { place: { ...objectPlace }, kind },
2039
- value,
2040
- loc,
2041
- });
2087
const properties = lvalue.get("properties");
2088
let hasError = false;
2089
for (let i = 0; i < properties.length; i++) {
2117
hasError = true;
2118
continue;
2119
}
2075
- const value: InstructionValue = {
2076
- kind: "PropertyLoad",
2120
+ const propertyPlace = buildTemporaryPlace(
2121
+ builder,
2122
+ property.node.loc ?? GeneratedSource
2123
+ );
2124
+ builder.push({
2125
+ id: makeInstructionId(0),
2126
+ lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2127
+ value: {
2128
+ kind: "PropertyLoad",
2129
+ loc,
2130
+ object: { ...value },
2131
+ property: key.node.name,
2132
+ optional: false, // Key of ObjectPattern (evaluation of LVal) cannot be optional.
2133
+ },
2134
loc,
2078
- object: { ...objectPlace },
2079
- property: key.node.name,
2080
- optional: false, // Key of ObjectPattern (evaluation of LVal) cannot be optional.
2081
- };
2082
- lowerAssignment(builder, loc, kind, element, value);
2135
+ });
2136
+ lowerAssignment(builder, loc, kind, element, propertyPlace);
2137
}
2138
return hasError
2139
? { kind: "UnsupportedNode", node: lvalueNode, loc }
2086
- : { kind: "LoadLocal", place: objectPlace, loc: objectPlace.loc };
2140
+ : { kind: "LoadLocal", place: value, loc: value.loc };
2141
}
2142
default: {
2143
builder.errors.push({