JS backend: don't use the temporary variables in SafeCall and SureCall when is not necessary.

For example:
val a : A? = null
a!!
a?.foo()

translated before:
var a = null;
var tmp$0, tmp$1;
(tmp$0 = a) != null ? tmp$0 : Kotlin.throwNPE();
(tmp$1 = a) != null ? tmp$1.foo() : null;

translated after:
var a = null;
a != null ? a : Kotlin.throwNPE();
a != null ? a.foo() : null;
This commit is contained in:
develar
2013-07-19 15:51:03 +04:00
committed by Zalim Bashorov
parent 94152da97b
commit 78945a9461
5 changed files with 47 additions and 20 deletions
@@ -156,8 +156,8 @@ public final class Namer {
}
@NotNull
public JsExpression throwNPEFunctionCall() {
return new JsInvocation(new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject()));
public JsExpression throwNPEFunctionRef() {
return new JsNameRef(THROW_NPE_FUN_NAME, kotlinObject());
}
@NotNull
@@ -311,6 +311,7 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@NotNull
public JsNode visitBinaryWithTypeRHSExpression(@NotNull JetBinaryExpressionWithTypeRHS expression,
@NotNull TranslationContext context) {
// KT-2670
// we actually do not care for types in js
return Translation.translateExpression(expression.getLeft(), context);
}
@@ -16,12 +16,10 @@
package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsConditional;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import org.jetbrains.k2js.translate.reference.CallType;
@@ -33,8 +31,7 @@ import static org.jetbrains.k2js.translate.general.Translation.translateAsExpres
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getOperationToken;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNotNullCheck;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.sure;
public final class UnaryOperationTranslator {
private UnaryOperationTranslator() {
@@ -58,14 +55,7 @@ public final class UnaryOperationTranslator {
@NotNull
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
JsExpression translatedExpression = translateAsExpression(getBaseExpression(expression), context);
TemporaryConstVariable tempVar = context.getOrDeclareTemporaryConstVariable(translatedExpression);
JsConditional ensureNotNull = new JsConditional(isNotNullCheck(tempVar.value()), tempVar.value(), context.namer().throwNPEFunctionCall());
// associate (cache) ensureNotNull expression to new LazyValue with same name.
context.associateExpressionToLazyValue(ensureNotNull, new TemporaryConstVariable(tempVar.name(), ensureNotNull));
return ensureNotNull;
return sure(translateAsExpression(getBaseExpression(expression), context), context);
}
@NotNull
@@ -24,10 +24,9 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetQualifiedExpression;
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression;
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.isNotNullCheck;
import static org.jetbrains.k2js.translate.utils.TranslationUtils.notNullConditional;
public enum CallType {
SAFE {
@@ -36,9 +35,9 @@ public enum CallType {
JsExpression constructCall(@Nullable JsExpression receiver, @NotNull CallConstructor constructor,
@NotNull TranslationContext context) {
assert receiver != null;
TemporaryConstVariable tempVar = context.getOrDeclareTemporaryConstVariable(receiver);
return new JsConditional(isNotNullCheck(tempVar.value()), constructor.construct(tempVar.value()), JsLiteral.NULL);
JsConditional expression = notNullConditional(receiver, JsLiteral.NULL, context);
expression.setThenExpression(constructor.construct(expression.getThenExpression()));
return expression;
}
},
//TODO: bang qualifier is not implemented in frontend for now
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyGetterDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.k2js.translate.context.TemporaryConstVariable;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.general.Translation;
@@ -75,7 +76,28 @@ public final class TranslationUtils {
JsBinaryOperator operator = isNegated ? JsBinaryOperator.NEQ : JsBinaryOperator.EQ;
return new JsBinaryOperation(operator, expressionToCheck, JsLiteral.NULL);
}
@NotNull
public static JsConditional notNullConditional(
@NotNull JsExpression expression,
@NotNull JsExpression elseExpression,
@NotNull TranslationContext context
) {
JsExpression testExpression;
JsExpression thenExpression;
if (isCacheNeeded(expression)) {
TemporaryConstVariable tempVar = context.getOrDeclareTemporaryConstVariable(expression);
testExpression = isNotNullCheck(tempVar.value());
thenExpression = tempVar.value();
}
else {
testExpression = isNotNullCheck(expression);
thenExpression = expression;
}
return new JsConditional(testExpression, thenExpression, elseExpression);
}
@NotNull
public static List<JsExpression> translateArgumentList(@NotNull TranslationContext context,
@NotNull List<? extends ValueArgument> jetArguments) {
@@ -189,4 +211,19 @@ public final class TranslationUtils {
return Pair.create(null, expression);
}
}
@NotNull
public static JsConditional sure(@NotNull JsExpression expression, @NotNull TranslationContext context) {
JsInvocation throwNPE = new JsInvocation(context.namer().throwNPEFunctionRef());
JsConditional ensureNotNull = notNullConditional(expression, throwNPE, context);
JsExpression thenExpression = ensureNotNull.getThenExpression();
if (thenExpression instanceof JsNameRef) {
// associate (cache) ensureNotNull expression to new TemporaryConstVariable with same name.
context.associateExpressionToLazyValue(ensureNotNull,
new TemporaryConstVariable(((JsNameRef) thenExpression).getName(), ensureNotNull));
}
return ensureNotNull;
}
}