diff --git a/.idea/workspace.xml b/.idea/workspace.xml index abe72c4fbe2..a7593997c22 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -6,41 +6,18 @@ - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - + + @@ -65,7 +42,20 @@ - + + + - + - + - + @@ -132,37 +122,37 @@ - - + + - + - - + + - + - - + + - + - - + + - + @@ -217,91 +207,91 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -323,22 +313,22 @@ @@ -594,63 +584,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -723,6 +663,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + localhost @@ -848,7 +844,7 @@ - + @@ -915,23 +911,16 @@ - + - + - + - - - - - - - - + @@ -943,41 +932,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -985,46 +939,88 @@ - + - + - + - + - + - + + + + + + + + + + + + + + + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/js.jar b/lib/js.jar new file mode 100644 index 00000000000..878b0d9422b Binary files /dev/null and b/lib/js.jar differ diff --git a/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsCatchScope.class b/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsCatchScope.class index 79d916026f2..8b43745bbbe 100644 Binary files a/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsCatchScope.class and b/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsCatchScope.class differ diff --git a/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsRootScope.class b/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsRootScope.class index 9d7aa936a36..8e7c8221ab3 100644 Binary files a/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsRootScope.class and b/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsRootScope.class differ diff --git a/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsScope.class b/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsScope.class index eac974f40c4..57c3e51710f 100644 Binary files a/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsScope.class and b/out/production/k2js/com/google/dart/compiler/backend/js/ast/JsScope.class differ diff --git a/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$FunctionVariableDeclaration.class b/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$FunctionVariableDeclaration.class index 7b64b371e27..a981cf1ce32 100644 Binary files a/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$FunctionVariableDeclaration.class and b/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$FunctionVariableDeclaration.class differ diff --git a/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$NamespacePropertyDeclaration.class b/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$NamespacePropertyDeclaration.class index b31289d3086..c01e6d1e8b3 100644 Binary files a/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$NamespacePropertyDeclaration.class and b/out/production/k2js/org/jetbrains/k2js/translate/DeclarationTranslator$NamespacePropertyDeclaration.class differ diff --git a/out/production/k2js/org/jetbrains/k2js/translate/FunctionTranslator.class b/out/production/k2js/org/jetbrains/k2js/translate/FunctionTranslator.class index d6aea207751..c22493230f7 100644 Binary files a/out/production/k2js/org/jetbrains/k2js/translate/FunctionTranslator.class and b/out/production/k2js/org/jetbrains/k2js/translate/FunctionTranslator.class differ diff --git a/out/production/k2js/org/jetbrains/k2js/translate/TranslationContext.class b/out/production/k2js/org/jetbrains/k2js/translate/TranslationContext.class index cab077100a6..b00a0789714 100644 Binary files a/out/production/k2js/org/jetbrains/k2js/translate/TranslationContext.class and b/out/production/k2js/org/jetbrains/k2js/translate/TranslationContext.class differ diff --git a/src/com/google/dart/compiler/backend/js/ast/JsCatchScope.java b/src/com/google/dart/compiler/backend/js/ast/JsCatchScope.java index 6c9ce22a0e8..5e5a2f2f577 100644 --- a/src/com/google/dart/compiler/backend/js/ast/JsCatchScope.java +++ b/src/com/google/dart/compiler/backend/js/ast/JsCatchScope.java @@ -65,7 +65,7 @@ public class JsCatchScope extends JsScope { } @Override - protected JsName findExistingNameNoRecurse(String ident) { + public JsName findExistingNameNoRecurse(String ident) { if (name.getIdent().equals(ident)) { return name; } else { diff --git a/src/com/google/dart/compiler/backend/js/ast/JsRootScope.java b/src/com/google/dart/compiler/backend/js/ast/JsRootScope.java index 25c50b2c9ad..33b71f26222 100644 --- a/src/com/google/dart/compiler/backend/js/ast/JsRootScope.java +++ b/src/com/google/dart/compiler/backend/js/ast/JsRootScope.java @@ -33,7 +33,7 @@ public final class JsRootScope extends JsScope { } @Override - protected JsName findExistingNameNoRecurse(String ident) { + public JsName findExistingNameNoRecurse(String ident) { JsName name = super.findExistingNameNoRecurse(ident); if (name == null) { if (JsReservedIdentifiers.getReservedGlobalSymbols().contains(ident)) { diff --git a/src/com/google/dart/compiler/backend/js/ast/JsScope.java b/src/com/google/dart/compiler/backend/js/ast/JsScope.java index 178f85e51f6..e5f0578fb49 100644 --- a/src/com/google/dart/compiler/backend/js/ast/JsScope.java +++ b/src/com/google/dart/compiler/backend/js/ast/JsScope.java @@ -18,18 +18,18 @@ import java.util.Map; * {@link com.google.dart.compiler.backend.js.ast.JsName}s. A JavaScript AST is * built in terms of abstract name objects without worrying about obfuscation, * keyword/identifier blacklisting, and so on. - * - *

- * + *

+ *

+ *

* Scopes are associated with * {@link com.google.dart.compiler.backend.js.ast.JsFunction}s, but the two are * not equivalent. Functions have scopes, but a scope does not * necessarily have an associated Function. Examples of this include the * {@link com.google.dart.compiler.backend.js.ast.JsRootScope} and synthetic * scopes that might be created by a client. - * - *

- * + *

+ *

+ *

* Scopes can have parents to provide constraints when allocating actual * identifiers for names. Specifically, names in child scopes are chosen such * that they do not conflict with names in their parent scopes. The ultimate @@ -41,258 +41,260 @@ import java.util.Map; */ public class JsScope implements Serializable { - private List children = Collections.emptyList(); - private final String description; - private Map names = Collections.emptyMap(); - private JsScope parent; - protected int tempIndex = 0; - private final String scopeId; + private List children = Collections.emptyList(); + private final String description; + private Map names = Collections.emptyMap(); + private JsScope parent; + protected int tempIndex = 0; + private final String scopeId; - /* - * Create a scope with parent. - */ - public JsScope(JsScope parent, String description) { - this(parent, description, null); - } - - /** - * Create a scope with parent. - */ - public JsScope(JsScope parent, String description, String scopeId) { - assert (parent != null); - this.scopeId = scopeId; - this.description = description; - this.parent = parent; - parent.children = Lists.add(parent.children, this); - } - - /** - * Rebase the function to a new scope. - * @param newParent The scope to add the function to. - */ - public void rebase(JsScope newParent) { - detachFromParent(); - parent = newParent; - parent.children = Lists.add(parent.children, this); - } - - /** - * Rebase the function's children to a new scope. - * @param newParent - */ - public void rebaseChildScopes(JsScope newParent) { - if (newParent == this) { - return; + /* + * Create a scope with parent. + */ + public JsScope(JsScope parent, String description) { + this(parent, description, null); } - parent.children = Lists.addAll(parent.children, children); - for (JsScope child : children) { - child.parent = newParent; + + /** + * Create a scope with parent. + */ + public JsScope(JsScope parent, String description, String scopeId) { + assert (parent != null); + this.scopeId = scopeId; + this.description = description; + this.parent = parent; + parent.children = Lists.add(parent.children, this); } - children = Collections.emptyList(); - } - /** - * Subclasses can detach and become parentless. - */ - protected void detachFromParent() { - JsScope oldParent = parent; - - oldParent.children = Lists.remove( - parent.children, oldParent.children.indexOf(this)); - - parent = null; - } - - /** - * Subclasses can be parentless. - */ - protected JsScope(String description) { - this.description = description; - this.parent = null; - this.scopeId = null; - } - - /** - * Gets a name object associated with the specified ident in this scope, - * creating it if necessary.
- * If the JsName does not exist yet, a new JsName is created. The ident, - * short name, and original name of the newly created JsName are equal to - * the given ident. - * - * @param ident An identifier that is unique within this scope. - */ - public JsName declareName(String ident) { - JsName name = findExistingNameNoRecurse(ident); - if (name != null) { - return name; + /** + * Rebase the function to a new scope. + * + * @param newParent The scope to add the function to. + */ + public void rebase(JsScope newParent) { + detachFromParent(); + parent = newParent; + parent.children = Lists.add(parent.children, this); } - return doCreateName(ident, ident, ident); - } - /** - * Creates a new variable with an unique ident in this scope. - * The generated JsName is guaranteed to have an identifier (but not short - * name) that does not clash with any existing variables in the scope. - * Future declarations of variables might however clash with the temporary - * (unless they use this function). - */ - public JsName declareFreshName(String shortName) { - String ident = shortName; - int counter = 0; - while (findExistingNameNoRecurse(ident) != null) { - ident = shortName + "_" + counter++; + /** + * Rebase the function's children to a new scope. + * + * @param newParent + */ + public void rebaseChildScopes(JsScope newParent) { + if (newParent == this) { + return; + } + parent.children = Lists.addAll(parent.children, children); + for (JsScope child : children) { + child.parent = newParent; + } + children = Collections.emptyList(); } - return doCreateName(ident, shortName, shortName); - } - String getNextTempName() { - // TODO(ngeoffray): Decide on a convention for temporary variables - // introduced by the compiler. - return "tmp$" + (scopeId != null ? scopeId + "$" : "") + tempIndex++; - } + /** + * Subclasses can detach and become parentless. + */ + protected void detachFromParent() { + JsScope oldParent = parent; - /** - * Creates a temporary variable with an unique name in this scope. - * The generated temporary is guaranteed to have an identifier (but not short - * name) that does not clash with any existing variables in the scope. - * Future declarations of variables might however clash with the temporary. - */ - public JsName declareTemporary() { - return declareFreshName(getNextTempName()); - } + oldParent.children = Lists.remove( + parent.children, oldParent.children.indexOf(this)); - /** - * Gets a name object associated with the specified ident in this scope, - * creating it if necessary.
- * If the JsName does not exist yet, a new JsName is created with the given - * ident, short name and original name. - * - * @param ident An identifier that is unique within this scope. - * @param shortIdent A "pretty" name that does not have to be unique. - * @throws IllegalArgumentException if ident already exists in this scope but - * the requested short name does not match the existing short name. - */ - public JsName declareName(String ident, String shortIdent) { - return declareName(ident, shortIdent, ident); - } - - /** - * Gets a name object associated with the specified ident in this scope, - * creating it if necessary.
- * If the JsName does not exist yet, a new JsName is created. The original - * name stored in the JsName is equal to the (unmangled) specified originalName. - * - * @param ident An identifier that is unique within this scope. - * @param shortIdent A "pretty" name that does not have to be unique. - * @param originalName The original name in the source. - * @throws IllegalArgumentException if ident already exists in this scope but - * the requested short name does not match the existing short name, - * or the original name does not match the existing original name. - */ - public JsName declareName(String ident, String shortIdent, String originalName) { - JsName name = findExistingNameNoRecurse(ident); - if (name != null) { - if (!name.getShortIdent().equals(shortIdent) - || !nullableEquals(name.getOriginalName(), originalName)) { - throw new IllegalArgumentException("Requested short name " + shortIdent - + " conflicts with preexisting short name " + name.getShortIdent() + " for identifier " - + ident); - } - return name; + parent = null; } - return doCreateName(ident, shortIdent, originalName); - } - boolean nullableEquals(String s1, String s2) { - return (s1 == null) ? (s2 == null) : s1.equals(s2); - } - - /** - * Attempts to find the name object for the specified ident, searching in this - * scope, and if not found, in the parent scopes. - * - * @return null if the identifier has no associated name - */ - public final JsName findExistingName(String ident) { - JsName name = findExistingNameNoRecurse(ident); - if (name == null && parent != null) { - return parent.findExistingName(ident); + /** + * Subclasses can be parentless. + */ + protected JsScope(String description) { + this.description = description; + this.parent = null; + this.scopeId = null; } - return name; - } - /** - * Attempts to find an unobfuscatable name object for the specified ident, - * searching in this scope, and if not found, in the parent scopes. - * - * @return null if the identifier has no associated name - */ - public final JsName findExistingUnobfuscatableName(String ident) { - JsName name = findExistingNameNoRecurse(ident); - if (name != null && name.isObfuscatable()) { - name = null; + /** + * Gets a name object associated with the specified ident in this scope, + * creating it if necessary.
+ * If the JsName does not exist yet, a new JsName is created. The ident, + * short name, and original name of the newly created JsName are equal to + * the given ident. + * + * @param ident An identifier that is unique within this scope. + */ + public JsName declareName(String ident) { + JsName name = findExistingNameNoRecurse(ident); + if (name != null) { + return name; + } + return doCreateName(ident, ident, ident); } - if (name == null && parent != null) { - return parent.findExistingUnobfuscatableName(ident); + + /** + * Creates a new variable with an unique ident in this scope. + * The generated JsName is guaranteed to have an identifier (but not short + * name) that does not clash with any existing variables in the scope. + * Future declarations of variables might however clash with the temporary + * (unless they use this function). + */ + public JsName declareFreshName(String shortName) { + String ident = shortName; + int counter = 0; + while (findExistingNameNoRecurse(ident) != null) { + ident = shortName + "_" + counter++; + } + return doCreateName(ident, shortName, shortName); } - return name; - } - /** - * Returns an iterator for all the names defined by this scope. - */ - public Iterator getAllNames() { - return names.values().iterator(); - } - - /** - * Returns a list of this scope's child scopes. - */ - public final List getChildren() { - return children; - } - - /** - * Returns the parent scope of this scope, or null if this is the - * root scope. - */ - public final JsScope getParent() { - return parent; - } - - /** - * Returns the associated program. - */ - public JsProgram getProgram() { - assert (parent != null) : "Subclasses must override getProgram() if they do not set a parent"; - return parent.getProgram(); - } - - @Override - public final String toString() { - if (parent != null) { - return description + "->" + parent; - } else { - return description; + String getNextTempName() { + // TODO(ngeoffray): Decide on a convention for temporary variables + // introduced by the compiler. + return "tmp$" + (scopeId != null ? scopeId + "$" : "") + tempIndex++; } - } - /** - * Creates a new name in this scope. - */ - protected JsName doCreateName(String ident, String shortIdent, String originalName) { - JsName name = new JsName(this, ident, shortIdent, originalName); - names = Maps.putOrdered(names, ident, name); - return name; - } + /** + * Creates a temporary variable with an unique name in this scope. + * The generated temporary is guaranteed to have an identifier (but not short + * name) that does not clash with any existing variables in the scope. + * Future declarations of variables might however clash with the temporary. + */ + public JsName declareTemporary() { + return declareFreshName(getNextTempName()); + } - /** - * Attempts to find the name object for the specified ident, searching in this - * scope only. - * - * @return null if the identifier has no associated name - */ - protected JsName findExistingNameNoRecurse(String ident) { - return names.get(ident); - } + /** + * Gets a name object associated with the specified ident in this scope, + * creating it if necessary.
+ * If the JsName does not exist yet, a new JsName is created with the given + * ident, short name and original name. + * + * @param ident An identifier that is unique within this scope. + * @param shortIdent A "pretty" name that does not have to be unique. + * @throws IllegalArgumentException if ident already exists in this scope but + * the requested short name does not match the existing short name. + */ + public JsName declareName(String ident, String shortIdent) { + return declareName(ident, shortIdent, ident); + } + + /** + * Gets a name object associated with the specified ident in this scope, + * creating it if necessary.
+ * If the JsName does not exist yet, a new JsName is created. The original + * name stored in the JsName is equal to the (unmangled) specified originalName. + * + * @param ident An identifier that is unique within this scope. + * @param shortIdent A "pretty" name that does not have to be unique. + * @param originalName The original name in the source. + * @throws IllegalArgumentException if ident already exists in this scope but + * the requested short name does not match the existing short name, + * or the original name does not match the existing original name. + */ + public JsName declareName(String ident, String shortIdent, String originalName) { + JsName name = findExistingNameNoRecurse(ident); + if (name != null) { + if (!name.getShortIdent().equals(shortIdent) + || !nullableEquals(name.getOriginalName(), originalName)) { + throw new IllegalArgumentException("Requested short name " + shortIdent + + " conflicts with preexisting short name " + name.getShortIdent() + " for identifier " + + ident); + } + return name; + } + return doCreateName(ident, shortIdent, originalName); + } + + boolean nullableEquals(String s1, String s2) { + return (s1 == null) ? (s2 == null) : s1.equals(s2); + } + + /** + * Attempts to find the name object for the specified ident, searching in this + * scope, and if not found, in the parent scopes. + * + * @return null if the identifier has no associated name + */ + public final JsName findExistingName(String ident) { + JsName name = findExistingNameNoRecurse(ident); + if (name == null && parent != null) { + return parent.findExistingName(ident); + } + return name; + } + + /** + * Attempts to find an unobfuscatable name object for the specified ident, + * searching in this scope, and if not found, in the parent scopes. + * + * @return null if the identifier has no associated name + */ + public final JsName findExistingUnobfuscatableName(String ident) { + JsName name = findExistingNameNoRecurse(ident); + if (name != null && name.isObfuscatable()) { + name = null; + } + if (name == null && parent != null) { + return parent.findExistingUnobfuscatableName(ident); + } + return name; + } + + /** + * Returns an iterator for all the names defined by this scope. + */ + public Iterator getAllNames() { + return names.values().iterator(); + } + + /** + * Returns a list of this scope's child scopes. + */ + public final List getChildren() { + return children; + } + + /** + * Returns the parent scope of this scope, or null if this is the + * root scope. + */ + public final JsScope getParent() { + return parent; + } + + /** + * Returns the associated program. + */ + public JsProgram getProgram() { + assert (parent != null) : "Subclasses must override getProgram() if they do not set a parent"; + return parent.getProgram(); + } + + @Override + public final String toString() { + if (parent != null) { + return description + "->" + parent; + } else { + return description; + } + } + + /** + * Creates a new name in this scope. + */ + protected JsName doCreateName(String ident, String shortIdent, String originalName) { + JsName name = new JsName(this, ident, shortIdent, originalName); + names = Maps.putOrdered(names, ident, name); + return name; + } + + /** + * Attempts to find the name object for the specified ident, searching in this + * scope only. + * + * @return null if the identifier has no associated name + */ + public JsName findExistingNameNoRecurse(String ident) { + return names.get(ident); + } } diff --git a/src/org/jetbrains/k2js/translate/DeclarationTranslator.java b/src/org/jetbrains/k2js/translate/DeclarationTranslator.java index a33885ffce4..3bb19ebdeeb 100644 --- a/src/org/jetbrains/k2js/translate/DeclarationTranslator.java +++ b/src/org/jetbrains/k2js/translate/DeclarationTranslator.java @@ -65,8 +65,7 @@ public class DeclarationTranslator extends AbstractTranslator { public final class FunctionVariableDeclaration extends State { @NotNull public JsStatement translateProperty(JetProperty declaration) { - String propertyName = declaration.getName(); - JsName jsPropertyName = getJSName(propertyName); + JsName jsPropertyName = translationContext().declareLocalName(declaration.getName()); JsExpression jsInitExpression = translateInitializer(declaration); return AstUtil.newVar(jsPropertyName, jsInitExpression); } @@ -76,8 +75,9 @@ public class DeclarationTranslator extends AbstractTranslator { public final class NamespacePropertyDeclaration extends State { @NotNull public JsStatement translateProperty(JetProperty declaration) { - String propertyName = declaration.getName(); - JsNameRef jsPropertyNameReference = translationContext().getNamespaceQualifiedReference(getJSName(propertyName)); + JsName propertyName = translationContext().declareLocalName(declaration.getName()); + JsNameRef jsPropertyNameReference = + translationContext().getNamespaceQualifiedReference(propertyName); JsExpression jsInitExpression = translateInitializer(declaration); JsExpression result; if (jsInitExpression != null) { diff --git a/src/org/jetbrains/k2js/translate/ExpressionVisitor.java b/src/org/jetbrains/k2js/translate/ExpressionVisitor.java index 854798ba96e..a1a89bd3fbd 100644 --- a/src/org/jetbrains/k2js/translate/ExpressionVisitor.java +++ b/src/org/jetbrains/k2js/translate/ExpressionVisitor.java @@ -5,6 +5,7 @@ import com.google.dart.compiler.util.AstUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.calls.ExpressionValueArgument; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lexer.JetToken; @@ -39,10 +40,11 @@ public class ExpressionVisitor extends K2JsVisitor { public JsNode visitBlockExpression(JetBlockExpression jetBlock, TranslationContext context) { List jetElements = jetBlock.getStatements(); JsBlock jsBlock = new JsBlock(); + TranslationContext newContext = context.newBlock(); for (JetElement jetElement : jetElements) { //TODO hack alert JetExpression jetExpression = (JetExpression) jetElement; - JsNode jsNode = jetExpression.accept(this, context.newBlock()); + JsNode jsNode = jetExpression.accept(this, newContext); jsBlock.addStatement(AstUtil.convertToStatement(jsNode)); } assert jsBlock != null; @@ -79,15 +81,24 @@ public class ExpressionVisitor extends K2JsVisitor { return jsBinaryOperation; } + //TODO think about recursive/non-recursive name look-up @Override @NotNull public JsNode visitSimpleNameExpression(JetSimpleNameExpression expression, TranslationContext context) { String referencedName = expression.getReferencedName(); - if (context.enclosingScope().findExistingName(referencedName) == null) { - JsName name = context.enclosingScope().declareName(referencedName); - return name.makeRef(); + JsName jsName = context.enclosingScope().findExistingNameNoRecurse(referencedName); + if (jsName != null) { + return jsName.makeRef(); } - return context.getNamespaceQualifiedReference(context.getJSName(referencedName)); + jsName = context.functionScope().findExistingNameNoRecurse(referencedName); + if (jsName != null) { + return context.getNamespaceQualifiedReference(jsName); + } + jsName = context.namespaceScope().findExistingNameNoRecurse(referencedName); + if (jsName != null) { + return context.getNamespaceQualifiedReference(jsName); + } + throw new AssertionError("Unindentified name " + expression.getReferencedName()); } @Override @@ -101,7 +112,7 @@ public class ExpressionVisitor extends K2JsVisitor { @NotNull public JsNode visitCallExpression(JetCallExpression expression, TranslationContext context) { JsExpression callee = getCallee(expression, context); - List arguments = generateArgumentList(expression.getFunctionLiteralArguments(), context); + List arguments = generateArgumentList(expression.getValueArguments(), context); return AstUtil.newInvocation(callee, arguments); } @@ -112,9 +123,10 @@ public class ExpressionVisitor extends K2JsVisitor { } @NotNull - private List generateArgumentList(List jetArguments, TranslationContext context) { + private List generateArgumentList(List jetArguments, TranslationContext context) { List jsArguments = new ArrayList(); - for (JetExpression jetExpression : jetArguments) { + for (ValueArgument argument : jetArguments) { + JetExpression jetExpression = argument.getArgumentExpression(); jsArguments.add(AstUtil.convertToExpression(jetExpression.accept(this, context))); } return jsArguments; diff --git a/src/org/jetbrains/k2js/translate/FunctionTranslator.java b/src/org/jetbrains/k2js/translate/FunctionTranslator.java index 9eba740dcc6..e1096e981b4 100644 --- a/src/org/jetbrains/k2js/translate/FunctionTranslator.java +++ b/src/org/jetbrains/k2js/translate/FunctionTranslator.java @@ -21,9 +21,10 @@ public class FunctionTranslator extends AbstractTranslator { @NotNull public JsStatement translateFunction(JetNamedFunction jetFunction) { - JsNameRef functionName = translationContext().getNamespaceQualifiedReference(getJSName(jetFunction.getName())); + JsName functionName = translationContext().namespaceScope().declareFreshName(jetFunction.getName()); JsFunction function = generateFunctionObject(jetFunction); - return AstUtil.convertToStatement(AstUtil.newAssignment(functionName, function)); + return AstUtil.convertToStatement(AstUtil.newAssignment + (translationContext().getNamespaceQualifiedReference(functionName), function)); } private JsFunction generateFunctionObject(JetNamedFunction jetFunction) { diff --git a/src/org/jetbrains/k2js/translate/TranslationContext.java b/src/org/jetbrains/k2js/translate/TranslationContext.java index f75c262bb9e..661cfc3f571 100644 --- a/src/org/jetbrains/k2js/translate/TranslationContext.java +++ b/src/org/jetbrains/k2js/translate/TranslationContext.java @@ -25,11 +25,7 @@ public class TranslationContext { public Scopes(JsScope enclosing, JsScope function, JsScope namespace) { this.enclosingScope = enclosing; this.functionScope = function; - this.namespaceScope = function; - } - - public Scopes(Scopes other) { - this(other.enclosingScope, other.functionScope, other.namespaceScope); + this.namespaceScope = namespace; } public final JsScope enclosingScope; @@ -42,7 +38,6 @@ public class TranslationContext { assert program != null; assert bindingContext != null; assert scopes != null; - assert currentNamespace != null; assert type != null; this.program = program; this.bindingContext = bindingContext; @@ -59,7 +54,6 @@ public class TranslationContext { program, bindingContext, scopes, ContextType.NAMESPACE_BODY); } - //TODO implement correct factories @NotNull public TranslationContext newNamespace(JsName namespaceName, JsFunction namespaceDummyFunction) { JsScope newScope = namespaceDummyFunction.getScope(); @@ -112,6 +106,21 @@ public class TranslationContext { return scopes.enclosingScope; } + @NotNull + JsScope namespaceScope() { + return scopes.namespaceScope; + } + + @NotNull + JsScope functionScope() { + return scopes.functionScope; + } + + @NotNull + JsName declareLocalName(String name) { + return scopes.enclosingScope.declareFreshName(name); + } + @NotNull ContextType type() { return type; diff --git a/test/org/jetbrains/k2js/test/TranslatorTests.java b/test/org/jetbrains/k2js/test/TranslatorTests.java index eea79046209..fa2e794097f 100644 --- a/test/org/jetbrains/k2js/test/TranslatorTests.java +++ b/test/org/jetbrains/k2js/test/TranslatorTests.java @@ -45,6 +45,8 @@ public class TranslatorTests { Object functionArgs[] = {}; Function function = (Function) box; Object result = function.call(cx, scope, scope, functionArgs); + assertTrue(result instanceof Boolean); + assertTrue((Boolean)result == true); String report = "foo.box() = " + Context.toString(result); System.out.println(report); diff --git a/test_files/test_cases/test.kt b/test_files/test_cases/test.kt index be2f39a55cc..98ee81ba1ea 100644 --- a/test_files/test_cases/test.kt +++ b/test_files/test_cases/test.kt @@ -5,4 +5,5 @@ fun box() : Boolean { val b = 3; var c = 4; return (a < c) -} \ No newline at end of file +} +