JS: get rid of JsEmptyExpression, use JsLiteral.NULL instead, rely on optimizer to remove redundant code

This commit is contained in:
Alexey Andreev
2016-05-16 18:59:27 +03:00
parent fe5a7aaf46
commit 9edb9fabe5
19 changed files with 73 additions and 173 deletions
@@ -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)
}
@@ -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!!)
}
}
@@ -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);
@@ -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)
}
@@ -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());
@@ -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 {
@@ -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;
@@ -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
@@ -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;
@@ -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);
@@ -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)
@@ -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 {
@@ -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 {
@@ -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);
}