JS: refactor generation of temporary variables

This commit is contained in:
Alexey Andreev
2016-05-23 14:00:47 +03:00
parent 9edb9fabe5
commit 9fcad45edb
9 changed files with 45 additions and 86 deletions
@@ -25,8 +25,6 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.reference.CallArgumentTranslator
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.asSyntheticStatement
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getReceiverParameterForReceiver
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
@@ -78,17 +76,14 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescri
if (!argsBlock.isEmpty && explicitReceivers.extensionOrDispatchReceiver != null) {
val receiverOrThisRef =
if (TranslationUtils.isCacheNeeded(explicitReceivers.extensionOrDispatchReceiver)) {
val receiverOrThisRefVar = this.declareTemporary(explicitReceivers.extensionOrDispatchReceiver)
this.addStatementToCurrentBlock(receiverOrThisRefVar.assignmentExpression().makeStmt())
receiverOrThisRefVar.reference()
defineTemporary(explicitReceivers.extensionOrDispatchReceiver)
}
else {
explicitReceivers.extensionOrDispatchReceiver
}
var receiverRef = explicitReceivers.extensionReceiver
if (receiverRef != null) {
receiverRef = this.declareTemporary(null).reference()
addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(receiverRef, explicitReceivers.extensionReceiver!!)))
receiverRef = defineTemporary(explicitReceivers.extensionReceiver!!)
}
ExplicitReceivers(receiverOrThisRef, receiverRef)
}
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.js.translate.context;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsName;
import com.google.dart.compiler.backend.js.ast.JsNameRef;
import com.google.dart.compiler.backend.js.ast.*;
import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,4 +58,9 @@ public class TemporaryVariable {
assert assignmentExpression != null;
return assignmentExpression;
}
@NotNull
public JsStatement assignmentStatement() {
return JsAstUtils.asSyntheticStatement(assignmentExpression());
}
}
@@ -239,6 +239,13 @@ public class TranslationContext {
return dynamicContext.declareTemporary(initExpression);
}
@NotNull
public JsExpression defineTemporary(@NotNull JsExpression initExpression) {
TemporaryVariable var = dynamicContext.declareTemporary(initExpression);
addStatementToCurrentBlock(var.assignmentStatement());
return var.reference();
}
@NotNull
public TemporaryConstVariable getOrDeclareTemporaryConstVariable(@NotNull JsExpression expression) {
TemporaryConstVariable tempVar = expressionToTempConstVariableCache.get(expression);
@@ -21,7 +21,6 @@ package org.jetbrains.kotlin.js.translate.expression
import com.google.dart.compiler.backend.js.ast.*
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable
import org.jetbrains.kotlin.js.translate.context.TranslationContext
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.CompositeFIF
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getHasNextCallable
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getIteratorFunction
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getNextFunction
import org.jetbrains.kotlin.js.translate.utils.BindingUtils.getTypeForExpression
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.*
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopParameter
import org.jetbrains.kotlin.js.translate.utils.PsiUtils.getLoopRange
@@ -61,10 +59,9 @@ fun createWhile(doWhile: Boolean, expression: KtWhileExpressionBase, context: Tr
if (doWhile) {
// translate to: tmpSecondRun = false; do { if(tmpSecondRun) { <expr> if(!tmpExprVar) break; } else tmpSecondRun=true; <body> } while(true)
val secondRun = context.declareTemporary(JsLiteral.FALSE)
context.addStatementToCurrentBlock(JsAstUtils.asSyntheticStatement(secondRun.assignmentExpression()))
val secondRun = context.defineTemporary(JsLiteral.FALSE)
conditionBlock.statements.add(breakIfConditionIsFalseStatement)
val ifStatement = JsIf(secondRun.reference(), conditionBlock, assignment(secondRun.reference(), JsLiteral.TRUE).makeStmt())
val ifStatement = JsIf(secondRun, conditionBlock, assignment(secondRun, JsLiteral.TRUE).makeStmt())
bodyBlock.statements.add(0, ifStatement)
}
else {
@@ -146,22 +143,19 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
val rightExpression = TranslationUtils.translateRightExpression(context, loopRange, endBlock)
val rangeStart =
if (TranslationUtils.isCacheNeeded(leftExpression)) {
val startVar = context.declareTemporary(leftExpression)
context.addStatementToCurrentBlock(asSyntheticStatement(startVar.assignmentExpression()))
startVar.reference()
context.defineTemporary(leftExpression)
}
else {
leftExpression
}
context.addStatementsToCurrentBlockFrom(startBlock)
context.addStatementsToCurrentBlockFrom(endBlock)
val rangeEnd = context.declareTemporary(rightExpression)
val rangeEnd = context.defineTemporary(rightExpression)
val body = translateBody(null)
val conditionExpression = lessThanEq(parameterName.makeRef(), rangeEnd.reference())
val conditionExpression = lessThanEq(parameterName.makeRef(), rangeEnd)
val incrementExpression = JsPostfixOperation(JsUnaryOperator.INC, parameterName.makeRef())
context.addStatementToCurrentBlock(asSyntheticStatement(rangeEnd.assignmentExpression()))
return if (parameterIsTemporary) {
JsFor(assignment(parameterName.makeRef(), rangeStart), conditionExpression, incrementExpression, body)
}
@@ -171,46 +165,40 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
}
fun translateForOverRange(): JsStatement {
val rangeExpression = context.declareTemporary(Translation.translateAsExpression(loopRange, context))
val rangeExpression = context.defineTemporary(Translation.translateAsExpression(loopRange, context))
fun getProperty(funName: String): JsExpression = JsNameRef(funName, rangeExpression.reference())
fun getProperty(funName: String): JsExpression = JsNameRef(funName, rangeExpression)
val start = context.declareTemporary(getProperty("first"))
val end = context.declareTemporary(getProperty("last"))
val increment = context.declareTemporary(getProperty("step"))
val start = context.defineTemporary(getProperty("first"))
val end = context.defineTemporary(getProperty("last"))
val increment = context.defineTemporary(getProperty("step"))
val body = translateBody(null)
val conditionExpression = lessThanEq(parameterName.makeRef(), end.reference())
val incrementExpression = addAssign(parameterName.makeRef(), increment.reference())
val conditionExpression = lessThanEq(parameterName.makeRef(), end)
val incrementExpression = addAssign(parameterName.makeRef(), increment)
context.addStatementToCurrentBlock(asSyntheticStatement(rangeExpression.assignmentExpression()))
context.addStatementToCurrentBlock(asSyntheticStatement(start.assignmentExpression()))
context.addStatementToCurrentBlock(asSyntheticStatement(end.assignmentExpression()))
context.addStatementToCurrentBlock(asSyntheticStatement(increment.assignmentExpression()))
return if (parameterIsTemporary) {
JsFor(assignment(parameterName.makeRef(), start.reference()), conditionExpression, incrementExpression, body)
JsFor(assignment(parameterName.makeRef(), start), conditionExpression, incrementExpression, body)
}
else {
JsFor(newVar(parameterName, start.reference()), conditionExpression, incrementExpression, body)
JsFor(newVar(parameterName, start), conditionExpression, incrementExpression, body)
}
}
fun translateForOverArray(): JsStatement {
val rangeExpression = context.declareTemporary(Translation.translateAsExpression(loopRange, context))
val length = CompositeFIF.LENGTH_PROPERTY_INTRINSIC.apply(rangeExpression.reference(), listOf<JsExpression>(), context)
val end = context.declareTemporary(length)
val rangeExpression = context.defineTemporary(Translation.translateAsExpression(loopRange, context))
val length = CompositeFIF.LENGTH_PROPERTY_INTRINSIC.apply(rangeExpression, listOf<JsExpression>(), context)
val end = context.defineTemporary(length)
val index = context.declareTemporary(context.program().getNumberLiteral(0))
val arrayAccess = JsArrayAccess(rangeExpression.reference(), index.reference())
val arrayAccess = JsArrayAccess(rangeExpression, index.reference())
val body = translateBody(arrayAccess)
val initExpression = assignment(index.name().makeRef(), context.program().getNumberLiteral(0))
val conditionExpression = inequality(index.reference(), end.reference())
val initExpression = assignment(index.reference(), context.program().getNumberLiteral(0))
val conditionExpression = inequality(index.reference(), end)
val incrementExpression = JsPrefixOperation(JsUnaryOperator.INC, index.reference())
context.addStatementToCurrentBlock(asSyntheticStatement(rangeExpression.assignmentExpression()))
context.addStatementToCurrentBlock(asSyntheticStatement(end.assignmentExpression()))
return JsFor(initExpression, conditionExpression, incrementExpression, body)
}
@@ -225,18 +213,14 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
return translateMethodInvocation(range, resolvedCall)
}
val iteratorVar: TemporaryVariable = context.declareTemporary(iteratorMethodInvocation())
fun nextMethodInvocation(): JsExpression =
translateMethodInvocation(iteratorVar.reference(), getNextFunction(context.bindingContext(), loopRange))
val iteratorVar = context.defineTemporary(iteratorMethodInvocation())
fun hasNextMethodInvocation(): JsExpression {
val resolvedCall = getHasNextCallable(context.bindingContext(), loopRange)
return translateMethodInvocation(iteratorVar.reference(), resolvedCall)
return translateMethodInvocation(iteratorVar, resolvedCall)
}
context.addStatementToCurrentBlock(iteratorVar.assignmentExpression().makeStmt())
val nextInvoke = nextMethodInvocation()
val nextInvoke = translateMethodInvocation(iteratorVar, getNextFunction(context.bindingContext(), loopRange))
val body = translateBody(nextInvoke)
return JsWhile(hasNextMethodInvocation(), body ?: nextInvoke.makeStmt())
}
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.general.Translation;
@@ -34,7 +33,6 @@ import org.jetbrains.kotlin.types.KotlinType;
import java.util.HashMap;
import java.util.Map;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.asSyntheticStatement;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.negated;
public final class WhenTranslator extends AbstractTranslator {
@@ -56,11 +54,7 @@ public final class WhenTranslator extends AbstractTranslator {
KtExpression subject = expression.getSubjectExpression();
if (subject != null) {
JsExpression subjectExpression = Translation.translateAsExpression(subject, context);
TemporaryVariable subjectVar = context.declareTemporary(null);
context.addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(subjectVar.reference(), subjectExpression)));
subjectExpression = subjectVar.reference();
expressionToMatch = subjectExpression;
expressionToMatch = context.defineTemporary(Translation.translateAsExpression(subject, context));
}
else {
expressionToMatch = null;
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator;
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.AbstractTranslator;
import org.jetbrains.kotlin.js.translate.general.Translation;
@@ -46,7 +45,6 @@ import java.util.Collections;
import static org.jetbrains.kotlin.js.translate.operation.AssignmentTranslator.isAssignmentOperator;
import static org.jetbrains.kotlin.js.translate.operation.CompareToTranslator.isCompareToCall;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getCallableDescriptorForOperationExpression;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.asSyntheticStatement;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.not;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.*;
@@ -137,9 +135,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
JsIf ifStatement;
if (BindingContextUtilsKt.isUsedAsExpression(expression, context().bindingContext())) {
if (TranslationUtils.isCacheNeeded(leftExpression)) {
TemporaryVariable resultVar = context().declareTemporary(leftExpression);
result = resultVar.reference();
context().addStatementToCurrentBlock(asSyntheticStatement(resultVar.assignmentExpression()));
result = context().defineTemporary(leftExpression);
}
else {
result = leftExpression;
@@ -174,9 +170,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
}
if (TranslationUtils.isCacheNeeded(leftExpression)) {
TemporaryVariable temporaryVariable = context().declareTemporary(null);
context().addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(temporaryVariable.reference(), leftExpression)));
leftExpression = temporaryVariable.reference();
leftExpression = context().defineTemporary(leftExpression);
}
context().addStatementsToCurrentBlockFrom(rightBlock);
@@ -215,9 +209,7 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
if (rightExpression instanceof JsNameRef) {
result = rightExpression; // Reuse tmp variable
} else {
TemporaryVariable resultVar = context().declareTemporary(rightExpression);
result = resultVar.reference();
rightBlock.getStatements().add(resultVar.assignmentExpression().makeStmt());
result = context().defineTemporary(rightExpression);
}
JsStatement assignmentStatement = JsAstUtils.assignment(result, literalResult).makeStmt();
ifStatement = JsAstUtils.newJsIf(leftExpression, rightBlock, assignmentStatement);
@@ -19,17 +19,13 @@ package org.jetbrains.kotlin.js.translate.reference;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.general.Translation;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.asSyntheticStatement;
public final class AccessTranslationUtils {
private AccessTranslationUtils() {
}
@@ -67,10 +63,7 @@ public final class AccessTranslationUtils {
for(KtExpression indexExpression : expression.getIndexExpressions()) {
JsExpression jsIndexExpression = Translation.translateAsExpression(indexExpression, context);
if (TranslationUtils.isCacheNeeded(jsIndexExpression)) {
TemporaryVariable temporaryVariable = context.declareTemporary(null);
context.addStatementToCurrentBlock(
asSyntheticStatement(JsAstUtils.assignment(temporaryVariable.reference(), jsIndexExpression)));
jsIndexExpression = temporaryVariable.reference();
jsIndexExpression = context.defineTemporary(jsIndexExpression);
}
indexesMap.put(indexExpression, jsIndexExpression);
}
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.js.translate.general.AbstractTranslator
import org.jetbrains.kotlin.js.translate.general.Translation
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils.asSyntheticStatement
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils
import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.model.*
@@ -296,9 +295,7 @@ class CallArgumentTranslator private constructor(
val argContext = argContexts[i]
val jsArgExpression = argExpressions[i]
if (argContext.currentBlockIsEmpty() && TranslationUtils.isCacheNeeded(jsArgExpression)) {
val temporaryVariable = context.declareTemporary(jsArgExpression)
context.addStatementToCurrentBlock(asSyntheticStatement(temporaryVariable.assignmentExpression()))
argExpressions[i] = temporaryVariable.reference()
argExpressions[i] = context.defineTemporary(jsArgExpression)
}
else {
context.addStatementsToCurrentBlockFrom(argContext)
@@ -22,17 +22,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
import org.jetbrains.kotlin.js.translate.utils.ErrorReportingUtils;
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import static org.jetbrains.kotlin.js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getDescriptorForReferenceExpression;
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.asSyntheticStatement;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getNotNullSimpleNameSelector;
import static org.jetbrains.kotlin.js.translate.utils.PsiUtils.getSelector;
@@ -46,9 +43,7 @@ public final class QualifiedExpressionTranslator {
@NotNull TranslationContext context, boolean forceOrderOfEvaluation) {
JsExpression receiver = translateReceiver(expression, context);
if (forceOrderOfEvaluation && receiver != null) {
TemporaryVariable temporaryVariable = context.declareTemporary(null);
context.addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(temporaryVariable.reference(), receiver)));
receiver = temporaryVariable.reference();
receiver = context.defineTemporary(receiver);
}
return VariableAccessTranslator.newInstance(context, getNotNullSimpleNameSelector(expression), receiver);
}