simplify AST (idea like)

This commit is contained in:
develar
2012-10-25 08:42:06 +04:00
parent a5b212e975
commit c41bf918bf
60 changed files with 1085 additions and 1232 deletions
@@ -11,93 +11,92 @@ import com.google.dart.compiler.backend.js.ast.*;
* normally be surrounded by parentheses.
*/
public class JsConstructExpressionVisitor extends JsVisitor {
public static boolean exec(JsExpression expression) {
if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return true;
public static boolean exec(JsExpression expression) {
if (JsPrecedenceVisitor.exec(expression) < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return true;
}
JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor();
visitor.accept(expression);
return visitor.containsInvocation;
}
JsConstructExpressionVisitor visitor = new JsConstructExpressionVisitor();
visitor.accept(expression);
return visitor.containsInvocation;
}
private boolean containsInvocation = false;
private boolean containsInvocation;
private JsConstructExpressionVisitor() {
}
/**
* We only look at the array expression since the index has its own scope.
*/
@Override
public boolean visit(JsArrayAccess x, JsContext ctx) {
accept(x.getArrayExpression());
return false;
}
/**
* Array literals have their own scoping.
*/
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
return false;
}
/**
* Functions have their own scoping.
*/
@Override
public boolean visit(JsFunction x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
containsInvocation = true;
return false;
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (!x.isLeaf()) {
accept(x.getQualifier());
private JsConstructExpressionVisitor() {
}
return false;
}
/**
* New constructs bind to the nearest set of parentheses.
*/
@Override
public boolean visit(JsNew x, JsContext ctx) {
return false;
}
/**
* Object literals have their own scope.
*/
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
return false;
}
/**
* We only look at nodes that would not normally be surrounded by parentheses.
*/
@Override
public <T extends JsVisitable> T accept(T node) {
// Assign to Object to prevent 'inconvertible types' compile errors due
// to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436
// reproducible in jdk1.6.0_02.
if (node instanceof JsExpression) {
JsExpression expression = (JsExpression) node;
int precedence = JsPrecedenceVisitor.exec(expression);
// Only visit expressions that won't automatically be surrounded by
// parentheses
if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return node;
}
/**
* We only look at the array expression since the index has its own scope.
*/
@Override
public boolean visit(JsArrayAccess x, JsContext ctx) {
accept(x.getArrayExpression());
return false;
}
/**
* Array literals have their own scoping.
*/
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
return false;
}
/**
* Functions have their own scoping.
*/
@Override
public boolean visit(JsFunction x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
containsInvocation = true;
return false;
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (!x.isLeaf()) {
accept(x.getQualifier());
}
return false;
}
/**
* New constructs bind to the nearest set of parentheses.
*/
@Override
public boolean visit(JsNew x, JsContext ctx) {
return false;
}
/**
* Object literals have their own scope.
*/
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
return false;
}
/**
* We only look at nodes that would not normally be surrounded by parentheses.
*/
@Override
public <T extends JsNode> T accept(T node) {
// Assign to Object to prevent 'inconvertible types' compile errors due
// to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6548436
// reproducible in jdk1.6.0_02.
if (node instanceof JsExpression) {
JsExpression expression = (JsExpression) node;
int precedence = JsPrecedenceVisitor.exec(expression);
// Only visit expressions that won't automatically be surrounded by
// parentheses
if (precedence < JsPrecedenceVisitor.PRECEDENCE_NEW) {
return node;
}
}
return super.accept(node);
}
return super.accept(node);
}
}
@@ -112,9 +112,4 @@ public class JsFirstExpressionVisitor extends JsVisitor {
public boolean visit(JsPrefixOperation x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsRegExp x, JsContext ctx) {
return false;
}
}
@@ -10,271 +10,267 @@ import com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
/**
* Precedence indices from "JavaScript - The Definitive Guide" 4th Edition (page
* 57)
*
* <p/>
* Precedence 17 is for indivisible primaries that either don't have children,
* or provide their own delimiters.
*
* <p/>
* Precedence 16 is for really important things that have their own AST classes.
*
* <p/>
* Precedence 15 is for the new construct.
*
* <p/>
* Precedence 14 is for unary operators.
*
* <p/>
* Precedences 12 through 4 are for non-assigning binary operators.
*
* <p/>
* Precedence 3 is for the tertiary conditional.
*
* <p/>
* Precedence 2 is for assignments.
*
* <p/>
* Precedence 1 is for comma operations.
*/
class JsPrecedenceVisitor extends JsVisitor {
static final int PRECEDENCE_NEW = 15;
static final int PRECEDENCE_NEW = 15;
public static int exec(JsExpression expression) {
JsPrecedenceVisitor visitor = new JsPrecedenceVisitor();
visitor.accept(expression);
if (visitor.answer < 0) {
throw new RuntimeException("Precedence must be >= 0!");
public static int exec(JsExpression expression) {
JsPrecedenceVisitor visitor = new JsPrecedenceVisitor();
visitor.accept(expression);
if (visitor.answer < 0) {
throw new RuntimeException("Precedence must be >= 0!");
}
return visitor.answer;
}
return visitor.answer;
}
private int answer = -1;
private int answer = -1;
private JsPrecedenceVisitor() {
}
@Override
public boolean visit(JsArrayAccess x, JsContext ctx) {
answer = 16;
return false;
}
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsBinaryOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsBlock x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsBreak x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsCase x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsCatch x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsConditional x, JsContext ctx) {
answer = 3;
return false;
}
@Override
public boolean visit(JsContinue x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDebugger x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDefault x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDoWhile x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsEmpty x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsExpressionStatement x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsFor x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsForIn x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsFunction x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsIf x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
answer = 16;
return false;
}
@Override
public boolean visit(JsLabel x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (x.isLeaf()) {
answer = 17; // primary
} else {
answer = 16; // property access
private JsPrecedenceVisitor() {
}
return false;
}
@Override
public boolean visit(JsNew x, JsContext ctx) {
answer = PRECEDENCE_NEW;
return false;
}
@Override
public boolean visit(JsNullLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
public boolean visit(JsArrayAccess x, JsContext ctx) {
answer = 16;
return false;
}
@Override
public boolean visit(JsArrayLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
public boolean visit(JsBinaryOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsBlock x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsBreak x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsParameter x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsCase x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPostfixOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsCatch x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPrefixOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsConditional x, JsContext ctx) {
answer = 3;
return false;
}
@Override
public boolean visit(JsProgram x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsContinue x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsDebugger x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsRegExp x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsDefault x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsReturn x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsDoWhile x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsStringLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public void visit(JsEmpty x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsSwitch x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsExpressionStatement x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsFor x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsThrow x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsForIn x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsTry x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsFunction x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsVar x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsIf x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsVars x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsInvocation x, JsContext ctx) {
answer = 16;
return false;
}
@Override
public boolean visit(JsWhile x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLabel x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsNameRef x, JsContext ctx) {
if (x.isLeaf()) {
answer = 17; // primary
}
else {
answer = 16; // property access
}
return false;
}
@Override
public boolean visit(JsNew x, JsContext ctx) {
answer = PRECEDENCE_NEW;
return false;
}
@Override
public void visit(JsNullLiteral x, JsContext ctx) {
answer = 17; // primary
}
@Override
public void visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
answer = 17; // primary
}
@Override
public void visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
answer = 17; // primary
}
@Override
public boolean visit(JsObjectLiteral x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsParameter x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPostfixOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsPrefixOperation x, JsContext ctx) {
answer = x.getOperator().getPrecedence();
return false;
}
@Override
public boolean visit(JsProgram x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsPropertyInitializer x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public void visit(JsRegExp x, JsContext ctx) {
answer = 17; // primary
}
@Override
public boolean visit(JsReturn x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public void visit(JsStringLiteral x, JsContext ctx) {
answer = 17; // primary
}
@Override
public boolean visit(JsSwitch x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsLiteral.JsThisRef x, JsContext ctx) {
answer = 17; // primary
return false;
}
@Override
public boolean visit(JsThrow x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsTry x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsVar x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsVars x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
@Override
public boolean visit(JsWhile x, JsContext ctx) {
throw new RuntimeException("Only expressions have precedence.");
}
}
@@ -55,11 +55,6 @@ public class JsRequiresSemiVisitor extends JsVisitor {
return false;
}
@Override
public boolean visit(JsEmpty x, JsContext ctx) {
return false;
}
@Override
public boolean visit(JsExpressionStatement x, JsContext ctx) {
return false;
@@ -323,7 +323,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
public boolean visit(JsCase x, JsContext ctx) {
p.print(CHARS_CASE);
space();
accept(x.getCaseExpr());
accept(x.getCaseExpression());
_colon();
newlineOpt();
@@ -450,8 +450,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
}
@Override
public boolean visit(JsEmpty x, JsContext ctx) {
return false;
public void visit(JsEmpty x, JsContext ctx) {
}
@Override
@@ -650,12 +649,12 @@ public class JsToStringGenerationVisitor extends JsVisitor {
p.print(CHARS_NEW);
space();
JsExpression ctorExpr = x.getConstructorExpression();
boolean needsParens = JsConstructExpressionVisitor.exec(ctorExpr);
JsExpression constructorExpression = x.getConstructorExpression();
boolean needsParens = JsConstructExpressionVisitor.exec(constructorExpression);
if (needsParens) {
leftParen();
}
accept(ctorExpr);
accept(constructorExpression);
if (needsParens) {
rightParen();
}
@@ -668,21 +667,18 @@ public class JsToStringGenerationVisitor extends JsVisitor {
}
@Override
public boolean visit(JsNullLiteral x, JsContext ctx) {
public void visit(JsNullLiteral x, JsContext ctx) {
p.print(CHARS_NULL);
return false;
}
@Override
public boolean visit(JsIntLiteral x, JsContext ctx) {
public void visit(JsIntLiteral x, JsContext ctx) {
p.print(x.value);
return false;
}
@Override
public boolean visit(JsDoubleLiteral x, JsContext ctx) {
public void visit(JsDoubleLiteral x, JsContext ctx) {
p.print(x.value);
return false;
}
@Override
@@ -788,7 +784,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
}
@Override
public boolean visit(JsRegExp x, JsContext ctx) {
public void visit(JsRegExp x, JsContext ctx) {
_slash();
p.print(x.getPattern());
_slash();
@@ -796,13 +792,12 @@ public class JsToStringGenerationVisitor extends JsVisitor {
if (flags != null) {
p.print(flags);
}
return false;
}
@Override
public boolean visit(JsReturn x, JsContext ctx) {
p.print(CHARS_RETURN);
JsExpression expr = x.getExpr();
JsExpression expr = x.getExpression();
if (expr != null) {
space();
accept(expr);
@@ -811,9 +806,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
}
@Override
public boolean visit(JsStringLiteral x, JsContext ctx) {
public void visit(JsStringLiteral x, JsContext ctx) {
p.print(javaScriptString(x.getValue()));
return false;
}
@Override
@@ -1,7 +1,5 @@
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.SourceInfo;
public class ChameleonJsExpression implements JsExpression {
private JsExpression expression;
@@ -47,8 +45,13 @@ public class ChameleonJsExpression implements JsExpression {
}
@Override
public void traverse(JsVisitor visitor, JsContext context) {
expression.traverse(visitor, context);
public void accept(JsVisitor visitor, JsContext context) {
expression.accept(visitor, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
expression.acceptChildren(visitor, context);
}
@Override
@@ -10,6 +10,5 @@ import java.util.List;
* Implemented by JavaScript objects that accept arguments.
*/
public interface HasArguments extends JsExpression {
List<JsExpression> getArguments();
}
@@ -8,60 +8,62 @@ package com.google.dart.compiler.backend.js.ast;
* Represents a javascript expression for array access.
*/
public final class JsArrayAccess extends JsExpressionImpl {
private JsExpression arrayExpression;
private JsExpression indexExpression;
private JsExpression arrayExpression;
private JsExpression indexExpression;
public JsArrayAccess() {
super();
}
public JsArrayAccess(JsExpression arrayExpression, JsExpression indexExpression) {
this.arrayExpression = arrayExpression;
this.indexExpression = indexExpression;
}
public JsExpression getArrayExpression() {
return arrayExpression;
}
public JsExpression getIndexExpression() {
return indexExpression;
}
@Override
public boolean hasSideEffects() {
return arrayExpression.hasSideEffects() || indexExpression.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setArrayExpression(JsExpression arrayExpression) {
this.arrayExpression = arrayExpression;
}
public void setIndexExpression(JsExpression indexExpression) {
this.indexExpression = indexExpression;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
arrayExpression = v.accept(arrayExpression);
indexExpression = v.accept(indexExpression);
public JsArrayAccess() {
super();
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.ARRAY_ACCESS;
}
public JsArrayAccess(JsExpression arrayExpression, JsExpression indexExpression) {
this.arrayExpression = arrayExpression;
this.indexExpression = indexExpression;
}
public JsExpression getArrayExpression() {
return arrayExpression;
}
public JsExpression getIndexExpression() {
return indexExpression;
}
@Override
public boolean hasSideEffects() {
return arrayExpression.hasSideEffects() || indexExpression.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setArrayExpression(JsExpression arrayExpression) {
this.arrayExpression = arrayExpression;
}
public void setIndexExpression(JsExpression indexExpression) {
this.indexExpression = indexExpression;
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
arrayExpression = visitor.accept(arrayExpression);
indexExpression = visitor.accept(indexExpression);
}
@Override
public NodeKind getKind() {
return NodeKind.ARRAY_ACCESS;
}
}
@@ -57,11 +57,13 @@ public final class JsArrayLiteral extends JsLiteral {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.acceptWithInsertRemove(expressions);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.acceptWithInsertRemove(expressions);
}
@Override
@@ -10,91 +10,82 @@ import org.jetbrains.annotations.Nullable;
* Represents a JavaScript binary operation.
*/
public final class JsBinaryOperation extends JsExpressionImpl {
private JsExpression arg1;
private JsExpression arg2;
private final JsBinaryOperator op;
private JsExpression arg1;
private JsExpression arg2;
private final JsBinaryOperator op;
public JsBinaryOperation(JsBinaryOperator op) {
this(op, null, null);
}
public JsBinaryOperation(JsBinaryOperator op, @Nullable JsExpression arg1, @Nullable JsExpression arg2) {
this.op = op;
this.arg1 = arg1;
this.arg2 = arg2;
}
public JsExpression getArg1() {
return arg1;
}
public JsExpression getArg2() {
return arg2;
}
public JsBinaryOperator getOperator() {
return op;
}
@Override
public boolean hasSideEffects() {
return op.isAssignment() || arg1.hasSideEffects() || arg2.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
// Precarious coding, but none of these can have null results.
if (op.getPrecedence() > 5) {
return true;
public JsBinaryOperation(JsBinaryOperator op) {
this(op, null, null);
}
if (op == JsBinaryOperator.OR) {
if (arg1 instanceof CanBooleanEval) {
if (((CanBooleanEval) arg1).isBooleanTrue()) {
assert arg1.isDefinitelyNotNull();
return true;
public JsBinaryOperation(JsBinaryOperator op, @Nullable JsExpression arg1, @Nullable JsExpression arg2) {
this.op = op;
this.arg1 = arg1;
this.arg2 = arg2;
}
public JsExpression getArg1() {
return arg1;
}
public JsExpression getArg2() {
return arg2;
}
public JsBinaryOperator getOperator() {
return op;
}
@Override
public boolean hasSideEffects() {
return op.isAssignment() || arg1.hasSideEffects() || arg2.hasSideEffects();
}
@Override
public boolean isDefinitelyNotNull() {
// Precarious coding, but none of these can have null results.
if (op.getPrecedence() > 5) {
return true;
}
}
}
// AND and OR can return nulls
if (op.isAssignment()) {
if (op == JsBinaryOperator.ASG) {
return arg2.isDefinitelyNotNull();
} else {
// All other ASG's are math ops.
return true;
}
if (op == JsBinaryOperator.OR) {
if (arg1 instanceof CanBooleanEval) {
if (((CanBooleanEval) arg1).isBooleanTrue()) {
assert arg1.isDefinitelyNotNull();
return true;
}
}
}
// AND and OR can return nulls
if (op.isAssignment()) {
return op != JsBinaryOperator.ASG || arg2.isDefinitelyNotNull();
}
return op == JsBinaryOperator.COMMA && arg2.isDefinitelyNotNull();
}
if (op == JsBinaryOperator.COMMA) {
return arg2.isDefinitelyNotNull();
@Override
public boolean isDefinitelyNull() {
return op == JsBinaryOperator.AND && arg1.isDefinitelyNull();
}
return false;
}
@Override
public boolean isDefinitelyNull() {
if (op == JsBinaryOperator.AND) {
return arg1.isDefinitelyNull();
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
return false;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
if (op.isAssignment()) {
arg1 = v.acceptLvalue(arg1);
} else {
arg1 = v.accept(arg1);
}
arg2 = v.accept(arg2);
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
if (op.isAssignment()) {
arg1 = visitor.acceptLvalue(arg1);
}
else {
arg1 = visitor.accept(arg1);
}
arg2 = visitor.accept(arg2);
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.BINARY_OP;
}
@Override
public NodeKind getKind() {
return NodeKind.BINARY_OP;
}
}
@@ -44,11 +44,13 @@ public class JsBlock extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.acceptWithInsertRemove(statements);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.acceptWithInsertRemove(statements);
}
@Override
@@ -22,8 +22,7 @@ public final class JsBreak extends JsContinue {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
}
@@ -8,32 +8,33 @@ package com.google.dart.compiler.backend.js.ast;
* Represents the JavaScript case statement.
*/
public final class JsCase extends JsSwitchMember {
private JsExpression caseExpression;
private JsExpression caseExpr;
public JsCase() {
super();
}
public JsExpression getCaseExpr() {
return caseExpr;
}
public void setCaseExpr(JsExpression caseExpr) {
this.caseExpr = caseExpr;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
caseExpr = v.accept(caseExpr);
v.acceptWithInsertRemove(statements);
public JsCase() {
super();
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.CASE;
}
public JsExpression getCaseExpression() {
return caseExpression;
}
public void setCaseExpression(JsExpression caseExpression) {
this.caseExpression = caseExpression;
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
caseExpression = visitor.accept(caseExpression);
super.acceptChildren(visitor, context);
}
@Override
public NodeKind getKind() {
return NodeKind.CASE;
}
}
@@ -9,58 +9,60 @@ package com.google.dart.compiler.backend.js.ast;
*/
public class JsCatch extends JsNodeImpl implements HasCondition {
protected final JsCatchScope scope;
private JsBlock body;
private JsExpression condition;
private JsParameter param;
protected final JsCatchScope scope;
private JsBlock body;
private JsExpression condition;
private JsParameter param;
public JsCatch(JsScope parent, String ident) {
super();
assert (parent != null);
scope = new JsCatchScope(parent, ident);
param = new JsParameter(scope.findName(ident));
}
public JsBlock getBody() {
return body;
}
@Override
public JsExpression getCondition() {
return condition;
}
public JsParameter getParameter() {
return param;
}
public JsScope getScope() {
return scope;
}
public void setBody(JsBlock body) {
this.body = body;
}
@Override
public void setCondition(JsExpression condition) {
this.condition = condition;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
param = v.accept(param);
if (condition != null) {
condition = v.accept(condition);
}
body = v.accept(body);
public JsCatch(JsScope parent, String ident) {
super();
assert (parent != null);
scope = new JsCatchScope(parent, ident);
param = new JsParameter(scope.findName(ident));
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.CATCH;
}
public JsBlock getBody() {
return body;
}
@Override
public JsExpression getCondition() {
return condition;
}
public JsParameter getParameter() {
return param;
}
public JsScope getScope() {
return scope;
}
public void setBody(JsBlock body) {
this.body = body;
}
@Override
public void setCondition(JsExpression condition) {
this.condition = condition;
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
param = visitor.accept(param);
if (condition != null) {
condition = visitor.accept(condition);
}
body = visitor.accept(body);
}
@Override
public NodeKind getKind() {
return NodeKind.CATCH;
}
}
@@ -61,13 +61,15 @@ public final class JsConditional extends JsExpressionImpl {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
testExpr = v.accept(testExpr);
thenExpr = v.accept(thenExpr);
elseExpr = v.accept(elseExpr);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
testExpr = visitor.accept(testExpr);
thenExpr = visitor.accept(thenExpr);
elseExpr = visitor.accept(elseExpr);
}
@Override
@@ -14,13 +14,13 @@ public interface JsContext {
boolean canRemove();
void insertAfter(JsVisitable node);
void insertAfter(JsNode node);
void insertBefore(JsVisitable node);
void insertBefore(JsNode node);
boolean isLvalue();
void removeMe();
void replaceMe(JsVisitable node);
void replaceMe(JsNode node);
}
@@ -6,9 +6,6 @@ package com.google.dart.compiler.backend.js.ast;
import org.jetbrains.annotations.Nullable;
/**
* Represents the JavaScript continue statement.
*/
public class JsContinue extends JsNodeImpl implements JsStatement {
protected final String label;
@@ -26,9 +23,13 @@ public class JsContinue extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
}
@Override
@@ -13,12 +13,16 @@ public class JsDebugger extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
}
@Override
public NodeKind getKind() {
return NodeKind.DEBUGGER;
}
@@ -8,17 +8,9 @@ package com.google.dart.compiler.backend.js.ast;
* Represents the default option in a JavaScript swtich statement.
*/
public final class JsDefault extends JsSwitchMember {
public JsDefault() {
super();
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.acceptWithInsertRemove(statements);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
@@ -21,11 +21,10 @@ public class JsDoWhile extends JsWhile {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
condition = v.accept(condition);
body = v.accept(body);
}
v.endVisit(this, context);
}
}
@@ -28,10 +28,15 @@ public class JsDocComment extends JsExpressionImpl {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
}
@Override
public boolean hasSideEffects() {
return false;
@@ -4,22 +4,21 @@
package com.google.dart.compiler.backend.js.ast;
/**
* Represents an empty statement in JavaScript.
*/
public class JsEmpty extends JsNodeImpl implements JsStatement {
// Interned by JsProgram
JsEmpty() {
}
JsEmpty() {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.EMPTY;
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
}
@Override
public NodeKind getKind() {
return NodeKind.EMPTY;
}
}
@@ -2,7 +2,7 @@ package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.HasSourceInfo;
public interface JsExpression extends JsNode, HasSourceInfo, JsVisitable {
public interface JsExpression extends JsNode, HasSourceInfo {
/**
* Determines whether the expression can cause side effects.
*/
@@ -4,6 +4,8 @@
package com.google.dart.compiler.backend.js.ast;
import java.util.List;
abstract class JsExpressionImpl extends JsNodeImpl implements JsExpression {
protected JsExpressionImpl() {
}
@@ -24,4 +26,17 @@ abstract class JsExpressionImpl extends JsNodeImpl implements JsExpression {
public JsStatement makeStmt() {
return new JsExpressionStatement(this);
}
protected abstract static class JsExpressionHasArguments extends JsExpressionImpl implements HasArguments {
protected final List<JsExpression> arguments;
public JsExpressionHasArguments(List<JsExpression> arguments) {
this.arguments = arguments;
}
@Override
public List<JsExpression> getArguments() {
return arguments;
}
}
}
@@ -16,11 +16,13 @@ public final class JsExpressionStatement extends AbstractNode implements JsState
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
expression = v.accept(expression);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
expression = visitor.accept(expression);
}
@Override
@@ -71,27 +71,29 @@ public class JsFor extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
assert (!(initExpression != null && initVars != null));
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
if (initExpression != null) {
initExpression = v.accept(initExpression);
}
else if (initVars != null) {
initVars = v.accept(initVars);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
assert (!(initExpression != null && initVars != null));
if (condition != null) {
condition = v.accept(condition);
}
if (incrementExpression != null) {
incrementExpression = v.accept(incrementExpression);
}
body = v.accept(body);
if (initExpression != null) {
initExpression = visitor.accept(initExpression);
}
v.endVisit(this, context);
else if (initVars != null) {
initVars = visitor.accept(initVars);
}
if (condition != null) {
condition = visitor.accept(condition);
}
if (incrementExpression != null) {
incrementExpression = visitor.accept(incrementExpression);
}
body = visitor.accept(body);
}
@Override
@@ -8,64 +8,67 @@ package com.google.dart.compiler.backend.js.ast;
* Represents a JavaScript for..in statement.
*/
public class JsForIn extends JsNodeImpl implements JsStatement {
private JsStatement body;
private JsExpression iterExpr;
private JsExpression objExpr;
private JsStatement body;
private JsExpression iterExpr;
private JsExpression objExpr;
// Optional: the name of a new iterator variable to introduce
private final JsName iterVarName;
// 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 getIterExpr() {
return iterExpr;
}
public JsName getIterVarName() {
return iterVarName;
}
public JsExpression getObjExpr() {
return objExpr;
}
public void setBody(JsStatement body) {
this.body = body;
}
public void setIterExpr(JsExpression iterExpr) {
this.iterExpr = iterExpr;
}
public void setObjExpr(JsExpression objExpr) {
this.objExpr = objExpr;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
if (iterExpr != null) {
iterExpr = v.acceptLvalue(iterExpr);
}
objExpr = v.accept(objExpr);
body = v.accept(body);
public JsForIn() {
this(null);
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.FOR_IN;
}
public JsForIn(JsName iterVarName) {
this.iterVarName = iterVarName;
}
public JsStatement getBody() {
return body;
}
public JsExpression getIterExpr() {
return iterExpr;
}
public JsName getIterVarName() {
return iterVarName;
}
public JsExpression getObjExpr() {
return objExpr;
}
public void setBody(JsStatement body) {
this.body = body;
}
public void setIterExpr(JsExpression iterExpr) {
this.iterExpr = iterExpr;
}
public void setObjExpr(JsExpression objExpr) {
this.objExpr = objExpr;
}
@Override
public void accept(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
}
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
if (iterExpr != null) {
iterExpr = visitor.acceptLvalue(iterExpr);
}
objExpr = visitor.accept(objExpr);
body = visitor.accept(body);
}
@Override
public NodeKind getKind() {
return NodeKind.FOR_IN;
}
}
@@ -90,12 +90,14 @@ public final class JsFunction extends JsLiteral implements HasName {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.acceptWithInsertRemove(params);
body = v.accept(body);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.acceptWithInsertRemove(params);
body = visitor.accept(body);
}
@Override
@@ -51,15 +51,17 @@ public final class JsIf extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
ifExpression = v.accept(ifExpression);
thenStatement = v.accept(thenStatement);
if (elseStatement != null) {
elseStatement = v.accept(elseStatement);
}
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
ifExpression = visitor.accept(ifExpression);
thenStatement = visitor.accept(thenStatement);
if (elseStatement != null) {
elseStatement = visitor.accept(elseStatement);
}
}
@Override
@@ -13,17 +13,16 @@ import java.util.List;
/**
* Represents a JavaScript invocation.
*/
public final class JsInvocation extends JsExpressionImpl implements HasArguments {
private final List<JsExpression> arguments;
public final class JsInvocation extends JsExpressionImpl.JsExpressionHasArguments {
private JsExpression qualifier;
public JsInvocation() {
arguments = new SmartList<JsExpression>();
super(new SmartList<JsExpression>());
}
public JsInvocation(JsExpression qualifier, List<JsExpression> arguments) {
super(arguments);
this.qualifier = qualifier;
this.arguments = arguments;
}
public JsInvocation(JsExpression qualifier, JsExpression arg) {
@@ -68,12 +67,14 @@ public final class JsInvocation extends JsExpressionImpl implements HasArguments
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
qualifier = v.accept(qualifier);
v.acceptList(arguments);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
qualifier = visitor.accept(qualifier);
visitor.acceptList(arguments);
}
@Override
@@ -42,12 +42,14 @@ public class JsLabel extends JsNodeImpl implements JsStatement, HasName {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
statement = v.accept(statement);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
statement = visitor.accept(statement);
}
@Override
public NodeKind getKind() {
@@ -43,9 +43,8 @@ public abstract class JsLiteral extends JsExpressionImpl implements CanBooleanEv
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
@@ -87,9 +86,8 @@ public abstract class JsLiteral extends JsExpressionImpl implements CanBooleanEv
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
@@ -97,4 +95,26 @@ public abstract class JsLiteral extends JsExpressionImpl implements CanBooleanEv
return NodeKind.BOOLEAN;
}
}
/**
* A JavaScript string literal expression.
*/
public abstract static class JsValueLiteral extends JsLiteral {
protected JsValueLiteral() {
}
@Override
public final boolean hasSideEffects() {
return false;
}
@Override
public final boolean isLeaf() {
return true;
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
}
}
}
@@ -56,14 +56,7 @@ public final class JsNameRef extends JsExpressionImpl implements CanBooleanEval,
@Override
public boolean hasSideEffects() {
if (qualifier == null) {
return false;
}
if (!qualifier.isDefinitelyNotNull()) {
// Could trigger NPE.
return true;
}
return qualifier.hasSideEffects();
return qualifier != null && (!qualifier.isDefinitelyNotNull() || qualifier.hasSideEffects());
}
@Override
@@ -83,25 +76,17 @@ public final class JsNameRef extends JsExpressionImpl implements CanBooleanEval,
@Override
public boolean isDefinitelyNull() {
if (name != null) {
return (JsLiteral.UNDEFINED.getName() == name);
}
return false;
return name != null && (JsLiteral.UNDEFINED.getName() == name);
}
@Override
public boolean isLeaf() {
if (qualifier == null) {
return true;
}
else {
return false;
}
return qualifier == null;
}
public void resolve(JsName name) {
this.name = name;
this.ident = null;
ident = null;
}
public void setQualifier(JsExpression qualifier) {
@@ -109,13 +94,15 @@ public final class JsNameRef extends JsExpressionImpl implements CanBooleanEval,
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
if (qualifier != null) {
qualifier = v.accept(qualifier);
}
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
if (qualifier != null) {
qualifier = visitor.accept(qualifier);
}
}
@Override
@@ -8,29 +8,20 @@ import com.intellij.util.SmartList;
import java.util.List;
/**
* Represents the JavaScript new expression.
*/
public final class JsNew extends JsExpressionImpl implements HasArguments {
private final List<JsExpression> arguments;
private JsExpression ctorExpression;
public final class JsNew extends JsExpressionImpl.JsExpressionHasArguments {
private JsExpression constructorExpression;
public JsNew(JsExpression ctorExpression) {
this(ctorExpression, new SmartList<JsExpression>());
public JsNew(JsExpression constructorExpression) {
this(constructorExpression, new SmartList<JsExpression>());
}
public JsNew(JsExpression ctorExpression, List<JsExpression> arguments) {
this.ctorExpression = ctorExpression;
this.arguments = arguments;
}
@Override
public List<JsExpression> getArguments() {
return arguments;
public JsNew(JsExpression constructorExpression, List<JsExpression> arguments) {
super(arguments);
this.constructorExpression = constructorExpression;
}
public JsExpression getConstructorExpression() {
return ctorExpression;
return constructorExpression;
}
@Override
@@ -51,12 +42,14 @@ public final class JsNew extends JsExpressionImpl implements HasArguments {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
ctorExpression = v.accept(ctorExpression);
v.acceptList(arguments);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
constructorExpression = visitor.accept(constructorExpression);
visitor.acceptList(arguments);
}
@Override
@@ -4,6 +4,16 @@
package com.google.dart.compiler.backend.js.ast;
public interface JsNode extends JsVisitable {
public interface JsNode {
NodeKind getKind();
/**
* Causes this object to have the visitor visit itself and its children.
*
* @param visitor the visitor that should traverse this node
* @param context the context of an existing traversal
*/
void accept(JsVisitor visitor, JsContext context);
void acceptChildren(JsVisitor visitor, JsContext context);
}
@@ -1,7 +1,5 @@
package com.google.dart.compiler.backend.js.ast;
import com.google.dart.compiler.common.SourceInfo;
abstract class JsNodeImpl extends AbstractNode {
private Object sourceInfo;
@@ -4,7 +4,7 @@
package com.google.dart.compiler.backend.js.ast;
public final class JsNullLiteral extends JsValueLiteral {
public final class JsNullLiteral extends JsLiteral.JsValueLiteral {
JsNullLiteral() {
}
@@ -29,9 +29,8 @@ public final class JsNullLiteral extends JsValueLiteral {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
@@ -4,7 +4,7 @@
package com.google.dart.compiler.backend.js.ast;
public abstract class JsNumberLiteral extends JsValueLiteral {
public abstract class JsNumberLiteral extends JsLiteral.JsValueLiteral {
@Override
public boolean isDefinitelyNotNull() {
return true;
@@ -38,9 +38,8 @@ public abstract class JsNumberLiteral extends JsValueLiteral {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
public String toString() {
@@ -66,9 +65,8 @@ public abstract class JsNumberLiteral extends JsValueLiteral {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
public String toString() {
@@ -69,11 +69,13 @@ public final class JsObjectLiteral extends JsLiteral {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.acceptWithInsertRemove(properties);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.acceptWithInsertRemove(properties);
}
@Override
@@ -10,30 +10,34 @@ import com.google.dart.compiler.common.Symbol;
* A JavaScript parameter.
*/
public final class JsParameter extends JsNodeImpl implements HasName {
private final JsName name;
private final JsName name;
public JsParameter(JsName name) {
this.name = name;
}
public JsParameter(JsName name) {
this.name = name;
}
@Override
public JsName getName() {
return name;
}
@Override
public JsName getName() {
return name;
}
@Override
public Symbol getSymbol() {
return name;
}
@Override
public Symbol getSymbol() {
return name;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.PARAMETER;
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
}
@Override
public NodeKind getKind() {
return NodeKind.PARAMETER;
}
}
@@ -28,11 +28,8 @@ public final class JsPostfixOperation extends JsUnaryOperation {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
super.traverse(v, context);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
@@ -4,9 +4,6 @@
package com.google.dart.compiler.backend.js.ast;
/**
* A JavaScript prefix operation.
*/
public final class JsPrefixOperation extends JsUnaryOperation implements CanBooleanEval {
public JsPrefixOperation(JsUnaryOperator op) {
@@ -35,18 +32,12 @@ public final class JsPrefixOperation extends JsUnaryOperation implements CanBool
CanBooleanEval eval = (CanBooleanEval) getArg();
return eval.isBooleanFalse();
}
if (getOperator() == JsUnaryOperator.TYPEOF) {
return true;
}
return false;
return getOperator() == JsUnaryOperator.TYPEOF;
}
@Override
public boolean isDefinitelyNotNull() {
if (getOperator() == JsUnaryOperator.TYPEOF) {
return true;
}
return getOperator() != JsUnaryOperator.VOID;
return getOperator() == JsUnaryOperator.TYPEOF || getOperator() != JsUnaryOperator.VOID;
}
@Override
@@ -55,11 +46,8 @@ public final class JsPrefixOperation extends JsUnaryOperation implements CanBool
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
super.traverse(v, context);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
@@ -18,7 +18,7 @@ import static com.google.dart.compiler.backend.js.ast.JsNumberLiteral.JsIntLiter
* A JavaScript program.
*/
public final class JsProgram extends JsNodeImpl {
private final JsEmpty emptyStmt;
private final JsEmpty emptyStatement;
private JsProgramFragment[] fragments;
@@ -29,19 +29,16 @@ public final class JsProgram extends JsNodeImpl {
private final Map<String, JsStringLiteral> stringLiteralMap = new THashMap<String, JsStringLiteral>();
private final JsScope topScope;
/**
* Constructs a JavaScript program object.
*/
public JsProgram(String unitId) {
rootScope = new JsRootScope(this);
topScope = new JsScope(rootScope, "Global", unitId);
setFragmentCount(1);
emptyStmt = new JsEmpty();
emptyStatement = new JsEmpty();
}
public JsEmpty getEmptyStmt() {
return emptyStmt;
public JsEmpty getEmptyStatement() {
return emptyStatement;
}
public JsBlock getFragmentBlock(int fragment) {
@@ -112,13 +109,15 @@ public final class JsProgram extends JsNodeImpl {
}
@Override
public void traverse(JsVisitor v, @Nullable JsContext context) {
if (v.visit(this, context)) {
for (JsProgramFragment fragment : fragments) {
v.accept(fragment);
}
public void accept(JsVisitor v, @Nullable JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
for (JsProgramFragment fragment : fragments) {
visitor.accept(fragment);
}
v.endVisit(this, context);
}
@Override
@@ -8,27 +8,28 @@ package com.google.dart.compiler.backend.js.ast;
* One independently loadable fragment of a {@link JsProgram}.
*/
public class JsProgramFragment extends JsNodeImpl {
private final JsGlobalBlock globalBlock;
private final JsGlobalBlock globalBlock;
public JsProgramFragment() {
this.globalBlock = new JsGlobalBlock();
}
public JsBlock getGlobalBlock() {
return globalBlock;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.accept(globalBlock);
public JsProgramFragment() {
globalBlock = new JsGlobalBlock();
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM_FRAGMENT;
}
public JsBlock getGlobalBlock() {
return globalBlock;
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.accept(globalBlock);
}
@Override
public NodeKind getKind() {
return NodeKind.PROGRAM_FRAGMENT;
}
}
@@ -39,12 +39,14 @@ public class JsPropertyInitializer extends JsNodeImpl {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
labelExpr = v.accept(labelExpr);
valueExpr = v.accept(valueExpr);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
labelExpr = visitor.accept(labelExpr);
valueExpr = visitor.accept(valueExpr);
}
@Override
@@ -7,58 +7,56 @@ package com.google.dart.compiler.backend.js.ast;
/**
* A JavaScript regular expression.
*/
public final class JsRegExp extends JsValueLiteral {
public final class JsRegExp extends JsLiteral.JsValueLiteral {
private String flags;
private String pattern;
private String flags;
private String pattern;
public JsRegExp() {
}
public JsRegExp() {
}
public String getFlags() {
return flags;
}
public String getFlags() {
return flags;
}
public String getPattern() {
return pattern;
}
public String getPattern() {
return pattern;
}
@Override
public boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanFalse() {
return false;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isBooleanTrue() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNotNull() {
return true;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
@Override
public boolean isDefinitelyNull() {
return false;
}
public void setFlags(String suffix) {
flags = suffix;
}
public void setFlags(String suffix) {
this.flags = suffix;
}
public void setPattern(String re) {
pattern = re;
}
public void setPattern(String re) {
this.pattern = re;
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void traverse(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.REGEXP;
}
@Override
public NodeKind getKind() {
return NodeKind.REGEXP;
}
}
@@ -8,36 +8,37 @@ package com.google.dart.compiler.backend.js.ast;
* A JavaScript return statement.
*/
public final class JsReturn extends JsNodeImpl implements JsStatement {
private JsExpression expression;
private JsExpression expr;
public JsReturn() {
}
public JsReturn(JsExpression expr) {
this.expr = expr;
}
public JsExpression getExpr() {
return expr;
}
public void setExpr(JsExpression expr) {
this.expr = expr;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
if (expr != null) {
expr = v.accept(expr);
}
public JsReturn() {
}
public JsReturn(JsExpression expression) {
this.expression = expression;
}
public JsExpression getExpression() {
return expression;
}
public void setExpression(JsExpression expression) {
this.expression = expression;
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.RETURN;
}
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
if (expression != null) {
expression = visitor.accept(expression);
}
}
@Override
public NodeKind getKind() {
return NodeKind.RETURN;
}
}
@@ -67,8 +67,8 @@ public class JsScope {
protected JsScope(@Nullable String description) {
this.description = description;
this.parent = null;
this.scopeId = null;
parent = null;
scopeId = null;
}
/**
@@ -7,7 +7,7 @@ package com.google.dart.compiler.backend.js.ast;
/**
* A JavaScript string literal expression.
*/
public final class JsStringLiteral extends JsValueLiteral {
public final class JsStringLiteral extends JsLiteral.JsValueLiteral {
private final String value;
@@ -41,9 +41,8 @@ public final class JsStringLiteral extends JsValueLiteral {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
v.endVisit(this, context);
}
@Override
@@ -12,36 +12,38 @@ import java.util.List;
*/
public class JsSwitch extends JsNodeImpl implements JsStatement {
private final List<JsSwitchMember> cases = new ArrayList<JsSwitchMember>();
private JsExpression expr;
private final List<JsSwitchMember> cases = new ArrayList<JsSwitchMember>();
private JsExpression expr;
public JsSwitch() {
super();
}
public List<JsSwitchMember> getCases() {
return cases;
}
public JsExpression getExpr() {
return expr;
}
public void setExpr(JsExpression expr) {
this.expr = expr;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
expr = v.accept(expr);
v.acceptWithInsertRemove(cases);
public JsSwitch() {
super();
}
v.endVisit(this, context);
}
@Override
public NodeKind getKind() {
return NodeKind.SWITCH;
}
public List<JsSwitchMember> getCases() {
return cases;
}
public JsExpression getExpr() {
return expr;
}
public void setExpr(JsExpression expr) {
this.expr = expr;
}
@Override
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
expr = visitor.accept(expr);
visitor.acceptWithInsertRemove(cases);
}
@Override
public NodeKind getKind() {
return NodeKind.SWITCH;
}
}
@@ -21,4 +21,9 @@ public abstract class JsSwitchMember extends JsNodeImpl {
public List<JsStatement> getStatements() {
return statements;
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.acceptWithInsertRemove(statements);
}
}
@@ -23,11 +23,13 @@ public class JsThrow extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
expression = v.accept(expression);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.accept(expression);
}
@Override
@@ -40,7 +40,7 @@ public class JsTry extends JsNodeImpl implements JsStatement {
}
public void setFinallyBlock(JsBlock block) {
this.finallyBlock = block;
finallyBlock = block;
}
public void setTryBlock(JsBlock block) {
@@ -48,15 +48,17 @@ public class JsTry extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
tryBlock = v.accept(tryBlock);
v.acceptWithInsertRemove(catches);
if (finallyBlock != null) {
finallyBlock = v.accept(finallyBlock);
}
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
tryBlock = visitor.accept(tryBlock);
visitor.acceptWithInsertRemove(catches);
if (finallyBlock != null) {
finallyBlock = visitor.accept(finallyBlock);
}
v.endVisit(this, context);
}
@Override
@@ -9,45 +9,46 @@ package com.google.dart.compiler.backend.js.ast;
*/
public abstract class JsUnaryOperation extends JsExpressionImpl {
private JsExpression arg;
private JsExpression arg;
private final JsUnaryOperator op;
private final JsUnaryOperator op;
public JsUnaryOperation(JsUnaryOperator op) {
this(op, null);
}
public JsUnaryOperation(JsUnaryOperator op, JsExpression arg) {
super();
this.op = op;
this.arg = arg;
}
public JsExpression getArg() {
return arg;
}
public JsUnaryOperator getOperator() {
return op;
}
@Override
public final boolean hasSideEffects() {
return op.isModifying() || arg.hasSideEffects();
}
public void setArg(JsExpression arg) {
this.arg = arg;
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (op.isModifying()) {
// The delete operator is practically like an assignment of undefined, so
// for practical purposes we're treating it as an lvalue.
arg = v.acceptLvalue(arg);
} else {
arg = v.accept(arg);
public JsUnaryOperation(JsUnaryOperator op) {
this(op, null);
}
public JsUnaryOperation(JsUnaryOperator op, JsExpression arg) {
super();
this.op = op;
this.arg = arg;
}
public JsExpression getArg() {
return arg;
}
public JsUnaryOperator getOperator() {
return op;
}
@Override
public final boolean hasSideEffects() {
return op.isModifying() || arg.hasSideEffects();
}
public void setArg(JsExpression arg) {
this.arg = arg;
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
if (op.isModifying()) {
// The delete operator is practically like an assignment of undefined, so
// for practical purposes we're treating it as an lvalue.
arg = visitor.acceptLvalue(arg);
}
else {
arg = visitor.accept(arg);
}
}
}
}
@@ -1,23 +0,0 @@
// 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;
/**
* A JavaScript string literal expression.
*/
public abstract class JsValueLiteral extends JsLiteral {
protected JsValueLiteral() {
}
@Override
public final boolean hasSideEffects() {
return false;
}
@Override
public final boolean isLeaf() {
return true;
}
}
@@ -81,13 +81,15 @@ public class JsVars extends JsNodeImpl implements JsStatement, Iterable<JsVars.J
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
if (initExpression != null) {
initExpression = v.accept(initExpression);
}
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
if (initExpression != null) {
initExpression = visitor.accept(initExpression);
}
v.endVisit(this, context);
}
@Override
@@ -116,11 +118,13 @@ public class JsVars extends JsNodeImpl implements JsStatement, Iterable<JsVars.J
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
v.acceptWithInsertRemove(vars);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
visitor.acceptWithInsertRemove(vars);
}
@Override
@@ -1,17 +0,0 @@
// 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.HasSourceInfo;
public interface JsVisitable extends HasSourceInfo {
/**
* Causes this object to have the visitor visit itself and its children.
*
* @param visitor the visitor that should traverse this node
* @param context the context of an existing traversal
*/
void traverse(JsVisitor visitor, JsContext context);
}
@@ -8,10 +8,7 @@ import com.google.dart.compiler.backend.js.ast.JsVars.JsVar;
import java.util.List;
/**
* Implemented by nodes that will visit child nodes.
*/
abstract public class JsVisitor {
public abstract class JsVisitor {
protected static final JsContext LVALUE_CONTEXT = new JsContext() {
@Override
public boolean canInsert() {
@@ -24,12 +21,12 @@ abstract public class JsVisitor {
}
@Override
public void insertAfter(JsVisitable node) {
public void insertAfter(JsNode node) {
throw new UnsupportedOperationException();
}
@Override
public void insertBefore(JsVisitable node) {
public void insertBefore(JsNode node) {
throw new UnsupportedOperationException();
}
@@ -44,13 +41,12 @@ abstract public class JsVisitor {
}
@Override
public void replaceMe(JsVisitable node) {
public void replaceMe(JsNode node) {
throw new UnsupportedOperationException();
}
};
protected static final JsContext UNMODIFIABLE_CONTEXT = new JsContext() {
@Override
public boolean canInsert() {
return false;
@@ -62,12 +58,12 @@ abstract public class JsVisitor {
}
@Override
public void insertAfter(JsVisitable node) {
public void insertAfter(JsNode node) {
throw new UnsupportedOperationException();
}
@Override
public void insertBefore(JsVisitable node) {
public void insertBefore(JsNode node) {
throw new UnsupportedOperationException();
}
@@ -82,17 +78,17 @@ abstract public class JsVisitor {
}
@Override
public void replaceMe(JsVisitable node) {
public void replaceMe(JsNode node) {
throw new UnsupportedOperationException();
}
};
public <T extends JsVisitable> T accept(T node) {
public <T extends JsNode> T accept(T node) {
doTraverse(node, UNMODIFIABLE_CONTEXT);
return node;
}
public final <T extends JsVisitable> void acceptList(List<T> collection) {
public final <T extends JsNode> void acceptList(List<T> collection) {
for (T node : collection) {
doTraverse(node, UNMODIFIABLE_CONTEXT);
}
@@ -103,138 +99,12 @@ abstract public class JsVisitor {
return expr;
}
public final <T extends JsVisitable> void acceptWithInsertRemove(List<T> collection) {
public final <T extends JsNode> void acceptWithInsertRemove(List<T> collection) {
for (T node : collection) {
doTraverse(node, UNMODIFIABLE_CONTEXT);
}
}
public void endVisit(JsArrayAccess x, JsContext ctx) {
}
public void endVisit(JsArrayLiteral x, JsContext ctx) {
}
public void endVisit(JsBinaryOperation x, JsContext ctx) {
}
public void endVisit(JsBlock x, JsContext ctx) {
}
public void endVisit(JsLiteral.JsBooleanLiteral x, JsContext ctx) {
}
public void endVisit(JsBreak x, JsContext ctx) {
}
public void endVisit(JsCase x, JsContext ctx) {
}
public void endVisit(JsCatch x, JsContext ctx) {
}
public void endVisit(JsConditional x, JsContext ctx) {
}
public void endVisit(JsContinue x, JsContext ctx) {
}
public void endVisit(JsDebugger x, JsContext ctx) {
}
public void endVisit(JsDefault x, JsContext ctx) {
}
public void endVisit(JsDoWhile x, JsContext ctx) {
}
public void endVisit(JsEmpty x, JsContext ctx) {
}
public void endVisit(JsExpressionStatement x, JsContext ctx) {
}
public void endVisit(JsFor x, JsContext ctx) {
}
public void endVisit(JsForIn x, JsContext ctx) {
}
public void endVisit(JsFunction x, JsContext ctx) {
}
public void endVisit(JsIf x, JsContext ctx) {
}
public void endVisit(JsInvocation x, JsContext ctx) {
}
public void endVisit(JsLabel x, JsContext ctx) {
}
public void endVisit(JsNameRef x, JsContext ctx) {
}
public void endVisit(JsNew x, JsContext ctx) {
}
public void endVisit(JsNullLiteral x, JsContext ctx) {
}
public void endVisit(JsNumberLiteral x, JsContext ctx) {
}
public void endVisit(JsObjectLiteral x, JsContext ctx) {
}
public void endVisit(JsParameter x, JsContext ctx) {
}
public void endVisit(JsPostfixOperation x, JsContext ctx) {
}
public void endVisit(JsPrefixOperation x, JsContext ctx) {
}
public void endVisit(JsProgram x, JsContext ctx) {
}
public void endVisit(JsProgramFragment x, JsContext ctx) {
}
public void endVisit(JsPropertyInitializer x, JsContext ctx) {
}
public void endVisit(JsRegExp x, JsContext ctx) {
}
public void endVisit(JsReturn x, JsContext ctx) {
}
public void endVisit(JsStringLiteral x, JsContext ctx) {
}
public void endVisit(JsSwitch x, JsContext ctx) {
}
public void endVisit(JsLiteral.JsThisRef x, JsContext ctx) {
}
public void endVisit(JsThrow x, JsContext ctx) {
}
public void endVisit(JsTry x, JsContext ctx) {
}
public void endVisit(JsVar x, JsContext ctx) {
}
public void endVisit(JsVars x, JsContext ctx) {
}
public void endVisit(JsWhile x, JsContext ctx) {
}
public boolean visit(JsArrayAccess x, JsContext ctx) {
return true;
}
@@ -287,8 +157,7 @@ abstract public class JsVisitor {
return true;
}
public boolean visit(JsEmpty x, JsContext ctx) {
return true;
public void visit(JsEmpty x, JsContext ctx) {
}
public boolean visit(JsExpressionStatement x, JsContext ctx) {
@@ -327,16 +196,13 @@ abstract public class JsVisitor {
return true;
}
public boolean visit(JsNullLiteral x, JsContext ctx) {
return true;
public void visit(JsNullLiteral x, JsContext ctx) {
}
public boolean visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
return true;
public void visit(JsNumberLiteral.JsIntLiteral x, JsContext ctx) {
}
public boolean visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
return true;
public void visit(JsNumberLiteral.JsDoubleLiteral x, JsContext ctx) {
}
public boolean visit(JsObjectLiteral x, JsContext ctx) {
@@ -367,16 +233,14 @@ abstract public class JsVisitor {
return true;
}
public boolean visit(JsRegExp x, JsContext ctx) {
return true;
public void visit(JsRegExp x, JsContext ctx) {
}
public boolean visit(JsReturn x, JsContext ctx) {
return true;
}
public boolean visit(JsStringLiteral x, JsContext ctx) {
return true;
public void visit(JsStringLiteral x, JsContext ctx) {
}
public boolean visit(JsSwitch x, JsContext ctx) {
@@ -411,7 +275,7 @@ abstract public class JsVisitor {
return true;
}
protected void doTraverse(JsVisitable node, JsContext context) {
node.traverse(this, context);
protected void doTraverse(JsNode node, JsContext context) {
node.accept(this, context);
}
}
}
@@ -36,12 +36,14 @@ public class JsWhile extends JsNodeImpl implements JsStatement {
}
@Override
public void traverse(JsVisitor v, JsContext context) {
if (v.visit(this, context)) {
condition = v.accept(condition);
body = v.accept(body);
}
v.endVisit(this, context);
public void accept(JsVisitor v, JsContext context) {
v.visit(this, context);
}
@Override
public void acceptChildren(JsVisitor visitor, JsContext context) {
condition = visitor.accept(condition);
body = visitor.accept(body);
}
@Override
@@ -0,0 +1,4 @@
package com.google.dart.compiler.backend.js.ast;
public abstract class RecursiveJsVisitor extends JsVisitor {
}