JS backend: return empty expression for unreachable code during translation

This commit is contained in:
Michael Nedzelsky
2014-08-29 15:46:14 +04:00
parent 6e728852d0
commit 81c7a1b1da
5 changed files with 23 additions and 36 deletions
@@ -192,9 +192,6 @@ object SuperCallCase : FunctionCallCase {
} }
fun FunctionCallInfo.translateFunctionCall(): JsExpression { fun FunctionCallInfo.translateFunctionCall(): JsExpression {
if (this.argumentsInfo.hasEmptyExpressionArgument())
return context.getEmptyExpression()
val intrinsic = DelegateFunctionIntrinsic.intrinsic(this) val intrinsic = DelegateFunctionIntrinsic.intrinsic(this)
return when { return when {
@@ -94,6 +94,11 @@ public final class Translation {
JsNode result = doTranslateExpression(expression, innerContext); JsNode result = doTranslateExpression(expression, innerContext);
context.moveVarsFrom(innerContext); context.moveVarsFrom(innerContext);
block.getStatements().addAll(innerContext.dynamicContext().jsBlock().getStatements()); block.getStatements().addAll(innerContext.dynamicContext().jsBlock().getStatements());
if (BindingContextUtilPackage.isUnreachableCode(expression, context.bindingContext())) {
return context.getEmptyExpression();
}
return result; return result;
} }
@@ -46,10 +46,6 @@ public final class IntrinsicAssignmentTranslator extends AssignmentTranslator {
@NotNull @NotNull
private JsExpression translate() { private JsExpression translate() {
if (JsAstUtils.isEmptyExpression(right)) {
return right;
}
if (isAssignment(getOperationToken(expression))) { if (isAssignment(getOperationToken(expression))) {
return translateAsPlainAssignment(); return translateAsPlainAssignment();
} }
@@ -45,10 +45,6 @@ public final class OverloadedAssignmentTranslator extends AssignmentTranslator {
@NotNull @NotNull
private JsExpression translate() { private JsExpression translate() {
if (JsAstUtils.isEmptyExpression(right)) {
return right;
}
if (isVariableReassignment) { if (isVariableReassignment) {
return reassignment(); return reassignment();
} }
@@ -66,17 +66,11 @@ public class CallArgumentTranslator extends AbstractTranslator {
private final List<JsExpression> translateArguments; private final List<JsExpression> translateArguments;
private final boolean hasSpreadOperator; private final boolean hasSpreadOperator;
private final TemporaryConstVariable cachedReceiver; private final TemporaryConstVariable cachedReceiver;
private final boolean hasEmptyExpressionArgument;
public ArgumentsInfo(List<JsExpression> arguments, boolean operator, TemporaryConstVariable receiver) { public ArgumentsInfo(List<JsExpression> arguments, boolean operator, TemporaryConstVariable receiver) {
this(arguments, operator, receiver, false);
}
public ArgumentsInfo(List<JsExpression> arguments, boolean operator, TemporaryConstVariable receiver, boolean hasEmptyExpressionArgument) {
translateArguments = arguments; translateArguments = arguments;
hasSpreadOperator = operator; hasSpreadOperator = operator;
cachedReceiver = receiver; cachedReceiver = receiver;
this.hasEmptyExpressionArgument = hasEmptyExpressionArgument;
} }
@NotNull @NotNull
@@ -92,13 +86,9 @@ public class CallArgumentTranslator extends AbstractTranslator {
public TemporaryConstVariable getCachedReceiver() { public TemporaryConstVariable getCachedReceiver() {
return cachedReceiver; return cachedReceiver;
} }
public boolean hasEmptyExpressionArgument() {
return hasEmptyExpressionArgument;
}
} }
public static enum ArgumentsKind { HAS_EMPTY_EXPRESSION_ARGUMENT, HAS_NOT_EMPTY_EXPRESSION_ARGUMENT } private static enum ArgumentsKind { HAS_EMPTY_EXPRESSION_ARGUMENT, HAS_NOT_EMPTY_EXPRESSION_ARGUMENT }
@NotNull @NotNull
public static ArgumentsKind translateSingleArgument( public static ArgumentsKind translateSingleArgument(
@@ -171,23 +161,29 @@ public class CallArgumentTranslator extends AbstractTranslator {
} }
} }
if (argumentsShouldBeExtractedToTmpVars) { if (argumentsShouldBeExtractedToTmpVars) {
extractArgumentsToTmpVars(list, argContexts, context); extractArguments(list, argContexts, context, resultKind == ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT);
} }
return resultKind; return resultKind;
} }
private static void extractArgumentsToTmpVars( private static void extractArguments(
@NotNull List<JsExpression> argExpressions, @NotNull List<JsExpression> argExpressions,
@NotNull List<TranslationContext> argContexts, @NotNull List<TranslationContext> argContexts,
@NotNull TranslationContext context @NotNull TranslationContext context,
boolean toTmpVars
) { ) {
for(int i=0; i<argExpressions.size(); i++) { for(int i=0; i<argExpressions.size(); i++) {
TranslationContext argContext = argContexts.get(i); TranslationContext argContext = argContexts.get(i);
JsExpression jsArgExpression = argExpressions.get(i); JsExpression jsArgExpression = argExpressions.get(i);
if (argContext.currentBlockIsEmpty() && TranslationUtils.isCacheNeeded(jsArgExpression)) { if (argContext.currentBlockIsEmpty() && TranslationUtils.isCacheNeeded(jsArgExpression)) {
TemporaryVariable temporaryVariable = context.declareTemporary(jsArgExpression); if (toTmpVars) {
context.addStatementToCurrentBlock(temporaryVariable.assignmentExpression().makeStmt()); TemporaryVariable temporaryVariable = context.declareTemporary(jsArgExpression);
argExpressions.set(i, temporaryVariable.reference()); context.addStatementToCurrentBlock(temporaryVariable.assignmentExpression().makeStmt());
argExpressions.set(i, temporaryVariable.reference());
}
else {
context.addStatementToCurrentBlock(jsArgExpression.makeStmt());
}
} else { } else {
context.addStatementsToCurrentBlockFrom(argContext); context.addStatementsToCurrentBlockFrom(argContext);
} }
@@ -222,7 +218,6 @@ public class CallArgumentTranslator extends AbstractTranslator {
} }
private ArgumentsInfo translate() { private ArgumentsInfo translate() {
boolean hasEmptyExpressionArgument = false;
List<ValueParameterDescriptor> valueParameters = resolvedCall.getResultingDescriptor().getValueParameters(); List<ValueParameterDescriptor> valueParameters = resolvedCall.getResultingDescriptor().getValueParameters();
if (valueParameters.isEmpty()) { if (valueParameters.isEmpty()) {
return new ArgumentsInfo(Collections.<JsExpression>emptyList(), false, null); return new ArgumentsInfo(Collections.<JsExpression>emptyList(), false, null);
@@ -238,6 +233,7 @@ public class CallArgumentTranslator extends AbstractTranslator {
List<JsExpression> argsBeforeVararg = null; List<JsExpression> argsBeforeVararg = null;
boolean argumentsShouldBeExtractedToTmpVars = false; boolean argumentsShouldBeExtractedToTmpVars = false;
List<TranslationContext> argContexts = new SmartList<TranslationContext>(); List<TranslationContext> argContexts = new SmartList<TranslationContext>();
ArgumentsKind kind = ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT;
for (ValueParameterDescriptor parameterDescriptor : valueParameters) { for (ValueParameterDescriptor parameterDescriptor : valueParameters) {
ResolvedValueArgument actualArgument = valueArgumentsByIndex.get(parameterDescriptor.getIndex()); ResolvedValueArgument actualArgument = valueArgumentsByIndex.get(parameterDescriptor.getIndex());
@@ -254,19 +250,16 @@ public class CallArgumentTranslator extends AbstractTranslator {
} }
} }
TranslationContext argContext = context().innerBlock(); TranslationContext argContext = context().innerBlock();
ArgumentsKind kind = translateSingleArgument(actualArgument, result, argContext, !isNativeFunctionCall && !hasSpreadOperator); kind = translateSingleArgument(actualArgument, result, argContext, !isNativeFunctionCall && !hasSpreadOperator);
context().moveVarsFrom(argContext); context().moveVarsFrom(argContext);
argContexts.add(argContext); argContexts.add(argContext);
argumentsShouldBeExtractedToTmpVars = argumentsShouldBeExtractedToTmpVars || !argContext.currentBlockIsEmpty(); argumentsShouldBeExtractedToTmpVars = argumentsShouldBeExtractedToTmpVars || !argContext.currentBlockIsEmpty();
if (kind == ArgumentsKind.HAS_EMPTY_EXPRESSION_ARGUMENT) { if (kind == ArgumentsKind.HAS_EMPTY_EXPRESSION_ARGUMENT) break;
hasEmptyExpressionArgument = true;
break;
}
} }
if (argumentsShouldBeExtractedToTmpVars) { if (argumentsShouldBeExtractedToTmpVars) {
extractArgumentsToTmpVars(result, argContexts, context()); extractArguments(result, argContexts, context(), kind == ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT);
} }
if (isNativeFunctionCall && hasSpreadOperator) { if (isNativeFunctionCall && hasSpreadOperator) {
@@ -285,7 +278,7 @@ public class CallArgumentTranslator extends AbstractTranslator {
} }
removeLastUndefinedArguments(result); removeLastUndefinedArguments(result);
return new ArgumentsInfo(result, hasSpreadOperator, cachedReceiver, hasEmptyExpressionArgument); return new ArgumentsInfo(result, hasSpreadOperator, cachedReceiver);
} }
} }