1093
const loc = expr.node.loc ?? GeneratedSource;
1094
const place = buildTemporaryPlace(builder, loc);
1095
const continuationBlock = builder.reserve(builder.currentBlockKind());
1096
+ const consequent = builder.reserve("value");
1097
+
1098
+ // block to evaluate if the callee is null/undefined, this sets the result of the call to undefined.
1099
+ const alternate = builder.enter("value", () => {
1100
+ const temp = lowerValueToTemporary(builder, {
1101
+ kind: "Primitive",
1102
+ value: undefined,
1103
+ loc,
1104
+ });
1105
+ lowerValueToTemporary(builder, {
1106
+ kind: "StoreLocal",
1107
+ lvalue: { kind: InstructionKind.Const, place: { ...place } },
1108
+ value: { ...temp },
1109
+ loc,
1110
+ });
1111
+ return {
1112
+ kind: "goto",
1113
+ variant: GotoVariant.Break,
1114
+ block: continuationBlock.id,
1115
+ id: makeInstructionId(0),
1116
+ loc,
1117
+ };
1118
+ });
1119
1120
// Lower the callee in the current block: the callee is always unconditionally evaluated
1121
// The test block's branch will test on this value to determine whether to evaluate the call (consequent)
1123
let callee:
1124
| { kind: "CallExpression"; callee: Place }
1125
| { kind: "MethodCall"; receiver: Place; property: Place };
1103
- if (
1104
- calleePath.isMemberExpression() ||
1105
- calleePath.isOptionalMemberExpression()
1106
- ) {
1107
- const memberExpr = lowerMemberExpression(builder, calleePath);
1108
- const propertyPlace = lowerValueToTemporary(builder, memberExpr.value);
1109
- callee = {
1110
- kind: "MethodCall",
1111
- receiver: memberExpr.object,
1112
- property: propertyPlace,
1113
- };
1114
- } else {
1115
- callee = {
1116
- kind: "CallExpression",
1117
- callee: lowerExpressionToTemporary(builder, calleePath),
1126
+ const testBlock = builder.enter("value", () => {
1127
+ if (
1128
+ calleePath.isMemberExpression() ||
1129
+ calleePath.isOptionalMemberExpression()
1130
+ ) {
1131
+ const memberExpr = lowerMemberExpression(builder, calleePath);
1132
+ const propertyPlace = lowerValueToTemporary(
1133
+ builder,
1134
+ memberExpr.value
1135
+ );
1136
+ callee = {
1137
+ kind: "MethodCall",
1138
+ receiver: memberExpr.object,
1139
+ property: propertyPlace,
1140
+ };
1141
+ } else {
1142
+ callee = {
1143
+ kind: "CallExpression",
1144
+ callee: lowerExpressionToTemporary(builder, calleePath),
1145
+ };
1146
+ }
1147
+ const testPlace =
1148
+ callee.kind === "CallExpression" ? callee.callee : callee.property;
1149
+ return {
1150
+ kind: "branch",
1151
+ test: { ...testPlace },
1152
+ consequent: consequent.id,
1153
+ alternate,
1154
+ id: makeInstructionId(0),
1155
+ loc,
1156
};
1119
- }
1157
+ });
1158
1159
// block to evaluate if the callee is non-null/undefined. arguments are lowered in this block to preserve
1160
// the semantic of conditional evaluation depending on the callee
1123
- const consequent = builder.enter("value", () => {
1161
+ builder.enterReserved(consequent, () => {
1162
const args = lowerArguments(builder, expr.get("arguments"));
1163
const temp = buildTemporaryPlace(builder, loc);
1164
if (callee.kind === "CallExpression") {
1202
};
1203
});
1204
1167
- // block to evaluate if the callee is null/undefined, this sets the result of the call to undefined.
1168
- const alternate = builder.enter("value", () => {
1169
- const temp = lowerValueToTemporary(builder, {
1170
- kind: "Primitive",
1171
- value: undefined,
1172
- loc,
1173
- });
1174
- lowerValueToTemporary(builder, {
1175
- kind: "StoreLocal",
1176
- lvalue: { kind: InstructionKind.Const, place: { ...place } },
1177
- value: { ...temp },
1178
- loc,
1179
- });
1180
- return {
1181
- kind: "goto",
1182
- variant: GotoVariant.Break,
1183
- block: continuationBlock.id,
1184
- id: makeInstructionId(0),
1185
- loc,
1186
- };
1187
- });
1188
-
1189
- const testBlock = builder.enter("value", () => {
1190
- const testPlace =
1191
- callee.kind === "CallExpression" ? callee.callee : callee.property;
1192
- return {
1193
- kind: "branch",
1194
- test: { ...testPlace },
1195
- consequent,
1196
- alternate,
1197
- id: makeInstructionId(0),
1198
- loc,
1199
- };
1200
- });
1201
-
1205
builder.terminateWithContinuation(
1206
{
1207
kind: "optional-call",