function literal as the last parameter supported

added temporary and partial solution to global namespace polluting problem
This commit is contained in:
Pavel Talanov
2012-01-06 19:28:08 +04:00
parent f52f568a51
commit c9eae93d68
8 changed files with 102 additions and 63 deletions
@@ -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<JsStatement> stmts = new ArrayList<JsStatement>();
private final LinkedList<JsStatement> stmts = new LinkedList<JsStatement>();
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<JsStatement> statements) {
assert this.stmts.isEmpty() : "Already contains statements.";
this.stmts.addAll(statements);
@@ -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
@@ -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);
@@ -62,10 +62,11 @@ public final class ExpressionVisitor extends TranslatorVisitor<JsNode> {
public JsNode visitBlockExpression(@NotNull JetBlockExpression jetBlock, @NotNull TranslationContext context) {
List<JetElement> 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;
@@ -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
@@ -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);
}
}
@@ -1,67 +1,67 @@
import java.util.*
class Lifetime() {
val attached = ArrayList< Function0<Unit> >()
public fun attach(action : ()->Unit)
{
attached.add(action)
}
fun close()
{
for(x in attached) x()
attached.clear()
}
val attached = ArrayList< Function0<Unit> >()
public fun attach(action : ()->Unit)
{
attached.add(action)
}
fun close()
{
for(x in attached) x()
attached.clear()
}
}
public class Viewable<T>()
{
val items = ArrayList<T>()
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<T>()
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<T> Dump(items:ArrayList<T>)
{
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<String>)
{
val v = Viewable<Int>()
val x = ArrayList<Int>()
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<Int>()
val x = ArrayList<Int>()
v.add(1)
v.add(2)
lifetime(
{
v.view(it, {(itemLifetime, item)->
x.add(item)
Dump(x)
itemLifetime.attach { x.remove(item); Dump(x) }
})
})
}
@@ -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
}