From cb071e3f745084f9192c0220b8be9ca6d05d5bb9 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Thu, 1 Dec 2011 19:12:07 +0400 Subject: [PATCH] implement some of the intrinsic functionality --- .../google/dart/compiler/util/AstUtil.java | 7 + .../intrinsic/BinaryOperationIntrinsic.java | 27 ---- .../k2js/intrinsic/IntrinsicFactory.java | 27 ---- .../jetbrains/k2js/intrinsic/Intrinsics.java | 86 ----------- .../expression/ExpressionVisitor.java | 22 +-- .../k2js/translate/general/StaticContext.java | 2 +- .../translate/general/TranslationContext.java | 2 +- .../ClassInitializerTranslator.java | 2 +- .../intrinsic/BinaryOperationIntrinsic.java | 38 +++++ .../intrinsic/CompareToIntrinsic.java | 25 ++++ .../translate/intrinsic/EqualsIntrinsic.java | 20 +++ .../{ => translate}/intrinsic/Intrinsic.java | 7 +- .../IntrinsicDeclarationVisitor.java | 2 +- .../k2js/translate/intrinsic/Intrinsics.java | 88 +++++++++++ .../PrimitiveCompareToIntrinsic.java | 31 ++++ .../intrinsic/PrimitiveEqualsIntrinsic.java | 32 ++++ .../intrinsic/UnaryOperationIntrinsic.java | 39 +++++ .../operation/BinaryOperationTranslator.java | 23 +-- .../translate/operation/EqualsTranslator.java | 9 ++ .../IntrinsicUnaryOperationTranslator.java | 64 ++++++++ .../operation/OperationTranslator.java | 131 ++++++++++------- .../OverloadedBinaryOperationTranslator.java | 2 +- .../OverloadedUnaryOperationTranslator.java | 44 ++++++ .../operation/UnaryOperationTranslator.java | 111 ++++---------- .../translate/reference/CallTranslator.java | 137 ++++++++++++++++++ .../reference/PropertyAccessTranslator.java | 16 +- .../reference/ReferenceTranslator.java | 48 +++--- .../k2js/translate/utils/BindingUtils.java | 87 ++++++----- .../translate/utils/TranslationUtils.java | 56 +++++-- 29 files changed, 780 insertions(+), 405 deletions(-) delete mode 100644 translator/src/org/jetbrains/k2js/intrinsic/BinaryOperationIntrinsic.java delete mode 100644 translator/src/org/jetbrains/k2js/intrinsic/IntrinsicFactory.java delete mode 100644 translator/src/org/jetbrains/k2js/intrinsic/Intrinsics.java create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/BinaryOperationIntrinsic.java create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/CompareToIntrinsic.java create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/EqualsIntrinsic.java rename translator/src/org/jetbrains/k2js/{ => translate}/intrinsic/Intrinsic.java (64%) rename translator/src/org/jetbrains/k2js/{ => translate}/intrinsic/IntrinsicDeclarationVisitor.java (96%) create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveCompareToIntrinsic.java create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveEqualsIntrinsic.java create mode 100644 translator/src/org/jetbrains/k2js/translate/intrinsic/UnaryOperationIntrinsic.java create mode 100644 translator/src/org/jetbrains/k2js/translate/operation/EqualsTranslator.java create mode 100644 translator/src/org/jetbrains/k2js/translate/operation/IntrinsicUnaryOperationTranslator.java create mode 100644 translator/src/org/jetbrains/k2js/translate/operation/OverloadedUnaryOperationTranslator.java create mode 100644 translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java diff --git a/js/src/com/google/dart/compiler/util/AstUtil.java b/js/src/com/google/dart/compiler/util/AstUtil.java index eca3f62f74b..5dcb376cc92 100644 --- a/js/src/com/google/dart/compiler/util/AstUtil.java +++ b/js/src/com/google/dart/compiler/util/AstUtil.java @@ -309,6 +309,13 @@ public class AstUtil { throw new AssertionError("Set qualifier should be applied only to JsInvocation or JsNameRef instances"); } + //TODO: look for should-be-usages + public static JsNameRef qualified(JsName selector, JsExpression qualifier) { + JsNameRef reference = selector.makeRef(); + AstUtil.setQualifier(reference, qualifier); + return reference; + } + public static JsBinaryOperation equals(JsExpression arg1, JsExpression arg2) { return new JsBinaryOperation(JsBinaryOperator.REF_EQ, arg1, arg2); } diff --git a/translator/src/org/jetbrains/k2js/intrinsic/BinaryOperationIntrinsic.java b/translator/src/org/jetbrains/k2js/intrinsic/BinaryOperationIntrinsic.java deleted file mode 100644 index d3a5947a94b..00000000000 --- a/translator/src/org/jetbrains/k2js/intrinsic/BinaryOperationIntrinsic.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.jetbrains.k2js.intrinsic; - -import com.google.dart.compiler.backend.js.ast.JsExpression; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetBinaryExpression; -import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.k2js.translate.general.TranslationContext; -import org.jetbrains.k2js.translate.operation.IntrinsicBinaryOperationTranslator; - -/** - * @author Talanov Pavel - */ -public enum BinaryOperationIntrinsic implements Intrinsic { - - INSTANCE; - - /*package*/ BinaryOperationIntrinsic() { - } - - @NotNull - @Override - public JsExpression apply(@NotNull JetExpression expression, - @NotNull TranslationContext context) { - assert expression instanceof JetBinaryExpression : "This intrinsic must be applied to binary operations."; - return IntrinsicBinaryOperationTranslator.translate((JetBinaryExpression) expression, context); - } -} diff --git a/translator/src/org/jetbrains/k2js/intrinsic/IntrinsicFactory.java b/translator/src/org/jetbrains/k2js/intrinsic/IntrinsicFactory.java deleted file mode 100644 index 087ea2f9fd3..00000000000 --- a/translator/src/org/jetbrains/k2js/intrinsic/IntrinsicFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.jetbrains.k2js.intrinsic; - -import org.jetbrains.annotations.NotNull; - -/** - * @author Talanov Pavel - */ -public final class IntrinsicFactory { - - @NotNull - private final Intrinsics intrinsics; - - private IntrinsicFactory(@NotNull Intrinsics intrinsics) { - this.intrinsics = intrinsics; - } - -// public Intrinsic getIntrinsicForExpression(@NotNull FunctionDescriptor descriptor, -// @NotNull JetExpression expression, -// @NotNull TranslationContext context) { -// assert intrinsics.hasDescriptor(descriptor); -// if (JetExpression instanceof JetBinaryExpression) { -// return new BinaryOperationIntrinsic() -// } -// } - - -} diff --git a/translator/src/org/jetbrains/k2js/intrinsic/Intrinsics.java b/translator/src/org/jetbrains/k2js/intrinsic/Intrinsics.java deleted file mode 100644 index 1f419ef4d5f..00000000000 --- a/translator/src/org/jetbrains/k2js/intrinsic/Intrinsics.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.jetbrains.k2js.intrinsic; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; -import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; -import org.jetbrains.jet.lang.types.JetStandardLibrary; -import org.jetbrains.jet.lang.types.expressions.OperatorConventions; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Talanov Pavel - */ -public final class Intrinsics { - - @NotNull - private final Map descriptorToIntrinsicMap = - new HashMap(); - - public static Intrinsics standardLibraryIntrinsics(@NotNull JetStandardLibrary library) { - return new Intrinsics(library); - } - - private Intrinsics(@NotNull JetStandardLibrary library) { - IntrinsicDeclarationVisitor visitor = new IntrinsicDeclarationVisitor(this); - for (DeclarationDescriptor descriptor : library.getLibraryScope().getAllDescriptors()) { - descriptor.accept(visitor, null); - } - } - - /*package*/ void declareIntrinsic(@NotNull DeclarationDescriptor descriptor) { - //TODO: this is a hack - descriptorToIntrinsicMap.put(descriptor, null); - addBinaryIntrinsics(descriptor); -// addUnaryIntrinsics(descriptor); -// addAssignmentIntrinsics(descriptor); -// addEqualsIntrinsics(descriptor); - } - - // private void addEqualsIntrinsics(FunctionDescriptor descriptor) { -// //BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic(); -// String functionName = descriptor.getName(); -// if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) { -// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic); -// } -// } -// -// private void addUnaryIntrinsics(@NotNull FunctionDescriptor descriptor) { -// BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic(); -// String functionName = descriptor.getName(); -// if (OperatorConventions.UNARY_OPERATION_NAMES.containsValue(functionName)) { -// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic); -// } -// } -// - private void addBinaryIntrinsics(@NotNull DeclarationDescriptor descriptor) { - String functionName = descriptor.getName(); - if (OperatorConventions.BINARY_OPERATION_NAMES.containsValue(functionName)) { - descriptorToIntrinsicMap.put(descriptor, BinaryOperationIntrinsic.INSTANCE); - } - } - - // -// private void addAssignmentIntrinsics(@NotNull FunctionDescriptor descriptor) { -// String functionName = descriptor.getName(); -// if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsValue(functionName)) { -// BinaryOperationIntrinsic binaryOperationIntrinsic = new BinaryOperationIntrinsic(); -// descriptorToIntrinsicMap.put(descriptor, binaryOperationIntrinsic); -// } -// } -// - public boolean hasDescriptor(@NotNull DeclarationDescriptor descriptor) { - if (descriptor instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor.getOriginal(); - return descriptorToIntrinsicMap.containsKey(functionDescriptor); - } - return false; - } - - public Intrinsic getIntrinsic(@NotNull DeclarationDescriptor descriptor) { - Intrinsic intrinsic = descriptorToIntrinsicMap.get(descriptor); -// assert intrinsic != null; - return intrinsic; - } -} diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 77f4219f188..a7d5523dda4 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -14,6 +14,7 @@ import org.jetbrains.k2js.translate.general.TranslatorVisitor; import org.jetbrains.k2js.translate.operation.OperationTranslator; import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator; import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator; +import org.jetbrains.k2js.translate.reference.CallTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; import org.jetbrains.k2js.translate.reference.ReferenceTranslator; import org.jetbrains.k2js.translate.utils.BindingUtils; @@ -108,24 +109,9 @@ public final class ExpressionVisitor extends TranslatorVisitor { @Override @NotNull - public JsNode visitCallExpression(JetCallExpression expression, TranslationContext context) { - JsExpression callee = translateCallee(expression, context); - List arguments = translateArgumentList(expression.getValueArguments(), context); - if (isConstructorInvocation(context, expression)) { - JsNew constructorCall = new JsNew(callee); - constructorCall.setArguments(arguments); - return constructorCall; - } - return AstUtil.newInvocation(callee, arguments); - } - - @NotNull - private JsExpression translateCallee(@NotNull JetCallExpression expression, @NotNull TranslationContext context) { - JetExpression callee = expression.getCalleeExpression(); - if (callee == null) { - throw new AssertionError("Call expression with no callee encountered!"); - } - return translateAsExpression(callee, context); + public JsNode visitCallExpression(@NotNull JetCallExpression expression, + @NotNull TranslationContext context) { + return CallTranslator.translate(expression, context); } @Override diff --git a/translator/src/org/jetbrains/k2js/translate/general/StaticContext.java b/translator/src/org/jetbrains/k2js/translate/general/StaticContext.java index ca8e3da92bf..e4e972501ea 100644 --- a/translator/src/org/jetbrains/k2js/translate/general/StaticContext.java +++ b/translator/src/org/jetbrains/k2js/translate/general/StaticContext.java @@ -10,7 +10,7 @@ import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.k2js.declarations.Declarations; -import org.jetbrains.k2js.intrinsic.Intrinsics; +import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.utils.Namer; public class StaticContext { diff --git a/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java index 95e1d6f2deb..2b0e3a70abb 100644 --- a/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java +++ b/translator/src/org/jetbrains/k2js/translate/general/TranslationContext.java @@ -8,7 +8,7 @@ import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.k2js.declarations.Declarations; -import org.jetbrains.k2js.intrinsic.Intrinsics; +import org.jetbrains.k2js.translate.intrinsic.Intrinsics; import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.Namer; diff --git a/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java b/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java index ce847210669..2f563829d3c 100644 --- a/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/initializer/ClassInitializerTranslator.java @@ -68,7 +68,7 @@ public final class ClassInitializerTranslator extends AbstractInitializerTransla @NotNull private List translateArguments(@NotNull JetDelegatorToSuperCall superCall) { - return TranslationUtils.translateArgumentList(superCall.getValueArguments(), context()); + return TranslationUtils.translateArgumentList(context(), superCall.getValueArguments()); } @Nullable diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/BinaryOperationIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/BinaryOperationIntrinsic.java new file mode 100644 index 00000000000..6baab3bcd1e --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/BinaryOperationIntrinsic.java @@ -0,0 +1,38 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; +import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.k2js.translate.general.TranslationContext; +import org.jetbrains.k2js.translate.operation.OperatorTable; + +import java.util.List; + +/** + * @author Talanov Pavel + */ +public class BinaryOperationIntrinsic implements Intrinsic { + + @NotNull + /*package*/ static BinaryOperationIntrinsic newInstance(@NotNull JetToken token) { + JsBinaryOperator operator = OperatorTable.getBinaryOperator(token); + return new BinaryOperationIntrinsic(operator); + } + + @NotNull + private final JsBinaryOperator operator; + + private BinaryOperationIntrinsic(@NotNull JsBinaryOperator operator) { + this.operator = operator; + } + + @NotNull + @Override + public JsExpression apply(@NotNull JsExpression receiver, @NotNull List arguments, + @NotNull TranslationContext context) { + assert arguments.size() == 1 : "Binary operator should have a receiver and one argument"; + return new JsBinaryOperation(operator, receiver, arguments.get(0)); + } +} diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/CompareToIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/CompareToIntrinsic.java new file mode 100644 index 00000000000..2201e6fda38 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/CompareToIntrinsic.java @@ -0,0 +1,25 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.types.expressions.OperatorConventions; +import org.jetbrains.jet.lexer.JetToken; + +/** + * @author Talanov Pavel + */ +public abstract class CompareToIntrinsic implements Intrinsic { + + private JetToken comparisonToken = null; + + @NotNull + public JetToken getComparisonToken() { + assert comparisonToken != null : "Should use set token first"; + return comparisonToken; + } + + public void setComparisonToken(@NotNull JetToken comparisonToken) { + assert OperatorConventions.COMPARISON_OPERATIONS.contains(comparisonToken) + : "Should be a comparison operation"; + this.comparisonToken = comparisonToken; + } +} diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/EqualsIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/EqualsIntrinsic.java new file mode 100644 index 00000000000..e123fbb03c4 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/EqualsIntrinsic.java @@ -0,0 +1,20 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import org.jetbrains.annotations.NotNull; + +/** + * @author Talanov Pavel + */ +public abstract class EqualsIntrinsic implements Intrinsic { + + @NotNull + private Boolean isNegated = false; + + public void setNegated(boolean isNegated) { + this.isNegated = isNegated; + } + + public boolean isNegated() { + return isNegated; + } +} diff --git a/translator/src/org/jetbrains/k2js/intrinsic/Intrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsic.java similarity index 64% rename from translator/src/org/jetbrains/k2js/intrinsic/Intrinsic.java rename to translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsic.java index e8164019356..954cb55da84 100644 --- a/translator/src/org/jetbrains/k2js/intrinsic/Intrinsic.java +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsic.java @@ -1,17 +1,18 @@ -package org.jetbrains.k2js.intrinsic; +package org.jetbrains.k2js.translate.intrinsic; import com.google.dart.compiler.backend.js.ast.JsExpression; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.k2js.translate.general.TranslationContext; +import java.util.List; + /** * @author Talanov Pavel */ public interface Intrinsic { @NotNull - public JsExpression apply(@NotNull JetExpression expression, + public JsExpression apply(@NotNull JsExpression receiver, @NotNull List arguments, @NotNull TranslationContext context); } diff --git a/translator/src/org/jetbrains/k2js/intrinsic/IntrinsicDeclarationVisitor.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/IntrinsicDeclarationVisitor.java similarity index 96% rename from translator/src/org/jetbrains/k2js/intrinsic/IntrinsicDeclarationVisitor.java rename to translator/src/org/jetbrains/k2js/translate/intrinsic/IntrinsicDeclarationVisitor.java index 8ae8fb54f22..d51c548c85a 100644 --- a/translator/src/org/jetbrains/k2js/intrinsic/IntrinsicDeclarationVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/IntrinsicDeclarationVisitor.java @@ -1,4 +1,4 @@ -package org.jetbrains.k2js.intrinsic; +package org.jetbrains.k2js.translate.intrinsic; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java new file mode 100644 index 00000000000..3b91bacfbff --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/Intrinsics.java @@ -0,0 +1,88 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.types.JetStandardLibrary; +import org.jetbrains.jet.lang.types.expressions.OperatorConventions; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.k2js.translate.operation.OperatorTable; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Talanov Pavel + */ +public final class Intrinsics { + + @NotNull + private final Map descriptorToIntrinsicMap = + new HashMap(); + + public static Intrinsics standardLibraryIntrinsics(@NotNull JetStandardLibrary library) { + return new Intrinsics(library); + } + + private Intrinsics(@NotNull JetStandardLibrary library) { + IntrinsicDeclarationVisitor visitor = new IntrinsicDeclarationVisitor(this); + for (DeclarationDescriptor descriptor : library.getLibraryScope().getAllDescriptors()) { + descriptor.accept(visitor, null); + } + } + + /*package*/ void declareIntrinsic(@NotNull FunctionDescriptor descriptor) { + //TODO: HACK! + addCompareToIntrinsics(descriptor); + addEqualsIntrinsics(descriptor); + addUnaryIntrinsics(descriptor); + addBinaryIntrinsics(descriptor); + + } + + private void addCompareToIntrinsics(@NotNull FunctionDescriptor descriptor) { + String functionName = descriptor.getName(); + if (functionName.equals("compareTo")) { + descriptorToIntrinsicMap.put(descriptor, PrimitiveCompareToIntrinsic.newInstance()); + } + } + + private void addEqualsIntrinsics(@NotNull FunctionDescriptor descriptor) { + String functionName = descriptor.getName(); + if (functionName.equals("equals")) { + descriptorToIntrinsicMap.put(descriptor, PrimitiveEqualsIntrinsic.newInstance()); + } + } + + private void addUnaryIntrinsics(@NotNull FunctionDescriptor descriptor) { + String functionName = descriptor.getName(); + JetToken token = OperatorConventions.UNARY_OPERATION_NAMES.inverse().get(functionName); + if (token != null) { + descriptorToIntrinsicMap.put(descriptor, UnaryOperationIntrinsic.newInstance(token)); + } + } + + private void addBinaryIntrinsics(@NotNull FunctionDescriptor descriptor) { + String functionName = descriptor.getName(); + JetToken token = OperatorConventions.BINARY_OPERATION_NAMES.inverse().get(functionName); + if (token != null && OperatorTable.hasCorrespondingBinaryOperator(token)) { + descriptorToIntrinsicMap.put(descriptor, BinaryOperationIntrinsic.newInstance(token)); + } + } + + public boolean hasDescriptor(@NotNull DeclarationDescriptor descriptor) { + if (descriptor instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor.getOriginal(); + return (descriptorToIntrinsicMap.get(functionDescriptor) != null); + } + return false; + } + + + @NotNull + public Intrinsic getIntrinsic(@NotNull DeclarationDescriptor descriptor) { + assert descriptor instanceof FunctionDescriptor; + Intrinsic intrinsic = descriptorToIntrinsicMap.get(descriptor); + return intrinsic; + } +} diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveCompareToIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveCompareToIntrinsic.java new file mode 100644 index 00000000000..a8abea879a4 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveCompareToIntrinsic.java @@ -0,0 +1,31 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import com.google.dart.compiler.backend.js.ast.JsBinaryOperation; +import com.google.dart.compiler.backend.js.ast.JsBinaryOperator; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.translate.general.TranslationContext; +import org.jetbrains.k2js.translate.operation.OperatorTable; + +import java.util.List; + +/** + * @author Talanov Pavel + */ +public final class PrimitiveCompareToIntrinsic extends CompareToIntrinsic { + + @NotNull + /*package*/ static PrimitiveCompareToIntrinsic newInstance() { + return new PrimitiveCompareToIntrinsic(); + } + + @NotNull + public JsExpression apply(@NotNull JsExpression receiver, @NotNull List arguments, + @NotNull TranslationContext context) { + assert arguments.size() == 1 : "Equals operation should have one argument"; + JsBinaryOperator operator = OperatorTable.getBinaryOperator(getComparisonToken()); + JsExpression argument = arguments.get(0); + return new JsBinaryOperation(operator, receiver, argument); + } + +} diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveEqualsIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveEqualsIntrinsic.java new file mode 100644 index 00000000000..fc504b8aeef --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/PrimitiveEqualsIntrinsic.java @@ -0,0 +1,32 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.util.AstUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.k2js.translate.general.TranslationContext; + +import java.util.List; + +/** + * @author Talanov Pavel + */ +public final class PrimitiveEqualsIntrinsic extends EqualsIntrinsic { + + + @NotNull + /*package*/ static PrimitiveEqualsIntrinsic newInstance() { + return new PrimitiveEqualsIntrinsic(); + } + + @NotNull + public JsExpression apply(@NotNull JsExpression receiver, @NotNull List arguments, + @NotNull TranslationContext context) { + assert arguments.size() == 1 : "Equals operation should have one argument"; + if (isNegated()) { + return AstUtil.notEqual(receiver, arguments.get(0)); + } else { + return AstUtil.equals(receiver, arguments.get(0)); + } + } + +} diff --git a/translator/src/org/jetbrains/k2js/translate/intrinsic/UnaryOperationIntrinsic.java b/translator/src/org/jetbrains/k2js/translate/intrinsic/UnaryOperationIntrinsic.java new file mode 100644 index 00000000000..63991827f77 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/intrinsic/UnaryOperationIntrinsic.java @@ -0,0 +1,39 @@ +package org.jetbrains.k2js.translate.intrinsic; + +import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.backend.js.ast.JsPrefixOperation; +import com.google.dart.compiler.backend.js.ast.JsUnaryOperator; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.k2js.translate.general.TranslationContext; +import org.jetbrains.k2js.translate.operation.OperatorTable; + +import java.util.List; + +/** + * @author Talanov Pavel + */ +public class UnaryOperationIntrinsic implements Intrinsic { + + @NotNull + /*package*/ static UnaryOperationIntrinsic newInstance(@NotNull JetToken token) { + JsUnaryOperator operator = OperatorTable.getUnaryOperator(token); + return new UnaryOperationIntrinsic(operator); + } + + @NotNull + private final JsUnaryOperator operator; + + private UnaryOperationIntrinsic(@NotNull JsUnaryOperator operator) { + this.operator = operator; + } + + @NotNull + @Override + public JsExpression apply(@NotNull JsExpression receiver, @NotNull List arguments, + @NotNull TranslationContext context) { + assert arguments.size() == 0 : "Unary operator should not have arguments."; + //TODO: note that we cannot use this for increment/decrement + return new JsPrefixOperation(operator, receiver); + } +} diff --git a/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java index 4760c9fce78..073d96a0329 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java @@ -4,12 +4,15 @@ import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsInvocation; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.JetBinaryExpression; -import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lexer.JetToken; -import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; +import static org.jetbrains.k2js.translate.utils.BindingUtils.isVariableReassignment; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateLeftExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression; + + /** * @author Talanov Pavel */ @@ -29,26 +32,16 @@ public abstract class BinaryOperationTranslator extends OperationTranslator { super(context); this.expression = expression; this.isPropertyOnTheLeft = isPropertyAccess(expression.getLeft()); - this.isVariableReassignment = isVariableReassignment(expression); + this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression); - this.right = translateRightExpression(); + this.right = translateRightExpression(context(), expression); //TODO: decide whether it is harmful to possibly translateNamespace left expression more than once - this.left = translateLeftExpression(); + this.left = translateLeftExpression(context(), expression); } @NotNull abstract protected JsExpression translate(); - private JsExpression translateLeftExpression() { - return Translation.translateAsExpression(expression.getLeft(), context()); - } - - @NotNull - private JsExpression translateRightExpression() { - JetExpression rightExpression = expression.getRight(); - assert rightExpression != null : "Binary expression should have a right expression"; - return Translation.translateAsExpression(rightExpression, context()); - } @NotNull protected JetToken getOperationToken() { diff --git a/translator/src/org/jetbrains/k2js/translate/operation/EqualsTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/EqualsTranslator.java new file mode 100644 index 00000000000..11ba6e06915 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/operation/EqualsTranslator.java @@ -0,0 +1,9 @@ +package org.jetbrains.k2js.translate.operation; + +/** + * @author Talanov Pavel + */ +public final class EqualsTranslator { + + +} diff --git a/translator/src/org/jetbrains/k2js/translate/operation/IntrinsicUnaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/IntrinsicUnaryOperationTranslator.java new file mode 100644 index 00000000000..164800d9a93 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/operation/IntrinsicUnaryOperationTranslator.java @@ -0,0 +1,64 @@ +package org.jetbrains.k2js.translate.operation; + +import com.google.dart.compiler.backend.js.ast.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetUnaryExpression; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.jet.lexer.JetTokens; +import org.jetbrains.k2js.translate.general.TranslationContext; + +/** + * @author Talanov Pavel + */ +public final class IntrinsicUnaryOperationTranslator extends UnaryOperationTranslator { + + + @NotNull + public static JsExpression translate(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { + return (new IntrinsicUnaryOperationTranslator(expression, context)) + .translate(); + } + + protected IntrinsicUnaryOperationTranslator(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { + super(expression, context); + } + + @Override + @NotNull + protected JsExpression translate() { + if (isPropertyAccess) { + return translateAsMethodCall(); + } + return jsUnaryExpression(); + } + + @NotNull + private JsExpression jsUnaryExpression() { + JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken()); + if (isPrefix) { + return new JsPrefixOperation(operator, baseExpression); + } else { + return new JsPostfixOperation(operator, baseExpression); + } + } + + @Override + @NotNull + protected JsExpression operationExpression(@NotNull JsExpression receiver) { + return unaryAsBinary(getOperationToken(), receiver); + } + + public JsBinaryOperation unaryAsBinary(@NotNull JetToken token, @NotNull JsExpression expression) { + JsNumberLiteral oneLiteral = context().program().getNumberLiteral(1); + if (token.equals(JetTokens.PLUSPLUS)) { + return new JsBinaryOperation(JsBinaryOperator.ADD, expression, oneLiteral); + } + if (token.equals(JetTokens.MINUSMINUS)) { + return new JsBinaryOperation(JsBinaryOperator.SUB, expression, oneLiteral); + } + throw new AssertionError("This method should be called only for increment and decrement operators"); + } + +} diff --git a/translator/src/org/jetbrains/k2js/translate/operation/OperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/OperationTranslator.java index 06a86a7834d..3ee4bb61fe8 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/OperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/OperationTranslator.java @@ -9,14 +9,24 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetBinaryExpression; import org.jetbrains.jet.lang.psi.JetExpression; -import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; -import org.jetbrains.k2js.intrinsic.Intrinsic; +import org.jetbrains.jet.lang.psi.JetOperationExpression; +import org.jetbrains.jet.lang.psi.JetUnaryExpression; +import org.jetbrains.jet.lexer.JetToken; +import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.TranslationContext; +import org.jetbrains.k2js.translate.intrinsic.CompareToIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.EqualsIntrinsic; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator; +import org.jetbrains.k2js.translate.reference.CallTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; -import org.jetbrains.k2js.translate.utils.BindingUtils; -import org.jetbrains.k2js.translate.utils.TranslationUtils; + +import java.util.Arrays; + +import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateLeftExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateRightExpression; /** * @author Talanov Pavel @@ -24,67 +34,92 @@ import org.jetbrains.k2js.translate.utils.TranslationUtils; public class OperationTranslator extends AbstractTranslator { @NotNull - static public JsExpression translate(@NotNull JetBinaryExpression expression, + public static JsExpression translate(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) { - JsExpression result = tryToApplyIntrinsic(expression, context); - if (result != null) return result; - + //TODO: move to assignment translator if (ArrayAccessTranslator.canBeArraySetterCall(expression)) { return ArrayAccessTranslator.translateAsArraySetterCall(expression, context); } - return translateAsBinary(expression, context); + DeclarationDescriptor descriptorForReferenceExpression = getDescriptorForReferenceExpression + (context.bindingContext(), expression.getOperation()); + if (descriptorForReferenceExpression == null) { + return IntrinsicBinaryOperationTranslator.translate(expression, context); + } + if (isEqualsCall(expression, context)) { + return translateAsEqualsCall(expression, context); + } + if (isCompareToCall(expression, context)) { + return translateAsCompareToCall(expression, context); + } + return CallTranslator.translate(expression, context); } @NotNull - private static JsExpression translateAsBinary(@NotNull JetBinaryExpression expression, - @NotNull TranslationContext context) { - if (TranslationUtils.isIntrinsicOperation(context, expression.getOperationReference())) { - return IntrinsicBinaryOperationTranslator.translate(expression, context); - } else { - return OverloadedBinaryOperationTranslator.translate(expression, context); - } + public static JsExpression translate(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { + return CallTranslator.translate(expression, context); } - @Nullable - private static JsExpression tryToApplyIntrinsic(@NotNull JetBinaryExpression expression, - @NotNull TranslationContext context) { - DeclarationDescriptor descriptor = BindingUtils.getDescriptorForReferenceExpression - (context.bindingContext(), expression.getOperationReference()); - if (descriptor == null) { - return null; - } - if (!context.intrinsics().hasDescriptor(descriptor)) { - return null; - } - //TODO: should be no nulls here - Intrinsic intrinsic = context.intrinsics().getIntrinsic(descriptor); - if (intrinsic == null) return null; - return intrinsic.apply(expression, context); + + public static boolean isEqualsCall(@NotNull JetBinaryExpression expression, + @NotNull TranslationContext context) { + DeclarationDescriptor operationDescriptor = getOperationDescriptor(expression, context); + //TODO: add descriptor is equals utils + boolean isEquals = operationDescriptor.getName().equals("equals"); + boolean isIntrinsic = context.intrinsics().hasDescriptor(operationDescriptor); + return isEquals && isIntrinsic; + } + + @NotNull + public static JsExpression translateAsEqualsCall(@NotNull JetBinaryExpression expression, + @NotNull TranslationContext context) { + Intrinsic intrinsic = context.intrinsics(). + getIntrinsic(getOperationDescriptor(expression, context)); + //TODO + ((EqualsIntrinsic) intrinsic).setNegated(expression.getOperationToken().equals(JetTokens.EXCLEQ)); + return intrinsic.apply(translateLeftExpression(context, expression), + Arrays.asList(translateRightExpression(context, expression)), context); + } + + public static boolean isCompareToCall(@NotNull JetBinaryExpression expression, + @NotNull TranslationContext context) { + DeclarationDescriptor operationDescriptor = getOperationDescriptor(expression, context); + return (operationDescriptor.getName().equals("compareTo") + && (context.intrinsics().hasDescriptor(operationDescriptor))); + } + + @NotNull + public static JsExpression translateAsCompareToCall(@NotNull JetBinaryExpression expression, + @NotNull TranslationContext context) { + Intrinsic intrinsic = context.intrinsics(). + getIntrinsic(getOperationDescriptor(expression, context)); + ((CompareToIntrinsic) intrinsic).setComparisonToken((JetToken) expression.getOperationToken()); + return intrinsic.apply(translateLeftExpression(context, expression), + Arrays.asList(translateRightExpression(context, expression)), context); } protected OperationTranslator(@NotNull TranslationContext context) { super(context); } + //TODO: refactor @Nullable - protected JsNameRef getOverloadedOperationReference(@NotNull JetSimpleNameExpression operationExpression) { - DeclarationDescriptor operationDescriptor = getOperationDescriptor(operationExpression); - if (operationDescriptor == null) { + protected static JsNameRef getOverloadedOperationReference(@NotNull JetOperationExpression operationExpression, + @NotNull TranslationContext context) { + DeclarationDescriptor operationDescriptor = getOperationDescriptor(operationExpression, context); + if (!context.isDeclared(operationDescriptor)) { return null; } - if (context().intrinsics().hasDescriptor(operationDescriptor)) { - return null; - } - if (!context().isDeclared(operationDescriptor)) { - return null; - } - return context().getNameForDescriptor(operationDescriptor).makeRef(); + return context.getNameForDescriptor(operationDescriptor).makeRef(); } - @Nullable - private DeclarationDescriptor getOperationDescriptor(@NotNull JetSimpleNameExpression expression) { - return BindingUtils.getDescriptorForReferenceExpression - (context().bindingContext(), expression); + @NotNull + private static DeclarationDescriptor getOperationDescriptor(@NotNull JetOperationExpression expression, + @NotNull TranslationContext context) { + DeclarationDescriptor descriptorForReferenceExpression = getDescriptorForReferenceExpression + (context.bindingContext(), expression.getOperation()); + assert descriptorForReferenceExpression != null; + return descriptorForReferenceExpression; } protected boolean isPropertyAccess(@NotNull JetExpression expression) { @@ -92,12 +127,6 @@ public class OperationTranslator extends AbstractTranslator { } - protected boolean isVariableReassignment(@NotNull JetExpression expression) { - return BindingUtils.isVariableReassignment - (context().bindingContext(), expression); - } - - protected final class TemporaryVariable { @NotNull diff --git a/translator/src/org/jetbrains/k2js/translate/operation/OverloadedBinaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/OverloadedBinaryOperationTranslator.java index 951018f9583..5ad71e2d15b 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/OverloadedBinaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/OverloadedBinaryOperationTranslator.java @@ -25,7 +25,7 @@ public final class OverloadedBinaryOperationTranslator extends BinaryOperationTr private OverloadedBinaryOperationTranslator(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) { super(expression, context); - JsNameRef overloadedOperationReference = getOverloadedOperationReference(expression.getOperationReference()); + JsNameRef overloadedOperationReference = getOverloadedOperationReference(expression, context); assert overloadedOperationReference != null; this.operationReference = overloadedOperationReference; } diff --git a/translator/src/org/jetbrains/k2js/translate/operation/OverloadedUnaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/OverloadedUnaryOperationTranslator.java new file mode 100644 index 00000000000..3220899701e --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/operation/OverloadedUnaryOperationTranslator.java @@ -0,0 +1,44 @@ +package org.jetbrains.k2js.translate.operation; + +import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.backend.js.ast.JsNameRef; +import com.google.dart.compiler.util.AstUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.psi.JetUnaryExpression; +import org.jetbrains.k2js.translate.general.TranslationContext; + +/** + * @author Talanov Pavel + */ +public final class OverloadedUnaryOperationTranslator extends UnaryOperationTranslator { + + @NotNull + public static JsExpression translate(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { + return (new OverloadedUnaryOperationTranslator(expression, context)) + .translate(); + } + + @NotNull + private final JsNameRef operationReference; + + private OverloadedUnaryOperationTranslator(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { + super(expression, context); + this.operationReference = getOverloadedOperationReference(expression, context); + } + + @Override + @NotNull + protected JsExpression translate() { + return translateAsMethodCall(); + } + + @Override + @NotNull + protected JsExpression operationExpression(@NotNull JsExpression receiver) { + AstUtil.setQualifier(operationReference, receiver); + return AstUtil.newInvocation(operationReference); + } + +} diff --git a/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java index 82e7dda0992..77266850435 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/UnaryOperationTranslator.java @@ -1,70 +1,55 @@ package org.jetbrains.k2js.translate.operation; -import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.backend.js.ast.JsExpression; +import com.google.dart.compiler.backend.js.ast.JsInvocation; +import com.google.dart.compiler.backend.js.ast.JsNameRef; import com.google.dart.compiler.util.AstUtil; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetPrefixExpression; +import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; +import org.jetbrains.jet.lang.psi.JetUnaryExpression; import org.jetbrains.jet.lexer.JetToken; -import org.jetbrains.jet.lexer.JetTokens; -import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; import org.jetbrains.k2js.translate.utils.BindingUtils; +import static org.jetbrains.k2js.translate.utils.BindingUtils.isVariableReassignment; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.getBaseExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.translateBaseExpression; /** * @author Talanov Pavel */ -public final class UnaryOperationTranslator extends OperationTranslator { - - - @NotNull - static public JsExpression translate(@NotNull JetPrefixExpression expression, - @NotNull TranslationContext context) { - return (new UnaryOperationTranslator(context, expression, true)).translate(); - } - - @NotNull - static public JsExpression translate(@NotNull JetPostfixExpression expression, - @NotNull TranslationContext context) { - return (new UnaryOperationTranslator(context, expression, false)).translate(); - } +//TODO: reexamine class, see if can be clearer +public abstract class UnaryOperationTranslator extends OperationTranslator { @NotNull private final JetUnaryExpression expression; @NotNull - private final JsExpression baseExpression; - private final boolean isPrefix; + protected final JsExpression baseExpression; + protected final boolean isPrefix; private final boolean isVariableReassignment; private final boolean isStatement; - private final boolean isPropertyAccess; - @Nullable - private final JsNameRef operationReference; + protected final boolean isPropertyAccess; - private UnaryOperationTranslator(@NotNull TranslationContext context, @NotNull JetUnaryExpression expression, - boolean isPrefix) { + protected UnaryOperationTranslator(@NotNull JetUnaryExpression expression, + @NotNull TranslationContext context) { super(context); this.expression = expression; - this.isPrefix = isPrefix; - this.isVariableReassignment = isVariableReassignment(expression); + this.isPrefix = isPrefix(expression); + this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression); this.isStatement = BindingUtils.isStatement(context().bindingContext(), expression); - this.baseExpression = translateBaseExpression(); - this.isPropertyAccess = isPropertyAccess(getBaseExpression()); - this.operationReference = getOverloadedOperationReference(expression.getOperationSign()); + this.baseExpression = translateBaseExpression(context, expression); + this.isPropertyAccess = isPropertyAccess(getBaseExpression(expression)); } @NotNull - JsExpression translate() { - if ((operationReference != null) || isPropertyAccess) { - return translateOverload(); - } - return jsUnaryExpression(); - } + protected abstract JsExpression translate(); @NotNull - private JsExpression translateOverload() { + protected JsExpression translateAsMethodCall() { if (isStatement || isPrefix) { return asPrefix(); } @@ -99,7 +84,6 @@ public final class UnaryOperationTranslator extends OperationTranslator { private JsExpression asPostfixWithNoReassignment() { // code fragment: expr(a++) // generate: expr( (t1 = a, t2 = t1, t2.inc(), t1) ) - assert operationReference != null; TemporaryVariable t1 = declareTemporary(baseExpression); TemporaryVariable t2 = declareTemporary(t1.nameReference()); JsExpression methodCall = operationExpression(t2.nameReference()); @@ -122,7 +106,7 @@ public final class UnaryOperationTranslator extends OperationTranslator { @NotNull private JsExpression propertyReassignment(@NotNull JsExpression toCallMethodUpon) { - JetExpression jetBaseExpression = getBaseExpression(); + JetExpression jetBaseExpression = getBaseExpression(expression); JsInvocation setterCall = PropertyAccessTranslator.translateAsPropertySetterCall(jetBaseExpression, context()); assert PropertyAccessTranslator.canBePropertyGetterCall(jetBaseExpression, context()) : "Should be a getter call"; @@ -132,52 +116,19 @@ public final class UnaryOperationTranslator extends OperationTranslator { } @NotNull - private JsExpression operationExpression(@NotNull JsExpression receiver) { - if (operationReference != null) { - AstUtil.setQualifier(operationReference, receiver); - return AstUtil.newInvocation(operationReference); - } - return unaryAsBinary(getOperationToken(), receiver); - } + abstract JsExpression operationExpression(@NotNull JsExpression receiver); @NotNull - private JsExpression jsUnaryExpression() { - JsUnaryOperator operator = OperatorTable.getUnaryOperator(getOperationToken()); - if (isPrefix) { - return new JsPrefixOperation(operator, baseExpression); - } else { - return new JsPostfixOperation(operator, baseExpression); - } - } - - @NotNull - private JsExpression translateBaseExpression() { - JetExpression baseExpression = getBaseExpression(); - return Translation.translateAsExpression(baseExpression, context()); - } - - private JetExpression getBaseExpression() { - JetExpression baseExpression = expression.getBaseExpression(); - assert baseExpression != null : "Unary expression should have a base expression"; - return baseExpression; - } - - @NotNull - private JetToken getOperationToken() { - JetSimpleNameExpression operationExpression = expression.getOperationSign(); + protected JetToken getOperationToken() { + JetSimpleNameExpression operationExpression = expression.getOperation(); IElementType elementType = operationExpression.getReferencedNameElementType(); assert elementType instanceof JetToken : "Unary expression should have IElementType of type JetToken"; return (JetToken) elementType; } - public JsBinaryOperation unaryAsBinary(@NotNull JetToken token, @NotNull JsExpression expression) { - JsNumberLiteral oneLiteral = context().program().getNumberLiteral(1); - if (token.equals(JetTokens.PLUSPLUS)) { - return new JsBinaryOperation(JsBinaryOperator.ADD, expression, oneLiteral); - } - if (token.equals(JetTokens.MINUSMINUS)) { - return new JsBinaryOperation(JsBinaryOperator.SUB, expression, oneLiteral); - } - throw new AssertionError("This method should be called only for increment and decrement operators"); + private boolean isPrefix(JetUnaryExpression expression) { + return (expression instanceof JetPrefixExpression); } + + } diff --git a/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java new file mode 100644 index 00000000000..373a4fa2e4c --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/reference/CallTranslator.java @@ -0,0 +1,137 @@ +package org.jetbrains.k2js.translate.reference; + +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.JsNew; +import com.google.dart.compiler.util.AstUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.psi.*; +import org.jetbrains.k2js.translate.general.AbstractTranslator; +import org.jetbrains.k2js.translate.general.TranslationContext; +import org.jetbrains.k2js.translate.intrinsic.Intrinsic; +import org.jetbrains.k2js.translate.utils.TranslationUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.jetbrains.k2js.translate.utils.BindingUtils.getDescriptorForReferenceExpression; +import static org.jetbrains.k2js.translate.utils.BindingUtils.getFunctionDescriptorForCallExpression; +import static org.jetbrains.k2js.translate.utils.TranslationUtils.*; + +/** + * @author Talanov Pavel + */ +public final class CallTranslator extends AbstractTranslator { + + public static boolean isFunctionCall(@NotNull JetOperationExpression expression, + @NotNull TranslationContext context) { + DeclarationDescriptor descriptor = getDescriptorForReferenceExpression + (context.bindingContext(), expression.getOperation()); + return (descriptor instanceof FunctionDescriptor); + } + + public static JsExpression translate(@NotNull JetUnaryExpression unaryExpression, + @NotNull TranslationContext context) { + JsExpression receiver = TranslationUtils.translateBaseExpression(context, unaryExpression); + List arguments = Collections.emptyList(); + DeclarationDescriptor descriptor = getDescriptorForReferenceExpression + (context.bindingContext(), unaryExpression.getOperation()); + assert descriptor instanceof FunctionDescriptor; + return (new CallTranslator(receiver, arguments, (FunctionDescriptor) descriptor, context)).translate(); + } + + public static JsExpression translate(@NotNull JetDotQualifiedExpression dotExpression, + @NotNull TranslationContext context) { + //TODO: look for duplication + JsExpression receiver = translateReceiver(context, dotExpression); + JetExpression selectorExpression = dotExpression.getSelectorExpression(); + assert selectorExpression instanceof JetCallExpression; + JetCallExpression callExpression = (JetCallExpression) selectorExpression; + List arguments = + translateArgumentList(context, callExpression.getValueArguments()); + FunctionDescriptor descriptor = + getFunctionDescriptorForCallExpression(context.bindingContext(), callExpression); + return (new CallTranslator(receiver, arguments, descriptor, context)).translate(); + } + + public static JsExpression translate(@NotNull JetCallExpression callExpression, + @NotNull TranslationContext context) { + DeclarationDescriptor descriptor = + getFunctionDescriptorForCallExpression(context.bindingContext(), callExpression); + JsExpression receiver = ReferenceTranslator.getImplicitReceiver(descriptor, context); + List arguments = translateArgumentList(context, callExpression.getValueArguments()); + return (new CallTranslator(receiver, arguments, (FunctionDescriptor) descriptor, context)).translate(); + } + + public static JsExpression translate(@NotNull JetBinaryExpression binaryExpression, + @NotNull TranslationContext context) { + JsExpression receiver = translateLeftExpression(context, binaryExpression); + List arguments = Arrays.asList(translateRightExpression(context, binaryExpression)); + //TODO: use PSI util method to get operation reference + DeclarationDescriptor descriptor = getDescriptorForReferenceExpression + (context.bindingContext(), binaryExpression.getOperation()); + assert descriptor instanceof FunctionDescriptor; + return (new CallTranslator(receiver, arguments, (FunctionDescriptor) descriptor, context)).translate(); + } + + @Nullable + private final JsExpression receiver; + + @NotNull + private final List arguments; + + @NotNull + private final FunctionDescriptor descriptor; + + private CallTranslator(@Nullable JsExpression receiver, @NotNull List arguments, + @NotNull FunctionDescriptor descriptor, @NotNull TranslationContext context) { + super(context); + this.receiver = receiver; + this.arguments = arguments; + this.descriptor = descriptor; + } + + @NotNull + private JsExpression translate() { + if (context().intrinsics().hasDescriptor(descriptor)) { + Intrinsic intrinsic = context().intrinsics().getIntrinsic(descriptor); + assert receiver != null : "Functions that have intrinsic implementation should have a receiver."; + return intrinsic.apply(receiver, arguments, context()); + } + if (isConstructorDescriptor(descriptor)) { + return constructorCall(); + } + return AstUtil.newInvocation(qualifiedMethodReference(), arguments); + } + + @NotNull + private JsNameRef qualifiedMethodReference() { + JsName methodName = context().getNameForDescriptor(descriptor); + if (receiver != null) { + return AstUtil.qualified(methodName, receiver); + } + return methodName.makeRef(); + } + + @NotNull + private JsExpression constructorCall() { + JsNew constructorCall = new JsNew(qualifiedMethodReference()); + constructorCall.setArguments(arguments); + return constructorCall; + } + +// //TODO: delete? +// @NotNull +// private JsExpression translateCallee(@NotNull JetCallExpression expression) { +// JetExpression callee = expression.getCalleeExpression(); +// assert callee != null : "Call expression with no callee encountered!"; +// return Translation.translateAsExpression(callee, context); +// } + + +} diff --git a/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java index c4898b29a2f..57a2e5e4da1 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/PropertyAccessTranslator.java @@ -18,7 +18,6 @@ import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.utils.BindingUtils; import org.jetbrains.k2js.translate.utils.PsiUtils; -import org.jetbrains.k2js.translate.utils.TranslationUtils; /** * @author Talanov Pavel @@ -147,17 +146,6 @@ public final class PropertyAccessTranslator extends AbstractTranslator { return AstUtil.newInvocation(accessorReference); } - @NotNull - private JsExpression defaultQualifier() { - if (BindingUtils.isOwnedByClass(propertyDescriptor)) { - return TranslationUtils.getThisQualifier(context()); - } - assert BindingUtils.isOwnedByNamespace(propertyDescriptor) - : "Property can be a member of class or a namespace."; - //NOTE: qualifier for descriptor and it's accessor should be equal - return context().declarations().getQualifier(propertyDescriptor); - } - @NotNull public JsInvocation translateAsPropertySetterCall() { JsName setterName = getNotNullSetterName(); @@ -169,7 +157,9 @@ public final class PropertyAccessTranslator extends AbstractTranslator { if (qualifier != null) { return Translation.translateAsExpression(qualifier, context()); } - return defaultQualifier(); + JsExpression implicitReceiver = ReferenceTranslator.getImplicitReceiver(propertyDescriptor, context()); + assert implicitReceiver != null : "Property can only be a member of class or a namespace."; + return implicitReceiver; } diff --git a/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java index 9e0ecc8ca21..ecab77fc081 100644 --- a/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/reference/ReferenceTranslator.java @@ -2,11 +2,11 @@ package org.jetbrains.k2js.translate.reference; import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsName; +import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; -import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.k2js.translate.general.AbstractTranslator; import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.utils.BindingUtils; @@ -38,10 +38,9 @@ public class ReferenceTranslator extends AbstractTranslator { @NotNull //TODO: make this process simpler and clearer public JsExpression translateSimpleName() { - tryResolveAsPropertyAccess(); - tryResolveAsThisQualifiedExpression(); tryResolveAsAliasReference(); - tryResolveAsGlobalReference(); + tryResolveAsPropertyAccess(); + tryResolveAsImplicitlyQualifiedExpression(); tryResolveAsLocalReference(); if (result != null) { return result; @@ -49,7 +48,8 @@ public class ReferenceTranslator extends AbstractTranslator { throw new AssertionError("Undefined name in this scope: " + simpleName.getReferencedName()); } - private void tryResolveAsThisQualifiedExpression() { + //TODO: refactor + private void tryResolveAsImplicitlyQualifiedExpression() { if (alreadyResolved()) return; DeclarationDescriptor referencedDescriptor = @@ -59,24 +59,24 @@ public class ReferenceTranslator extends AbstractTranslator { if (!context().isDeclared(referencedDescriptor)) return; JsName referencedName = context().getNameForDescriptor(referencedDescriptor); + JsExpression implicitReceiver = getImplicitReceiver(referencedDescriptor, context()); - if (!requiresThisQualifier(simpleName, referencedName)) return; + if (implicitReceiver == null) return; - if (BindingUtils.isOwnedByClass(referencedDescriptor)) { - result = TranslationUtils.getThisQualifiedNameReference(context(), referencedName); - } - if (BindingUtils.isOwnedByNamespace(referencedDescriptor)) { - result = TranslationUtils.getQualifiedReference(context(), referencedDescriptor); - } + result = AstUtil.qualified(referencedName, implicitReceiver); } - private boolean requiresThisQualifier(@NotNull JetSimpleNameExpression expression, - @NotNull JsName referencedName) { + @Nullable + public static JsExpression getImplicitReceiver(@NotNull DeclarationDescriptor referencedDescriptor, + @NotNull TranslationContext context) { + if (!context.isDeclared(referencedDescriptor)) return null; - JsName name = context().enclosingScope().findExistingName(referencedName.getIdent()); - boolean isClassMember = context().classScope().ownsName(name); - boolean isBackingFieldAccess = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER; - return (isBackingFieldAccess || isClassMember); + if (BindingUtils.isOwnedByClass(referencedDescriptor)) { + return TranslationUtils.getThisQualifier(context); + } + if (!BindingUtils.isOwnedByNamespace(referencedDescriptor)) return null; + + return context.declarations().getQualifier(referencedDescriptor); } private void tryResolveAsAliasReference() { @@ -104,18 +104,6 @@ public class ReferenceTranslator extends AbstractTranslator { result = PropertyAccessTranslator.translateAsPropertyGetterCall(simpleName, context()); } - private void tryResolveAsGlobalReference() { - if (alreadyResolved()) return; - - DeclarationDescriptor referencedDescriptor = - BindingUtils.getDescriptorForReferenceExpression(context().bindingContext(), simpleName); - - if (referencedDescriptor == null) return; - if (!context().isDeclared(referencedDescriptor)) return; - - result = TranslationUtils.getQualifiedReference(context(), referencedDescriptor); - } - private void tryResolveAsLocalReference() { if (alreadyResolved()) return; diff --git a/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java b/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java index 5558eb50d6f..6081712fe6f 100644 --- a/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/utils/BindingUtils.java @@ -36,37 +36,37 @@ public final class BindingUtils { } @NotNull - static public ClassDescriptor getClassDescriptor(@NotNull BindingContext context, @NotNull JetClass declaration) { + public static ClassDescriptor getClassDescriptor(@NotNull BindingContext context, @NotNull JetClass declaration) { return getDescriptorForExpression(context, declaration, ClassDescriptor.class); } @NotNull - static public NamespaceDescriptor getNamespaceDescriptor(@NotNull BindingContext context, + public static NamespaceDescriptor getNamespaceDescriptor(@NotNull BindingContext context, @NotNull JetNamespace declaration) { return getDescriptorForExpression(context, declaration, NamespaceDescriptor.class); } @NotNull - static public FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context, + public static FunctionDescriptor getFunctionDescriptor(@NotNull BindingContext context, @NotNull JetNamedFunction declaration) { return getDescriptorForExpression(context, declaration, FunctionDescriptor.class); } @NotNull - static public PropertyAccessorDescriptor getPropertyAccessorDescriptor(@NotNull BindingContext context, + public static PropertyAccessorDescriptor getPropertyAccessorDescriptor(@NotNull BindingContext context, @NotNull JetPropertyAccessor declaration) { return getDescriptorForExpression(context, declaration, PropertyAccessorDescriptor.class); } @NotNull - static public PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context, + public static PropertyDescriptor getPropertyDescriptor(@NotNull BindingContext context, @NotNull JetProperty declaration) { return getDescriptorForExpression(context, declaration, PropertyDescriptor.class); } //TODO: possibly remove // @NotNull -// static public PropertySetterDescriptor getPropertySetterDescriptorForProperty(@NotNull BindingContext context, +// public static PropertySetterDescriptor getPropertySetterDescriptorForProperty(@NotNull BindingContext context, // @NotNull JetProperty property) { // PropertySetterDescriptor result = getPropertyDescriptor(context, property).getSetter(); // assert result != null : "Property should have a setter descriptor"; @@ -74,7 +74,7 @@ public final class BindingUtils { // } // // @NotNull -// static public PropertyGetterDescriptor getPropertyGetterDescriptorForProperty(@NotNull BindingContext context, +// public static PropertyGetterDescriptor getPropertyGetterDescriptorForProperty(@NotNull BindingContext context, // @NotNull JetProperty property) { // PropertyGetterDescriptor result = getPropertyDescriptor(context, property).getGetter(); // assert result != null : "Property should have a getter descriptor"; @@ -82,7 +82,7 @@ public final class BindingUtils { // } @NotNull - static public JetClass getClassForDescriptor(@NotNull BindingContext context, + public static JetClass getClassForDescriptor(@NotNull BindingContext context, @NotNull ClassDescriptor descriptor) { PsiElement result = context.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); assert result instanceof JetClass : "ClassDescriptor should have declaration of type JetClass"; @@ -91,7 +91,7 @@ public final class BindingUtils { //TODO: delete? @Nullable - static public JetDeclaration getDeclarationForDescriptor(@NotNull BindingContext context, + public static JetDeclaration getDeclarationForDescriptor(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) { PsiElement result = context.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); if (!(result instanceof JetDeclaration)) { @@ -101,14 +101,14 @@ public final class BindingUtils { } @NotNull - static public List getSuperclassDescriptors(@NotNull BindingContext context, + public static List getSuperclassDescriptors(@NotNull BindingContext context, @NotNull JetClass classDeclaration) { ClassDescriptor classDescriptor = getClassDescriptor(context, classDeclaration); return getSuperclassDescriptors(classDescriptor); } @NotNull - static public List getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) { + public static List getSuperclassDescriptors(@NotNull ClassDescriptor classDescriptor) { Collection superclassTypes = classDescriptor.getTypeConstructor().getSupertypes(); List superClassDescriptors = new ArrayList(); for (JetType type : superclassTypes) { @@ -121,7 +121,7 @@ public final class BindingUtils { } @NotNull - static public ClassDescriptor getClassDescriptorForType(@NotNull JetType type) { + public static ClassDescriptor getClassDescriptorForType(@NotNull JetType type) { DeclarationDescriptor superClassDescriptor = type.getConstructor().getDeclarationDescriptor(); assert superClassDescriptor instanceof ClassDescriptor @@ -129,19 +129,19 @@ public final class BindingUtils { return (ClassDescriptor) superClassDescriptor; } - static public boolean hasAncestorClass(@NotNull BindingContext context, @NotNull JetClass classDeclaration) { + public static boolean hasAncestorClass(@NotNull BindingContext context, @NotNull JetClass classDeclaration) { List superclassDescriptors = getSuperclassDescriptors(context, classDeclaration); return (findAncestorClass(superclassDescriptors) != null); } - static public boolean isStatement(@NotNull BindingContext context, @NotNull JetExpression expression) { + public static boolean isStatement(@NotNull BindingContext context, @NotNull JetExpression expression) { Boolean isStatement = context.get(BindingContext.STATEMENT, expression); assert isStatement != null : "Invalid behaviour of get(BindingContext.STATEMENT)"; return isStatement; } @NotNull - static public JetType getTypeByReference(@NotNull BindingContext context, + public static JetType getTypeByReference(@NotNull BindingContext context, @NotNull JetTypeReference typeReference) { JetType result = context.get(BindingContext.TYPE, typeReference); assert result != null : "TypeReference should reference a type"; @@ -149,19 +149,19 @@ public final class BindingUtils { } @NotNull - static public ClassDescriptor getClassDescriptorForTypeReference(@NotNull BindingContext context, + public static ClassDescriptor getClassDescriptorForTypeReference(@NotNull BindingContext context, @NotNull JetTypeReference typeReference) { return getClassDescriptorForType(getTypeByReference(context, typeReference)); } @Nullable - static public PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context, + public static PropertyDescriptor getPropertyDescriptorForConstructorParameter(@NotNull BindingContext context, @NotNull JetParameter parameter) { return context.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); } @Nullable - static public JetProperty getPropertyForDescriptor(@NotNull BindingContext context, + public static JetProperty getPropertyForDescriptor(@NotNull BindingContext context, @NotNull PropertyDescriptor property) { PsiElement result = context.get(BindingContext.DESCRIPTOR_TO_DECLARATION, property); if (!(result instanceof JetProperty)) { @@ -171,7 +171,7 @@ public final class BindingUtils { } @Nullable - static public DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context, + public static DeclarationDescriptor getDescriptorForReferenceExpression(@NotNull BindingContext context, @NotNull JetReferenceExpression reference) { return context.get(BindingContext.REFERENCE_TARGET, reference); } @@ -182,7 +182,7 @@ public final class BindingUtils { //TODO move unrelated utils to other class @Nullable - static public ClassDescriptor findAncestorClass(@NotNull List superclassDescriptors) { + public static ClassDescriptor findAncestorClass(@NotNull List superclassDescriptors) { for (ClassDescriptor descriptor : superclassDescriptors) { if (descriptor.getKind() == ClassKind.CLASS) { return descriptor; @@ -191,11 +191,11 @@ public final class BindingUtils { return null; } - static public boolean isOwnedByNamespace(@NotNull DeclarationDescriptor descriptor) { + public static boolean isOwnedByNamespace(@NotNull DeclarationDescriptor descriptor) { return (descriptor.getContainingDeclaration() instanceof NamespaceDescriptor); } - static public boolean isOwnedByClass(@NotNull DeclarationDescriptor descriptor) { + public static boolean isOwnedByClass(@NotNull DeclarationDescriptor descriptor) { return (descriptor.getContainingDeclaration() instanceof ClassDescriptor); } @@ -204,31 +204,44 @@ public final class BindingUtils { @Nullable public static PropertyDescriptor getPropertyDescriptorForSimpleName(@NotNull BindingContext context, @NotNull JetSimpleNameExpression expression) { - ResolvedCall resolvedCall = - BindingUtils.getResolvedCall(context, expression); - if (resolvedCall != null) { - DeclarationDescriptor descriptor = resolvedCall.getCandidateDescriptor(); - if (descriptor instanceof PropertyDescriptor) { - return (PropertyDescriptor) descriptor; - } - if (descriptor instanceof VariableAsFunctionDescriptor) { - VariableAsFunctionDescriptor functionVariable = (VariableAsFunctionDescriptor) descriptor; - VariableDescriptor variableDescriptor = functionVariable.getVariableDescriptor(); - if (variableDescriptor instanceof PropertyDescriptor) { - return (PropertyDescriptor) variableDescriptor; - } + ResolvedCall resolvedCall = BindingUtils.getResolvedCall(context, expression); + if (resolvedCall == null) return null; + + DeclarationDescriptor descriptor = resolvedCall.getCandidateDescriptor(); + if (descriptor instanceof PropertyDescriptor) { + return (PropertyDescriptor) descriptor; + } + if (descriptor instanceof VariableAsFunctionDescriptor) { + VariableAsFunctionDescriptor functionVariable = (VariableAsFunctionDescriptor) descriptor; + VariableDescriptor variableDescriptor = functionVariable.getVariableDescriptor(); + if (variableDescriptor instanceof PropertyDescriptor) { + return (PropertyDescriptor) variableDescriptor; } } return null; } @Nullable - static public ResolvedCall getResolvedCall(@NotNull BindingContext context, + public static ResolvedCall getResolvedCall(@NotNull BindingContext context, @NotNull JetExpression expression) { return (context.get(BindingContext.RESOLVED_CALL, expression)); } - static public boolean isVariableReassignment(@NotNull BindingContext context, @NotNull JetExpression expression) { + @NotNull + public static FunctionDescriptor getFunctionDescriptorForCallExpression(@NotNull BindingContext context, + @NotNull JetCallExpression expression) { + //TODO: move to PSI utils + JetExpression calleeExpression = expression.getCalleeExpression(); + assert calleeExpression != null; + ResolvedCall resolvedCall = getResolvedCall(context, calleeExpression); + //TODO + CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor(); + assert descriptor instanceof FunctionDescriptor : + "Callee expression must have resolved call with descriptor of type FunctionDescriptor"; + return (FunctionDescriptor) descriptor; + } + + public static boolean isVariableReassignment(@NotNull BindingContext context, @NotNull JetExpression expression) { Boolean result = context.get(BindingContext.VARIABLE_REASSIGNMENT, expression); assert result != null; return result; diff --git a/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java b/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java index ea0f02ec191..b051510d185 100644 --- a/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java @@ -4,12 +4,11 @@ import com.google.dart.compiler.backend.js.ast.*; import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; import org.jetbrains.k2js.translate.general.Translation; import org.jetbrains.k2js.translate.general.TranslationContext; @@ -43,8 +42,8 @@ public final class TranslationUtils { @NotNull - public static List translateArgumentList(@NotNull List jetArguments, - @NotNull TranslationContext context) { + public static List translateArgumentList(@NotNull TranslationContext context, + @NotNull List jetArguments) { List jsArguments = new ArrayList(); for (ValueArgument argument : jetArguments) { jsArguments.add(translateArgument(context, argument)); @@ -102,15 +101,8 @@ public final class TranslationUtils { return jsInitExpression; } - public static boolean isConstructorInvocation(@NotNull TranslationContext context, - @NotNull JetCallExpression expression) { - JetExpression calleeExpression = expression.getCalleeExpression(); - assert calleeExpression != null : "JetCallExpression should have not null callee"; - ResolvedCall resolvedCall = BindingUtils.getResolvedCall(context.bindingContext(), calleeExpression); - if (resolvedCall == null) { - return false; - } - CallableDescriptor descriptor = resolvedCall.getCandidateDescriptor(); + //TODO: move to descriptor UTILS + public static boolean isConstructorDescriptor(@NotNull FunctionDescriptor descriptor) { return (descriptor instanceof ConstructorDescriptor); } @@ -184,4 +176,42 @@ public final class TranslationUtils { return (context.intrinsics().hasDescriptor(descriptor)); } + + + @NotNull + public static JsExpression translateBaseExpression(@NotNull TranslationContext context, + @NotNull JetUnaryExpression expression) { + JetExpression baseExpression = getBaseExpression(expression); + return Translation.translateAsExpression(baseExpression, context); + } + + //TODO: move to psi utils + @NotNull + public static JetExpression getBaseExpression(@NotNull JetUnaryExpression expression) { + JetExpression baseExpression = expression.getBaseExpression(); + assert baseExpression != null : "Unary expression should have a base expression"; + return baseExpression; + } + + @NotNull + public static JsExpression translateReceiver(@NotNull TranslationContext context, + @NotNull JetDotQualifiedExpression expression) { + return Translation.translateAsExpression(expression.getReceiverExpression(), context); + } + + + @NotNull + public static JsExpression translateLeftExpression(@NotNull TranslationContext context, + @NotNull JetBinaryExpression expression) { + return Translation.translateAsExpression(expression.getLeft(), context); + } + + @NotNull + public static JsExpression translateRightExpression(@NotNull TranslationContext context, + @NotNull JetBinaryExpression expression) { + JetExpression rightExpression = expression.getRight(); + assert rightExpression != null : "Binary expression should have a right expression"; + return Translation.translateAsExpression(rightExpression, context); + } + }