str, which could
+ * potentially cause a parse failure in a browser, for example, embedding a
+ * closing <script> tag.
+ *
+ * @param str an unescaped literal; May be null
+ */
+ private static void escapeClosingTags(StringBuilder str) {
+ if (str == null) {
+ return;
+ }
+
+ int index = 0;
+ while ((index = str.indexOf("", index)) != -1) {
+ str.insert(index + 1, '\\');
+ }
+ }
+
+ protected boolean needSemi = true;
+ private boolean lineBreakAfterBlock = true;
+
+ /**
+ * "Global" blocks are either the global block of a fragment, or a block
+ * nested directly within some other global block. This definition matters
+ * because the statements designated by statementEnds and statementStarts are
+ * those that appear directly within these global blocks.
+ */
+ private Setop is printed followed by arg,
+ * there needs to be a space between the operator and expression.
+ *
+ * @return true if a space needs to be printed
+ */
+ private static boolean spaceCalc(JsOperator op, JsExpression arg) {
+ if (op.isKeyword()) {
+ return true;
+ }
+ if (arg instanceof JsBinaryOperation) {
+ JsBinaryOperation binary = (JsBinaryOperation) arg;
+ /*
+ * If the binary operation has a higher precedence than op, then it won't
+ * be parenthesized, so check the first argument of the binary operation.
+ */
+ return binary.getOperator().getPrecedence() > op.getPrecedence() && spaceCalc(op, binary.getArg1());
+ }
+ if (arg instanceof JsPrefixOperation) {
+ JsOperator op2 = ((JsPrefixOperation) arg).getOperator();
+ return (op == JsBinaryOperator.SUB || op == JsUnaryOperator.NEG)
+ && (op2 == JsUnaryOperator.DEC || op2 == JsUnaryOperator.NEG)
+ || (op == JsBinaryOperator.ADD && op2 == JsUnaryOperator.INC);
+ }
+ if (arg instanceof JsNumberLiteral && (op == JsBinaryOperator.SUB || op == JsUnaryOperator.NEG)) {
+ if (arg instanceof JsIntLiteral) {
+ return ((JsIntLiteral) arg).value < 0;
+ }
+ else {
+ assert arg instanceof JsDoubleLiteral;
+ //noinspection CastConflictsWithInstanceof
+ return ((JsDoubleLiteral) arg).value < 0;
+ }
+ }
+ return false;
+ }
+
+ private void spaceOpt() {
+ p.printOpt(' ');
+ }
+
+ private void var() {
+ p.print(CHARS_VAR);
+ }
+
+ private void _while() {
+ p.print(CHARS_WHILE);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/AbstractNode.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/AbstractNode.java
new file mode 100644
index 00000000000..d2d906be326
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/AbstractNode.java
@@ -0,0 +1,13 @@
+package com.google.dart.compiler.backend.js.ast;
+
+import com.google.dart.compiler.backend.js.JsToStringGenerationVisitor;
+import com.google.dart.compiler.util.TextOutputImpl;
+
+abstract class AbstractNode implements JsNode {
+ @Override
+ public String toString() {
+ TextOutputImpl out = new TextOutputImpl();
+ new JsToStringGenerationVisitor(out).accept(this);
+ return out.toString();
+ }
+}
\ No newline at end of file
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java
new file mode 100644
index 00000000000..c50d40e8166
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/ChameleonJsExpression.java
@@ -0,0 +1,51 @@
+package com.google.dart.compiler.backend.js.ast;
+
+public class ChameleonJsExpression implements JsExpression {
+ private JsExpression expression;
+
+ public ChameleonJsExpression(JsExpression initialExpression) {
+ expression = initialExpression;
+ }
+
+ public ChameleonJsExpression() {
+ }
+
+ public void resolve(JsExpression expression) {
+ this.expression = expression;
+ }
+
+ @Override
+ public boolean isLeaf() {
+ return expression.isLeaf();
+ }
+
+ @Override
+ public JsStatement makeStmt() {
+ return expression.makeStmt();
+ }
+
+ @Override
+ public void accept(JsVisitor visitor) {
+ expression.accept(visitor);
+ }
+
+ @Override
+ public void acceptChildren(JsVisitor visitor) {
+ expression.acceptChildren(visitor);
+ }
+
+ @Override
+ public Object getSource() {
+ return expression.getSource();
+ }
+
+ @Override
+ public void setSource(Object info) {
+ expression.setSource(info);
+ }
+
+ @Override
+ public JsExpression source(Object info) {
+ return expression.source(info);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/HasArguments.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/HasArguments.java
new file mode 100644
index 00000000000..29b12859174
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/HasArguments.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.backend.js.ast;
+
+import java.util.List;
+
+/**
+ * Implemented by JavaScript objects that accept arguments.
+ */
+public interface HasArguments extends JsExpression {
+ Listfor statement. If specified at all, the initializer part is
+ * either a declaration of one or more variables, in which case
+ * {@link #getInitVars()} is used, or an expression, in which case
+ * {@link #getInitExpression()} is used. In the latter case, the comma operator is
+ * often used to create a compound expression.
+ *
+ *
+ * Note that any of the parts of the for loop header can be
+ * null, although the body will never be null.
+ */
+public class JsFor extends SourceInfoAwareJsNode implements JsStatement {
+ private JsStatement body;
+ private JsExpression condition;
+ private JsExpression incrementExpression;
+ private JsExpression initExpression;
+ private JsVars initVars;
+
+ public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression) {
+ this(initVars, condition, incrementExpression, null);
+ }
+
+ public JsFor(JsVars initVars, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
+ this.initVars = initVars;
+ this.incrementExpression = incrementExpression;
+ this.condition = condition;
+ this.body = body;
+ initExpression = null;
+ }
+
+ public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression) {
+ this(initExpression, condition, incrementExpression, null);
+ }
+
+ public JsFor(JsExpression initExpression, JsExpression condition, JsExpression incrementExpression, JsStatement body) {
+ this.initExpression = initExpression;
+ this.incrementExpression = incrementExpression;
+ this.condition = condition;
+ this.body = body;
+ initVars = null;
+ }
+
+ public JsStatement getBody() {
+ return body;
+ }
+
+ public JsExpression getCondition() {
+ return condition;
+ }
+
+ public JsExpression getIncrementExpression() {
+ return incrementExpression;
+ }
+
+ public JsExpression getInitExpression() {
+ return initExpression;
+ }
+
+ public JsVars getInitVars() {
+ return initVars;
+ }
+
+ public void setBody(JsStatement body) {
+ this.body = body;
+ }
+
+ @Override
+ public void accept(JsVisitor v) {
+ v.visitFor(this);
+ }
+
+ @Override
+ public void acceptChildren(JsVisitor visitor) {
+ assert (!(initExpression != null && initVars != null));
+
+ if (initExpression != null) {
+ visitor.accept(initExpression);
+ }
+ else if (initVars != null) {
+ visitor.accept(initVars);
+ }
+
+ if (condition != null) {
+ visitor.accept(condition);
+ }
+
+ if (incrementExpression != null) {
+ visitor.accept(incrementExpression);
+ }
+ visitor.accept(body);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java
new file mode 100644
index 00000000000..3fc4a915abf
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsForIn.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.backend.js.ast;
+
+public class JsForIn extends SourceInfoAwareJsNode implements JsStatement {
+ private JsStatement body;
+ private JsExpression iterExpression;
+ private JsExpression objectExpression;
+
+ // Optional: the name of a new iterator variable to introduce
+ private final JsName iterVarName;
+
+ public JsForIn() {
+ this(null);
+ }
+
+ public JsForIn(JsName iterVarName) {
+ this.iterVarName = iterVarName;
+ }
+
+ public JsStatement getBody() {
+ return body;
+ }
+
+ public JsExpression getIterExpression() {
+ return iterExpression;
+ }
+
+ public JsName getIterVarName() {
+ return iterVarName;
+ }
+
+ public JsExpression getObjectExpression() {
+ return objectExpression;
+ }
+
+ public void setBody(JsStatement body) {
+ this.body = body;
+ }
+
+ public void setIterExpression(JsExpression iterExpression) {
+ this.iterExpression = iterExpression;
+ }
+
+ public void setObjectExpression(JsExpression objectExpression) {
+ this.objectExpression = objectExpression;
+ }
+
+ @Override
+ public void accept(JsVisitor v) {
+ v.visitForIn(this);
+ }
+
+ @Override
+ public void acceptChildren(JsVisitor visitor) {
+ if (iterExpression != null) {
+ visitor.acceptLvalue(iterExpression);
+ }
+ visitor.accept(objectExpression);
+ visitor.accept(body);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java
new file mode 100644
index 00000000000..1bc7b301b8a
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsFunction.java
@@ -0,0 +1,76 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.backend.js.ast;
+
+import com.google.dart.compiler.common.Symbol;
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public final class JsFunction extends JsLiteral implements HasName {
+ private JsBlock body;
+ private Listnull if the identifier has no associated name
+ */
+ @Nullable
+ public final JsName findName(String ident) {
+ JsName name = findOwnName(ident);
+ if (name == null && parent != null) {
+ return parent.findName(ident);
+ }
+ return name;
+ }
+
+ protected boolean hasOwnName(@NotNull String name) {
+ return names.containsKey(name);
+ }
+
+ /**
+ * Returns the parent scope of this scope, or null if this is the
+ * root scope.
+ */
+ public final JsScope getParent() {
+ return parent;
+ }
+
+ 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;
+ }
+ }
+
+ protected JsName doCreateName(String ident) {
+ JsName name = new JsName(this, ident);
+ names = Maps.put(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
+ */
+ protected JsName findOwnName(String ident) {
+ return names.get(ident);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStatement.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStatement.java
new file mode 100644
index 00000000000..a3ea11cec92
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStatement.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.backend.js.ast;
+
+public interface JsStatement extends JsNode {
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java
new file mode 100644
index 00000000000..08d9d40fbf7
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsStringLiteral.java
@@ -0,0 +1,24 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.backend.js.ast;
+
+public final class JsStringLiteral extends JsLiteral.JsValueLiteral {
+
+ private final String value;
+
+ // These only get created by JsProgram so that they can be interned.
+ JsStringLiteral(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public void accept(JsVisitor v) {
+ v.visitString(this);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java
new file mode 100644
index 00000000000..763c6c1feeb
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/JsSwitch.java
@@ -0,0 +1,44 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.backend.js.ast;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A JavaScript switch statement.
+ */
+public class JsSwitch extends SourceInfoAwareJsNode implements JsStatement {
+
+ private final Listtry statement.
+ */
+public class JsTry extends SourceInfoAwareJsNode implements JsStatement {
+ private final Listvar statement.
+ */
+public class JsVars extends SourceInfoAwareJsNode implements JsStatement, Iterablevar statement.
+ */
+ public static class JsVar extends SourceInfoAwareJsNode implements HasName {
+ private final JsName name;
+ private JsExpression initExpression;
+
+ public JsVar(JsName name) {
+ this.name = name;
+ }
+
+ public JsVar(JsName name, @Nullable JsExpression initExpression) {
+ this.name = name;
+ this.initExpression = initExpression;
+ }
+
+ public JsExpression getInitExpression() {
+ return initExpression;
+ }
+
+ @Override
+ public JsName getName() {
+ return name;
+ }
+
+ @Override
+ public Symbol getSymbol() {
+ return name;
+ }
+
+ public void setInitExpression(JsExpression initExpression) {
+ this.initExpression = initExpression;
+ }
+
+ @Override
+ public void accept(JsVisitor v) {
+ v.visit(this);
+ }
+
+ @Override
+ public void acceptChildren(JsVisitor visitor) {
+ if (initExpression != null) {
+ visitor.accept(initExpression);
+ }
+ }
+ }
+
+ public void add(JsVar var) {
+ vars.add(var);
+ }
+
+ public void addIfHasInitializer(JsVar var) {
+ if (var.getInitExpression() != null) {
+ add(var);
+ }
+ }
+
+ public boolean isEmpty() {
+ return vars.isEmpty();
+ }
+
+ @Override
+ public Iteratorwhile statement.
+ */
+public class JsWhile extends SourceInfoAwareJsNode implements JsStatement {
+ protected JsStatement body;
+ protected JsExpression condition;
+
+ public JsWhile() {
+ }
+
+ public JsWhile(JsExpression condition, JsStatement body) {
+ this.condition = condition;
+ this.body = body;
+ }
+
+ public JsStatement getBody() {
+ return body;
+ }
+
+ public JsExpression getCondition() {
+ return condition;
+ }
+
+ public void setBody(JsStatement body) {
+ this.body = body;
+ }
+
+ public void setCondition(JsExpression condition) {
+ this.condition = condition;
+ }
+
+ @Override
+ public void accept(JsVisitor v) {
+ v.visitWhile(this);
+ }
+
+ @Override
+ public void acceptChildren(JsVisitor visitor) {
+ visitor.accept(condition);
+ visitor.accept(body);
+ }
+}
\ No newline at end of file
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/RecursiveJsVisitor.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/RecursiveJsVisitor.java
new file mode 100644
index 00000000000..56cb331b789
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/RecursiveJsVisitor.java
@@ -0,0 +1,8 @@
+package com.google.dart.compiler.backend.js.ast;
+
+public abstract class RecursiveJsVisitor extends JsVisitor {
+ @Override
+ protected void visitElement(JsNode node) {
+ node.acceptChildren(this);
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/SourceInfoAwareJsNode.java b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/SourceInfoAwareJsNode.java
new file mode 100644
index 00000000000..bfed21105a7
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/backend/js/ast/SourceInfoAwareJsNode.java
@@ -0,0 +1,25 @@
+package com.google.dart.compiler.backend.js.ast;
+
+abstract class SourceInfoAwareJsNode extends AbstractNode {
+ private Object source;
+
+ @Override
+ public Object getSource() {
+ return source;
+ }
+
+ @Override
+ public void setSource(Object info) {
+ source = info;
+ }
+
+ @Override
+ public void acceptChildren(JsVisitor visitor) {
+ }
+
+ @Override
+ public JsNode source(Object info) {
+ source = info;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/common/HasSymbol.java b/js/js.dart-ast/src/com/google/dart/compiler/common/HasSymbol.java
new file mode 100644
index 00000000000..0128679bed1
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/common/HasSymbol.java
@@ -0,0 +1,16 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.common;
+
+/**
+ * @author johnlenz@google.com (John Lenz)
+ */
+public interface HasSymbol {
+ /**
+ * @return Return the original user visible name for a Object represented
+ * in a source map.
+ */
+ Symbol getSymbol();
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/common/SourceInfo.java b/js/js.dart-ast/src/com/google/dart/compiler/common/SourceInfo.java
new file mode 100644
index 00000000000..6e0efc8e505
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/common/SourceInfo.java
@@ -0,0 +1,59 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.common;
+
+import com.google.dart.compiler.Source;
+
+import java.io.Serializable;
+
+/**
+ * Tracks file and line information for AST nodes.
+ */
+public interface SourceInfo extends Serializable {
+
+ /**
+ * The source code provider.
+ */
+ Source getSource();
+
+ /**
+ * @return A 1-based line number into the original source file indicating
+ * where the source fragment begins.
+ */
+ int getLine();
+
+ /**
+ * @return A 1-based column number into the original source file indicating
+ * where the source fragment begins.
+ */
+ int getColumn();
+
+ /**
+ * Returns the character index into the original source file indicating
+ * where the source fragment corresponding to this node begins.
+ *
+ *
+ * The parser supplies useful well-defined source ranges to the nodes it creates.
+ *
+ * @return the 0-based character index, or -1
+ * if no source startPosition information is recorded for this node
+ * @see #getLength()
+ * @see HasSourceInfo#setSourceLocation(Source, int, int, int, int)
+ */
+ int getStart();
+
+ /**
+ * Returns the length in characters of the original source file indicating
+ * where the source fragment corresponding to this node ends.
+ *
+ * The parser supplies useful well-defined source ranges to the nodes it creates.
+ *
+ * @return a (possibly 0) length, or 0
+ * if no source source position information is recorded for this node
+ * @see #getStart()
+ * @see HasSourceInfo#setSourceLocation(Source, int, int, int, int)
+ */
+ int getLength();
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/common/SourceInfoImpl.java b/js/js.dart-ast/src/com/google/dart/compiler/common/SourceInfoImpl.java
new file mode 100644
index 00000000000..450f873e3e5
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/common/SourceInfoImpl.java
@@ -0,0 +1,44 @@
+package com.google.dart.compiler.common;
+
+import com.google.dart.compiler.Source;
+
+public class SourceInfoImpl implements SourceInfo {
+ protected Source source = null;
+ protected int line = -1;
+ protected int column = -1;
+ protected int start = -1;
+ protected int length = -1;
+
+ public SourceInfoImpl(Source source, int line, int column, int start, int length) {
+ this.source = source;
+ this.line = line;
+ this.column = column;
+ this.start = start;
+ this.length = length;
+ }
+
+ @Override
+ public Source getSource() {
+ return source;
+ }
+
+ @Override
+ public int getLine() {
+ return line;
+ }
+
+ @Override
+ public int getColumn() {
+ return column;
+ }
+
+ @Override
+ public int getStart() {
+ return start;
+ }
+
+ @Override
+ public int getLength() {
+ return length;
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/common/Symbol.java b/js/js.dart-ast/src/com/google/dart/compiler/common/Symbol.java
new file mode 100644
index 00000000000..6e786358883
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/common/Symbol.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.common;
+
+/**
+ * @author johnlenz@google.com (John Lenz)
+ */
+public interface Symbol {
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java b/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java
new file mode 100644
index 00000000000..0be554fb7af
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/util/AstUtil.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.util;
+
+import com.google.dart.compiler.backend.js.ast.*;
+
+/**
+ * @author johnlenz@google.com (John Lenz)
+ */
+public final class AstUtil {
+ private AstUtil() {
+ }
+
+ /**
+ * Returns a sequence of expressions (using the binary sequence operator).
+ *
+ * @param exprs - expressions to add to sequence
+ * @return a sequence of expressions.
+ */
+ public static JsBinaryOperation newSequence(JsExpression... exprs) {
+ if (exprs.length < 2) {
+ throw new RuntimeException("newSequence expects at least two arguments");
+ }
+ JsExpression result = exprs[exprs.length - 1];
+ for (int i = exprs.length - 2; i >= 0; i--) {
+ result = new JsBinaryOperation(JsBinaryOperator.COMMA, exprs[i], result);
+ }
+ return (JsBinaryOperation) result;
+ }
+}
diff --git a/js/js.dart-ast/src/com/google/dart/compiler/util/Maps.java b/js/js.dart-ast/src/com/google/dart/compiler/util/Maps.java
new file mode 100644
index 00000000000..5ca74c3a370
--- /dev/null
+++ b/js/js.dart-ast/src/com/google/dart/compiler/util/Maps.java
@@ -0,0 +1,41 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.google.dart.compiler.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Utility methods for operating on memory-efficient maps. All maps of size 0 or
+ * 1 are assumed to be immutable. All maps of size greater than 1 are assumed to
+ * be mutable.
+ */
+public class Maps {
+ private Maps() {
+ }
+
+ public static