JS backend: translate labeled for expressions.

#KT-2986 fixed

(cherry picked from commit b0836a6)
This commit is contained in:
develar
2012-10-23 19:08:47 +04:00
committed by Zalim Bashorov
parent 764b5c5a90
commit 67592829b6
11 changed files with 78 additions and 72 deletions
@@ -29,4 +29,8 @@ public final class ForeachTest extends AbstractExpressionTest {
public void testForOnEmptyArray() throws Exception {
fooBoxTest();
}
public void testLabeledFor() throws Exception {
fooBoxTest();
}
}
Binary file not shown.
Binary file not shown.
@@ -17,6 +17,7 @@
package org.jetbrains.k2js.translate.expression;
import com.google.dart.compiler.backend.js.ast.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
@@ -291,9 +292,21 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
@Override
@NotNull
public JsNode visitPrefixExpression(@NotNull JetPrefixExpression expression,
@NotNull TranslationContext context) {
return UnaryOperationTranslator.translate(expression, context);
public JsNode visitPrefixExpression(
@NotNull JetPrefixExpression expression,
@NotNull TranslationContext context
) {
JetSimpleNameExpression operationReference = expression.getOperationReference();
IElementType operationToken = operationReference.getReferencedNameElementType();
if (JetTokens.LABELS.contains(operationToken)) {
JetExpression baseExpression = expression.getBaseExpression();
assert baseExpression != null;
return source(new JsLabel(context.scope().declareName(getReferencedName(operationReference)),
convertToStatement(baseExpression.accept(this, context))), expression);
}
else {
return UnaryOperationTranslator.translate(expression, context);
}
}
@Override
@@ -343,18 +356,35 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
return TranslationUtils.sure(jsExpression, context);
}
private static String getReferencedName(JetSimpleNameExpression expression) {
String name = expression.getReferencedName();
return name.charAt(0) == '@' ? name.substring(1) + '$' : name;
}
private static String getTargetLabel(JetLabelQualifiedExpression expression, TranslationContext context) {
JetSimpleNameExpression labelElement = expression.getTargetLabel();
if (labelElement == null) {
return null;
}
else {
JsName name = context.scope().findName(getReferencedName(labelElement));
assert name != null;
return name.getIdent();
}
}
@Override
@NotNull
public JsNode visitBreakExpression(@NotNull JetBreakExpression expression,
@NotNull TranslationContext context) {
return new JsBreak();
return new JsBreak(getTargetLabel(expression, context));
}
@Override
@NotNull
public JsNode visitContinueExpression(@NotNull JetContinueExpression expression,
@NotNull TranslationContext context) {
return new JsContinue();
return new JsContinue(getTargetLabel(expression, context));
}
@Override
@@ -46,7 +46,6 @@ import org.jetbrains.k2js.translate.utils.dangerous.DangerousData;
import org.jetbrains.k2js.translate.utils.dangerous.DangerousTranslator;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.plugin.JetMainDetector.getMainFunction;
@@ -175,23 +174,10 @@ public final class Translation {
if (mainFunction == null) {
return null;
}
JsInvocation translatedCall = generateInvocation(context, mainFunction);
setArguments(context, arguments, translatedCall);
return translatedCall.makeStmt();
}
@NotNull
private static JsInvocation generateInvocation(@NotNull TranslationContext context, @NotNull JetNamedFunction mainFunction) {
FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), mainFunction);
JsExpression translatedCall = CallBuilder.build(context).descriptor(functionDescriptor).translate();
assert translatedCall instanceof JsInvocation;
return (JsInvocation) translatedCall;
}
private static void setArguments(@NotNull TranslationContext context, @NotNull List<String> arguments,
@NotNull JsInvocation translatedCall) {
JsArrayLiteral arrayLiteral = new JsArrayLiteral(toStringLiteralList(arguments, context.program()));
JsAstUtils.setArguments(translatedCall, Collections.<JsExpression>singletonList(arrayLiteral));
return CallBuilder.build(context)
.args(new JsArrayLiteral(toStringLiteralList(arguments, context.program())))
.descriptor(functionDescriptor)
.translate().makeStmt();
}
}
@@ -21,6 +21,7 @@ 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 com.google.dart.compiler.util.AstUtil;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
@@ -41,8 +42,9 @@ import static org.jetbrains.k2js.translate.utils.TranslationUtils.hasCorrespondi
// TODO: provide better increment translator logic
public abstract class IncrementTranslator extends AbstractTranslator {
public static boolean isIncrement(@NotNull JetUnaryExpression expression) {
return OperatorConventions.INCREMENT_OPERATIONS.contains(getOperationToken(expression));
public static boolean isIncrement(IElementType operationToken) {
//noinspection SuspiciousMethodCalls
return OperatorConventions.INCREMENT_OPERATIONS.contains(operationToken);
}
@NotNull
@@ -18,16 +18,14 @@ package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetUnaryExpression;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.k2js.translate.context.TranslationContext;
import org.jetbrains.k2js.translate.reference.CallBuilder;
import org.jetbrains.k2js.translate.reference.CallType;
import org.jetbrains.k2js.translate.utils.TranslationUtils;
import java.util.Collections;
import static org.jetbrains.k2js.translate.general.Translation.translateAsExpression;
import static org.jetbrains.k2js.translate.utils.BindingUtils.getResolvedCall;
import static org.jetbrains.k2js.translate.utils.PsiUtils.getBaseExpression;
@@ -41,12 +39,15 @@ public final class UnaryOperationTranslator {
}
@NotNull
public static JsExpression translate(@NotNull JetUnaryExpression expression,
@NotNull TranslationContext context) {
if (isExclExcl(expression)) {
return translateExclExclOperator(expression, context);
public static JsExpression translate(
@NotNull JetUnaryExpression expression,
@NotNull TranslationContext context
) {
IElementType operationToken = expression.getOperationReference().getReferencedNameElementType();
if (operationToken == JetTokens.EXCLEXCL) {
return sure(translateAsExpression(getBaseExpression(expression), context), context);
}
if (IncrementTranslator.isIncrement(expression)) {
if (IncrementTranslator.isIncrement(operationToken)) {
return IncrementTranslator.translate(expression, context);
}
@@ -54,16 +55,11 @@ public final class UnaryOperationTranslator {
if (isExclForBinaryEqualLikeExpr(expression, baseExpression)) {
return translateExclForBinaryEqualLikeExpr((JsBinaryOperation) baseExpression);
}
return translateAsCall(expression, context, baseExpression);
}
private static boolean isExclExcl(@NotNull JetUnaryExpression expression) {
return getOperationToken(expression).equals(JetTokens.EXCLEXCL);
}
@NotNull
private static JsExpression translateExclExclOperator(@NotNull JetUnaryExpression expression, @NotNull TranslationContext context) {
return sure(translateAsExpression(getBaseExpression(expression), context), context);
return CallBuilder.build(context)
.receiver(TranslationUtils.translateBaseExpression(context, expression))
.resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference()))
.translate();
}
private static boolean isExclForBinaryEqualLikeExpr(@NotNull JetUnaryExpression expression, @NotNull JsExpression baseExpression) {
@@ -74,15 +70,4 @@ public final class UnaryOperationTranslator {
}
return false;
}
@NotNull
private static JsExpression translateAsCall(@NotNull JetUnaryExpression expression,
@NotNull TranslationContext context,
@NotNull JsExpression baseExpression) {
return CallBuilder.build(context)
.receiver(baseExpression)
.args(Collections.<JsExpression>emptyList())
.resolvedCall(getResolvedCall(context.bindingContext(), expression.getOperationReference()))
.type(CallType.NORMAL).translate();
}
}
@@ -16,7 +16,6 @@
package org.jetbrains.k2js.translate.reference;
import com.google.common.collect.Lists;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,6 +33,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.k2js.translate.context.TranslationContext;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public final class CallBuilder {
@@ -47,7 +47,7 @@ public final class CallBuilder {
@Nullable
private /*var*/ JsExpression receiver = null;
@NotNull
private final List<JsExpression> args = Lists.newArrayList();
private List<JsExpression> args = Collections.emptyList();
@NotNull
private /*var*/ CallType callType = CallType.NORMAL;
@Nullable
@@ -70,8 +70,8 @@ public final class CallBuilder {
@NotNull
public CallBuilder args(@NotNull List<JsExpression> args) {
assert this.args.isEmpty();
this.args.addAll(args);
assert this.args == Collections.EMPTY_LIST;
this.args = args;
return this;
}
@@ -165,12 +165,6 @@ public final class JsAstUtils {
return new JsVars(new JsVars.JsVar(name, expr));
}
public static void setArguments(@NotNull JsInvocation invocation, @NotNull List<JsExpression> newArgs) {
List<JsExpression> arguments = invocation.getArguments();
assert arguments.isEmpty() : "Arguments already set.";
arguments.addAll(newArgs);
}
public static void setArguments(@NotNull HasArguments invocation, @NotNull List<JsExpression> newArgs) {
List<JsExpression> arguments = invocation.getArguments();
assert arguments.isEmpty() : "Arguments already set.";
@@ -16,7 +16,6 @@
package org.jetbrains.k2js.translate.utils;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -121,14 +120,6 @@ public final class PsiUtils {
return Collections.emptyList();
}
@NotNull
public static JetObjectDeclaration getObjectDeclarationForName(@NotNull JetObjectDeclarationName name) {
PsiElement parent = name.getParent();
assert parent instanceof JetObjectDeclaration :
"ObjectDeclarationName should have a parent of type ObjectDeclaration.";
return (JetObjectDeclaration) parent;
}
@NotNull
public static JetObjectDeclarationName getObjectDeclarationName(@NotNull JetObjectDeclaration objectDeclaration) {
//TODO: util
@@ -0,0 +1,14 @@
package foo
val a1 = arrayOfNulls<Int>(0)
fun box(): Boolean {
var bar = 33
@outer for (a in array(1, 2)) {
for (b in array(1, 4)) {
break @outer
}
bar = 42
}
return bar == 33;
}