From b77133bd59c715701b4e6448162524ffdee753f2 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Wed, 30 Nov 2011 19:59:42 +0400 Subject: [PATCH] supported array access expressions. --- .../expression/ExpressionVisitor.java | 12 +- .../operation/BinaryOperationTranslator.java | 4 + .../reference/ArrayAccessTranslator.java | 106 ++++++++++++++++++ .../translate/utils/TranslationUtils.java | 10 ++ .../k2js/test/StandardClassesTest.java | 5 + translator/testFiles/kotlin_lib.js | 4 +- .../standardClasses/cases/arrayAccess.kt | 8 ++ 7 files changed, 144 insertions(+), 5 deletions(-) create mode 100644 translator/src/org/jetbrains/k2js/translate/reference/ArrayAccessTranslator.java create mode 100644 translator/testFiles/standardClasses/cases/arrayAccess.kt diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index e7b2fc45ae5..af065100aae 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -13,6 +13,7 @@ import org.jetbrains.k2js.translate.general.TranslationContext; import org.jetbrains.k2js.translate.general.TranslatorVisitor; import org.jetbrains.k2js.translate.operation.BinaryOperationTranslator; import org.jetbrains.k2js.translate.operation.UnaryOperationTranslator; +import org.jetbrains.k2js.translate.reference.ArrayAccessTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; import org.jetbrains.k2js.translate.reference.ReferenceTranslator; import org.jetbrains.k2js.translate.utils.BindingUtils; @@ -189,9 +190,7 @@ public final class ExpressionVisitor extends TranslatorVisitor { private JsExpression translateConditionExpression(@Nullable JetExpression expression, @NotNull TranslationContext context) { JsExpression jsCondition = translateNullableExpression(expression, context); - if (jsCondition == null) { - throw new AssertionError("Empty condition!"); - } + assert (jsCondition != null) : "Condition should not be empty"; return AstUtil.convertToExpression(jsCondition); } @@ -385,5 +384,12 @@ public final class ExpressionVisitor extends TranslatorVisitor { return new JsThisRef(); } + @Override + @NotNull + public JsInvocation visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression, + @NotNull TranslationContext context) { + return ArrayAccessTranslator.translateAsArrayGetterCall(expression, context); + } + } diff --git a/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java b/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java index ce5d47b9208..b5b7995ca98 100644 --- a/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/operation/BinaryOperationTranslator.java @@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.types.expressions.OperatorConventions; 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.ArrayAccessTranslator; import org.jetbrains.k2js.translate.reference.PropertyAccessTranslator; /** @@ -48,6 +49,9 @@ public final class BinaryOperationTranslator extends OperationTranslator { @NotNull JsExpression translate() { + if (ArrayAccessTranslator.canBeArraySetterCall(expression)) { + return ArrayAccessTranslator.translateAsArraySetterCall(expression, context()); + } if (isCompareTo()) { return asCompareToOverload(); } diff --git a/translator/src/org/jetbrains/k2js/translate/reference/ArrayAccessTranslator.java b/translator/src/org/jetbrains/k2js/translate/reference/ArrayAccessTranslator.java new file mode 100644 index 00000000000..f25909a4b08 --- /dev/null +++ b/translator/src/org/jetbrains/k2js/translate/reference/ArrayAccessTranslator.java @@ -0,0 +1,106 @@ +package org.jetbrains.k2js.translate.reference; + +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 org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetArrayAccessExpression; +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.AbstractTranslator; +import org.jetbrains.k2js.translate.general.Translation; +import org.jetbrains.k2js.translate.general.TranslationContext; +import org.jetbrains.k2js.translate.operation.OperatorTable; +import org.jetbrains.k2js.translate.utils.BindingUtils; +import org.jetbrains.k2js.translate.utils.TranslationUtils; + +import java.util.List; + +/** + * @author Talanov Pavel + */ +public final class ArrayAccessTranslator extends AbstractTranslator { + + + public static boolean canBeArraySetterCall(@NotNull JetBinaryExpression expression) { + //TODO: move unsafe cat to util + return (OperatorTable.isAssignment((JetToken) expression.getOperationToken()) + && (expression.getLeft() instanceof JetArrayAccessExpression)); + } + + public static JsInvocation translateAsArrayGetterCall(@NotNull JetArrayAccessExpression expression, + @NotNull TranslationContext context) { + return (new ArrayAccessTranslator(expression, null, context)).translateAsArrayGet(); + } + + public static JsInvocation translateAsArraySetterCall(@NotNull JetBinaryExpression expression, + @NotNull TranslationContext context) { + JetExpression arrayAccess = expression.getLeft(); + assert (arrayAccess instanceof JetArrayAccessExpression) : "Check with canBeArraySetterCall"; + JetExpression right = expression.getRight(); + assert right != null : "Binary expression should have a right expression"; + JsExpression expressionToSetTo = Translation.translateAsExpression(right, context); + return (new ArrayAccessTranslator((JetArrayAccessExpression) arrayAccess, expressionToSetTo, context)) + .translateAsArraySet(); + } + + @NotNull + private final JetArrayAccessExpression expression; + @NotNull + private final DeclarationDescriptor methodDescriptor; + @Nullable + private final JsExpression expressionToSetTo; + + + private ArrayAccessTranslator(@NotNull JetArrayAccessExpression expression, + @Nullable JsExpression expressionToSetTo, + @NotNull TranslationContext context) { + super(context); + this.expression = expression; + DeclarationDescriptor descriptorForReferenceExpression = + BindingUtils.getDescriptorForReferenceExpression(context.bindingContext(), expression); + assert descriptorForReferenceExpression != null : "Array access expression must reference a descriptor"; + this.methodDescriptor = descriptorForReferenceExpression; + this.expressionToSetTo = expressionToSetTo; + } + + @NotNull + private JsInvocation translateAsArrayGet() { + return translateAsArrayAccessWithIndices(); + } + + private JsInvocation translateAsArrayAccessWithIndices() { + JsNameRef accessMethodReference = getAccessMethodReference(); + AstUtil.setQualifier(accessMethodReference, translateArrayExpression()); + return AstUtil.newInvocation(accessMethodReference, translateIndexExpressions()); + } + + @NotNull + private JsInvocation translateAsArraySet() { + assert expressionToSetTo != null; + JsInvocation setCall = translateAsArrayAccessWithIndices(); + setCall.getArguments().add(expressionToSetTo); + return setCall; + } + + @NotNull + private List translateIndexExpressions() { + return TranslationUtils.translateExpressionList(context(), expression.getIndexExpressions()); + } + + @NotNull + private JsNameRef getAccessMethodReference() { + return context().getNameForDescriptor(methodDescriptor).makeRef(); + } + + @NotNull + private JsExpression translateArrayExpression() { + return Translation.translateAsExpression(expression.getArrayExpression(), context()); + } + + +} diff --git a/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java b/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java index 382bbf25990..82400108828 100644 --- a/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java +++ b/translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java @@ -167,4 +167,14 @@ public final class TranslationUtils { } return qualifier; } + + @NotNull + public static List translateExpressionList(@NotNull TranslationContext context, + @NotNull List expressions) { + List result = new ArrayList(); + for (JetExpression expression : expressions) { + result.add(Translation.translateAsExpression(expression, context)); + } + return result; + } } diff --git a/translator/test/org/jetbrains/k2js/test/StandardClassesTest.java b/translator/test/org/jetbrains/k2js/test/StandardClassesTest.java index 6ac28bbcfd9..0a1f87203c6 100644 --- a/translator/test/org/jetbrains/k2js/test/StandardClassesTest.java +++ b/translator/test/org/jetbrains/k2js/test/StandardClassesTest.java @@ -17,4 +17,9 @@ public class StandardClassesTest extends TranslationTest { public void array() throws Exception { testFooBoxIsTrue("array.kt"); } + + @Test + public void arrayAccess() throws Exception { + testFooBoxIsTrue("arrayAccess.kt"); + } } diff --git a/translator/testFiles/kotlin_lib.js b/translator/testFiles/kotlin_lib.js index ed0bf3a6f24..9872777595c 100644 --- a/translator/testFiles/kotlin_lib.js +++ b/translator/testFiles/kotlin_lib.js @@ -452,10 +452,10 @@ Kotlin.Array = Class.create({ this.array = []; }, get:function (index) { - return this.array[index]; + return (this.array)[index]; }, set:function (index, value) { - this.array[index] = value; + (this.array)[index] = value; } }) diff --git a/translator/testFiles/standardClasses/cases/arrayAccess.kt b/translator/testFiles/standardClasses/cases/arrayAccess.kt new file mode 100644 index 00000000000..cfa5fe20750 --- /dev/null +++ b/translator/testFiles/standardClasses/cases/arrayAccess.kt @@ -0,0 +1,8 @@ +namespace foo + +fun box() : Boolean { + val a = Array(4) + a[1] = 2 + a[2] = 3 + return a.get(1) == 2 +} \ No newline at end of file