902
calleePath.isExpression(),
903
"Call expressions only support callees that are expressions (v8 intrinsics not supported)"
904
);
905
- const callee = lowerExpressionToPlace(builder, calleePath);
906
- const argPaths = expr.get("arguments");
907
- const args = argPaths.map((arg) => {
908
- todoInvariant(
909
- arg.isExpression(),
910
- "todo: support non-expression call arguments"
905
+ if (calleePath.isMemberExpression()) {
906
+ const { object, property, value } = lowerMemberExpression(
907
+ builder,
908
+ calleePath
909
);
912
- return lowerExpressionToPlace(builder, arg);
913
- });
914
- return {
915
- kind: "CallExpression",
916
- callee,
917
- args,
918
- loc: exprLoc,
919
- };
910
+ const args = expr.get("arguments").map((arg) => {
911
+ todoInvariant(
912
+ arg.isExpression(),
913
+ "todo: support non-expression call arguments"
914
+ );
915
+ return lowerExpressionToPlace(builder, arg);
916
+ });
917
+ if (typeof property === "string") {
918
+ return {
919
+ kind: "PropertyCall",
920
+ receiver: object,
921
+ property,
922
+ args,
923
+ loc: exprLoc,
924
+ };
925
+ } else {
926
+ return {
927
+ kind: "ComputedCall",
928
+ receiver: object,
929
+ property,
930
+ args,
931
+ loc: exprLoc,
932
+ };
933
+ }
934
+ } else {
935
+ const callee = lowerExpressionToPlace(builder, calleePath);
936
+ const args = expr.get("arguments").map((arg) => {
937
+ todoInvariant(
938
+ arg.isExpression(),
939
+ "todo: support non-expression call arguments"
940
+ );
941
+ return lowerExpressionToPlace(builder, arg);
942
+ });
943
+ return {
944
+ kind: "CallExpression",
945
+ callee,
946
+ args,
947
+ loc: exprLoc,
948
+ };
949
+ }
950
}
951
case "BinaryExpression": {
952
const expr = exprPath as NodePath<t.BinaryExpression>;
1171
}
1172
case "MemberExpression": {
1173
const expr = exprPath as NodePath<t.MemberExpression>;
1144
- const object = lowerExpressionToPlace(builder, expr.get("object"));
1145
- invariant(object.kind === "Identifier", "scope cannot appear here");
1146
- const property = expr.get("property");
1147
- let value: InstructionValue;
1148
- if (!expr.node.computed) {
1149
- todoInvariant(property.isIdentifier(), "Support private names");
1150
- value = {
1151
- kind: "PropertyLoad",
1152
- object,
1153
- property: property.node.name,
1154
- loc: exprLoc,
1155
- };
1156
- } else {
1157
- invariant(
1158
- property.isExpression(),
1159
- "Expected private names to be non-computed"
1160
- );
1161
- const propertyPlace = lowerExpressionToPlace(builder, property);
1162
- value = {
1163
- kind: "ComputedLoad",
1164
- object,
1165
- property: propertyPlace,
1166
- loc: exprLoc,
1167
- };
1168
- }
1174
+ const { value } = lowerMemberExpression(builder, expr);
1175
const place: Place = buildTemporaryPlace(builder, exprLoc);
1176
builder.push({
1177
id: makeInstructionId(0),
1264
}
1265
}
1266
1267
+function lowerMemberExpression(
1268
+ builder: HIRBuilder,
1269
+ expr: NodePath<t.MemberExpression>
1270
+): { object: Place; property: Place | string; value: InstructionValue } {
1271
+ const exprLoc = expr.node.loc ?? GeneratedSource;
1272
+ const object = lowerExpressionToPlace(builder, expr.get("object"));
1273
+ const property = expr.get("property");
1274
+ if (!expr.node.computed) {
1275
+ todoInvariant(property.isIdentifier(), "Support private names");
1276
+ const value: InstructionValue = {
1277
+ kind: "PropertyLoad",
1278
+ object: { ...object },
1279
+ property: property.node.name,
1280
+ loc: exprLoc,
1281
+ };
1282
+ return { object, property: property.node.name, value };
1283
+ } else {
1284
+ invariant(
1285
+ property.isExpression(),
1286
+ "Expected private names to be non-computed"
1287
+ );
1288
+ const propertyPlace = lowerExpressionToPlace(builder, property);
1289
+ const value: InstructionValue = {
1290
+ kind: "ComputedLoad",
1291
+ object: { ...object },
1292
+ property: { ...propertyPlace },
1293
+ loc: exprLoc,
1294
+ };
1295
+ return { object, property: propertyPlace, value };
1296
+ }
1297
+}
1298
+
1299
function lowerConditional(
1300
builder: HIRBuilder,
1301
test: Place,