JS: get rid of JsEmptyExpression, use JsLiteral.NULL instead, rely on optimizer to remove redundant code
This commit is contained in:
@@ -18,7 +18,6 @@ import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsIntLiter
|
||||
* A JavaScript program.
|
||||
*/
|
||||
public final class JsProgram extends SourceInfoAwareJsNode {
|
||||
@NotNull final JsExpression emptyExpression;
|
||||
|
||||
private JsProgramFragment[] fragments;
|
||||
|
||||
@@ -33,13 +32,6 @@ public final class JsProgram extends SourceInfoAwareJsNode {
|
||||
rootScope = new JsRootScope(this);
|
||||
topScope = new JsObjectScope(rootScope, "Global", unitId);
|
||||
setFragmentCount(1);
|
||||
|
||||
emptyExpression = new JsEmptyExpression();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getEmptyExpression() {
|
||||
return emptyExpression;
|
||||
}
|
||||
|
||||
public JsBlock getFragmentBlock(int fragment) {
|
||||
|
||||
@@ -26,6 +26,7 @@ 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
|
||||
@@ -87,7 +88,7 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescri
|
||||
var receiverRef = explicitReceivers.extensionReceiver
|
||||
if (receiverRef != null) {
|
||||
receiverRef = this.declareTemporary(null).reference()
|
||||
this.addStatementToCurrentBlock(JsAstUtils.assignment(receiverRef, explicitReceivers.extensionReceiver!!).makeStmt())
|
||||
addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(receiverRef, explicitReceivers.extensionReceiver!!)))
|
||||
}
|
||||
ExplicitReceivers(receiverOrThisRef, receiverRef)
|
||||
}
|
||||
|
||||
+9
-14
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.translate.callTranslator
|
||||
|
||||
import com.google.dart.compiler.backend.js.ast.JsEmptyExpression
|
||||
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.metadata.HasMetadata
|
||||
@@ -73,19 +72,15 @@ fun VariableAccessInfo.getAccessFunctionName(): String {
|
||||
}
|
||||
|
||||
fun VariableAccessInfo.constructAccessExpression(ref: JsExpression): JsExpression {
|
||||
if (isGetAccess()) {
|
||||
return ref
|
||||
} else {
|
||||
return if (value !is JsEmptyExpression) {
|
||||
// This is useful when passing AST to TemporaryAssignmentElimination. It can bring
|
||||
// property assignment like `obj.propertyName = $tmp` to places where `$tmp` gets its value,
|
||||
// but only when it's sure that no side effects possible.
|
||||
(ref as? HasMetadata)?.let { it.sideEffects = SideEffectKind.PURE }
|
||||
JsAstUtils.assignment(ref, value!!)
|
||||
}
|
||||
else {
|
||||
context.emptyExpression
|
||||
}
|
||||
return if (isGetAccess()) {
|
||||
ref
|
||||
}
|
||||
else {
|
||||
// This is useful when passing AST to TemporaryAssignmentElimination. It can bring
|
||||
// property assignment like `obj.propertyName = $tmp` to places where `$tmp` gets its value,
|
||||
// but only when it's sure that no side effects possible.
|
||||
(ref as? HasMetadata)?.let { it.sideEffects = SideEffectKind.PURE }
|
||||
JsAstUtils.assignment(ref, value!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-4
@@ -306,10 +306,6 @@ object DynamicOperatorCallCase : FunctionCallCase() {
|
||||
}
|
||||
|
||||
fun FunctionCallInfo.translateFunctionCall(): JsExpression {
|
||||
// When call has `continue` or `break` as one of its argument, they'll be temporarily represented ad JsEmptyExpression.
|
||||
// Such call should not be translated. All side effects are already extracted by this point.
|
||||
if (argumentsInfo.valueArguments.any { JsAstUtils.isEmptyExpression(it) }) return context.emptyExpression
|
||||
|
||||
val intrinsic = DelegateFunctionIntrinsic.intrinsic(this)
|
||||
|
||||
return when {
|
||||
|
||||
@@ -320,11 +320,6 @@ public class TranslationContext {
|
||||
return dynamicContext.jsBlock();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JsExpression getEmptyExpression() {
|
||||
return program().getEmptyExpression();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JsExpression getAliasForDescriptor(@NotNull DeclarationDescriptor descriptor) {
|
||||
JsNameRef nameRef = captureIfNeedAndGetCapturedName(descriptor);
|
||||
|
||||
+6
-5
@@ -101,11 +101,12 @@ class CatchTranslator(
|
||||
|
||||
private fun translateCatchBody(context: TranslationContext, catchClause: KtCatchClause): JsBlock {
|
||||
val catchBody = catchClause.catchBody
|
||||
val jsCatchBody =
|
||||
if (catchBody != null)
|
||||
translateAsStatementAndMergeInBlockIfNeeded(catchBody, context)
|
||||
else
|
||||
context.emptyExpression.makeStmt()
|
||||
val jsCatchBody = if (catchBody != null) {
|
||||
translateAsStatementAndMergeInBlockIfNeeded(catchBody, context)
|
||||
}
|
||||
else {
|
||||
JsAstUtils.asSyntheticStatement(JsLiteral.NULL)
|
||||
}
|
||||
|
||||
return convertToBlock(jsCatchBody)
|
||||
}
|
||||
|
||||
+1
-10
@@ -73,7 +73,7 @@ import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFun
|
||||
public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
@Override
|
||||
protected JsNode emptyResult(@NotNull TranslationContext context) {
|
||||
return context.getEmptyExpression();
|
||||
return JsLiteral.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,9 +156,6 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
}
|
||||
else {
|
||||
JsExpression jsReturnExpression = translateAsExpression(returned, context);
|
||||
if (JsAstUtils.isEmptyExpression(jsReturnExpression)) {
|
||||
return context.getEmptyExpression();
|
||||
}
|
||||
|
||||
jsReturn = new JsReturn(jsReturnExpression);
|
||||
}
|
||||
@@ -221,9 +218,6 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
VariableDescriptor descriptor = BindingContextUtils.getNotNull(context.bindingContext(), BindingContext.VARIABLE, expression);
|
||||
|
||||
JsExpression initializer = translateInitializerForProperty(expression, context);
|
||||
if (initializer != null && JsAstUtils.isEmptyExpression(initializer)) {
|
||||
return context.getEmptyExpression();
|
||||
}
|
||||
|
||||
KtExpression delegateExpression = expression.getDelegateExpression();
|
||||
if (delegateExpression != null) {
|
||||
@@ -267,9 +261,6 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
|
||||
public JsNode visitIfExpression(@NotNull KtIfExpression expression, @NotNull TranslationContext context) {
|
||||
assert expression.getCondition() != null : "condition should not ne null: " + expression.getText();
|
||||
JsExpression testExpression = Translation.translateAsExpression(expression.getCondition(), context);
|
||||
if (JsAstUtils.isEmptyExpression(testExpression)) {
|
||||
return testExpression;
|
||||
}
|
||||
|
||||
boolean isKotlinExpression = BindingContextUtilsKt.isUsedAsExpression(expression, context.bindingContext());
|
||||
|
||||
|
||||
+6
-18
@@ -29,6 +29,7 @@ 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
|
||||
@@ -46,7 +47,6 @@ fun createWhile(doWhile: Boolean, expression: KtWhileExpressionBase, context: Tr
|
||||
throw IllegalArgumentException("condition expression should not be null: ${expression.text}")
|
||||
val conditionBlock = JsBlock()
|
||||
var jsCondition = Translation.translateAsExpression(conditionExpression, context, conditionBlock)
|
||||
val isEmptyLoopCondition = isEmptyExpression(jsCondition)
|
||||
val body = expression.body
|
||||
var bodyStatement =
|
||||
if (body != null)
|
||||
@@ -62,30 +62,18 @@ 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(secondRun.assignmentExpression().makeStmt())
|
||||
if (!isEmptyLoopCondition) {
|
||||
conditionBlock.statements.add(breakIfConditionIsFalseStatement)
|
||||
}
|
||||
context.addStatementToCurrentBlock(JsAstUtils.asSyntheticStatement(secondRun.assignmentExpression()))
|
||||
conditionBlock.statements.add(breakIfConditionIsFalseStatement)
|
||||
val ifStatement = JsIf(secondRun.reference(), conditionBlock, assignment(secondRun.reference(), JsLiteral.TRUE).makeStmt())
|
||||
bodyBlock.statements.add(0, ifStatement)
|
||||
}
|
||||
else {
|
||||
// translate to: while (true) { <expr> if(!tmpExprVar) break; <body> }
|
||||
if (isEmptyLoopCondition) {
|
||||
bodyBlock.statements.clear()
|
||||
context.addStatementsToCurrentBlockFrom(conditionBlock)
|
||||
}
|
||||
else {
|
||||
conditionBlock.statements.add(breakIfConditionIsFalseStatement)
|
||||
bodyBlock.statements.addAll(0, conditionBlock.statements)
|
||||
}
|
||||
conditionBlock.statements.add(breakIfConditionIsFalseStatement)
|
||||
bodyBlock.statements.addAll(0, conditionBlock.statements)
|
||||
}
|
||||
|
||||
bodyStatement = bodyBlock
|
||||
}
|
||||
else if (isEmptyLoopCondition) {
|
||||
jsCondition = JsLiteral.FALSE
|
||||
}
|
||||
|
||||
val result = if (doWhile) JsDoWhile() else JsWhile()
|
||||
result.condition = jsCondition
|
||||
@@ -159,7 +147,7 @@ fun translateForExpression(expression: KtForExpression, context: TranslationCont
|
||||
val rangeStart =
|
||||
if (TranslationUtils.isCacheNeeded(leftExpression)) {
|
||||
val startVar = context.declareTemporary(leftExpression)
|
||||
context.addStatementToCurrentBlock(startVar.assignmentExpression().makeStmt())
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(startVar.assignmentExpression()))
|
||||
startVar.reference()
|
||||
}
|
||||
else {
|
||||
|
||||
-3
@@ -83,7 +83,6 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
assert isCastExpression(expression): "Expected cast expression, got " + expression;
|
||||
KtExpression left = expression.getLeft();
|
||||
JsExpression expressionToCast = Translation.translateAsExpression(left, context());
|
||||
if (JsAstUtils.isEmptyExpression(expressionToCast)) return expressionToCast;
|
||||
|
||||
TemporaryVariable temporary = context().declareTemporary(expressionToCast);
|
||||
|
||||
@@ -124,8 +123,6 @@ public final class PatternTranslator extends AbstractTranslator {
|
||||
@Nullable
|
||||
public JsExpression translateIsCheck(@NotNull JsExpression subject, @Nullable KotlinType sourceType,
|
||||
@NotNull KtTypeReference targetTypeReference) {
|
||||
if (JsAstUtils.isEmptyExpression(subject)) return subject;
|
||||
|
||||
KotlinType targetType = getTypeByReference(bindingContext(), targetTypeReference);
|
||||
if (sourceType != null && !DynamicTypesKt.isDynamic(sourceType) && TypeUtilsKt.isSubtypeOf(sourceType, targetType)) return null;
|
||||
|
||||
|
||||
+5
-15
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.js.translate.expression;
|
||||
|
||||
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;
|
||||
import org.jetbrains.kotlin.js.translate.context.TemporaryVariable;
|
||||
@@ -27,7 +26,6 @@ import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||
import org.jetbrains.kotlin.js.translate.operation.InOperationTranslator;
|
||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.TranslationUtils;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
@@ -36,6 +34,7 @@ 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 {
|
||||
@@ -58,14 +57,9 @@ public final class WhenTranslator extends AbstractTranslator {
|
||||
KtExpression subject = expression.getSubjectExpression();
|
||||
if (subject != null) {
|
||||
JsExpression subjectExpression = Translation.translateAsExpression(subject, context);
|
||||
if (!JsAstUtils.isEmptyExpression(subjectExpression)) {
|
||||
TemporaryVariable subjectVar = context.declareTemporary(null);
|
||||
JsExpressionStatement subjectAssignment = new JsExpressionStatement(
|
||||
JsAstUtils.assignment(subjectVar.reference(), subjectExpression));
|
||||
MetadataProperties.setSynthetic(subjectAssignment, true);
|
||||
context.addStatementToCurrentBlock(subjectAssignment);
|
||||
subjectExpression = subjectVar.reference();
|
||||
}
|
||||
TemporaryVariable subjectVar = context.declareTemporary(null);
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(subjectVar.reference(), subjectExpression)));
|
||||
subjectExpression = subjectVar.reference();
|
||||
expressionToMatch = subjectExpression;
|
||||
}
|
||||
else {
|
||||
@@ -74,10 +68,6 @@ public final class WhenTranslator extends AbstractTranslator {
|
||||
}
|
||||
|
||||
private JsNode translate() {
|
||||
if (expressionToMatch != null && JsAstUtils.isEmptyExpression(expressionToMatch)) {
|
||||
return JsEmpty.INSTANCE;
|
||||
}
|
||||
|
||||
JsIf currentIf = null;
|
||||
JsIf resultIf = null;
|
||||
for (KtWhenEntry entry : whenExpression.getEntries()) {
|
||||
@@ -106,7 +96,7 @@ public final class WhenTranslator extends AbstractTranslator {
|
||||
currentIf = nextIf;
|
||||
}
|
||||
}
|
||||
return resultIf != null ? resultIf : context().getEmptyExpression();
|
||||
return resultIf != null ? resultIf : JsLiteral.NULL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -143,7 +143,7 @@ public final class Translation {
|
||||
}
|
||||
|
||||
block.getStatements().add(convertToStatement(jsNode));
|
||||
return context.getEmptyExpression();
|
||||
return JsLiteral.NULL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+14
-38
@@ -46,6 +46,7 @@ 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.*;
|
||||
|
||||
@@ -124,9 +125,6 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
@NotNull
|
||||
private JsExpression translateElvis() {
|
||||
JsExpression leftExpression = Translation.translateAsExpression(leftKtExpression, context());
|
||||
if (JsAstUtils.isEmptyExpression(leftExpression)) {
|
||||
return leftExpression;
|
||||
}
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
JsExpression rightExpression = Translation.translateAsExpression(rightKtExpression, context(), rightBlock);
|
||||
@@ -141,19 +139,17 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
if (TranslationUtils.isCacheNeeded(leftExpression)) {
|
||||
TemporaryVariable resultVar = context().declareTemporary(leftExpression);
|
||||
result = resultVar.reference();
|
||||
context().addStatementToCurrentBlock(resultVar.assignmentExpression().makeStmt());
|
||||
context().addStatementToCurrentBlock(asSyntheticStatement(resultVar.assignmentExpression()));
|
||||
}
|
||||
else {
|
||||
result = leftExpression;
|
||||
}
|
||||
JsExpression testExpression = TranslationUtils.isNullCheck(result);
|
||||
if (!JsAstUtils.isEmptyExpression(rightExpression)) {
|
||||
rightBlock.getStatements().add(JsAstUtils.assignment(result, rightExpression).makeStmt());
|
||||
}
|
||||
rightBlock.getStatements().add(JsAstUtils.assignment(result, rightExpression).makeStmt());
|
||||
ifStatement = JsAstUtils.newJsIf(testExpression, rightBlock);
|
||||
}
|
||||
else {
|
||||
result = context().getEmptyExpression();
|
||||
result = JsLiteral.NULL;
|
||||
JsExpression testExpression = TranslationUtils.isNullCheck(leftExpression);
|
||||
ifStatement = JsAstUtils.newJsIf(testExpression, rightBlock);
|
||||
}
|
||||
@@ -169,9 +165,6 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
@NotNull
|
||||
private JsExpression applyIntrinsic(@NotNull BinaryOperationIntrinsic intrinsic) {
|
||||
JsExpression leftExpression = Translation.translateAsExpression(leftKtExpression, context());
|
||||
if (JsAstUtils.isEmptyExpression(leftExpression)) {
|
||||
return leftExpression;
|
||||
}
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
JsExpression rightExpression = Translation.translateAsExpression(rightKtExpression, context(), rightBlock);
|
||||
@@ -180,17 +173,9 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
return intrinsic.apply(expression, leftExpression, rightExpression, context());
|
||||
}
|
||||
|
||||
if (JsAstUtils.isEmptyExpression(rightExpression)) {
|
||||
if (TranslationUtils.isCacheNeeded(leftExpression)) {
|
||||
context().addStatementToCurrentBlock(leftExpression.makeStmt());
|
||||
}
|
||||
context().addStatementsToCurrentBlockFrom(rightBlock);
|
||||
return context().getEmptyExpression();
|
||||
}
|
||||
|
||||
if (TranslationUtils.isCacheNeeded(leftExpression)) {
|
||||
TemporaryVariable temporaryVariable = context().declareTemporary(null);
|
||||
context().addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), leftExpression).makeStmt());
|
||||
context().addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(temporaryVariable.reference(), leftExpression)));
|
||||
leftExpression = temporaryVariable.reference();
|
||||
}
|
||||
context().addStatementsToCurrentBlockFrom(rightBlock);
|
||||
@@ -207,9 +192,6 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
assert OperatorConventions.NOT_OVERLOADABLE.contains(operationToken);
|
||||
JsBinaryOperator operator = OperatorTable.getBinaryOperator(operationToken);
|
||||
JsExpression leftExpression = Translation.translateAsExpression(leftKtExpression, context());
|
||||
if (JsAstUtils.isEmptyExpression(leftExpression)) {
|
||||
return leftExpression;
|
||||
}
|
||||
|
||||
JsBlock rightBlock = new JsBlock();
|
||||
JsExpression rightExpression = Translation.translateAsExpression(rightKtExpression, context(), rightBlock);
|
||||
@@ -230,25 +212,19 @@ public final class BinaryOperationTranslator extends AbstractTranslator {
|
||||
JsIf ifStatement;
|
||||
JsExpression result;
|
||||
if (BindingContextUtilsKt.isUsedAsExpression(expression, context().bindingContext())) {
|
||||
if (!JsAstUtils.isEmptyExpression(rightExpression)) {
|
||||
if (rightExpression instanceof JsNameRef) {
|
||||
result = rightExpression; // Reuse tmp variable
|
||||
} else {
|
||||
TemporaryVariable resultVar = context().declareTemporary(rightExpression);
|
||||
result = resultVar.reference();
|
||||
rightBlock.getStatements().add(resultVar.assignmentExpression().makeStmt());
|
||||
}
|
||||
JsStatement assignmentStatement = JsAstUtils.assignment(result, literalResult).makeStmt();
|
||||
ifStatement = JsAstUtils.newJsIf(leftExpression, rightBlock, assignmentStatement);
|
||||
}
|
||||
else {
|
||||
ifStatement = JsAstUtils.newJsIf(leftExpression, rightBlock);
|
||||
result = literalResult;
|
||||
if (rightExpression instanceof JsNameRef) {
|
||||
result = rightExpression; // Reuse tmp variable
|
||||
} else {
|
||||
TemporaryVariable resultVar = context().declareTemporary(rightExpression);
|
||||
result = resultVar.reference();
|
||||
rightBlock.getStatements().add(resultVar.assignmentExpression().makeStmt());
|
||||
}
|
||||
JsStatement assignmentStatement = JsAstUtils.assignment(result, literalResult).makeStmt();
|
||||
ifStatement = JsAstUtils.newJsIf(leftExpression, rightBlock, assignmentStatement);
|
||||
}
|
||||
else {
|
||||
ifStatement = JsAstUtils.newJsIf(leftExpression, rightBlock);
|
||||
result = context().getEmptyExpression();
|
||||
result = JsLiteral.NULL;
|
||||
}
|
||||
context().addStatementToCurrentBlock(ifStatement);
|
||||
return result;
|
||||
|
||||
+4
-1
@@ -28,6 +28,8 @@ 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() {
|
||||
}
|
||||
@@ -66,7 +68,8 @@ public final class AccessTranslationUtils {
|
||||
JsExpression jsIndexExpression = Translation.translateAsExpression(indexExpression, context);
|
||||
if (TranslationUtils.isCacheNeeded(jsIndexExpression)) {
|
||||
TemporaryVariable temporaryVariable = context.declareTemporary(null);
|
||||
context.addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), jsIndexExpression).makeStmt());
|
||||
context.addStatementToCurrentBlock(
|
||||
asSyntheticStatement(JsAstUtils.assignment(temporaryVariable.reference(), jsIndexExpression)));
|
||||
jsIndexExpression = temporaryVariable.reference();
|
||||
}
|
||||
indexesMap.put(indexExpression, jsIndexExpression);
|
||||
|
||||
+16
-41
@@ -29,6 +29,7 @@ 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.*
|
||||
@@ -51,11 +52,6 @@ class CallArgumentTranslator private constructor(
|
||||
get() = reifiedArguments + valueArguments
|
||||
}
|
||||
|
||||
private enum class ArgumentsKind {
|
||||
HAS_EMPTY_EXPRESSION_ARGUMENT,
|
||||
HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||
}
|
||||
|
||||
private val isNativeFunctionCall = AnnotationsUtils.isNativeObject(resolvedCall.candidateDescriptor)
|
||||
|
||||
private fun removeLastUndefinedArguments(result: MutableList<JsExpression>) {
|
||||
@@ -85,7 +81,6 @@ class CallArgumentTranslator private constructor(
|
||||
var argsBeforeVararg: List<JsExpression>? = null
|
||||
var argumentsShouldBeExtractedToTmpVars = false
|
||||
val argContexts = SmartList<TranslationContext>()
|
||||
var kind = ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||
var concatArguments: MutableList<JsExpression>? = null
|
||||
|
||||
for (parameterDescriptor in valueParameters) {
|
||||
@@ -107,15 +102,15 @@ class CallArgumentTranslator private constructor(
|
||||
argsBeforeVararg = result
|
||||
result = SmartList<JsExpression>()
|
||||
val list = SmartList<JsExpression>()
|
||||
kind = translateValueArguments(arguments, list, argContext)
|
||||
translateValueArguments(arguments, list, argContext)
|
||||
concatArguments = prepareConcatArguments(arguments, list)
|
||||
}
|
||||
else {
|
||||
kind = translateVarargArgument(arguments, result, argContext, size > 1)
|
||||
translateVarargArgument(arguments, result, argContext, size > 1)
|
||||
}
|
||||
}
|
||||
else {
|
||||
kind = if (isNativeFunctionCall) {
|
||||
if (isNativeFunctionCall) {
|
||||
translateValueArguments(arguments, result, argContext)
|
||||
}
|
||||
else {
|
||||
@@ -124,18 +119,16 @@ class CallArgumentTranslator private constructor(
|
||||
}
|
||||
}
|
||||
else {
|
||||
kind = translateSingleArgument(actualArgument, result, argContext)
|
||||
translateSingleArgument(actualArgument, result, argContext)
|
||||
}
|
||||
|
||||
context().moveVarsFrom(argContext)
|
||||
argContexts.add(argContext)
|
||||
argumentsShouldBeExtractedToTmpVars = argumentsShouldBeExtractedToTmpVars || !argContext.currentBlockIsEmpty()
|
||||
|
||||
if (kind == ArgumentsKind.HAS_EMPTY_EXPRESSION_ARGUMENT) break
|
||||
}
|
||||
|
||||
if (argumentsShouldBeExtractedToTmpVars) {
|
||||
extractArguments(result, argContexts, context(), kind == ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT)
|
||||
extractArguments(result, argContexts, context())
|
||||
}
|
||||
|
||||
if (isNativeFunctionCall && hasSpreadOperator) {
|
||||
@@ -186,12 +179,12 @@ class CallArgumentTranslator private constructor(
|
||||
}
|
||||
|
||||
private fun translateSingleArgument(actualArgument: ResolvedValueArgument, result: MutableList<JsExpression>,
|
||||
context: TranslationContext): ArgumentsKind {
|
||||
context: TranslationContext) {
|
||||
val valueArguments = actualArgument.arguments
|
||||
|
||||
if (actualArgument is DefaultValueArgument) {
|
||||
result += Namer.getUndefinedExpression()
|
||||
return ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||
return
|
||||
}
|
||||
|
||||
assert(actualArgument is ExpressionValueArgument)
|
||||
@@ -201,22 +194,15 @@ class CallArgumentTranslator private constructor(
|
||||
|
||||
val jsExpression = Translation.translateAsExpression(argumentExpression, context)
|
||||
result.add(jsExpression)
|
||||
|
||||
if (JsAstUtils.isEmptyExpression(jsExpression)) {
|
||||
return ArgumentsKind.HAS_EMPTY_EXPRESSION_ARGUMENT
|
||||
}
|
||||
else {
|
||||
return ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||
}
|
||||
}
|
||||
|
||||
private fun translateVarargArgument(arguments: List<ValueArgument>, result: MutableList<JsExpression>,
|
||||
context: TranslationContext, shouldWrapVarargInArray: Boolean): ArgumentsKind {
|
||||
context: TranslationContext, shouldWrapVarargInArray: Boolean) {
|
||||
if (arguments.isEmpty()) {
|
||||
if (shouldWrapVarargInArray) {
|
||||
result.add(JsArrayLiteral(listOf<JsExpression>()).apply { sideEffects = SideEffectKind.DEPENDS_ON_STATE })
|
||||
}
|
||||
return ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||
return
|
||||
}
|
||||
|
||||
val list: MutableList<JsExpression>
|
||||
@@ -242,8 +228,7 @@ class CallArgumentTranslator private constructor(
|
||||
}
|
||||
|
||||
private fun translateValueArguments(arguments: List<ValueArgument>, list: MutableList<JsExpression>,
|
||||
context: TranslationContext): ArgumentsKind {
|
||||
var resultKind = ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT
|
||||
context: TranslationContext) {
|
||||
val argContexts = SmartList<TranslationContext>()
|
||||
var argumentsShouldBeExtractedToTmpVars = false
|
||||
for (argument in arguments) {
|
||||
@@ -254,15 +239,10 @@ class CallArgumentTranslator private constructor(
|
||||
context.moveVarsFrom(argContext)
|
||||
argContexts.add(argContext)
|
||||
argumentsShouldBeExtractedToTmpVars = argumentsShouldBeExtractedToTmpVars || !argContext.currentBlockIsEmpty()
|
||||
if (JsAstUtils.isEmptyExpression(argExpression)) {
|
||||
resultKind = ArgumentsKind.HAS_EMPTY_EXPRESSION_ARGUMENT
|
||||
break
|
||||
}
|
||||
}
|
||||
if (argumentsShouldBeExtractedToTmpVars) {
|
||||
extractArguments(list, argContexts, context, resultKind == ArgumentsKind.HAS_NOT_EMPTY_EXPRESSION_ARGUMENT)
|
||||
extractArguments(list, argContexts, context)
|
||||
}
|
||||
return resultKind
|
||||
}
|
||||
|
||||
private fun concatArgumentsIfNeeded(concatArguments: List<JsExpression>): JsExpression {
|
||||
@@ -311,19 +291,14 @@ class CallArgumentTranslator private constructor(
|
||||
}
|
||||
|
||||
private fun extractArguments(argExpressions: MutableList<JsExpression>, argContexts: List<TranslationContext>,
|
||||
context: TranslationContext, toTmpVars: Boolean) {
|
||||
context: TranslationContext) {
|
||||
for (i in argExpressions.indices) {
|
||||
val argContext = argContexts[i]
|
||||
val jsArgExpression = argExpressions[i]
|
||||
if (argContext.currentBlockIsEmpty() && TranslationUtils.isCacheNeeded(jsArgExpression)) {
|
||||
if (toTmpVars) {
|
||||
val temporaryVariable = context.declareTemporary(jsArgExpression)
|
||||
context.addStatementToCurrentBlock(temporaryVariable.assignmentExpression().makeStmt())
|
||||
argExpressions[i] = temporaryVariable.reference()
|
||||
}
|
||||
else {
|
||||
context.addStatementToCurrentBlock(jsArgExpression.makeStmt())
|
||||
}
|
||||
val temporaryVariable = context.declareTemporary(jsArgExpression)
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(temporaryVariable.assignmentExpression()))
|
||||
argExpressions[i] = temporaryVariable.reference()
|
||||
}
|
||||
else {
|
||||
context.addStatementsToCurrentBlockFrom(argContext)
|
||||
|
||||
+1
-1
@@ -106,7 +106,7 @@ public final class CallExpressionTranslator extends AbstractCallExpressionTransl
|
||||
int size = statements.size();
|
||||
|
||||
if (size == 0) {
|
||||
return program().getEmptyExpression();
|
||||
return JsLiteral.NULL;
|
||||
} else if (size > 1) {
|
||||
return new JsBlock(statements);
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ object CallableReferenceTranslator {
|
||||
|
||||
private fun reportNotSupported(context: TranslationContext, expression: KtCallableReferenceExpression): JsExpression {
|
||||
context.bindingTrace().report(ErrorsJs.REFERENCE_TO_BUILTIN_MEMBERS_NOT_SUPPORTED.on(expression, expression))
|
||||
return context.emptyExpression
|
||||
return JsLiteral.NULL
|
||||
}
|
||||
|
||||
private fun translateForFunction(descriptor: FunctionDescriptor, context: TranslationContext, expression: KtCallableReferenceExpression): JsExpression {
|
||||
|
||||
+2
-1
@@ -32,6 +32,7 @@ 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,7 +47,7 @@ public final class QualifiedExpressionTranslator {
|
||||
JsExpression receiver = translateReceiver(expression, context);
|
||||
if (forceOrderOfEvaluation && receiver != null) {
|
||||
TemporaryVariable temporaryVariable = context.declareTemporary(null);
|
||||
context.addStatementToCurrentBlock(JsAstUtils.assignment(temporaryVariable.reference(), receiver).makeStmt());
|
||||
context.addStatementToCurrentBlock(asSyntheticStatement(JsAstUtils.assignment(temporaryVariable.reference(), receiver)));
|
||||
receiver = temporaryVariable.reference();
|
||||
}
|
||||
return VariableAccessTranslator.newInstance(context, getNotNullSimpleNameSelector(expression), receiver);
|
||||
|
||||
@@ -56,7 +56,11 @@ public final class JsAstUtils {
|
||||
assert (jsNode instanceof JsExpression) || (jsNode instanceof JsStatement)
|
||||
: "Unexpected node of type: " + jsNode.getClass().toString();
|
||||
if (jsNode instanceof JsExpression) {
|
||||
return ((JsExpression) jsNode).makeStmt();
|
||||
JsExpressionStatement statement = new JsExpressionStatement((JsExpression) jsNode);
|
||||
if (jsNode instanceof JsNullLiteral) {
|
||||
MetadataProperties.setSynthetic(statement, true);
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
return (JsStatement) jsNode;
|
||||
}
|
||||
@@ -118,10 +122,6 @@ public final class JsAstUtils {
|
||||
return statement instanceof JsEmpty;
|
||||
}
|
||||
|
||||
public static boolean isEmptyExpression(@NotNull JsExpression expression) {
|
||||
return expression instanceof JsEmptyExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsInvocation invokeKotlinFunction(@NotNull String name, @NotNull JsExpression... argument) {
|
||||
return invokeMethod(Namer.kotlinObject(), name, argument);
|
||||
|
||||
@@ -247,7 +247,6 @@ public final class TranslationUtils {
|
||||
|
||||
public static boolean isCacheNeeded(@NotNull JsExpression expression) {
|
||||
return !(expression instanceof JsLiteral.JsValueLiteral) &&
|
||||
!JsAstUtils.isEmptyExpression(expression) &&
|
||||
(!(expression instanceof JsNameRef) || ((JsNameRef) expression).getQualifier() != null);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user