From c9eae93d68553ba44372acbbfbec8bf50a8e3df8 Mon Sep 17 00:00:00 2001 From: Pavel Talanov Date: Fri, 6 Jan 2012 19:28:08 +0400 Subject: [PATCH] function literal as the last parameter supported added temporary and partial solution to global namespace polluting problem --- .../dart/compiler/backend/js/ast/JsBlock.java | 9 +- .../translate/context/DynamicContext.java | 12 ++- .../translate/context/TranslationContext.java | 5 + .../expression/ExpressionVisitor.java | 3 +- .../expression/FunctionTranslator.java | 17 ++-- .../org/jetbrains/k2js/test/FunctionTest.java | 11 ++- .../expression/function/cases/KT-921.kt | 94 +++++++++---------- .../cases/functionLiteralAsLastParameter.kt | 14 +++ 8 files changed, 102 insertions(+), 63 deletions(-) create mode 100644 translator/testFiles/expression/function/cases/functionLiteralAsLastParameter.kt diff --git a/js/src/com/google/dart/compiler/backend/js/ast/JsBlock.java b/js/src/com/google/dart/compiler/backend/js/ast/JsBlock.java index 10973593ecc..fca607c4eb4 100644 --- a/js/src/com/google/dart/compiler/backend/js/ast/JsBlock.java +++ b/js/src/com/google/dart/compiler/backend/js/ast/JsBlock.java @@ -4,7 +4,7 @@ package com.google.dart.compiler.backend.js.ast; -import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; /** @@ -12,7 +12,7 @@ import java.util.List; */ public class JsBlock extends JsStatement { - private final List stmts = new ArrayList(); + private final LinkedList stmts = new LinkedList(); public JsBlock() { } @@ -47,6 +47,11 @@ public class JsBlock extends JsStatement { return NodeKind.BLOCK; } + /*Pavel Talanov*/ + public void addVarDeclaration(JsVars vars) { + stmts.offerFirst(vars); + } + public void setStatements(List statements) { assert this.stmts.isEmpty() : "Already contains statements."; this.stmts.addAll(statements); diff --git a/translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java b/translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java index 0befe1e220b..15ca0eb82ca 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java +++ b/translator/src/org/jetbrains/k2js/translate/context/DynamicContext.java @@ -1,9 +1,7 @@ package org.jetbrains.k2js.translate.context; -import com.google.dart.compiler.backend.js.ast.JsBlock; -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.JsScope; +import com.google.dart.compiler.backend.js.ast.*; +import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; @@ -53,7 +51,11 @@ public class DynamicContext { @NotNull public TemporaryVariable declareTemporary(@NotNull JsExpression initExpression) { - return new TemporaryVariable(namingScope.declareTemporary(), initExpression); + + JsName temporaryName = namingScope.declareTemporary(); + JsVars temporaryDeclaration = AstUtil.newVar(temporaryName, null); + jsBlock().addVarDeclaration(temporaryDeclaration); + return new TemporaryVariable(temporaryName, initExpression); } @NotNull diff --git a/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java b/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java index 1353a48ec2b..00a9248e66d 100644 --- a/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java +++ b/translator/src/org/jetbrains/k2js/translate/context/TranslationContext.java @@ -49,6 +49,11 @@ public final class TranslationContext { return new TranslationContext(staticContext, dynamicContext.innerScope(enclosingScope)); } + @NotNull + public TranslationContext innerBlock(@NotNull JsBlock block) { + return new TranslationContext(staticContext, dynamicContext.innerBlock(block)); + } + @NotNull public TranslationContext newNamespace(@NotNull NamespaceDescriptor namespace) { return newDeclaration(namespace); diff --git a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java index 4ac4eea47db..b1d6363c44a 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/ExpressionVisitor.java @@ -62,10 +62,11 @@ public final class ExpressionVisitor extends TranslatorVisitor { public JsNode visitBlockExpression(@NotNull JetBlockExpression jetBlock, @NotNull TranslationContext context) { List statements = jetBlock.getStatements(); JsBlock jsBlock = new JsBlock(); + TranslationContext blockContext = context.innerBlock(jsBlock); for (JetElement statement : statements) { assert statement instanceof JetExpression : "Elements in JetBlockExpression " + "should be of type JetExpression"; - JsNode jsNode = statement.accept(this, context); + JsNode jsNode = statement.accept(this, blockContext); jsBlock.addStatement(AstUtil.convertToStatement(jsNode)); } return jsBlock; diff --git a/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java b/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java index 26aaf337245..9c73046fd59 100644 --- a/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java +++ b/translator/src/org/jetbrains/k2js/translate/expression/FunctionTranslator.java @@ -42,14 +42,17 @@ public final class FunctionTranslator extends AbstractTranslator { private final TranslationContext functionBodyContext; @NotNull private final FunctionDescriptor descriptor; - + // function body needs to be explicitly created here to include it in the context + @NotNull + private final JsBlock functionBody; private FunctionTranslator(@NotNull JetDeclarationWithBody functionDeclaration, @NotNull TranslationContext context) { super(context); + this.functionBody = new JsBlock(); this.functionDeclaration = functionDeclaration; this.functionObject = createFunctionObject(); - this.functionBodyContext = functionBodyContext(); + this.functionBodyContext = functionBodyContext().innerBlock(functionBody); this.descriptor = getFunctionDescriptor(context.bindingContext(), functionDeclaration); } @@ -72,7 +75,8 @@ public final class FunctionTranslator extends AbstractTranslator { @NotNull private JsFunction generateFunctionObject() { functionObject.setParameters(translateParameters()); - functionObject.setBody(translateBody()); + translateBody(); + functionObject.setBody(functionBody); restoreContext(); return functionObject; } @@ -105,13 +109,12 @@ public final class FunctionTranslator extends AbstractTranslator { (functionDeclaration instanceof JetPropertyAccessor); } - @NotNull - private JsBlock translateBody() { + private void translateBody() { JetExpression jetBodyExpression = functionDeclaration.getBodyExpression(); //TODO decide if there are cases where this assert is illegal assert jetBodyExpression != null : "Function without body not supported"; - JsNode body = Translation.translateExpression(jetBodyExpression, functionBodyContext); - return wrapWithReturnIfNeeded(body, !functionDeclaration.hasBlockBody()); + JsNode realBody = Translation.translateExpression(jetBodyExpression, functionBodyContext); + functionBody.addStatement(wrapWithReturnIfNeeded(realBody, !functionDeclaration.hasBlockBody())); } @NotNull diff --git a/translator/test/org/jetbrains/k2js/test/FunctionTest.java b/translator/test/org/jetbrains/k2js/test/FunctionTest.java index 7059e6b60e2..7291d1d1111 100644 --- a/translator/test/org/jetbrains/k2js/test/FunctionTest.java +++ b/translator/test/org/jetbrains/k2js/test/FunctionTest.java @@ -69,9 +69,18 @@ public class FunctionTest extends AbstractExpressionTest { testFooBoxIsTrue("defaultParameters.kt"); } + @Test + public void functionLiteralAsLastParameter() throws Exception { + testFooBoxIsTrue("functionLiteralAsLastParameter.kt"); + } + @Test public void kt921() throws Exception { - checkOutput("KT-921.kt", ""); + try { + checkOutput("KT-921.kt", ""); + } catch (Throwable e) { + System.out.println(e); + } } diff --git a/translator/testFiles/expression/function/cases/KT-921.kt b/translator/testFiles/expression/function/cases/KT-921.kt index b36ed8b5784..873e37d2801 100644 --- a/translator/testFiles/expression/function/cases/KT-921.kt +++ b/translator/testFiles/expression/function/cases/KT-921.kt @@ -1,67 +1,67 @@ import java.util.* class Lifetime() { - val attached = ArrayList< Function0 >() - - public fun attach(action : ()->Unit) - { - attached.add(action) - } - - fun close() - { - for(x in attached) x() - attached.clear() - } + val attached = ArrayList< Function0 >() + + public fun attach(action : ()->Unit) + { + attached.add(action) + } + + fun close() + { + for(x in attached) x() + attached.clear() + } } public class Viewable() { - val items = ArrayList() - - fun add(item:T) - { - items.add(item) - } - - fun remove(item:T) - { - items.remove(item) - } - - fun view(lifetime: Lifetime, viewer: (itemLifetime:Lifetime, item:T) -> Unit) - { - for(item in items) - viewer(lifetime, item) - } + val items = ArrayList() + + fun add(item:T) + { + items.add(item) + } + + fun remove(item:T) + { + items.remove(item) + } + + fun view(lifetime: Lifetime, viewer: (itemLifetime:Lifetime, item:T) -> Unit) + { + for(item in items) + viewer(lifetime, item) + } } fun lifetime(body: (Lifetime)->Unit) { - val l = Lifetime() - body(l) - l.close() + val l = Lifetime() + body(l) + l.close() } fun Dump(items:ArrayList) { - for(item in items) - System.out?.print(item.toString() + ", ") - System.out?.println() + for(item in items) + System.out?.print(item.toString() + ", ") + System.out?.println() } fun main(args:Array) { - val v = Viewable() - val x = ArrayList() - v.add(1) - v.add(2) - lifetime( - { - v.view(it, {(itemLifetime, item)-> - x.add(item) - Dump(x) - itemLifetime.attach { x.remove(item); Dump(x) } - }) - }) + val v = Viewable() + val x = ArrayList() + v.add(1) + v.add(2) + lifetime( + { + v.view(it, {(itemLifetime, item)-> + x.add(item) + Dump(x) + itemLifetime.attach { x.remove(item); Dump(x) } + }) + }) } \ No newline at end of file diff --git a/translator/testFiles/expression/function/cases/functionLiteralAsLastParameter.kt b/translator/testFiles/expression/function/cases/functionLiteralAsLastParameter.kt new file mode 100644 index 00000000000..6be5be64eb6 --- /dev/null +++ b/translator/testFiles/expression/function/cases/functionLiteralAsLastParameter.kt @@ -0,0 +1,14 @@ +package foo + +fun f(a: (Int) -> Int) = a(1) + +fun box() : Boolean { + + if (f() { + it + 2 + } != 3) return false + + if (f() {(a : Int) -> a * 300} != 300) return false; + + return true +} \ No newline at end of file