Submitting changes/scottb/compiler_refactor into the trunk.
MAJOR compiler refactor:
- Java AST visitation/traversal was refactored
- Java AST changes are applied using the new JModVistor
- Removed the whole idea of change lists
- Java AST now contains file/line source info from JDT
New DeadCodeElimination visitor base on patch by sandymac:
- Optimizes if (booleanConstant); while (false); for (; false; ); do while (false)
- Optimizes !booleanConstant
- Short-circuit eval of binary operators && and ||
- Removes unnecessary try blocks
- Removes empty blocks
TODO:
- Revisit design of JVisitor/JModVisitor
- Implement InternalCompilerException.addNode() and log much better info when an ICE occurs
Patch by: sandymac (just DeadCodeElimination.java; adapted by me)
Reviewed by: mmendez
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@340 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
index e0503cb..262ca4d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -36,6 +36,7 @@
import com.google.gwt.dev.jjs.impl.CastOptimizer;
import com.google.gwt.dev.jjs.impl.CatchBlockNormalizer;
import com.google.gwt.dev.jjs.impl.CompoundAssignmentNormalizer;
+import com.google.gwt.dev.jjs.impl.DeadCodeElimination;
import com.google.gwt.dev.jjs.impl.GenerateJavaAST;
import com.google.gwt.dev.jjs.impl.GenerateJavaScriptAST;
import com.google.gwt.dev.jjs.impl.JavaScriptObjectCaster;
@@ -75,8 +76,8 @@
private static void findEntryPoints(TreeLogger logger,
String[] mainClassNames, JProgram program)
throws UnableToCompleteException {
- JMethod bootStrapMethod = program.createMethod("init".toCharArray(), null,
- program.getTypeVoid(), false, true, true, false, false);
+ JMethod bootStrapMethod = program.createMethod(null, "init".toCharArray(),
+ null, program.getTypeVoid(), false, true, true, false, false);
bootStrapMethod.freezeParamTypes();
for (int i = 0; i < mainClassNames.length; ++i) {
@@ -153,14 +154,14 @@
}
// Construct a new instance of the class to qualify the non-static call
- JNewInstance newInstance = new JNewInstance(program, mainClass);
- qualifier = new JMethodCall(program, newInstance, noArgCtor);
+ JNewInstance newInstance = new JNewInstance(program, null, mainClass);
+ qualifier = new JMethodCall(program, null, newInstance, noArgCtor);
}
- JMethodCall onModuleLoadCall = new JMethodCall(program, qualifier,
+ JMethodCall onModuleLoadCall = new JMethodCall(program, null, qualifier,
mainMethod);
bootStrapMethod.body.statements.add(new JExpressionStatement(program,
- onModuleLoadCall));
+ null, onModuleLoadCall));
}
program.addEntryMethod(bootStrapMethod);
}
@@ -339,6 +340,7 @@
didChange = CastOptimizer.exec(jprogram) || didChange;
// dead code removal??
+ didChange = DeadCodeElimination.exec(jprogram) || didChange;
// inlining
didChange = MethodInliner.exec(jprogram) || didChange;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/Mutator.java b/dev/core/src/com/google/gwt/dev/jjs/ast/Context.java
similarity index 64%
rename from dev/core/src/com/google/gwt/dev/jjs/ast/Mutator.java
rename to dev/core/src/com/google/gwt/dev/jjs/ast/Context.java
index ced4091..0062716 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/Mutator.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/Context.java
@@ -16,18 +16,21 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Abstracts the process of modifying an AST node.
+ * The context in which a JNode visitation occurs. This represents the set of
+ * possible operations a JVisitor subclass can perform on the currently visited
+ * node.
*/
-public abstract class Mutator {
+public interface Context {
- public abstract JExpression get();
+ boolean canInsert();
- public abstract void insertAfter(JExpression node);
+ boolean canRemove();
- public abstract void insertBefore(JExpression node);
+ void insertAfter(JNode node);
- public abstract void remove();
+ void insertBefore(JNode node);
- public abstract JExpression set(JExpression value);
+ void removeMe();
+ void replaceMe(JNode node);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/Holder.java b/dev/core/src/com/google/gwt/dev/jjs/ast/Holder.java
deleted file mode 100644
index cb7dc51..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/Holder.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast;
-
-/**
- * A mutable reference to an AST node.
- */
-public class Holder extends Mutator implements JVisitable {
-
- private JExpression value;
-
- public Holder() {
- }
-
- public Holder(JExpression value) {
- this.value = value;
- }
-
- public JExpression get() {
- return value;
- }
-
- public void insertAfter(JExpression node) {
- throw new UnsupportedOperationException();
- }
-
- public void insertBefore(JExpression node) {
- throw new UnsupportedOperationException();
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- public JExpression set(JExpression value) {
- return this.value = value;
- }
-
- public void traverse(JVisitor visitor) {
- if (value != null) {
- value.traverse(visitor, this);
- }
- }
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/HolderList.java b/dev/core/src/com/google/gwt/dev/jjs/ast/HolderList.java
deleted file mode 100644
index 7893e8d..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/HolderList.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- * A list of {@link Holder} objects.
- */
-public class HolderList/* <T extends JNode> */implements List/* <T> */,
- JVisitable {
-
- private final class ListIt implements ListIterator/* <T> */ {
-
- private final ListIterator/* <Mutator<T>> */itImpl;
- private final ListIterator/* <T> */itPeer;
-
- private ListIt(ListIterator/* <Mutator<T>> */itImpl,
- ListIterator/* <T> */itPeer) {
- this.itImpl = itImpl;
- this.itPeer = itPeer;
- }
-
- public void add(Object o) {
- itImpl.add(new MutatorImpl());
- itPeer.add(o);
- }
-
- public boolean hasNext() {
- return itPeer.hasNext();
- }
-
- public boolean hasPrevious() {
- return itPeer.hasPrevious();
- }
-
- public Object next() {
- itImpl.next();
- return itPeer.next();
- }
-
- public int nextIndex() {
- return itPeer.nextIndex();
- }
-
- public Object previous() {
- itImpl.previous();
- return itPeer.previous();
- }
-
- public int previousIndex() {
- return itPeer.previousIndex();
- }
-
- public void remove() {
- itImpl.remove();
- itPeer.remove();
- }
-
- public void set(Object o) {
- itPeer.set(o);
- }
- }
-
- private class MutatorImpl extends Mutator {
-
- public JExpression get() {
- int pos = impl.indexOf(this);
- if (pos < 0) {
- throw new IndexOutOfBoundsException();
- }
- return (JExpression) HolderList.this.get(pos);
- }
-
- public void insertAfter(JExpression node) {
- int pos = impl.indexOf(this);
- if (pos < 0) {
- throw new IndexOutOfBoundsException();
- }
- HolderList.this.add(pos, node);
- }
-
- public void insertBefore(JExpression node) {
- int pos = impl.indexOf(this);
- if (pos < 0) {
- throw new IndexOutOfBoundsException();
- }
- HolderList.this.add(pos + 1, node);
- }
-
- public void remove() {
- int pos = impl.indexOf(this);
- if (pos < 0) {
- throw new IndexOutOfBoundsException();
- }
- HolderList.this.remove(pos);
- }
-
- public JExpression set(JExpression value) {
- int pos = impl.indexOf(this);
- if (pos < 0) {
- throw new IndexOutOfBoundsException();
- }
- return (JExpression) HolderList.this.set(pos, value);
- }
- }
-
- private final ArrayList/* <Mutator<T>> */impl = new ArrayList/* <Mutator<T>> */();
- private final ArrayList/* <T> */peer = new ArrayList/* <T> */();
-
- public void add(int index, Object element) {
- impl.add(index, new MutatorImpl());
- peer.add(index, element);
- }
-
- public boolean add(Object o) {
- impl.add(new MutatorImpl());
- return peer.add(o);
- }
-
- public boolean addAll(Collection/* <? extends T> */c) {
- boolean result = false;
- for (Iterator it = c.iterator(); it.hasNext();) {
- JNode item = (JNode) it.next();
- this.add(item);
- result = true;
- }
- return result;
- }
-
- public boolean addAll(int index, Collection/* <? extends T> */c) {
- boolean result = false;
- for (Iterator it = c.iterator(); it.hasNext();) {
- JNode item = (JNode) it.next();
- this.add(index++, item);
- result = true;
- }
- return result;
- }
-
- public void clear() {
- peer.clear();
- impl.clear();
- }
-
- public boolean contains(Object o) {
- return peer.contains(o);
- }
-
- public boolean containsAll(Collection/* <?> */c) {
- throw new UnsupportedOperationException();
- }
-
- public Object get(int index) {
- return peer.get(index);
- }
-
- public JExpression getExpr(int index) {
- return (JExpression) peer.get(index);
- }
-
- public Mutator getMutator(int index) {
- return (Mutator) impl.get(index);
- }
-
- public List/* <Mutator<T>> */getMutators() {
- return impl;
- }
-
- public int indexOf(Object o) {
- return peer.indexOf(o);
- }
-
- public boolean isEmpty() {
- return peer.isEmpty();
- }
-
- public Iterator/* <T> */iterator() {
- return new ListIt(impl.listIterator(), peer.listIterator());
- }
-
- public int lastIndexOf(Object o) {
- return peer.lastIndexOf(o);
- }
-
- public ListIterator/* <T> */listIterator() {
- return new ListIt(impl.listIterator(), peer.listIterator());
- }
-
- public ListIterator/* <T> */listIterator(int index) {
- return new ListIt(impl.listIterator(index), peer.listIterator(index));
- }
-
- public Object remove(int index) {
- impl.remove(index);
- return peer.remove(index);
- }
-
- public boolean remove(Object o) {
- int i = peer.indexOf(o);
- if (i < 0) {
- return false;
- }
- impl.remove(i);
- peer.remove(i);
- return true;
- }
-
- public boolean removeAll(Collection/* <?> */c) {
- throw new UnsupportedOperationException();
- }
-
- public boolean retainAll(Collection/* <?> */c) {
- throw new UnsupportedOperationException();
- }
-
- public Object set(int index, Object element) {
- return peer.set(index, element);
- }
-
- public int size() {
- return peer.size();
- }
-
- public List/* <T> */subList(int fromIndex, int toIndex) {
- throw new UnsupportedOperationException();
- }
-
- public Object[] toArray() {
- return peer.toArray();
- }
-
- public/* <T> */Object[] toArray(Object[] a) {
- return peer.toArray(a);
- }
-
- public void traverse(JVisitor visitor) {
- for (int i = 0, c = impl.size(); i < c; ++i) {
- JExpression value = (JExpression) peer.get(i);
- value.traverse(visitor, (Mutator) impl.get(i));
- }
- }
-
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JAbsentArrayDimension.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JAbsentArrayDimension.java
index 009116a..0c402fa 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JAbsentArrayDimension.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JAbsentArrayDimension.java
@@ -32,14 +32,10 @@
return program.getTypeVoid();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java
index bae50f1..e3cc019 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayRef.java
@@ -20,25 +20,26 @@
*/
public class JArrayRef extends JExpression {
- public final Holder instance = new Holder();
- public final Holder indexExpr = new Holder();
+ private JExpression instance;
+ private JExpression indexExpr;
- public JArrayRef(JProgram program, JExpression instance, JExpression indexExpr) {
- super(program);
- this.instance.set(instance);
- this.indexExpr.set(indexExpr);
+ public JArrayRef(JProgram program, JSourceInfo info, JExpression instance,
+ JExpression indexExpr) {
+ super(program, info);
+ this.instance = instance;
+ this.indexExpr = indexExpr;
}
public JExpression getIndexExpr() {
- return indexExpr.get();
+ return indexExpr;
}
public JExpression getInstance() {
- return instance.get();
+ return instance;
}
public JType getType() {
- JType type = instance.get().getType();
+ JType type = instance.getType();
if (type == program.getTypeNull()) {
return type;
}
@@ -47,19 +48,15 @@
}
public boolean hasSideEffects() {
- return instance.get().hasSideEffects() || indexExpr.get().hasSideEffects();
+ return instance.hasSideEffects() || indexExpr.hasSideEffects();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- this.instance.traverse(visitor);
- this.indexExpr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ instance = visitor.accept(instance);
+ indexExpr = visitor.accept(indexExpr);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
index 4c4e244..035a5d0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JArrayType.java
@@ -28,15 +28,14 @@
return name;
}
- public JType leafType;
-
- public int dims;
+ private int dims;
+ private JType leafType;
/**
* These are only supposed to be constructed by JProgram.
*/
JArrayType(JProgram program, JType leafType, int dims) {
- super(program, calcName(leafType, dims), false, false);
+ super(program, null, calcName(leafType, dims), false, false);
this.leafType = leafType;
this.dims = dims;
}
@@ -80,10 +79,10 @@
return false;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JAssertStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JAssertStatement.java
index c8448ae..d474694 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JAssertStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JAssertStatement.java
@@ -20,29 +20,31 @@
*/
public class JAssertStatement extends JStatement {
- private final Holder testExpr = new Holder();
- private final Holder arg = new Holder();
+ private JExpression testExpr;
+ private JExpression arg;
- public JAssertStatement(JProgram program, JExpression testExpr, JExpression arg) {
- super(program);
- this.testExpr.set(testExpr);
- this.arg.set(arg);
+ public JAssertStatement(JProgram program, JSourceInfo info,
+ JExpression testExpr, JExpression arg) {
+ super(program, info);
+ this.testExpr = testExpr;
+ this.arg = arg;
}
public JExpression getArg() {
- return arg.get();
+ return arg;
}
public JExpression getTestExpr() {
- return testExpr.get();
+ return testExpr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- testExpr.traverse(visitor);
- arg.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ testExpr = visitor.accept(testExpr);
+ if (arg != null) {
+ arg = visitor.accept(arg);
+ }
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperation.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperation.java
index 3beeb72..5908bf3 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JBinaryOperation.java
@@ -20,26 +20,30 @@
*/
public class JBinaryOperation extends JExpression implements HasSettableType {
- public JBinaryOperator op;
- public final Holder lhs = new Holder();
- public final Holder rhs = new Holder();
+ private JExpression lhs;
+ private final JBinaryOperator op;
+ private JExpression rhs;
private JType type;
- public JBinaryOperation(JProgram program, JType type, JBinaryOperator op,
- JExpression lhs, JExpression rhs) {
- super(program);
+ public JBinaryOperation(JProgram program, JSourceInfo info, JType type,
+ JBinaryOperator op, JExpression lhs, JExpression rhs) {
+ super(program, info);
this.op = op;
this.type = type;
- this.lhs.set(lhs);
- this.rhs.set(rhs);
+ this.lhs = lhs;
+ this.rhs = rhs;
}
public JExpression getLhs() {
- return lhs.get();
+ return lhs;
+ }
+
+ public JBinaryOperator getOp() {
+ return op;
}
public JExpression getRhs() {
- return rhs.get();
+ return rhs;
}
public JType getType() {
@@ -68,16 +72,12 @@
type = newType;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- lhs.traverse(visitor);
- rhs.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ lhs = visitor.accept(lhs);
+ rhs = visitor.accept(rhs);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JBlock.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JBlock.java
index 21de0a8..34def70 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JBlock.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JBlock.java
@@ -23,20 +23,17 @@
*/
public class JBlock extends JStatement {
- public List/*<JStatement>*/ statements = new ArrayList/*<JStatement>*/();
+ public List/* <JStatement> */statements = new ArrayList/* <JStatement> */();
- public JBlock(JProgram program) {
- super(program);
+ public JBlock(JProgram program, JSourceInfo info) {
+ super(program, info);
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < statements.size(); ++i) {
- JStatement stmt = (JStatement) statements.get(i);
- stmt.traverse(visitor);
- }
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.acceptWithInsertRemove(statements);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JBooleanLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JBooleanLiteral.java
index c710210..6232752 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JBooleanLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JBooleanLiteral.java
@@ -20,7 +20,7 @@
*/
public class JBooleanLiteral extends JLiteral {
- public final boolean value;
+ private final boolean value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,14 +34,14 @@
return program.getTypePrimitiveBoolean();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public boolean getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JBreakStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JBreakStatement.java
index 0d6dc16..8bd64b5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JBreakStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JBreakStatement.java
@@ -20,20 +20,23 @@
*/
public class JBreakStatement extends JStatement {
- public JLabel label;
+ private final JLabel label;
- public JBreakStatement(JProgram program, JLabel label) {
- super(program);
+ public JBreakStatement(JProgram program, JSourceInfo info, JLabel label) {
+ super(program, info);
this.label = label;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- if (label != null) {
- label.traverse(visitor);
- }
- }
- visitor.endVisit(this);
+ public JLabel getLabel() {
+ return label;
}
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ if (label != null) {
+ visitor.accept(label);
+ }
+ }
+ visitor.endVisit(this, ctx);
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JCaseStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JCaseStatement.java
index 4677505..82cefb0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JCaseStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JCaseStatement.java
@@ -16,26 +16,28 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java case statement.
+ * Java case statement.
*/
public class JCaseStatement extends JStatement {
- private final Holder/*<JLiteral>*/ expr = new Holder/*<JLiteral>*/();
+ private final JLiteral expr;
- public JCaseStatement(JProgram program, JLiteral expr) {
- super(program);
- this.expr.set(expr);
+ public JCaseStatement(JProgram program, JSourceInfo info, JLiteral expr) {
+ super(program, info);
+ this.expr = expr;
}
- public JLiteral getExpression() {
- return (JLiteral) expr.get();
+ public JLiteral getExpr() {
+ return expr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- expr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ if (expr != null) {
+ visitor.accept(expr);
+ }
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JCastOperation.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JCastOperation.java
index b5d1eb3..2adf61d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JCastOperation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JCastOperation.java
@@ -20,17 +20,22 @@
*/
public class JCastOperation extends JExpression {
- public final JType castType;
- public final Holder expr = new Holder();
+ private JExpression expr;
+ private final JType castType;
- public JCastOperation(JProgram program, JType castType, JExpression expression) {
- super(program);
+ public JCastOperation(JProgram program, JSourceInfo info, JType castType,
+ JExpression expr) {
+ super(program, info);
this.castType = castType;
- this.expr.set(expression);
+ this.expr = expr;
}
- public JExpression getExpression() {
- return expr.get();
+ public JType getCastType() {
+ return castType;
+ }
+
+ public JExpression getExpr() {
+ return expr;
}
public JType getType() {
@@ -41,18 +46,14 @@
// technically this isn't true, but since the same cast on the same
// expression always evaluates the same way, it effectively has no side
// effects
- return getExpression().hasSideEffects();
+ return getExpr().hasSideEffects();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- expr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ expr = visitor.accept(expr);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JCharLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JCharLiteral.java
index 35b40b0..6df96b8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JCharLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JCharLiteral.java
@@ -20,7 +20,7 @@
*/
public class JCharLiteral extends JLiteral {
- public final char value;
+ private final char value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,14 +34,14 @@
return program.getTypePrimitiveChar();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public char getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
index 7f78e2c..079aaa2 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassLiteral.java
@@ -16,11 +16,11 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java class literal expression.
+ * Java class literal expression.
*/
public class JClassLiteral extends JLiteral {
- public final JType refType;
+ private final JType refType;
/**
* These are only supposed to be constructed by JProgram.
@@ -30,17 +30,17 @@
refType = type;
}
+ public JType getRefType() {
+ return refType;
+ }
+
public JType getType() {
return program.getTypeJavaLangClass();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
index b82d908..1f7776e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JClassType.java
@@ -16,15 +16,16 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java class type reference expression.
+ * Java class type reference expression.
*/
public class JClassType extends JReferenceType implements CanBeSetFinal {
private final boolean isAbstract;
private boolean isFinal;
- public JClassType(JProgram program, String name, boolean isAbstract, boolean isFinal) {
- super(program, name);
+ public JClassType(JProgram program, JSourceInfo info, String name,
+ boolean isAbstract, boolean isFinal) {
+ super(program, info, name);
this.isAbstract = isAbstract;
this.isFinal = isFinal;
}
@@ -41,18 +42,12 @@
isFinal = b;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < fields.size(); ++i) {
- JField field = (JField) fields.get(i);
- field.traverse(visitor);
- }
- for (int i = 0; i < methods.size(); ++i) {
- JMethod method = (JMethod) methods.get(i);
- method.traverse(visitor);
- }
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.acceptWithInsertRemove(fields);
+ visitor.acceptWithInsertRemove(methods);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JConditional.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JConditional.java
index fc8bc37..39b9287 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JConditional.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JConditional.java
@@ -20,59 +20,54 @@
*/
public class JConditional extends JExpression {
- public final Holder thenExpr = new Holder();
- public final Holder elseExpr = new Holder();
+ private JExpression elseExpr;
+ private JExpression ifTest;
+ private JExpression thenExpr;
private final JType type;
- private final Holder ifTest = new Holder();
- public JConditional(JProgram program, JType type, JExpression ifTest,
- JExpression thenExpr, JExpression elseExpr) {
- super(program);
+ public JConditional(JProgram program, JSourceInfo info, JType type,
+ JExpression ifTest, JExpression thenExpr, JExpression elseExpr) {
+ super(program, info);
this.type = type;
- this.ifTest.set(ifTest);
- this.thenExpr.set(thenExpr);
- this.elseExpr.set(elseExpr);
+ this.ifTest = ifTest;
+ this.thenExpr = thenExpr;
+ this.elseExpr = elseExpr;
}
public JExpression getElseExpr() {
- return elseExpr.get();
+ return elseExpr;
}
public JExpression getIfTest() {
- return ifTest.get();
+ return ifTest;
}
public JExpression getThenExpr() {
- return thenExpr.get();
+ return thenExpr;
}
public JType getType() {
// TODO(later): allow multiple types for Type Flow?
if (type instanceof JReferenceType) {
- return program.generalizeTypes(
- (JReferenceType) thenExpr.get().getType(),
- (JReferenceType) elseExpr.get().getType());
+ return program.generalizeTypes((JReferenceType) thenExpr.getType(),
+ (JReferenceType) elseExpr.getType());
} else {
return type;
}
}
public boolean hasSideEffects() {
- return ifTest.get().hasSideEffects() || thenExpr.get().hasSideEffects()
- || elseExpr.get().hasSideEffects();
+ return ifTest.hasSideEffects() || thenExpr.hasSideEffects()
+ || elseExpr.hasSideEffects();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- ifTest.traverse(visitor);
- thenExpr.traverse(visitor);
- elseExpr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ ifTest = visitor.accept(ifTest);
+ thenExpr = visitor.accept(thenExpr);
+ elseExpr = visitor.accept(elseExpr);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JContinueStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JContinueStatement.java
index 395f31e..d6d93df 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JContinueStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JContinueStatement.java
@@ -20,20 +20,24 @@
*/
public class JContinueStatement extends JStatement {
- public JLabel label;
+ private final JLabel label;
- public JContinueStatement(JProgram program, JLabel label) {
- super(program);
+ public JContinueStatement(JProgram program, JSourceInfo info, JLabel label) {
+ super(program, info);
this.label = label;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public JLabel getLabel() {
+ return label;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
if (label != null) {
- label.traverse(visitor);
+ visitor.accept(label);
}
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JDoStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JDoStatement.java
index 76282d2..8adc008 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JDoStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JDoStatement.java
@@ -20,27 +20,32 @@
*/
public class JDoStatement extends JStatement {
- private final Holder testExpr = new Holder();
- public JStatement body;
+ private JStatement body;
+ private JExpression testExpr;
- public JDoStatement(JProgram program, JExpression testExpr, JStatement body) {
- super(program);
- this.testExpr.set(testExpr);
+ public JDoStatement(JProgram program, JSourceInfo info, JExpression testExpr,
+ JStatement body) {
+ super(program, info);
+ this.testExpr = testExpr;
this.body = body;
}
- public JExpression getTestExpr() {
- return testExpr.get();
+ public JStatement getBody() {
+ return body;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- testExpr.traverse(visitor);
+ public JExpression getTestExpr() {
+ return testExpr;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ testExpr = visitor.accept(testExpr);
if (body != null) {
- body.traverse(visitor);
+ body = visitor.accept(body);
}
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JDoubleLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JDoubleLiteral.java
index 5d8f4fb..6116d6a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JDoubleLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JDoubleLiteral.java
@@ -20,7 +20,7 @@
*/
public class JDoubleLiteral extends JLiteral {
- public final double value;
+ private final double value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,13 +34,13 @@
return program.getTypePrimitiveDouble();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public double getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java
index 9be3120..7f8c18d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpression.java
@@ -16,16 +16,14 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Base class for all Java expressions.
+ * Base class for all Java expressions.
*/
public abstract class JExpression extends JNode implements HasType {
- public JExpression(JProgram program) {
- super(program);
+ public JExpression(JProgram program, JSourceInfo info) {
+ super(program, info);
}
public abstract boolean hasSideEffects();
- public abstract void traverse(JVisitor visitor, Mutator mutator);
-
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java
index bb16984..6b921cd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JExpressionStatement.java
@@ -20,22 +20,23 @@
*/
public class JExpressionStatement extends JStatement {
- private final Holder expr = new Holder();
+ private JExpression expr;
- public JExpressionStatement(JProgram program, JExpression expr) {
- super(program);
- this.expr.set(expr);
+ public JExpressionStatement(JProgram program, JSourceInfo info,
+ JExpression expr) {
+ super(program, info);
+ this.expr = expr;
}
- public JExpression getExpression() {
- return expr.get();
+ public JExpression getExpr() {
+ return expr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- expr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ expr = visitor.accept(expr);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
index 3b768ee..0611e7c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JField.java
@@ -20,14 +20,14 @@
*/
public class JField extends JVariable implements CanBeStatic, HasEnclosingType {
- public JReferenceType enclosingType;
+ private JReferenceType enclosingType;
public JLiteral constInitializer;
private final boolean isStatic;
private final boolean hasInitializer;
- JField(JProgram program, String name, JReferenceType enclosingType,
- JType type, boolean isStatic, boolean isFinal, boolean hasInitializer) {
- super(program, name, type, isFinal);
+ JField(JProgram program, JSourceInfo info, String name,
+ JReferenceType enclosingType, JType type, boolean isStatic, boolean isFinal, boolean hasInitializer) {
+ super(program, info, name, type, isFinal);
this.enclosingType = enclosingType;
this.isStatic = isStatic;
this.hasInitializer = hasInitializer;
@@ -45,10 +45,10 @@
return isStatic;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java
index 6806db7..96b3e43 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JFieldRef.java
@@ -21,24 +21,25 @@
public class JFieldRef extends JVariableRef implements HasEnclosingType {
/**
- * This can only be null if the referenced field is static.
- */
- public final Holder instance = new Holder();
-
- /**
- * The referenced field.
- */
- public JField field;
-
- /**
* The enclosing type of this reference.
*/
private final JReferenceType enclosingType;
- public JFieldRef(JProgram program, JExpression instance, JField field,
- JReferenceType enclosingType) {
- super(program, field);
- this.instance.set(instance);
+ /**
+ * The referenced field.
+ */
+ private JField field;
+
+ /**
+ * This can only be null if the referenced field is static.
+ */
+ private JExpression instance;
+
+ public JFieldRef(JProgram program, JSourceInfo info, JExpression instance,
+ JField field, JReferenceType enclosingType) {
+ super(program, info, field);
+ assert (instance != null || field.isStatic());
+ this.instance = instance;
this.field = field;
this.enclosingType = enclosingType;
}
@@ -52,37 +53,35 @@
}
public JExpression getInstance() {
- return instance.get();
+ return instance;
}
public boolean hasSideEffects() {
// A cross-class reference to a static, non constant field forces clinit
if (field.isStatic()
- && (!field.isFinal() || field.constInitializer == null)) {
+ && (!field.isFinal() || field.constInitializer == null)) {
JReferenceType fieldEncloser = field.getEnclosingType();
if (enclosingType != fieldEncloser
- && program.typeOracle.hasClinit(fieldEncloser)) {
+ && program.typeOracle.hasClinit(fieldEncloser)) {
// Therefore, we have side effects
return true;
}
}
- JExpression expr = instance.get();
+ JExpression expr = instance;
if (expr == null) {
return false;
}
return expr.hasSideEffects();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- instance.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ if (instance != null) {
+ instance = visitor.accept(instance);
+ }
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java
index da647c3..1ff769e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JFloatLiteral.java
@@ -20,7 +20,7 @@
*/
public class JFloatLiteral extends JLiteral {
- public final float value;
+ private final float value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,13 +34,13 @@
return program.getTypePrimitiveFloat();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public float getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java
index 4a63f35..082677b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JForStatement.java
@@ -22,21 +22,25 @@
*/
public class JForStatement extends JStatement {
- public final JStatement body;
- private final List/* <JStatement> */initializers;
- private final Holder testExpr = new Holder();
+ private JStatement body;
private final List/* <JExpressionStatement> */increments;
+ private final List/* <JStatement> */initializers;
+ private JExpression testExpr;
- public JForStatement(JProgram program, List/* <JStatement> */initializers,
- JExpression testExpr, List/* <JExpressionStatement> */increments,
- JStatement body) {
- super(program);
+ public JForStatement(JProgram program, JSourceInfo info,
+ List/* <JStatement> */initializers, JExpression testExpr,
+ List/* <JExpressionStatement> */increments, JStatement body) {
+ super(program, info);
this.initializers = initializers;
- this.testExpr.set(testExpr);
+ this.testExpr = testExpr;
this.increments = increments;
this.body = body;
}
+ public JStatement getBody() {
+ return body;
+ }
+
public List/* <JExpressionStatement> */getIncrements() {
return increments;
}
@@ -46,25 +50,21 @@
}
public JExpression getTestExpr() {
- return testExpr.get();
+ return testExpr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < initializers.size(); ++i) {
- JStatement stmt = (JStatement) initializers.get(i);
- stmt.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.acceptWithInsertRemove(initializers);
+ if (testExpr != null) {
+ testExpr = visitor.accept(testExpr);
}
- testExpr.traverse(visitor);
- for (int i = 0; i < increments.size(); ++i) {
- JExpressionStatement stmt = (JExpressionStatement) increments.get(i);
- stmt.traverse(visitor);
- }
+ visitor.acceptWithInsertRemove(increments);
if (body != null) {
- body.traverse(visitor);
+ body = visitor.accept(body);
}
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JIfStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JIfStatement.java
index ea03bed..38389a9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JIfStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JIfStatement.java
@@ -16,38 +16,45 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java if statement.
+ * Java if statement.
*/
public class JIfStatement extends JStatement {
- private final Holder ifExpr = new Holder();
- public JStatement thenStmt;
- public JStatement elseStmt;
+ private JStatement elseStmt;
+ private JExpression ifExpr;
+ private JStatement thenStmt;
- public JIfStatement(JProgram program, JExpression ifExpr,
- JStatement thenStmt, JStatement elseStmt) {
- super(program);
- this.ifExpr.set(ifExpr);
+ public JIfStatement(JProgram program, JSourceInfo info,
+ JExpression ifExpr, JStatement thenStmt, JStatement elseStmt) {
+ super(program, info);
+ this.ifExpr = ifExpr;
this.thenStmt = thenStmt;
this.elseStmt = elseStmt;
}
- public JExpression getIfExpr() {
- return ifExpr.get();
+ public JStatement getElseStmt() {
+ return elseStmt;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- ifExpr.traverse(visitor);
+ public JExpression getIfExpr() {
+ return ifExpr;
+ }
+
+ public JStatement getThenStmt() {
+ return thenStmt;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ ifExpr = visitor.accept(ifExpr);
if (thenStmt != null) {
- thenStmt.traverse(visitor);
+ thenStmt = visitor.accept(thenStmt);
}
-
if (elseStmt != null) {
- elseStmt.traverse(visitor);
+ elseStmt = visitor.accept(elseStmt);
}
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JInstanceOf.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JInstanceOf.java
index d9d4fd6..d7cd5f5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JInstanceOf.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JInstanceOf.java
@@ -16,22 +16,26 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java instance of expression.
+ * Java instance of expression.
*/
public class JInstanceOf extends JExpression {
- public final JReferenceType testType;
- public final Holder expr = new Holder();
+ private JExpression expr;
+ private final JReferenceType testType;
- public JInstanceOf(JProgram program, JReferenceType testType,
- JExpression expression) {
- super(program);
+ public JInstanceOf(JProgram program, JSourceInfo info,
+ JReferenceType testType, JExpression expression) {
+ super(program, info);
this.testType = testType;
- this.expr.set(expression);
+ this.expr = expression;
}
- public JExpression getExpression() {
- return expr.get();
+ public JExpression getExpr() {
+ return expr;
+ }
+
+ public JReferenceType getTestType() {
+ return testType;
}
public JType getType() {
@@ -42,15 +46,11 @@
return false;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- expr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ expr = visitor.accept(expr);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JIntLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JIntLiteral.java
index f6d3599..37832fd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JIntLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JIntLiteral.java
@@ -20,7 +20,7 @@
*/
public class JIntLiteral extends JLiteral {
- public final int value;
+ private final int value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,14 +34,14 @@
return program.getTypePrimitiveInt();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public int getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java
index 6b18f58..ab0db6d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JInterfaceType.java
@@ -16,12 +16,12 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java interface type definition.
+ * Java interface type definition.
*/
public class JInterfaceType extends JReferenceType {
- JInterfaceType(JProgram program, String name) {
- super(program, name);
+ JInterfaceType(JProgram program, JSourceInfo info, String name) {
+ super(program, info, name);
}
public boolean isAbstract() {
@@ -32,17 +32,11 @@
return false;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < fields.size(); ++i) {
- JField field = (JField) fields.get(i);
- field.traverse(visitor);
- }
- for (int i = 0; i < methods.size(); ++i) {
- JMethod method = (JMethod) methods.get(i);
- method.traverse(visitor);
- }
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.acceptWithInsertRemove(fields);
+ visitor.acceptWithInsertRemove(methods);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLabel.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLabel.java
index 76c20cb..b0ae9eb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLabel.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLabel.java
@@ -20,10 +20,10 @@
*/
public class JLabel extends JNode implements HasName {
- public final String name;
-
- public JLabel(JProgram program, String name) {
- super(program);
+ private final String name;
+
+ public JLabel(JProgram program, JSourceInfo info, String name) {
+ super(program, info);
this.name = name;
}
@@ -31,10 +31,10 @@
return name;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLabeledStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLabeledStatement.java
index 0b77a29..3bdcdf1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLabeledStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLabeledStatement.java
@@ -20,20 +20,29 @@
*/
public class JLabeledStatement extends JStatement {
- public final JLabel label;
- public JStatement body;
-
- public JLabeledStatement(JProgram program, JLabel label, JStatement body) {
- super(program);
+ private JStatement body;
+ private final JLabel label;
+
+ public JLabeledStatement(JProgram program, JSourceInfo info, JLabel label,
+ JStatement body) {
+ super(program, info);
this.label = label;
this.body = body;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- label.traverse(visitor);
- body.traverse(visitor);
+ public JStatement getBody() {
+ return body;
+ }
+
+ public JLabel getLabel() {
+ return label;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(label);
+ body = visitor.accept(body);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLiteral.java
index 837b14f..6d1f498 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLiteral.java
@@ -21,7 +21,7 @@
public abstract class JLiteral extends JExpression {
public JLiteral(JProgram program) {
- super(program);
+ super(program, null);
}
public boolean hasSideEffects() {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java
index c5d10ec..0b83cbb 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocal.java
@@ -16,15 +16,15 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java local variable definition.
+ * Java local variable definition.
*/
public class JLocal extends JVariable implements HasEnclosingMethod {
private final JMethod enclosingMethod;
- JLocal(JProgram program, String name, JType type, boolean isFinal,
- JMethod enclosingMethod) {
- super(program, name, type, isFinal);
+ JLocal(JProgram program, JSourceInfo info, String name, JType type,
+ boolean isFinal, JMethod enclosingMethod) {
+ super(program, info, name, type, isFinal);
this.enclosingMethod = enclosingMethod;
}
@@ -32,10 +32,10 @@
return enclosingMethod;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalDeclarationStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalDeclarationStatement.java
index 90d7df4..2cb070e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalDeclarationStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalDeclarationStatement.java
@@ -20,30 +20,32 @@
*/
public class JLocalDeclarationStatement extends JStatement {
- public final Holder initializer = new Holder();
- private final Holder/* <JLocalRef> */localRef = new Holder/* <JLocalRef> */();
+ public JExpression initializer;
+ private JLocalRef localRef;
- public JLocalDeclarationStatement(JProgram program, JLocalRef localRef,
- JExpression intializer) {
- super(program);
- this.localRef.set(localRef);
- this.initializer.set(intializer);
+ public JLocalDeclarationStatement(JProgram program, JSourceInfo info,
+ JLocalRef localRef, JExpression intializer) {
+ super(program, info);
+ this.localRef = localRef;
+ this.initializer = intializer;
}
public JExpression getInitializer() {
- return initializer.get();
+ return initializer;
}
public JLocalRef getLocalRef() {
- return (JLocalRef) localRef.get();
+ return localRef;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- localRef.traverse(visitor);
- initializer.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ localRef = (JLocalRef) visitor.accept(localRef);
+ if (initializer != null) {
+ initializer = visitor.accept(initializer);
+ }
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java
index 2222746..fddabe0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLocalRef.java
@@ -23,28 +23,24 @@
/**
* The referenced local.
*/
- public JLocal local;
+ private JLocal local;
- public JLocalRef(JProgram program, JLocal local) {
- super(program, local);
+ public JLocalRef(JProgram program, JSourceInfo info, JLocal local) {
+ super(program, info, local);
this.local = local;
}
public JLocal getLocal() {
return local;
}
-
+
public boolean hasSideEffects() {
return false;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JLongLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JLongLiteral.java
index 03df222..dc0ecee 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JLongLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JLongLiteral.java
@@ -20,7 +20,7 @@
*/
public class JLongLiteral extends JLiteral {
- public final long value;
+ private final long value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,13 +34,13 @@
return program.getTypePrimitiveLong();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public long getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
index 4637c7c..d655577 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -49,14 +49,14 @@
/**
* These are only supposed to be constructed by JProgram.
*/
- public JMethod(JProgram program, String name, JReferenceType enclosingType,
- JType returnType, boolean isAbstract, boolean isStatic, boolean isFinal,
- boolean isPrivate) {
- super(program);
+ public JMethod(JProgram program, JSourceInfo info, String name,
+ JReferenceType enclosingType, JType returnType, boolean isAbstract,
+ boolean isStatic, boolean isFinal, boolean isPrivate) {
+ super(program, info);
this.name = name;
this.enclosingType = enclosingType;
this.returnType = returnType;
- this.body = new JBlock(program);
+ this.body = new JBlock(program, info);
this.isAbstract = isAbstract;
this.isStatic = isStatic;
this.isFinal = isFinal;
@@ -121,19 +121,13 @@
returnType = newType;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < params.size(); ++i) {
- JParameter param = (JParameter) params.get(i);
- param.traverse(visitor);
- }
- for (int i = 0; i < locals.size(); ++i) {
- JLocal local = (JLocal) locals.get(i);
- local.traverse(visitor);
- }
- body.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(params);
+ visitor.accept(locals);
+ visitor.accept(body);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java
index 5f75fdc..cb878f6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethodCall.java
@@ -15,20 +15,23 @@
*/
package com.google.gwt.dev.jjs.ast;
+import java.util.ArrayList;
+
/**
* Java method call expression.
*/
public class JMethodCall extends JExpression {
- public HolderList args = new HolderList();
- public final Holder instance = new Holder();
+ private ArrayList args = new ArrayList();
+ private JExpression instance;
private final JMethod method;
private final JType overrideReturnType;
private boolean staticDispatchOnly = false;
- public JMethodCall(JProgram program, JExpression instance, JMethod method) {
- super(program);
- this.instance.set(instance);
+ public JMethodCall(JProgram program, JSourceInfo info, JExpression instance,
+ JMethod method) {
+ super(program, info);
+ this.instance = instance;
this.method = method;
this.staticDispatchOnly = false;
this.overrideReturnType = null;
@@ -45,21 +48,34 @@
* allows us to preserve type information during the latter phases of
* compilation.
*/
- public JMethodCall(JProgram program, JExpression instance, JMethod method,
- JType overrideReturnType) {
- super(program);
- this.instance.set(instance);
+ public JMethodCall(JProgram program, JSourceInfo info, JExpression instance,
+ JMethod method, JType overrideReturnType) {
+ super(program, info);
+ this.instance = instance;
this.method = method;
assert (overrideReturnType != null);
this.overrideReturnType = overrideReturnType;
}
+ public JMethodCall(JProgram program, JSourceInfo info, JExpression instance,
+ JMethod method, boolean staticDispatchOnly) {
+ super(program, info);
+ this.instance = instance;
+ this.method = method;
+ this.staticDispatchOnly = staticDispatchOnly;
+ this.overrideReturnType = null;
+ }
+
public boolean canBePolymorphic() {
return !staticDispatchOnly && !method.isFinal() && !method.isStatic();
}
+ public ArrayList getArgs() {
+ return args;
+ }
+
public JExpression getInstance() {
- return instance.get();
+ return instance;
}
public JMethod getTarget() {
@@ -87,16 +103,14 @@
this.staticDispatchOnly = true;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- instance.traverse(visitor);
- args.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ if (instance != null) {
+ instance = visitor.accept(instance);
+ }
+ visitor.accept(args);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JModVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JModVisitor.java
new file mode 100644
index 0000000..59721d2
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JModVisitor.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2006 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.ast;
+
+import com.google.gwt.dev.jjs.impl.InternalCompilerException;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A visitor for iterating through and modifying an AST.
+ */
+public class JModVisitor extends JVisitor {
+
+ private interface ContextFactory {
+ Context create();
+ }
+
+ private class ContextPool extends ArrayList {
+
+ private ContextFactory factory;
+ private int pos = 0;
+
+ public ContextPool(ContextFactory factory) {
+ this.factory = factory;
+ }
+
+ public void release(Context ctx) {
+ if (get(--pos) != ctx) {
+ throw new InternalCompilerException(
+ "Tried to release the wrong context");
+ }
+ }
+
+ public Context take() {
+ if (pos == size()) {
+ add(factory.create());
+ }
+ return (Context) get(pos++);
+ }
+ }
+
+ private class ListContext implements Context {
+ private int index;
+ private List list;
+ private boolean removed;
+ private boolean replaced;
+
+ public boolean canInsert() {
+ return true;
+ }
+
+ public boolean canRemove() {
+ return true;
+ }
+
+ public void insertAfter(JNode node) {
+ checkRemoved();
+ list.add(index + 1, node);
+ didChange = true;
+ }
+
+ public void insertBefore(JNode node) {
+ checkRemoved();
+ list.add(index++, node);
+ didChange = true;
+ }
+
+ public void removeMe() {
+ checkState();
+ list.remove(index--);
+ didChange = removed = true;
+ }
+
+ public void replaceMe(JNode node) {
+ checkState();
+ checkReplacement((JNode) list.get(index), node);
+ list.set(index, node);
+ didChange = replaced = true;
+ }
+
+ protected void doReplace(Class targetClass, JNode x) {
+ checkState();
+ checkReplacement((JNode) list.get(index), x);
+ list.set(index, x);
+ didChange = replaced = true;
+ }
+
+ protected void traverse(List list) {
+ this.list = list;
+ for (index = 0; index < list.size(); ++index) {
+ removed = replaced = false;
+ doTraverse((JNode) list.get(index), this);
+ }
+ }
+
+ private void checkRemoved() {
+ if (removed) {
+ throw new InternalCompilerException("Node was already removed");
+ }
+ }
+
+ private void checkState() {
+ checkRemoved();
+ if (replaced) {
+ throw new InternalCompilerException("Node was already replaced");
+ }
+ }
+ }
+
+ private class NodeContext implements Context {
+ private JNode node;
+ private boolean replaced;
+
+ public boolean canInsert() {
+ return false;
+ }
+
+ public boolean canRemove() {
+ return false;
+ }
+
+ public void insertAfter(JNode node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void insertBefore(JNode node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeMe() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void replaceMe(JNode node) {
+ if (replaced) {
+ throw new InternalCompilerException("Node was already replaced");
+ }
+ checkReplacement(this.node, node);
+ this.node = node;
+ didChange = replaced = true;
+ }
+
+ protected JNode traverse(JNode node) {
+ this.node = node;
+ replaced = false;
+ doTraverse(node, this);
+ return this.node;
+ }
+ }
+
+ protected static void checkReplacement(JNode origNode, JNode newNode) {
+ if (newNode == null) {
+ throw new InternalCompilerException("Cannot replace with null");
+ }
+ if (newNode == origNode) {
+ throw new InternalCompilerException(
+ "The replacement is the same as the original");
+ }
+ }
+
+ protected boolean didChange = false;
+
+ private final ContextPool listContextPool = new ContextPool(
+ new ContextFactory() {
+ public Context create() {
+ return new ListContext();
+ }
+ });
+
+ private final ContextPool nodeContextPool = new ContextPool(
+ new ContextFactory() {
+ public Context create() {
+ return new NodeContext();
+ }
+ });
+
+ public boolean didChange() {
+ return didChange;
+ }
+
+ protected JNode doAccept(JNode node) {
+ NodeContext ctx = (NodeContext) nodeContextPool.take();
+ try {
+ return ctx.traverse(node);
+ } finally {
+ nodeContextPool.release(ctx);
+ }
+ }
+
+ protected void doAccept(List list) {
+ NodeContext ctx = (NodeContext) nodeContextPool.take();
+ try {
+ for (int i = 0, c = list.size(); i < c; ++i) {
+ list.set(i, ctx.traverse((JNode) list.get(i)));
+ }
+ } finally {
+ nodeContextPool.release(ctx);
+ }
+ }
+
+ protected void doAcceptWithInsertRemove(List list) {
+ ListContext ctx = (ListContext) listContextPool.take();
+ try {
+ ctx.traverse(list);
+ } finally {
+ listContextPool.release(ctx);
+ }
+ }
+
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
index f415e30..06ad7bc 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewArray.java
@@ -15,17 +15,19 @@
*/
package com.google.gwt.dev.jjs.ast;
+import java.util.ArrayList;
+
/**
* New array experssion.
*/
public class JNewArray extends JExpression implements HasSettableType {
- public HolderList dims = null;
- public HolderList initializers = null;
+ public ArrayList dims = null;
+ public ArrayList initializers = null;
private JArrayType arrayType;
- public JNewArray(JProgram program, JArrayType arrayType) {
- super(program);
+ public JNewArray(JProgram program, JSourceInfo info, JArrayType arrayType) {
+ super(program, info);
this.arrayType = arrayType;
}
@@ -45,22 +47,18 @@
this.arrayType = (JArrayType) arrayType;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
assert ((dims != null) ^ (initializers != null));
if (dims != null) {
- dims.traverse(visitor);
+ visitor.accept(dims);
}
if (initializers != null) {
- initializers.traverse(visitor);
+ visitor.accept(initializers);
}
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewInstance.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewInstance.java
index e8387b6..b12751d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNewInstance.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNewInstance.java
@@ -22,8 +22,8 @@
private final JClassType classType;
- public JNewInstance(JProgram program, JClassType classType) {
- super(program);
+ public JNewInstance(JProgram program, JSourceInfo info, JClassType classType) {
+ super(program, info);
this.classType = classType;
}
@@ -39,14 +39,10 @@
return true;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
index 4dc4152..d5fbf6c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNode.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.ast;
+import com.google.gwt.dev.jjs.impl.SourceGenerationVisitor;
import com.google.gwt.dev.jjs.impl.ToStringGenerationVisitor;
import com.google.gwt.dev.util.TextOutputOnCharArray;
@@ -22,26 +23,37 @@
* Base class for all visitable AST nodes.
*/
public abstract class JNode implements JVisitable {
- /*
- * The current visitor pattern uses reflection, but it could be
- * replaced by direct code for better performance.
- */
- protected final JProgram program;
- protected JNode(JProgram program) {
+ protected final JProgram program;
+ private final JSourceInfo info;
+
+ protected JNode(JProgram program, JSourceInfo info) {
if (program == null) {
assert (this instanceof JProgram);
this.program = (JProgram) this;
} else {
this.program = program;
}
+ this.info = info;
+ }
+
+ public JSourceInfo getSourceInfo() {
+ return info;
+ }
+
+ // Causes source generation to delegate to the one visitor
+ public final String toSource() {
+ TextOutputOnCharArray p = new TextOutputOnCharArray(false);
+ SourceGenerationVisitor v = new SourceGenerationVisitor(p);
+ v.accept(this);
+ return new String(p.getText());
}
// Causes source generation to delegate to the one visitor
public final String toString() {
TextOutputOnCharArray p = new TextOutputOnCharArray(false);
ToStringGenerationVisitor v = new ToStringGenerationVisitor(p);
- traverse(v);
+ v.accept(this);
return new String(p.getText());
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNullLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNullLiteral.java
index f70d3a3..d775268 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNullLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNullLiteral.java
@@ -31,13 +31,9 @@
return program.getTypeNull();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java
index 69c29a5..76f3d76 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JNullType.java
@@ -21,7 +21,7 @@
public class JNullType extends JReferenceType {
public JNullType(JProgram program) {
- super(program, "<null>");
+ super(program, null, "<null>");
}
public String getJavahSignatureName() {
@@ -40,10 +40,10 @@
return true;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
index 1e09853..ef3ab83 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
@@ -22,9 +22,9 @@
private final JMethod enclosingMethod;
- JParameter(JProgram program, String name, JType type, boolean isFinal,
- JMethod enclosingMethod) {
- super(program, name, type, isFinal);
+ JParameter(JProgram program, JSourceInfo info, String name, JType type,
+ boolean isFinal, JMethod enclosingMethod) {
+ super(program, info, name, type, isFinal);
this.enclosingMethod = enclosingMethod;
}
@@ -32,9 +32,9 @@
return enclosingMethod;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java
index d6334d0..914f4c9 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameterRef.java
@@ -25,8 +25,8 @@
*/
private final JParameter param;
- public JParameterRef(JProgram program, JParameter param) {
- super(program, param);
+ public JParameterRef(JProgram program, JSourceInfo info, JParameter param) {
+ super(program, info, param);
this.param = param;
}
@@ -38,13 +38,9 @@
return false;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JPostfixOperation.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JPostfixOperation.java
index cde0eec..05c55d8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JPostfixOperation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JPostfixOperation.java
@@ -16,42 +16,43 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java postfix expression.
+ * Java postfix expression.
*/
public class JPostfixOperation extends JExpression {
- private final Holder arg = new Holder();
- public JUnaryOperator op;
+ private JExpression arg;
+ private final JUnaryOperator op;
- public JPostfixOperation(JProgram program, JUnaryOperator op, JExpression arg) {
- super(program);
+ public JPostfixOperation(JProgram program, JSourceInfo info,
+ JUnaryOperator op, JExpression arg) {
+ super(program, info);
this.op = op;
- this.arg.set(arg);
+ this.arg = arg;
}
public JExpression getArg() {
- return arg.get();
+ return arg;
+ }
+
+ public JUnaryOperator getOp() {
+ return op;
}
public JType getType() {
// Unary operators don't change the type of their expression
- return arg.get().getType();
+ return arg.getType();
}
public boolean hasSideEffects() {
return op == JUnaryOperator.DEC || op == JUnaryOperator.INC
- || arg.get().hasSideEffects();
+ || arg.hasSideEffects();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- arg.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ arg = visitor.accept(arg);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrefixOperation.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrefixOperation.java
index e228190..e550cbd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrefixOperation.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrefixOperation.java
@@ -20,38 +20,39 @@
*/
public class JPrefixOperation extends JExpression {
- private final Holder arg = new Holder();
- public JUnaryOperator op;
+ private JExpression arg;
+ private final JUnaryOperator op;
- public JPrefixOperation(JProgram program, JUnaryOperator op, JExpression arg) {
- super(program);
+ public JPrefixOperation(JProgram program, JSourceInfo info, JUnaryOperator op,
+ JExpression arg) {
+ super(program, info);
this.op = op;
- this.arg.set(arg);
+ this.arg = arg;
}
public JExpression getArg() {
- return arg.get();
+ return arg;
+ }
+
+ public JUnaryOperator getOp() {
+ return op;
}
public JType getType() {
// Unary operators don't change the type of their expression
- return arg.get().getType();
+ return arg.getType();
}
public boolean hasSideEffects() {
- return op == JUnaryOperator.DEC || op == JUnaryOperator.INC
- || arg.get().hasSideEffects();
+ return getOp() == JUnaryOperator.DEC || getOp() == JUnaryOperator.INC
+ || arg.hasSideEffects();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- arg.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ arg = visitor.accept(arg);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
index f43dece..6a16876 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JPrimitiveType.java
@@ -16,7 +16,7 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Base class for all Java primitive types.
+ * Base class for all Java primitive types.
*/
public class JPrimitiveType extends JType {
@@ -25,8 +25,9 @@
/**
* These are only supposed to be constructed by JProgram.
*/
- JPrimitiveType(JProgram program, String name, String signatureName, JLiteral defaultValue) {
- super(program, name, defaultValue);
+ JPrimitiveType(JProgram program, String name, String signatureName,
+ JLiteral defaultValue) {
+ super(program, null, name, defaultValue);
this.signatureName = signatureName;
}
@@ -38,10 +39,10 @@
return signatureName;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
index 7ea27b8..a56a874 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -204,7 +204,7 @@
null);
public JProgram(TreeLogger logger, RebindOracle rebindOracle) {
- super(null);
+ super(null, null);
this.logger = logger;
this.rebindOracle = rebindOracle;
}
@@ -218,17 +218,17 @@
/**
* Helper to create an assignment, used to initalize fields, etc.
*/
- public JExpressionStatement createAssignmentStmt(JExpression lhs,
- JExpression rhs) {
- JBinaryOperation assign = new JBinaryOperation(this, lhs.getType(),
+ public JExpressionStatement createAssignmentStmt(JSourceInfo info,
+ JExpression lhs, JExpression rhs) {
+ JBinaryOperation assign = new JBinaryOperation(this, info, lhs.getType(),
JBinaryOperator.ASG, lhs, rhs);
- return new JExpressionStatement(this, assign);
+ return new JExpressionStatement(this, info, assign);
}
- public JClassType createClass(char[][] name, boolean isAbstract,
- boolean isFinal) {
+ public JClassType createClass(JSourceInfo info, char[][] name,
+ boolean isAbstract, boolean isFinal) {
String sname = dotify(name);
- JClassType x = new JClassType(this, sname, isAbstract, isFinal);
+ JClassType x = new JClassType(this, info, sname, isAbstract, isFinal);
allTypes.add(x);
putIntoTypeMap(sname, x);
@@ -256,8 +256,9 @@
return x;
}
- public JField createField(char[] name, JReferenceType enclosingType,
- JType type, boolean isStatic, boolean isFinal, boolean hasInitializer) {
+ public JField createField(JSourceInfo info, char[] name,
+ JReferenceType enclosingType, JType type, boolean isStatic,
+ boolean isFinal, boolean hasInitializer) {
assert (name != null);
assert (enclosingType != null);
assert (type != null);
@@ -273,8 +274,8 @@
}
String sname = String.valueOf(name);
- JField x = new JField(this, sname, enclosingType, type, isStatic, isFinal,
- hasInitializer);
+ JField x = new JField(this, info, sname, enclosingType, type, isStatic,
+ isFinal, hasInitializer);
if (isSpecialField) {
specialFields.put(enclosingType.getShortName() + '.' + sname, x);
@@ -285,9 +286,9 @@
return x;
}
- public JInterfaceType createInterface(char[][] name) {
+ public JInterfaceType createInterface(JSourceInfo info, char[][] name) {
String sname = dotify(name);
- JInterfaceType x = new JInterfaceType(this, sname);
+ JInterfaceType x = new JInterfaceType(this, info, sname);
allTypes.add(x);
putIntoTypeMap(sname, x);
@@ -295,13 +296,13 @@
return x;
}
- public JLocal createLocal(char[] name, JType type, boolean isFinal,
- JMethod enclosingMethod) {
+ public JLocal createLocal(JSourceInfo info, char[] name, JType type,
+ boolean isFinal, JMethod enclosingMethod) {
assert (name != null);
assert (type != null);
assert (enclosingMethod != null);
- JLocal x = new JLocal(this, String.valueOf(name), type, isFinal,
+ JLocal x = new JLocal(this, info, String.valueOf(name), type, isFinal,
enclosingMethod);
enclosingMethod.locals.add(x);
@@ -309,9 +310,9 @@
return x;
}
- public JMethod createMethod(char[] name, JReferenceType enclosingType,
- JType returnType, boolean isAbstract, boolean isStatic, boolean isFinal,
- boolean isPrivate, boolean isNative) {
+ public JMethod createMethod(JSourceInfo info, char[] name,
+ JReferenceType enclosingType, JType returnType, boolean isAbstract,
+ boolean isStatic, boolean isFinal, boolean isPrivate, boolean isNative) {
assert (name != null);
assert (returnType != null);
assert (!isAbstract || !isNative);
@@ -319,10 +320,10 @@
JMethod x;
String sname = String.valueOf(name);
if (isNative) {
- x = new JsniMethod(this, sname, enclosingType, returnType, isStatic,
- isFinal, isPrivate);
+ x = new JsniMethod(this, info, sname, enclosingType, returnType,
+ isStatic, isFinal, isPrivate);
} else {
- x = new JMethod(this, sname, enclosingType, returnType, isAbstract,
+ x = new JMethod(this, info, sname, enclosingType, returnType, isAbstract,
isStatic, isFinal, isPrivate);
}
@@ -341,14 +342,14 @@
return x;
}
- public JParameter createParameter(char[] name, JType type, boolean isFinal,
- JMethod enclosingMethod) {
+ public JParameter createParameter(JSourceInfo info, char[] name, JType type,
+ boolean isFinal, JMethod enclosingMethod) {
assert (name != null);
assert (type != null);
assert (enclosingMethod != null);
- JParameter x = new JParameter(this, String.valueOf(name), type, isFinal,
- enclosingMethod);
+ JParameter x = new JParameter(this, info, String.valueOf(name), type,
+ isFinal, enclosingMethod);
enclosingMethod.params.add(x);
@@ -374,8 +375,8 @@
return allTypes;
}
- public JThisRef getExpressionThisRef(JClassType enclosingType) {
- return new JThisRef(this, enclosingType);
+ public JThisRef getExprThisRef(JSourceInfo info, JClassType enclosingType) {
+ return new JThisRef(this, info, enclosingType);
}
public JReferenceType getFromTypeMap(String qualifiedBinaryOrSourceName) {
@@ -449,16 +450,16 @@
public JField getNullField() {
if (nullField == null) {
- nullField = new JField(this, "nullField", null, typeNull, false, true,
- true);
+ nullField = new JField(this, null, "nullField", null, typeNull, false,
+ true, true);
}
return nullField;
}
public JMethod getNullMethod() {
if (nullMethod == null) {
- nullMethod = new JsniMethod(this, "nullMethod", null, typeNull, false,
- true, true);
+ nullMethod = new JsniMethod(this, null, "nullMethod", null, typeNull,
+ false, true, true);
}
return nullMethod;
}
@@ -688,18 +689,12 @@
return type1;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < entryMethods.size(); ++i) {
- JMethod method = (JMethod) entryMethods.get(i);
- method.traverse(visitor);
- }
- for (int i = 0; i < allTypes.size(); ++i) {
- JReferenceType type = (JReferenceType) allTypes.get(i);
- type.traverse(visitor);
- }
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(entryMethods);
+ visitor.accept(allTypes);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
JReferenceType generalizeTypes(JReferenceType type1, JReferenceType type2) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JReferenceType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JReferenceType.java
index 11b60fd..9548010 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JReferenceType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JReferenceType.java
@@ -24,13 +24,13 @@
public abstract class JReferenceType extends JType implements CanBeAbstract,
CanBeFinal {
- public List/*<JField>*/ fields = new ArrayList/*<JField>*/();
- public List/*<JMethod>*/ methods = new ArrayList/*<JMethod>*/();
+ public List/* <JField> */fields = new ArrayList/* <JField> */();
+ public List/* <JMethod> */methods = new ArrayList/* <JMethod> */();
public JClassType extnds;
- public List/*<JInterfaceType>*/ implments = new ArrayList/*<JInterfaceType>*/();
+ public List/* <JInterfaceType> */implments = new ArrayList/* <JInterfaceType> */();
- public JReferenceType(JProgram program, String name) {
- super(program, name, program.getLiteralNull());
+ public JReferenceType(JProgram program, JSourceInfo info, String name) {
+ super(program, info, name, program.getLiteralNull());
}
public String getJavahSignatureName() {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JReturnStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JReturnStatement.java
index 0b84cb1..5662f7f 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JReturnStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JReturnStatement.java
@@ -20,22 +20,24 @@
*/
public class JReturnStatement extends JStatement {
- public final Holder expr = new Holder();
+ private JExpression expr;
- public JReturnStatement(JProgram program, JExpression expr) {
- super(program);
- this.expr.set(expr);
+ public JReturnStatement(JProgram program, JSourceInfo info, JExpression expr) {
+ super(program, info);
+ this.expr = expr;
}
- public JExpression getExpression() {
- return expr.get();
+ public JExpression getExpr() {
+ return expr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- expr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ if (expr != null) {
+ expr = visitor.accept(expr);
+ }
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JSourceInfo.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JSourceInfo.java
new file mode 100644
index 0000000..62b14ac
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JSourceInfo.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.ast;
+
+/**
+ * Tracks file and line information for AST nodes.
+ */
+public class JSourceInfo {
+
+ private final int endPos;
+ private final String fileName;
+ private final int startLine;
+ private final int startPos;
+
+ public JSourceInfo(int startPos, int endPos, int startLine, String fileName) {
+ this.startPos = startPos;
+ this.endPos = endPos;
+ this.startLine = startLine;
+ this.fileName = fileName;
+ }
+
+ public int getEndPos() {
+ return endPos;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public int getStartLine() {
+ return startLine;
+ }
+
+ public int getStartPos() {
+ return startPos;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JStatement.java
index 48f6afd..26a5f3b 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JStatement.java
@@ -20,8 +20,8 @@
*/
public abstract class JStatement extends JNode {
- public JStatement(JProgram program) {
- super(program);
+ public JStatement(JProgram program, JSourceInfo info) {
+ super(program, info);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JStringLiteral.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JStringLiteral.java
index 9e57356..e3f7da3 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JStringLiteral.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JStringLiteral.java
@@ -20,7 +20,7 @@
*/
public class JStringLiteral extends JLiteral {
- public final String value;
+ private final String value;
/**
* These are only supposed to be constructed by JProgram.
@@ -34,13 +34,13 @@
return program.getTypeJavaLangString();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
+ public String getValue() {
+ return value;
}
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JSwitchStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JSwitchStatement.java
index f408c12..1b2fd20 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JSwitchStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JSwitchStatement.java
@@ -16,29 +16,34 @@
package com.google.gwt.dev.jjs.ast;
/**
- * Java switch statement.
+ * Java switch statement.
*/
public class JSwitchStatement extends JStatement {
- private final Holder expr = new Holder();
- public JBlock body;
+ private final JBlock body;
+ private JExpression expr;
- public JSwitchStatement(JProgram program, JExpression expr, JBlock body) {
- super(program);
- this.expr.set(expr);
+ public JSwitchStatement(JProgram program, JSourceInfo info, JExpression expr,
+ JBlock body) {
+ super(program, info);
+ this.expr = expr;
this.body = body;
}
- public JExpression getExpression() {
- return expr.get();
+ public JBlock getBody() {
+ return body;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- expr.traverse(visitor);
- body.traverse(visitor);
+ public JExpression getExpr() {
+ return expr;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ expr = visitor.accept(expr);
+ visitor.accept(body);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JThisRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JThisRef.java
index ce0181d..5d3c9bd 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JThisRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JThisRef.java
@@ -20,13 +20,13 @@
*/
public class JThisRef extends JExpression {
- public JClassType classType;
+ private final JClassType classType;
/**
* These are only supposed to be constructed by JProgram.
*/
- JThisRef(JProgram program, JClassType classType) {
- super(program);
+ JThisRef(JProgram program, JSourceInfo info, JClassType classType) {
+ super(program, info);
this.classType = classType;
}
@@ -42,14 +42,10 @@
return false;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JThrowStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JThrowStatement.java
index 83230b6..9645be7 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JThrowStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JThrowStatement.java
@@ -20,22 +20,22 @@
*/
public class JThrowStatement extends JStatement {
- private final Holder expr = new Holder();
+ private JExpression expr;
- public JThrowStatement(JProgram program, JExpression expr) {
- super(program);
- this.expr.set(expr);
+ public JThrowStatement(JProgram program, JSourceInfo info, JExpression expr) {
+ super(program, info);
+ this.expr = expr;
}
- public JExpression getExpression() {
- return expr.get();
+ public JExpression getExpr() {
+ return expr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- expr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ expr = visitor.accept(expr);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java
index 8c174bb..38a4fd3 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTryStatement.java
@@ -22,32 +22,48 @@
*/
public class JTryStatement extends JStatement {
- public JBlock tryBlock;
- public final HolderList catchArgs = new HolderList();
- public List/*<JBlock>*/ catchBlocks;
- public JBlock finallyBlock;
+ private final List catchArgs;
+ private final List catchBlocks;
+ private final JBlock finallyBlock;
+ private final JBlock tryBlock;
- public JTryStatement(JProgram program, JBlock tryBlock, List/*<JLocalRef>*/ catchArgs,
- List/*<JBlock>*/ catchBlocks, JBlock finallyBlock) {
- super(program);
+ public JTryStatement(JProgram program, JSourceInfo info, JBlock tryBlock,
+ List/* <JLocalRef> */catchArgs, List/* <JBlock> */catchBlocks,
+ JBlock finallyBlock) {
+ super(program, info);
+ assert (catchArgs.size() == catchBlocks.size());
this.tryBlock = tryBlock;
- this.catchArgs.addAll(catchArgs);
+ this.catchArgs = catchArgs;
this.catchBlocks = catchBlocks;
this.finallyBlock = finallyBlock;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- tryBlock.traverse(visitor);
- catchArgs.traverse(visitor);
- for (int i = 0; i < catchBlocks.size(); ++i) {
- JBlock block = (JBlock) catchBlocks.get(i);
- block.traverse(visitor);
- }
+ public List getCatchArgs() {
+ return catchArgs;
+ }
+
+ public List/* <JBlock> */getCatchBlocks() {
+ return catchBlocks;
+ }
+
+ public JBlock getFinallyBlock() {
+ return finallyBlock;
+ }
+
+ public JBlock getTryBlock() {
+ return tryBlock;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(tryBlock);
+ visitor.accept(catchArgs);
+ visitor.accept(catchBlocks);
+ // TODO: normalize this so it's never null?
if (finallyBlock != null) {
- finallyBlock.traverse(visitor);
+ visitor.accept(finallyBlock);
}
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
index 6b864bd..3a35958 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JType.java
@@ -20,11 +20,12 @@
*/
public abstract class JType extends JNode implements HasName {
- public String name;
- public JLiteral defaultValue;
+ protected final String name;
+ private final JLiteral defaultValue;
- public JType(JProgram program, String name, JLiteral defaultValue) {
- super(program);
+ public JType(JProgram program, JSourceInfo info, String name,
+ JLiteral defaultValue) {
+ super(program, info);
this.name = name;
this.defaultValue = defaultValue;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java
index 75f5265..c8b27c8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVariable.java
@@ -21,12 +21,13 @@
public abstract class JVariable extends JNode implements CanBeFinal, HasName,
HasType, HasSettableType {
- public JType type;
- public String name;
- public boolean isFinal;
+ private boolean isFinal;
+ private final String name;
+ private JType type;
- JVariable(JProgram program, String name, JType type, boolean isFinal) {
- super(program);
+ JVariable(JProgram program, JSourceInfo info, String name, JType type,
+ boolean isFinal) {
+ super(program, info);
this.name = name;
this.type = type;
this.isFinal = isFinal;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVariableRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVariableRef.java
index 4c0f6a3..9a7e302 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVariableRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVariableRef.java
@@ -20,17 +20,17 @@
*/
public abstract class JVariableRef extends JExpression {
- public JVariable target;
-
- public JVariableRef(JProgram program, JVariable target) {
- super(program);
+ protected JVariable target;
+
+ public JVariableRef(JProgram program, JSourceInfo info, JVariable target) {
+ super(program, info);
this.target = target;
}
public JVariable getTarget() {
return target;
}
-
+
public JType getType() {
return target.getType();
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitable.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitable.java
index 87d2425..d18836a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitable.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitable.java
@@ -19,5 +19,12 @@
* Abstracts the idea that a class can be traversed.
*/
public interface JVisitable {
- void traverse(JVisitor visitor);
+
+ /**
+ * Causes this object to have the visitor visit itself and its children.
+ *
+ * @param visitor the visitor that should traverse this node
+ * @param ctx the context of an existing traversal
+ */
+ void traverse(JVisitor visitor, Context ctx);
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
index 1fb1f5b..fc9c259 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JVisitor.java
@@ -23,423 +23,533 @@
import com.google.gwt.dev.jjs.ast.js.JsonArray;
import com.google.gwt.dev.jjs.ast.js.JsonObject;
import com.google.gwt.dev.jjs.ast.js.JsonObject.JsonPropInit;
+import com.google.gwt.dev.jjs.impl.InternalCompilerException;
+
+import java.util.Iterator;
+import java.util.List;
/**
- * A visitor for iterating through the parse tree.
+ * A visitor for iterating through an AST.
*/
public class JVisitor {
- public void endVisit(JAbsentArrayDimension x, Mutator m) {
+ protected static final Context UNMODIFIABLE_CONTEXT = new Context() {
+
+ public boolean canInsert() {
+ return false;
+ }
+
+ public boolean canRemove() {
+ return false;
+ }
+
+ public void insertAfter(JNode node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void insertBefore(JNode node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void removeMe() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void replaceMe(JNode node) {
+ throw new UnsupportedOperationException();
+ }
+
+ };
+
+ public final JExpression accept(JExpression node) {
+ return (JExpression) doAccept(node);
}
- public void endVisit(JArrayRef x, Mutator m) {
+ public final JNode accept(JNode node) {
+ return doAccept(node);
}
- public void endVisit(JArrayType x) {
+ public final JStatement accept(JStatement node) {
+ return (JStatement) doAccept(node);
}
- public void endVisit(JAssertStatement x) {
+ public final void accept(List list) {
+ doAccept(list);
}
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public final void acceptWithInsertRemove(List list) {
+ doAcceptWithInsertRemove(list);
}
- public void endVisit(JBlock x) {
+ public boolean didChange() {
+ throw new UnsupportedOperationException();
}
- public void endVisit(JBooleanLiteral x, Mutator m) {
+ public void endVisit(JAbsentArrayDimension x, Context ctx) {
}
- public void endVisit(JBreakStatement x) {
+ public void endVisit(JArrayRef x, Context ctx) {
}
- public void endVisit(JCaseStatement x) {
+ public void endVisit(JArrayType x, Context ctx) {
}
- public void endVisit(JCastOperation x, Mutator m) {
+ public void endVisit(JAssertStatement x, Context ctx) {
}
- public void endVisit(JCharLiteral x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
}
- public void endVisit(JClassLiteral x, Mutator m) {
+ public void endVisit(JBlock x, Context ctx) {
}
- public void endVisit(JClassSeed x, Mutator m) {
+ public void endVisit(JBooleanLiteral x, Context ctx) {
}
- public void endVisit(JClassType x) {
+ public void endVisit(JBreakStatement x, Context ctx) {
}
- public void endVisit(JConditional x, Mutator m) {
+ public void endVisit(JCaseStatement x, Context ctx) {
}
- public void endVisit(JContinueStatement x) {
+ public void endVisit(JCastOperation x, Context ctx) {
}
- public void endVisit(JDoStatement x) {
+ public void endVisit(JCharLiteral x, Context ctx) {
}
- public void endVisit(JDoubleLiteral x, Mutator m) {
+ public void endVisit(JClassLiteral x, Context ctx) {
}
- public void endVisit(JExpressionStatement x) {
+ public void endVisit(JClassSeed x, Context ctx) {
}
- public void endVisit(JField x) {
+ public void endVisit(JClassType x, Context ctx) {
}
- public void endVisit(JFieldRef x, Mutator m) {
+ public void endVisit(JConditional x, Context ctx) {
}
- public void endVisit(JFloatLiteral x, Mutator m) {
+ public void endVisit(JContinueStatement x, Context ctx) {
}
- public void endVisit(JForStatement x) {
+ public void endVisit(JDoStatement x, Context ctx) {
}
- public void endVisit(JIfStatement x) {
+ public void endVisit(JDoubleLiteral x, Context ctx) {
}
- public void endVisit(JInstanceOf x, Mutator m) {
+ public void endVisit(JExpressionStatement x, Context ctx) {
}
- public void endVisit(JInterfaceType x) {
+ public void endVisit(JField x, Context ctx) {
}
- public void endVisit(JIntLiteral x, Mutator m) {
+ public void endVisit(JFieldRef x, Context ctx) {
}
- public void endVisit(JLabel x) {
+ public void endVisit(JFloatLiteral x, Context ctx) {
}
- public void endVisit(JLabeledStatement x) {
+ public void endVisit(JForStatement x, Context ctx) {
}
- public void endVisit(JLocal x) {
+ public void endVisit(JIfStatement x, Context ctx) {
}
- public void endVisit(JLocalDeclarationStatement x) {
+ public void endVisit(JInstanceOf x, Context ctx) {
}
- public void endVisit(JLocalRef x, Mutator m) {
+ public void endVisit(JInterfaceType x, Context ctx) {
}
- public void endVisit(JLongLiteral x, Mutator m) {
+ public void endVisit(JIntLiteral x, Context ctx) {
}
- public void endVisit(JMethod x) {
+ public void endVisit(JLabel x, Context ctx) {
}
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JLabeledStatement x, Context ctx) {
}
- public void endVisit(JMultiExpression x, Mutator m) {
+ public void endVisit(JLocal x, Context ctx) {
}
- public void endVisit(JNewArray x, Mutator m) {
+ public void endVisit(JLocalDeclarationStatement x, Context ctx) {
}
- public void endVisit(JNewInstance x, Mutator m) {
+ public void endVisit(JLocalRef x, Context ctx) {
}
- public void endVisit(JNullLiteral x, Mutator m) {
+ public void endVisit(JLongLiteral x, Context ctx) {
}
- public void endVisit(JNullType x) {
+ public void endVisit(JMethod x, Context ctx) {
}
- public void endVisit(JParameter x) {
+ public void endVisit(JMethodCall x, Context ctx) {
}
- public void endVisit(JParameterRef x, Mutator m) {
+ public void endVisit(JMultiExpression x, Context ctx) {
}
- public void endVisit(JPostfixOperation x, Mutator m) {
+ public void endVisit(JNewArray x, Context ctx) {
}
- public void endVisit(JPrefixOperation x, Mutator m) {
+ public void endVisit(JNewInstance x, Context ctx) {
}
- public void endVisit(JPrimitiveType x) {
+ public void endVisit(JNullLiteral x, Context ctx) {
}
- public void endVisit(JProgram x) {
+ public void endVisit(JNullType x, Context ctx) {
}
- public void endVisit(JReturnStatement x) {
+ public void endVisit(JParameter x, Context ctx) {
}
- public void endVisit(JsniFieldRef x) {
+ public void endVisit(JParameterRef x, Context ctx) {
}
- public void endVisit(JsniMethod x) {
+ public void endVisit(JPostfixOperation x, Context ctx) {
}
- public void endVisit(JsniMethodRef x) {
+ public void endVisit(JPrefixOperation x, Context ctx) {
}
- public void endVisit(JsonArray x, Mutator m) {
+ public void endVisit(JPrimitiveType x, Context ctx) {
}
- public void endVisit(JsonObject x, Mutator m) {
+ public void endVisit(JProgram x, Context ctx) {
}
- public void endVisit(JsonPropInit x) {
+ public void endVisit(JReturnStatement x, Context ctx) {
}
- public void endVisit(JStringLiteral x, Mutator m) {
+ public void endVisit(JsniFieldRef x, Context ctx) {
}
- public void endVisit(JSwitchStatement x) {
+ public void endVisit(JsniMethod x, Context ctx) {
}
- public void endVisit(JThisRef x, Mutator m) {
+ public void endVisit(JsniMethodRef x, Context ctx) {
}
- public void endVisit(JThrowStatement x) {
+ public void endVisit(JsonArray x, Context ctx) {
}
- public void endVisit(JTryStatement x) {
+ public void endVisit(JsonObject x, Context ctx) {
}
- public void endVisit(JWhileStatement x) {
+ public void endVisit(JsonPropInit x, Context ctx) {
}
- public boolean visit(JAbsentArrayDimension x, Mutator m) {
+ public void endVisit(JStringLiteral x, Context ctx) {
+ }
+
+ public void endVisit(JSwitchStatement x, Context ctx) {
+ }
+
+ public void endVisit(JThisRef x, Context ctx) {
+ }
+
+ public void endVisit(JThrowStatement x, Context ctx) {
+ }
+
+ public void endVisit(JTryStatement x, Context ctx) {
+ }
+
+ public void endVisit(JWhileStatement x, Context ctx) {
+ }
+
+ public boolean visit(JAbsentArrayDimension x, Context ctx) {
return true;
}
- public boolean visit(JArrayRef x, Mutator m) {
+ public boolean visit(JArrayRef x, Context ctx) {
return true;
}
- public boolean visit(JArrayType x) {
+ public boolean visit(JArrayType x, Context ctx) {
return true;
}
- public boolean visit(JAssertStatement x) {
+ public boolean visit(JAssertStatement x, Context ctx) {
return true;
}
- public boolean visit(JBinaryOperation x, Mutator m) {
+ public boolean visit(JBinaryOperation x, Context ctx) {
return true;
}
- public boolean visit(JBlock x) {
+ public boolean visit(JBlock x, Context ctx) {
return true;
}
- public boolean visit(JBooleanLiteral x, Mutator m) {
+ public boolean visit(JBooleanLiteral x, Context ctx) {
return true;
}
- public boolean visit(JBreakStatement x) {
+ public boolean visit(JBreakStatement x, Context ctx) {
return true;
}
- public boolean visit(JCaseStatement x) {
+ public boolean visit(JCaseStatement x, Context ctx) {
return true;
}
- public boolean visit(JCastOperation x, Mutator m) {
+ public boolean visit(JCastOperation x, Context ctx) {
return true;
}
- public boolean visit(JCharLiteral x, Mutator m) {
+ public boolean visit(JCharLiteral x, Context ctx) {
return true;
}
- public boolean visit(JClassLiteral x, Mutator m) {
+ public boolean visit(JClassLiteral x, Context ctx) {
return true;
}
- public boolean visit(JClassSeed x, Mutator m) {
+ public boolean visit(JClassSeed x, Context ctx) {
return true;
}
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
return true;
}
- public boolean visit(JConditional x, Mutator m) {
+ public boolean visit(JConditional x, Context ctx) {
return true;
}
- public boolean visit(JContinueStatement x) {
+ public boolean visit(JContinueStatement x, Context ctx) {
return true;
}
- public boolean visit(JDoStatement x) {
+ public boolean visit(JDoStatement x, Context ctx) {
return true;
}
- public boolean visit(JDoubleLiteral x, Mutator m) {
+ public boolean visit(JDoubleLiteral x, Context ctx) {
return true;
}
- public boolean visit(JExpressionStatement x) {
+ public boolean visit(JExpressionStatement x, Context ctx) {
return true;
}
- public boolean visit(JField x) {
+ public boolean visit(JField x, Context ctx) {
return true;
}
- public boolean visit(JFieldRef x, Mutator m) {
+ public boolean visit(JFieldRef x, Context ctx) {
return true;
}
- public boolean visit(JFloatLiteral x, Mutator m) {
+ public boolean visit(JFloatLiteral x, Context ctx) {
return true;
}
- public boolean visit(JForStatement x) {
+ public boolean visit(JForStatement x, Context ctx) {
return true;
}
- public boolean visit(JIfStatement x) {
+ public boolean visit(JIfStatement x, Context ctx) {
return true;
}
- public boolean visit(JInstanceOf x, Mutator m) {
+ public boolean visit(JInstanceOf x, Context ctx) {
return true;
}
- public boolean visit(JInterfaceType x) {
+ public boolean visit(JInterfaceType x, Context ctx) {
return true;
}
- public boolean visit(JIntLiteral x, Mutator m) {
+ public boolean visit(JIntLiteral x, Context ctx) {
return true;
}
- public boolean visit(JLabel x) {
+ public boolean visit(JLabel x, Context ctx) {
return true;
}
- public boolean visit(JLabeledStatement x) {
+ public boolean visit(JLabeledStatement x, Context ctx) {
return true;
}
- public boolean visit(JLocal x) {
+ public boolean visit(JLocal x, Context ctx) {
return true;
}
- public boolean visit(JLocalDeclarationStatement x) {
+ public boolean visit(JLocalDeclarationStatement x, Context ctx) {
return true;
}
- public boolean visit(JLocalRef x, Mutator m) {
+ public boolean visit(JLocalRef x, Context ctx) {
return true;
}
- public boolean visit(JLongLiteral x, Mutator m) {
+ public boolean visit(JLongLiteral x, Context ctx) {
return true;
}
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
return true;
}
- public boolean visit(JMethodCall x, Mutator m) {
+ public boolean visit(JMethodCall x, Context ctx) {
return true;
}
- public boolean visit(JMultiExpression x, Mutator m) {
+ public boolean visit(JMultiExpression x, Context ctx) {
return true;
}
- public boolean visit(JNewArray x, Mutator m) {
+ public boolean visit(JNewArray x, Context ctx) {
return true;
}
- public boolean visit(JNewInstance x, Mutator m) {
+ public boolean visit(JNewInstance x, Context ctx) {
return true;
}
- public boolean visit(JNullLiteral x, Mutator m) {
+ public boolean visit(JNullLiteral x, Context ctx) {
return true;
}
- public boolean visit(JNullType x) {
+ public boolean visit(JNullType x, Context ctx) {
return true;
}
- public boolean visit(JParameter x) {
+ public boolean visit(JParameter x, Context ctx) {
return true;
}
- public boolean visit(JParameterRef x, Mutator m) {
+ public boolean visit(JParameterRef x, Context ctx) {
return true;
}
- public boolean visit(JPostfixOperation x, Mutator m) {
+ public boolean visit(JPostfixOperation x, Context ctx) {
return true;
}
- public boolean visit(JPrefixOperation x, Mutator m) {
+ public boolean visit(JPrefixOperation x, Context ctx) {
return true;
}
- public boolean visit(JPrimitiveType x) {
+ public boolean visit(JPrimitiveType x, Context ctx) {
return true;
}
- public boolean visit(JProgram x) {
+ public boolean visit(JProgram x, Context ctx) {
return true;
}
- public boolean visit(JReturnStatement x) {
+ public boolean visit(JReturnStatement x, Context ctx) {
return true;
}
- public boolean visit(JsniFieldRef x) {
+ public boolean visit(JsniFieldRef x, Context ctx) {
return true;
}
- public boolean visit(JsniMethod x) {
+ public boolean visit(JsniMethod x, Context ctx) {
return true;
}
- public boolean visit(JsniMethodRef x) {
+ public boolean visit(JsniMethodRef x, Context ctx) {
return true;
}
- public boolean visit(JsonArray x, Mutator m) {
+ public boolean visit(JsonArray x, Context ctx) {
return true;
}
- public boolean visit(JsonObject x, Mutator m) {
+ public boolean visit(JsonObject x, Context ctx) {
return true;
}
- public boolean visit(JsonPropInit x) {
+ public boolean visit(JsonPropInit x, Context ctx) {
return true;
}
- public boolean visit(JStringLiteral x, Mutator m) {
+ public boolean visit(JStringLiteral x, Context ctx) {
return true;
}
- public boolean visit(JSwitchStatement x) {
+ public boolean visit(JSwitchStatement x, Context ctx) {
return true;
}
- public boolean visit(JThisRef x, Mutator m) {
+ public boolean visit(JThisRef x, Context ctx) {
return true;
}
- public boolean visit(JThrowStatement x) {
+ public boolean visit(JThrowStatement x, Context ctx) {
return true;
}
- public boolean visit(JTryStatement x) {
+ public boolean visit(JTryStatement x, Context ctx) {
return true;
}
- public boolean visit(JWhileStatement x) {
+ public boolean visit(JWhileStatement x, Context ctx) {
return true;
}
+ protected JNode doAccept(JNode node) {
+ doTraverse(node, UNMODIFIABLE_CONTEXT);
+ return node;
+ }
+
+ protected void doAccept(List list) {
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ doTraverse((JNode) it.next(), UNMODIFIABLE_CONTEXT);
+ }
+ }
+
+ protected void doAcceptWithInsertRemove(List list) {
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ doTraverse((JNode) it.next(), UNMODIFIABLE_CONTEXT);
+ }
+ }
+
+ protected final void doTraverse(JNode node, Context ctx) {
+ // boolean trace = false;
+ // String before = null;
+ try {
+ // trace = !(this instanceof ToStringGenerationVisitor)
+ // && (node instanceof JTryStatement);
+ // if (trace) {
+ // before = node.toSource();
+ // }
+ node.traverse(this, ctx);
+ // if (trace) {
+ // String after = node.toSource();
+ // if (!before.equals(after)) {
+ // System.out.println(this.getClass().getName() + ":");
+ // System.out.println("--");
+ // System.out.println(before);
+ // System.out.println("VV");
+ // System.out.println(after);
+ // System.out.println("---------------------------------------------------------");
+ // }
+ // }
+ } catch (InternalCompilerException ice) {
+ ice.addNode(node);
+ throw ice;
+ } catch (Throwable e) {
+ // if (trace) {
+ // System.out.println(this.getClass().getName() + ":");
+ // System.out.println("--");
+ // System.out.println(before);
+ // System.out.println(e);
+ // }
+ InternalCompilerException ice = new InternalCompilerException(
+ "Unexpected error during visit.", e);
+ ice.addNode(node);
+ throw ice;
+ }
+ }
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JWhileStatement.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JWhileStatement.java
index 646d0c1..39a11d6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/JWhileStatement.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JWhileStatement.java
@@ -20,27 +20,32 @@
*/
public class JWhileStatement extends JStatement {
- private final Holder testExpr = new Holder();
- public JStatement body;
+ private JStatement body;
+ private JExpression testExpr;
- public JWhileStatement(JProgram program, JExpression testExpr, JStatement body) {
- super(program);
- this.testExpr.set(testExpr);
+ public JWhileStatement(JProgram program, JSourceInfo info,
+ JExpression testExpr, JStatement body) {
+ super(program, info);
+ this.testExpr = testExpr;
this.body = body;
}
- public JExpression getTestExpr() {
- return testExpr.get();
+ public JStatement getBody() {
+ return body;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- testExpr.traverse(visitor);
+ public JExpression getTestExpr() {
+ return testExpr;
+ }
+
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ testExpr = visitor.accept(testExpr);
if (body != null) {
- body.traverse(visitor);
+ body = visitor.accept(body);
}
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddAll.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddAll.java
deleted file mode 100644
index 73cc64d..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddAll.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-
-import java.util.List;
-
-class AddAll/* <N extends JNode> */extends ChangeBase {
-
- final List/* <N> */source;
- final List/* <N> */list;
- private final int index;
-
- public AddAll(List/* <N> */source, int index, List/* <N> */list) {
- this.source = source;
- this.index = index;
- this.list = list;
- }
-
- public void apply() {
- if (index < 0) {
- list.addAll(source);
- } else {
- list.addAll(index, source);
- }
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- if (index < 0) {
- logger.log(type, "Add a list to a list", null);
- } else {
- logger.log(type, "Add a list to a list at index " + index, null);
- }
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddNode.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddNode.java
deleted file mode 100644
index 509a382..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddNode.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.JNode;
-
-import java.util.List;
-
-class AddNode/* <N extends JNode> */extends ChangeBase {
-
- final List/* <N> */list;
- private final JNode node;
- private final int index;
-
- public AddNode(JNode node, int index, List/* <N> */list) {
- this.node = node;
- this.index = index;
- this.list = list;
- assert (!list.contains(node));
- }
-
- public void apply() {
- if (index < 0) {
- list.add(node);
- } else {
- list.add(index, node);
- }
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- if (index < 0) {
- logger.log(type, "Add " + ChangeList.getNodeString(node)
- + ChangeList.getEnclosingTypeString(" to the end of", node), null);
- } else {
- logger.log(type, "Add " + ChangeList.getNodeString(node)
- + ChangeList.getEnclosingTypeString(" to", node) + " at index "
- + index, null);
- }
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddNodeMutator.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddNodeMutator.java
deleted file mode 100644
index 4f06e28..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/AddNodeMutator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.Mutator;
-
-import java.util.List;
-
-class AddNodeMutator/* <N extends JNode> */extends ChangeBase {
-
- final List/* <N> */list;
- private final Mutator/* <N> */node;
- private final int index;
-
- public AddNodeMutator(Mutator/* <N> */node, int index, List/* <N> */list) {
- this.node = node;
- this.index = index;
- this.list = list;
- assert (!list.contains(node));
- }
-
- public void apply() {
- assert (!list.contains(node));
- if (index < 0) {
- list.add(node.get());
- } else {
- list.add(index, node.get());
- }
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- if (index < 0) {
- logger.log(type, "Add the eventual value of "
- + ChangeList.getNodeString(node.get()) + " to a list", null);
- } else {
- logger.log(type, "Add the eventual value of "
- + ChangeList.getNodeString(node.get()) + " to a list at index "
- + index, null);
- }
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ChangeBase.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/ChangeBase.java
deleted file mode 100644
index 979bb92..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ChangeBase.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-abstract class ChangeBase implements Change {
-
- public String toString() {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw, true);
- PrintWriterTreeLogger logger = new PrintWriterTreeLogger(pw);
- logger.setMaxDetail(TreeLogger.INFO);
- describe(logger, TreeLogger.INFO);
- return sw.toString();
- }
-
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ChangeList.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/ChangeList.java
deleted file mode 100644
index dfea792..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ChangeList.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.CanBeSetFinal;
-import com.google.gwt.dev.jjs.ast.HasEnclosingType;
-import com.google.gwt.dev.jjs.ast.HasSettableType;
-import com.google.gwt.dev.jjs.ast.JBlock;
-import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.JField;
-import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JReferenceType;
-import com.google.gwt.dev.jjs.ast.JStatement;
-import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.jjs.ast.Mutator;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Manages a list of {@link Change} objects to apply to the AST.
- */
-public class ChangeList extends ChangeBase {
-
- static String getEnclosingTypeString(String prefix, Object x) {
- if (x instanceof HasEnclosingType) {
- JReferenceType enclosingType = ((HasEnclosingType) x).getEnclosingType();
- if (enclosingType != null) {
- return prefix + " type '" + enclosingType.getName() + "'";
- }
- }
- return "";
- }
-
- static String getNodeString(JNode x) {
- if (x == null) {
- return String.valueOf(x);
- }
- return x.getClass().getName() + " '" + x + "'";
- }
-
- private final List/* <Change> */changes = new ArrayList/* <Change> */();
-
- private final String description;
-
- public ChangeList(String description) {
- this.description = description;
- }
-
- public void add(Change change) {
- changes.add(change);
- }
-
- public/* <N extends JNode> */void addAll(List/* <N> */x, int index,
- List/* <N> */list) {
- AddAll change = new AddAll/* <N> */(x, index, list);
- changes.add(change);
- }
-
- public void addExpression(JExpression x, List/* <JExpression> */list) {
- addNode(x, -1, list);
- }
-
- public void addExpression(Mutator x, List/* <JExpression> */list) {
- addNode(x, -1, list);
- }
-
- public void addMethod(JMethod x) {
- addNode(x, -1, x.getEnclosingType().methods);
- }
-
- public/* <N extends JNode> */void addNode(JNode x, int index,
- List/* <N> */list) {
- AddNode change = new AddNode/* <N> */(x, index, list);
- changes.add(change);
- }
-
- public/* <N extends JNode> */void addNode(Mutator/* <N> */x, int index,
- List/* <N> */list) {
- AddNodeMutator change = new AddNodeMutator/* <N> */(x, index, list);
- changes.add(change);
- }
-
- public void addStatement(JStatement x, int index, JBlock body) {
- addNode(x, index, body.statements);
- }
-
- public void addStatement(JStatement x, JBlock body) {
- addNode(x, -1, body.statements);
- }
-
- public void apply() {
- for (int i = 0; i < changes.size(); ++i) {
- Change change = (Change) changes.get(i);
- change.apply();
- }
- }
-
- public void changeType(HasSettableType x, JType type) {
- TypeChange change = new TypeChange(x, type);
- changes.add(change);
- }
-
- public/* <N extends JNode> */void clear(List/* <N> */list) {
- ClearList/* <N> */change = new ClearList/* <N> */(list);
- changes.add(change);
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- TreeLogger branch = logger.branch(type, description, null);
- for (int i = 0; i < changes.size(); ++i) {
- Change change = (Change) changes.get(i);
- change.describe(branch, type);
- }
- }
-
- public boolean empty() {
- return changes.size() == 0;
- }
-
- public void makeFinal(CanBeSetFinal x) {
- MakeFinal change = new MakeFinal(x);
- changes.add(change);
- }
-
- public void moveBody(JMethod sourceMethod, JMethod targetMethod) {
- JBlock source = sourceMethod.body;
- JBlock target = targetMethod.body;
- MoveBlock change = new MoveBlock(source, target);
- changes.add(change);
- }
-
- public void removeField(JField x) {
- removeNode(x, x.getEnclosingType().fields);
- }
-
- public void removeMethod(JMethod x) {
- removeNode(x, x.getEnclosingType().methods);
- }
-
- public/* <N extends JNode> */void removeNode(JNode x, List/* <N> */list) {
- RemoveNode/* <N> */change = new RemoveNode/* <N> */(x, list);
- changes.add(change);
- }
-
- public/* <N extends JNode> */void removeNode(Mutator/* <N> */x,
- List/* <N> */list) {
- RemoveNodeMutator/* <N> */change = new RemoveNodeMutator/* <N> */(x, list);
- changes.add(change);
- }
-
- public void removeType(JReferenceType x) {
- removeNode(x, x.getProgram().getDeclaredTypes());
- }
-
- public void replaceExpression(Mutator original, JExpression replace) {
- ReplaceNode change = new ReplaceNode/* <JExpression> */(original, replace);
- changes.add(change);
- }
-
- public void replaceExpression(Mutator original, Mutator replace) {
- ReplaceNodeMutator change = new ReplaceNodeMutator(original, replace);
- changes.add(change);
- }
-
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ClearList.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/ClearList.java
deleted file mode 100644
index 3172358..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ClearList.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-
-import java.util.List;
-
-class ClearList/* <N extends JNode> */extends ChangeBase {
-
- private final List/* <N> */list;
-
- public ClearList(List/* <N> */list) {
- this.list = list;
- }
-
- public void apply() {
- list.clear();
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Clear a list", null);
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/MakeFinal.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/MakeFinal.java
deleted file mode 100644
index 679a9a7..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/MakeFinal.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.CanBeSetFinal;
-import com.google.gwt.dev.jjs.ast.JNode;
-
-class MakeFinal implements Change {
- private final CanBeSetFinal x;
-
- public MakeFinal(CanBeSetFinal x) {
- this.x = x;
- }
-
- public void apply() {
- x.setFinal(true);
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Make final " + ChangeList.getNodeString((JNode) x)
- + ChangeList.getEnclosingTypeString(" from", x), null);
- }
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/MoveBlock.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/MoveBlock.java
deleted file mode 100644
index 9e92dff..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/MoveBlock.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.JBlock;
-
-class MoveBlock implements Change {
- final JBlock source;
- final JBlock target;
-
- public MoveBlock(JBlock source, JBlock target) {
- super();
- this.source = source;
- this.target = target;
- }
-
- public void apply() {
- assert (target.statements.size() == 0);
- target.statements.addAll(source.statements);
- source.statements.clear();
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Move the body of " + ChangeList.getNodeString(source)
- + " to " + ChangeList.getNodeString(target), null);
- }
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/RemoveNode.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/RemoveNode.java
deleted file mode 100644
index 7d73e7e..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/RemoveNode.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.JNode;
-
-import java.util.List;
-
-class RemoveNode/* <N extends JNode> */extends ChangeBase {
-
- final List/* <N> */list;
- private final JNode node;
-
- public RemoveNode(JNode node, List/* <N> */list) {
- this.node = node;
- this.list = list;
- assert (list.contains(node));
- }
-
- public void apply() {
- boolean removed = list.remove(node);
- assert (removed);
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Remove " + ChangeList.getNodeString(node)
- + ChangeList.getEnclosingTypeString(" from", node), null);
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/RemoveNodeMutator.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/RemoveNodeMutator.java
deleted file mode 100644
index afa7e7d..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/RemoveNodeMutator.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.Mutator;
-
-import java.util.List;
-
-class RemoveNodeMutator/* <N extends JNode> */extends ChangeBase {
-
- final List/* <N> */list;
- private final Mutator/* <N> */node;
-
- public RemoveNodeMutator(Mutator/* <N> */node, List/* <N> */list) {
- this.node = node;
- this.list = list;
- assert (list.contains(node.get()));
- }
-
- public void apply() {
- boolean removed = list.remove(node.get());
- assert (removed);
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Remove " + ChangeList.getNodeString(node.get())
- + ChangeList.getEnclosingTypeString(" from", node.get()), null);
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ReplaceNode.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/ReplaceNode.java
deleted file mode 100644
index fc0100a..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ReplaceNode.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.JExpression;
-import com.google.gwt.dev.jjs.ast.Mutator;
-
-class ReplaceNode/* <N extends JNode> */extends ChangeBase {
-
- final Mutator/* <N> */original;
- final JExpression replace;
-
- public ReplaceNode(Mutator/* <N> */original, JExpression replace) {
- this.original = original;
- this.replace = replace;
- }
-
- public void apply() {
- original.set(replace);
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Replace " + ChangeList.getNodeString(original.get())
- + " with " + ChangeList.getNodeString(replace), null);
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ReplaceNodeMutator.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/ReplaceNodeMutator.java
deleted file mode 100644
index 70f0668..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/ReplaceNodeMutator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.Mutator;
-
-class ReplaceNodeMutator/* <N extends JNode> */extends ChangeBase {
-
- final Mutator/* <N> */original;
- final Mutator/* <N> */replace;
-
- public ReplaceNodeMutator(Mutator/* <N> */original, Mutator/* <N> */replace) {
- this.original = original;
- this.replace = replace;
- }
-
- public void apply() {
- original.set(replace.get());
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Replace " + ChangeList.getNodeString(original.get())
- + " with " + ChangeList.getNodeString(replace.get()), null);
- }
-
-}
\ No newline at end of file
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/TypeChange.java b/dev/core/src/com/google/gwt/dev/jjs/ast/change/TypeChange.java
deleted file mode 100644
index d6f8812..0000000
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/TypeChange.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2006 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
-import com.google.gwt.dev.jjs.ast.HasSettableType;
-import com.google.gwt.dev.jjs.ast.JNode;
-import com.google.gwt.dev.jjs.ast.JType;
-
-/**
- * Changes the <code>JType</code> of a <code>JNode</code>.
- */
-public class TypeChange extends ChangeBase {
-
- final JType targetType;
- private final HasSettableType node;
- private final JType oldType;
-
- public TypeChange(HasSettableType node, JType targetType) {
- this.node = node;
- this.oldType = node.getType();
- this.targetType = targetType;
- }
-
- public void apply() {
- assert (oldType == node.getType());
- node.setType(targetType);
- }
-
- public void describe(TreeLogger logger, TreeLogger.Type type) {
- logger.log(type, "Change type of " + ChangeList.getNodeString((JNode) node)
- + " from " + ChangeList.getNodeString(node.getType()) + " to "
- + ChangeList.getNodeString(targetType), null);
- }
-
-}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JClassSeed.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JClassSeed.java
index 6571691..cc02da5 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JClassSeed.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JClassSeed.java
@@ -15,12 +15,12 @@
*/
package com.google.gwt.dev.jjs.ast.js;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
/**
* An AST node representing a class's constructor function. Only used by
@@ -31,24 +31,24 @@
/**
* The class being referred to.
*/
- public final JClassType refType;
+ private final JClassType refType;
public JClassSeed(JProgram program, JClassType type) {
super(program);
refType = type;
}
+ public JClassType getRefType() {
+ return refType;
+ }
+
public JType getType() {
return program.getTypeJavaLangObject();
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JMultiExpression.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JMultiExpression.java
index c167090..dd93820 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JMultiExpression.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JMultiExpression.java
@@ -15,22 +15,24 @@
*/
package com.google.gwt.dev.jjs.ast.js;
-import com.google.gwt.dev.jjs.ast.HolderList;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
+
+import java.util.ArrayList;
/**
* Represents multiple ordered expressions as a single compound expression.
*/
public class JMultiExpression extends JExpression {
- public HolderList exprs = new HolderList();
+ public ArrayList exprs = new ArrayList();
- public JMultiExpression(JProgram program) {
- super(program);
+ public JMultiExpression(JProgram program, JSourceInfo info) {
+ super(program, info);
}
public JType getType() {
@@ -38,14 +40,13 @@
if (c == 0) {
return program.getTypeVoid();
} else {
- return exprs.getExpr(c - 1).getType();
+ return ((JExpression) exprs.get(c - 1)).getType();
}
}
public boolean hasSideEffects() {
-
for (int i = 0; i < exprs.size(); ++i) {
- JExpression expr = exprs.getExpr(i);
+ JExpression expr = (JExpression) exprs.get(i);
if (expr.hasSideEffects()) {
return true;
}
@@ -53,15 +54,11 @@
return false;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- exprs.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(exprs);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java
index 2675676..32764df 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniFieldRef.java
@@ -15,25 +15,27 @@
*/
package com.google.gwt.dev.jjs.ast.js;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
/**
* JSNI reference to a Java field.
*/
public class JsniFieldRef extends JFieldRef {
- public JsniFieldRef(JProgram program, JField field,
- JReferenceType enclosingType) {
- super(program, null, field, enclosingType);
+ public JsniFieldRef(JProgram program, JSourceInfo info,
+ JField field, JReferenceType enclosingType) {
+ super(program, info, null, field, enclosingType);
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethod.java
index 1c8a700..17b393c 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethod.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethod.java
@@ -15,12 +15,13 @@
*/
package com.google.gwt.dev.jjs.ast.js;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JMethod;
-import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
import com.google.gwt.dev.js.ast.JsFunction;
import java.util.ArrayList;
@@ -35,11 +36,11 @@
public final List/* <JsniMethodRef> */jsniMethodRefs = new ArrayList/* <JsniMethodRef> */();
private JsFunction jsFunction = null;
- public JsniMethod(JProgram program, String name,
- JReferenceType enclosingType, JType returnType, boolean isStatic,
- boolean isFinal, boolean isPrivate) {
- super(program, name, enclosingType, returnType, false, isStatic, isFinal,
- isPrivate);
+ public JsniMethod(JProgram program, JSourceInfo info,
+ String name, JReferenceType enclosingType, JType returnType,
+ boolean isStatic, boolean isFinal, boolean isPrivate) {
+ super(program, info, name, enclosingType, returnType, false, isStatic,
+ isFinal, isPrivate);
}
public JsFunction getFunc() {
@@ -56,22 +57,13 @@
this.jsFunction = jsFunction;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- for (int i = 0; i < params.size(); ++i) {
- JParameter param = (JParameter) params.get(i);
- param.traverse(visitor);
- }
- for (int i = 0; i < jsniFieldRefs.size(); ++i) {
- JsniFieldRef fieldRef = (JsniFieldRef) jsniFieldRefs.get(i);
- fieldRef.traverse(visitor);
- }
- for (int i = 0; i < jsniMethodRefs.size(); ++i) {
- JsniMethodRef methodRef = (JsniMethodRef) jsniMethodRefs.get(i);
- methodRef.traverse(visitor);
- }
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(params);
+ visitor.accept(jsniFieldRefs);
+ visitor.accept(jsniMethodRefs);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java
index f479a99..b5c20b8 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsniMethodRef.java
@@ -15,23 +15,25 @@
*/
package com.google.gwt.dev.jjs.ast.js;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
/**
* A call to a JSNI method.
*/
public class JsniMethodRef extends JMethodCall {
- public JsniMethodRef(JProgram program, JMethod method) {
- super(program, null, method);
+ public JsniMethodRef(JProgram program, JSourceInfo info, JMethod method) {
+ super(program, info, null, method);
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonArray.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonArray.java
index 36f731a..6eae09a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonArray.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonArray.java
@@ -15,41 +15,41 @@
*/
package com.google.gwt.dev.jjs.ast.js;
-import com.google.gwt.dev.jjs.ast.HolderList;
+import com.google.gwt.dev.jjs.ast.Context;
+import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
+
+import java.util.ArrayList;
/**
* A JSON-style list of JS expressions.
*/
public class JsonArray extends JExpression {
- public HolderList exprs = new HolderList();
+ public ArrayList exprs = new ArrayList();
public JsonArray(JProgram program) {
- super(program);
+ super(program, null);
}
public JType getType() {
- return program.getTypeVoid();
+ // If JavaScriptObject type is not available, just return the Object type
+ JClassType jsoType = program.getSpecialJavaScriptObject();
+ return (jsoType != null) ? jsoType : program.getTypeJavaLangObject();
}
public boolean hasSideEffects() {
return true;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- exprs.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(exprs);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonObject.java b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonObject.java
index e514c33..08ef343 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonObject.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/ast/js/JsonObject.java
@@ -15,13 +15,12 @@
*/
package com.google.gwt.dev.jjs.ast.js;
-import com.google.gwt.dev.jjs.ast.Holder;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JNode;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
import java.util.ArrayList;
import java.util.List;
@@ -36,29 +35,29 @@
*/
public static class JsonPropInit extends JNode {
- public final Holder labelExpr = new Holder();
- public final Holder valueExpr = new Holder();
+ public JExpression labelExpr;
+ public JExpression valueExpr;
public JsonPropInit(JProgram program, JExpression labelExpr,
JExpression valueExpr) {
- super(program);
- this.labelExpr.set(labelExpr);
- this.valueExpr.set(valueExpr);
+ super(program, null);
+ this.labelExpr = labelExpr;
+ this.valueExpr = valueExpr;
}
- public void traverse(JVisitor visitor) {
- if (visitor.visit(this)) {
- labelExpr.traverse(visitor);
- valueExpr.traverse(visitor);
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ labelExpr = visitor.accept(labelExpr);
+ valueExpr = visitor.accept(valueExpr);
}
- visitor.endVisit(this);
+ visitor.endVisit(this, ctx);
}
}
public final List/* <JsonPropInit> */propInits = new ArrayList/* <JsonPropInit> */();
public JsonObject(JProgram program) {
- super(program);
+ super(program, null);
}
public JType getType() {
@@ -69,18 +68,11 @@
return true;
}
- public void traverse(JVisitor visitor) {
- traverse(visitor, null);
- }
-
- public void traverse(JVisitor visitor, Mutator mutator) {
- if (visitor.visit(this, mutator)) {
- for (int i = 0; i < propInits.size(); ++i) {
- JsonPropInit propInit = (JsonPropInit) propInits.get(i);
- propInit.traverse(visitor);
- }
+ public void traverse(JVisitor visitor, Context ctx) {
+ if (visitor.visit(this, ctx)) {
+ visitor.accept(propInits);
}
- visitor.endVisit(this, mutator);
+ visitor.endVisit(this, ctx);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
index fc5e56e..6663635 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ArrayNormalizer.java
@@ -15,22 +15,22 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
+import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
import com.google.gwt.dev.jjs.ast.js.JsonArray;
/**
@@ -40,34 +40,15 @@
*/
public class ArrayNormalizer {
- private class ArrayVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Transform array accesses to check bounds.");
+ private class ArrayVisitor extends JModVisitor {
// @Override
- public void endVisit(JNewArray x, Mutator m) {
- JArrayType type = x.getArrayType();
- JLiteral litTypeName = program.getLiteralString(calcClassName(type));
-
- if (x.initializers != null) {
- processInitializers(x, m, type, litTypeName);
- } else {
- processDims(x, m, type, litTypeName);
- }
- }
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- // @Override
- public boolean visit(JBinaryOperation x, Mutator m) {
- if (x.op == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
+ if (x.getOp() == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) {
JArrayRef arrayRef = (JArrayRef) x.getLhs();
if (arrayRef.getType() instanceof JNullType) {
// will generate a null pointer exception instead
- return false;
+ return;
}
JArrayType arrayType = (JArrayType) arrayRef.getInstance().getType();
JType elementType = arrayType.getElementType();
@@ -78,23 +59,26 @@
&& !((JReferenceType) elementType).isFinal()) {
// replace this assignment with a call to setCheck()
- // DON'T VISIT ARRAYREF, but do visit its children
- arrayRef.instance.traverse(this);
- arrayRef.indexExpr.traverse(this);
- x.rhs.traverse(this);
-
- JMethodCall call = new JMethodCall(program, null, setCheckMethod);
- ChangeList myChanges = new ChangeList("Replace " + x
- + " with a call to Array.setCheck()");
- myChanges.replaceExpression(m, call);
- myChanges.addExpression(arrayRef.instance, call.args);
- myChanges.addExpression(arrayRef.indexExpr, call.args);
- myChanges.addExpression(x.rhs, call.args);
- changeList.add(myChanges);
- return false;
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ setCheckMethod);
+ call.getArgs().add(arrayRef.getInstance());
+ call.getArgs().add(arrayRef.getIndexExpr());
+ call.getArgs().add(x.getRhs());
+ ctx.replaceMe(call);
}
}
- return true;
+ }
+
+ // @Override
+ public void endVisit(JNewArray x, Context ctx) {
+ JArrayType type = x.getArrayType();
+ JLiteral litTypeName = program.getLiteralString(calcClassName(type));
+
+ if (x.initializers != null) {
+ processInitializers(x, ctx, type, litTypeName);
+ } else {
+ processDims(x, ctx, type, litTypeName);
+ }
}
private char[] calcClassName(JArrayType type) {
@@ -111,20 +95,19 @@
return className;
}
- private void processDims(JNewArray x, Mutator m, JArrayType arrayType,
+ private void processDims(JNewArray x, Context ctx, JArrayType arrayType,
JLiteral litTypeName) {
- ChangeList myChanges = new ChangeList("Replace " + x
- + " with a call to Array.initDims()");
// override the type of the called method with the array's type
- JMethodCall call = new JMethodCall(program, null, initDims, arrayType);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ initDims, arrayType);
JsonArray typeIdList = new JsonArray(program);
JsonArray queryIdList = new JsonArray(program);
JsonArray dimList = new JsonArray(program);
JType leafType = arrayType.getLeafType();
- int outstandingDims = arrayType.dims;
+ int outstandingDims = arrayType.getDims();
for (int i = 0; i < x.dims.size(); ++i) {
- Mutator dim = x.dims.getMutator(i);
- if (dim.get() instanceof JAbsentArrayDimension) {
+ JExpression dim = (JExpression) x.dims.get(i);
+ if (dim instanceof JAbsentArrayDimension) {
break;
}
@@ -141,44 +124,40 @@
*/
JArrayType cur = program.getTypeArray(leafType, outstandingDims--);
JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(cur));
- myChanges.addExpression(typeIdLit, typeIdList.exprs);
+ typeIdList.exprs.add(typeIdLit);
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(cur));
- myChanges.addExpression(queryIdLit, queryIdList.exprs);
- myChanges.addExpression(dim, dimList.exprs);
+ queryIdList.exprs.add(queryIdLit);
+ dimList.exprs.add(dim);
}
JType targetType = leafType;
if (outstandingDims > 0) {
targetType = program.getTypeArray(targetType, outstandingDims);
}
- myChanges.addExpression(litTypeName, call.args);
- myChanges.addExpression(typeIdList, call.args);
- myChanges.addExpression(queryIdList, call.args);
- myChanges.addExpression(dimList, call.args);
- myChanges.addExpression(targetType.getDefaultValue(), call.args);
- myChanges.replaceExpression(m, call);
- changeList.add(myChanges);
+ call.getArgs().add(litTypeName);
+ call.getArgs().add(typeIdList);
+ call.getArgs().add(queryIdList);
+ call.getArgs().add(dimList);
+ call.getArgs().add(targetType.getDefaultValue());
+ ctx.replaceMe(call);
}
- private void processInitializers(JNewArray x, Mutator m,
+ private void processInitializers(JNewArray x, Context ctx,
JArrayType arrayType, JLiteral litTypeName) {
// override the type of the called method with the array's type
- JMethodCall call = new JMethodCall(program, null, initValues, arrayType);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ initValues, arrayType);
JLiteral typeIdLit = program.getLiteralInt(program.getTypeId(arrayType));
JLiteral queryIdLit = program.getLiteralInt(tryGetQueryId(arrayType));
JsonArray initList = new JsonArray(program);
- ChangeList myChanges = new ChangeList("Replace " + x
- + " with a call to Array.initValues()");
for (int i = 0; i < x.initializers.size(); ++i) {
- Mutator initializer = x.initializers.getMutator(i);
- myChanges.addExpression(initializer, initList.exprs);
+ initList.exprs.add(x.initializers.get(i));
}
- myChanges.addExpression(litTypeName, call.args);
- myChanges.addExpression(typeIdLit, call.args);
- myChanges.addExpression(queryIdLit, call.args);
- myChanges.addExpression(initList, call.args);
- myChanges.replaceExpression(m, call);
- changeList.add(myChanges);
+ call.getArgs().add(litTypeName);
+ call.getArgs().add(typeIdLit);
+ call.getArgs().add(queryIdLit);
+ call.getArgs().add(initList);
+ ctx.replaceMe(call);
}
private int tryGetQueryId(JArrayType type) {
@@ -195,13 +174,10 @@
new ArrayNormalizer(program).execImpl();
}
- private final JMethod setCheckMethod;
-
private final JMethod initDims;
-
private final JMethod initValues;
-
private final JProgram program;
+ private final JMethod setCheckMethod;
private ArrayNormalizer(JProgram program) {
this.program = program;
@@ -212,11 +188,7 @@
private void execImpl() {
ArrayVisitor visitor = new ArrayVisitor();
- program.traverse(visitor);
- ChangeList changes = visitor.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ visitor.accept(program);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index 326fb6a..7f5dd22 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -23,6 +23,7 @@
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.js.JsniMethod;
import com.google.gwt.dev.js.JsParser;
@@ -34,6 +35,7 @@
import com.google.gwt.dev.js.ast.JsStatements;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -41,6 +43,7 @@
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.env.IGenericType;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
@@ -55,6 +58,7 @@
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
+import org.eclipse.jdt.internal.compiler.problem.ProblemHandler;
import java.io.IOException;
import java.io.StringReader;
@@ -89,11 +93,25 @@
*/
private static class BuildDeclMapVisitor extends ASTVisitor {
- private ArrayList/* <TypeDeclaration> */typeDecls = new ArrayList/* <TypeDeclaration> */();
- private final TypeMap typeMap;
- private JProgram program;
- private final JsProgram jsProgram;
+ private static JSourceInfo makeSourceInfo(
+ AbstractMethodDeclaration methodDecl) {
+ CompilationResult compResult = methodDecl.compilationResult;
+ int[] indexes = compResult.lineSeparatorPositions;
+ String fileName = String.valueOf(compResult.fileName);
+ int startLine = ProblemHandler.searchLineNumber(indexes,
+ methodDecl.sourceStart);
+ return new JSourceInfo(methodDecl.sourceStart, methodDecl.bodyEnd,
+ startLine, fileName);
+ }
+
+ private String currentFileName;
+ private int[] currentSeparatorPositions;
private final JsParser jsParser = new JsParser();
+ private final JsProgram jsProgram;
+ private JProgram program;
+ private ArrayList/* <TypeDeclaration> */typeDecls = new ArrayList/* <TypeDeclaration> */();
+
+ private final TypeMap typeMap;
public BuildDeclMapVisitor(TypeMap typeMap, JsProgram jsProgram) {
this.typeMap = typeMap;
@@ -110,10 +128,11 @@
return true;
}
+ JSourceInfo info = makeInfo(argument);
LocalVariableBinding b = argument.binding;
JType localType = (JType) typeMap.get(b.type);
JMethod enclosingMethod = findEnclosingMethod(scope);
- JLocal newLocal = program.createLocal(argument.name, localType,
+ JLocal newLocal = program.createLocal(info, argument.name, localType,
b.isFinal(), enclosingMethod);
typeMap.put(b, newLocal);
return true;
@@ -130,7 +149,8 @@
MethodBinding b = ctorDecl.binding;
JClassType enclosingType = (JClassType) typeMap.get(scope.enclosingSourceType());
String name = enclosingType.getShortName();
- JMethod newMethod = program.createMethod(name.toCharArray(),
+ JSourceInfo info = makeSourceInfo(ctorDecl);
+ JMethod newMethod = program.createMethod(info, name.toCharArray(),
enclosingType, enclosingType, false, false, true, b.isPrivate(),
false);
mapThrownExceptions(newMethod, ctorDecl);
@@ -182,8 +202,10 @@
public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) {
FieldBinding b = fieldDeclaration.binding;
+ JSourceInfo info = makeInfo(fieldDeclaration);
JReferenceType enclosingType = (JReferenceType) typeMap.get(scope.enclosingSourceType());
- createField(b, enclosingType, fieldDeclaration.initialization != null);
+ createField(info, b, enclosingType,
+ fieldDeclaration.initialization != null);
return true;
}
@@ -191,19 +213,22 @@
LocalVariableBinding b = localDeclaration.binding;
JType localType = (JType) typeMap.get(localDeclaration.type.resolvedType);
JMethod enclosingMethod = findEnclosingMethod(scope);
- JLocal newLocal = program.createLocal(localDeclaration.name, localType,
- b.isFinal(), enclosingMethod);
+ JSourceInfo info = makeInfo(localDeclaration);
+ JLocal newLocal = program.createLocal(info, localDeclaration.name,
+ localType, b.isFinal(), enclosingMethod);
typeMap.put(b, newLocal);
return true;
}
public boolean visit(MethodDeclaration methodDeclaration, ClassScope scope) {
MethodBinding b = methodDeclaration.binding;
+ JSourceInfo info = makeSourceInfo(methodDeclaration);
JType returnType = (JType) typeMap.get(methodDeclaration.returnType.resolvedType);
JReferenceType enclosingType = (JReferenceType) typeMap.get(scope.enclosingSourceType());
- JMethod newMethod = program.createMethod(methodDeclaration.selector,
- enclosingType, returnType, b.isAbstract(), b.isStatic(), b.isFinal(),
- b.isPrivate(), b.isNative());
+ JMethod newMethod = program.createMethod(info,
+ methodDeclaration.selector, enclosingType, returnType,
+ b.isAbstract(), b.isStatic(), b.isFinal(), b.isPrivate(),
+ b.isNative());
mapThrownExceptions(newMethod, methodDeclaration);
mapParameters(newMethod, methodDeclaration);
@@ -218,23 +243,21 @@
int endPos = jsniCode.lastIndexOf("}-*/");
if (startPos < 0 && endPos < 0) {
GenerateJavaAST.reportJsniError(
+ info,
methodDeclaration,
- "Native methods require a JavaScript implementation enclosed with /*-{ and }-*/",
- 0);
+ "Native methods require a JavaScript implementation enclosed with /*-{ and }-*/");
return true;
}
if (startPos < 0) {
- GenerateJavaAST.reportJsniError(
- methodDeclaration,
- "Unable to find start of native block; begin your JavaScript block with: /*-{",
- 0);
+ GenerateJavaAST.reportJsniError(info, methodDeclaration,
+ "Unable to find start of native block; begin your JavaScript block with: /*-{");
return true;
}
if (endPos < 0) {
GenerateJavaAST.reportJsniError(
+ info,
methodDeclaration,
- "Unable to find end of native block; terminate your JavaScript block with: }-*/",
- 0);
+ "Unable to find end of native block; terminate your JavaScript block with: }-*/");
return true;
}
@@ -261,6 +284,7 @@
StringReader sr = new StringReader(syntheticFnHeader + '\n' + jsniCode);
try {
// start at -1 to avoid counting our synthetic header
+ // TODO: get the character position start correct
JsStatements result = jsParser.parse(jsProgram.getScope(), sr, -1);
JsExprStmt jsExprStmt = (JsExprStmt) result.get(0);
JsFunction jsFunction = (JsFunction) jsExprStmt.getExpression();
@@ -270,7 +294,6 @@
"Internal error parsing JSNI in method '" + newMethod
+ "' in type '" + enclosingType.getName() + "'", e);
} catch (JsParserException e) {
-
/*
* count the number of characters to the problem (from the start of
* the JSNI code)
@@ -297,10 +320,13 @@
// CHECKSTYLE_ON
}
+ // TODO: check this
// Map into the original source stream;
i += startPos + detail.getLineOffset();
- String message = e.getMessage();
- GenerateJavaAST.reportJsniError(methodDeclaration, message, i);
+ info = new JSourceInfo(i, i, info.getStartLine() + detail.getLine(),
+ info.getFileName());
+ GenerateJavaAST.reportJsniError(info, methodDeclaration,
+ e.getMessage());
}
}
@@ -320,11 +346,11 @@
return process(typeDeclaration);
}
- private JField createField(FieldBinding binding,
+ private JField createField(JSourceInfo info, FieldBinding binding,
JReferenceType enclosingType, boolean hasInitializer) {
JType type = (JType) typeMap.get(binding.type);
- JField field = program.createField(binding.name, enclosingType, type,
- binding.isStatic(), binding.isFinal(), hasInitializer);
+ JField field = program.createField(info, binding.name, enclosingType,
+ type, binding.isStatic(), binding.isFinal(), hasInitializer);
typeMap.put(binding, field);
return field;
}
@@ -332,8 +358,8 @@
private JField createField(SyntheticArgumentBinding binding,
JReferenceType enclosingType) {
JType type = (JType) typeMap.get(binding.type);
- JField field = program.createField(binding.name, enclosingType, type,
- false, true, true);
+ JField field = program.createField(null, binding.name, enclosingType,
+ type, false, true, true);
if (binding.matchingField != null) {
typeMap.put(binding.matchingField, field);
}
@@ -344,7 +370,8 @@
private JParameter createParameter(LocalVariableBinding binding,
JMethod enclosingMethod) {
JType type = (JType) typeMap.get(binding.type);
- JParameter param = program.createParameter(binding.name, type,
+ JSourceInfo info = makeInfo(binding.declaration);
+ JParameter param = program.createParameter(info, binding.name, type,
binding.isFinal(), enclosingMethod);
typeMap.put(binding, param);
return param;
@@ -353,8 +380,8 @@
private JParameter createParameter(SyntheticArgumentBinding arg,
String argName, JMethod enclosingMethod) {
JType type = (JType) typeMap.get(arg.type);
- JParameter param = program.createParameter(argName.toCharArray(), type,
- true, enclosingMethod);
+ JParameter param = program.createParameter(null, argName.toCharArray(),
+ type, true, enclosingMethod);
return param;
}
@@ -376,6 +403,13 @@
return (JMethod) typeMap.get(referenceMethod.binding);
}
+ private JSourceInfo makeInfo(Statement stmt) {
+ int startLine = ProblemHandler.searchLineNumber(
+ currentSeparatorPositions, stmt.sourceStart);
+ return new JSourceInfo(stmt.sourceStart, stmt.sourceEnd, startLine,
+ currentFileName);
+ }
+
private void mapParameters(JMethod method, AbstractMethodDeclaration x) {
MethodBinding b = x.binding;
int paramCount = (b.parameters != null ? b.parameters.length : 0);
@@ -409,6 +443,9 @@
* implements the stuff under the hood anyway.
*/
private boolean process(TypeDeclaration typeDeclaration) {
+ CompilationResult compResult = typeDeclaration.compilationResult;
+ currentSeparatorPositions = compResult.lineSeparatorPositions;
+ currentFileName = String.valueOf(compResult.fileName);
SourceTypeBinding binding = typeDeclaration.binding;
if (binding.constantPoolName() == null) {
/*
@@ -467,8 +504,18 @@
*/
private static class BuildTypeMapVisitor extends ASTVisitor {
- private final TypeMap typeMap;
+ private static JSourceInfo makeSourceInfo(TypeDeclaration typeDecl) {
+ CompilationResult compResult = typeDecl.compilationResult;
+ int[] indexes = compResult.lineSeparatorPositions;
+ String fileName = String.valueOf(compResult.fileName);
+ int startLine = ProblemHandler.searchLineNumber(indexes,
+ typeDecl.sourceStart);
+ return new JSourceInfo(typeDecl.sourceStart, typeDecl.bodyEnd, startLine,
+ fileName);
+ }
+
private final JProgram program;
+ private final TypeMap typeMap;
public BuildTypeMapVisitor(TypeMap typeMap) {
this.typeMap = typeMap;
@@ -511,12 +558,13 @@
name[0] = localName;
}
+ JSourceInfo info = makeSourceInfo(typeDeclaration);
JReferenceType newType;
if (binding.isClass()) {
- newType = program.createClass(name, binding.isAbstract(),
+ newType = program.createClass(info, name, binding.isAbstract(),
binding.isFinal());
} else if (binding.isInterface()) {
- newType = program.createInterface(name);
+ newType = program.createInterface(info, name);
} else {
assert (false);
return false;
@@ -528,13 +576,13 @@
* like output JavaScript. Clinit is always in slot 0, init (if it exists)
* is always in slot 1.
*/
- JMethod clinit = program.createMethod("$clinit".toCharArray(), newType,
- program.getTypeVoid(), false, true, true, true, false);
+ JMethod clinit = program.createMethod(null, "$clinit".toCharArray(),
+ newType, program.getTypeVoid(), false, true, true, true, false);
clinit.freezeParamTypes();
if (newType instanceof JClassType) {
- JMethod init = program.createMethod("$init".toCharArray(), newType,
- program.getTypeVoid(), false, false, true, true, false);
+ JMethod init = program.createMethod(null, "$init".toCharArray(),
+ newType, program.getTypeVoid(), false, false, true, true, false);
init.freezeParamTypes();
}
@@ -569,4 +617,5 @@
unitDecls[i].traverse(v1, unitDecls[i].scope);
}
}
+
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
index 2102401..70d4589 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastNormalizer.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -26,6 +27,7 @@
import com.google.gwt.dev.jjs.ast.JIntLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
@@ -34,8 +36,6 @@
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JTypeOracle;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
import com.google.gwt.dev.jjs.ast.js.JClassSeed;
import com.google.gwt.dev.jjs.ast.js.JsonObject;
import com.google.gwt.dev.jjs.ast.js.JsonObject.JsonPropInit;
@@ -62,11 +62,8 @@
Set/* <JClassType> */alreadyRan = new HashSet/* <JClassType> */();
private Map/* <JReferenceType, Set<JReferenceType>> */queriedTypes = new IdentityHashMap();
private int nextQueryId = 1; // 0 is reserved
-
private final List/* <JArrayType> */instantiatedArrayTypes = new ArrayList/* <JArrayType> */();
-
private List/* <JClassType> */classes = new ArrayList/* <JClassType> */();
-
private List/* <JsonObject> */jsonObjects = new ArrayList/* <JsonObject> */();
{
@@ -112,8 +109,8 @@
* must record a query on the element type being assigned to.
*/
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
- if (x.op == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
+ if (x.getOp() == JBinaryOperator.ASG && x.getLhs() instanceof JArrayRef) {
// first, calculate the transitive closure of all possible runtime types
// the lhs could be
@@ -157,13 +154,13 @@
}
// @Override
- public void endVisit(JCastOperation x, Mutator m) {
- recordCast(x.castType, x.getExpression());
+ public void endVisit(JCastOperation x, Context ctx) {
+ recordCast(x.getCastType(), x.getExpr());
}
// @Override
- public void endVisit(JInstanceOf x, Mutator m) {
- recordCast(x.testType, x.getExpression());
+ public void endVisit(JInstanceOf x, Context ctx) {
+ recordCast(x.getTestType(), x.getExpr());
}
/**
@@ -179,9 +176,9 @@
/*
* IMPORTANT: Visit my supertype first. The implementation of
- * {@link com.google.gwt.lang.Cast#wrapJSO()} depends on all superclasses
- * having typeIds that are less than all their subclasses. This allows the
- * same JSO to be wrapped stronger but not weaker.
+ * com.google.gwt.lang.Cast.wrapJSO() depends on all superclasses having
+ * typeIds that are less than all their subclasses. This allows the same
+ * JSO to be wrapped stronger but not weaker.
*/
computeSourceClass(type.extnds);
@@ -275,46 +272,50 @@
* Explicitly convert any char-typed expressions within a concat operation
* into strings.
*/
- private class ConcatVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Convert chars to Strings inside of concat operations.");
+ private class ConcatVisitor extends JModVisitor {
private JMethod stringValueOfChar = null;
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
if (x.getType() != program.getTypeJavaLangString()) {
return;
}
- if (x.op == JBinaryOperator.ADD) {
- convertCharString(x.lhs);
- convertCharString(x.rhs);
- } else if (x.op == JBinaryOperator.ASG_ADD) {
- convertCharString(x.rhs);
+ if (x.getOp() == JBinaryOperator.ADD) {
+ JExpression newLhs = convertCharString(x.getLhs());
+ JExpression newRhs = convertCharString(x.getRhs());
+ if (newLhs != x.getLhs() || newRhs != x.getRhs()) {
+ JBinaryOperation newExpr = new JBinaryOperation(program,
+ x.getSourceInfo(), program.getTypeJavaLangString(),
+ JBinaryOperator.ADD, newLhs, newRhs);
+ ctx.replaceMe(newExpr);
+ }
+ } else if (x.getOp() == JBinaryOperator.ASG_ADD) {
+ JExpression newRhs = convertCharString(x.getRhs());
+ if (newRhs != x.getRhs()) {
+ JBinaryOperation newExpr = new JBinaryOperation(program,
+ x.getSourceInfo(), program.getTypeJavaLangString(),
+ JBinaryOperator.ASG_ADD, x.getLhs(), newRhs);
+ ctx.replaceMe(newExpr);
+ }
}
}
- public ChangeList getChangeList() {
- return changeList;
- }
-
- private void convertCharString(Mutator m) {
+ private JExpression convertCharString(JExpression expr) {
JPrimitiveType charType = program.getTypePrimitiveChar();
- JExpression expr = m.get();
if (expr.getType() == charType) {
+ // Replace the character with a call to Cast.charToString()
if (stringValueOfChar == null) {
stringValueOfChar = program.getSpecialMethod("Cast.charToString");
assert (stringValueOfChar != null);
}
- JMethodCall call = new JMethodCall(program, null, stringValueOfChar);
- ChangeList myChangeList = new ChangeList("Replace '" + expr
- + "' with a call to Cast.charToString()");
- myChangeList.addExpression(m, call.args);
- myChangeList.replaceExpression(m, call);
- changeList.add(myChangeList);
+ JMethodCall call = new JMethodCall(program, expr.getSourceInfo(), null,
+ stringValueOfChar);
+ call.getArgs().add(expr);
+ return call;
}
+ return expr;
}
}
@@ -322,72 +323,69 @@
* Explicitly cast all integral divide operations to trigger replacements with
* narrowing calls in the next pass.
*/
- private class DivVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Explicitly cast all integral division operations.");
+ private class DivVisitor extends JModVisitor {
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
JType type = x.getType();
- if (x.op == JBinaryOperator.DIV
+ if (x.getOp() == JBinaryOperator.DIV
&& type != program.getTypePrimitiveFloat()
&& type != program.getTypePrimitiveDouble()) {
- JCastOperation cast = new JCastOperation(program, type,
- program.getLiteralNull());
- ChangeList myChangeList = new ChangeList("Cast '" + x + "' to type '"
- + type + "'");
- myChangeList.changeType(x, program.getTypePrimitiveDouble());
- myChangeList.replaceExpression(cast.expr, m);
- myChangeList.replaceExpression(m, cast);
- changeList.add(myChangeList);
+ x.setType(program.getTypePrimitiveDouble());
+ JCastOperation cast = new JCastOperation(program, x.getSourceInfo(),
+ type, x);
+ ctx.replaceMe(cast);
}
}
-
- public ChangeList getChangeList() {
- return changeList;
- }
}
- private class ReplaceTypeChecksVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Replace all casts and instanceof operations.");
+ /**
+ * Replaces all casts and instanceof operations with calls to implementation
+ * methods.
+ */
+ private class ReplaceTypeChecksVisitor extends JModVisitor {
// @Override
- public void endVisit(JCastOperation x, Mutator m) {
- JType toType = x.castType;
+ public void endVisit(JCastOperation x, Context ctx) {
+ JExpression replaceExpr;
+ JType toType = x.getCastType();
if (toType instanceof JReferenceType) {
+ JExpression curExpr = x.getExpr();
JReferenceType refType = (JReferenceType) toType;
- JType argType = x.getExpression().getType();
+ JType argType = x.getExpr().getType();
if (program.isJavaScriptObject(argType)) {
/*
* A JSO-derived class that is about to be cast must be "wrapped"
* first. Since a JSO was never constructed, it may not have an
* accessible prototype. Instead we copy fields from the seed
* function's prototype directly onto the target object as expandos.
- * See {@link com.google.gwt.lang.Cast#wrapJSO()}.
+ * See com.google.gwt.lang.Cast.wrapJSO().
*/
- ChangeList myChangeList = new ChangeList("Wrap a JavaScript Object");
JMethod wrap = program.getSpecialMethod("Cast.wrapJSO");
// override the type of the called method with the JSO's type
- JMethodCall call = new JMethodCall(program, null, wrap, argType);
- myChangeList.addExpression(x.expr, call.args);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ wrap, argType);
JClassSeed seed = program.getLiteralClassSeed((JClassType) argType);
- myChangeList.addExpression(seed, call.args);
- myChangeList.replaceExpression(x.expr, call);
- changeList.add(myChangeList);
+ call.getArgs().add(curExpr);
+ call.getArgs().add(seed);
+ curExpr = call;
}
if (argType instanceof JClassType
&& program.typeOracle.canTriviallyCast((JClassType) argType,
refType)) {
+ // TODO(???): why is this only for JClassType?
// just remove the cast
- changeList.replaceExpression(m, x.expr);
+ replaceExpr = curExpr;
} else {
JMethod method = program.getSpecialMethod("Cast.dynamicCast");
// override the type of the called method with the target cast type
- JMethodCall call = new JMethodCall(program, null, method, toType);
- replaceCast(call, refType, m, x.expr);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ method, toType);
+ Integer boxedInt = (Integer) queryIds.get(refType);
+ JIntLiteral qId = program.getLiteralInt(boxedInt.intValue());
+ call.getArgs().add(curExpr);
+ call.getArgs().add(qId);
+ replaceExpr = call;
}
} else {
/*
@@ -403,7 +401,7 @@
JPrimitiveType tLong = program.getTypePrimitiveLong();
JPrimitiveType tFloat = program.getTypePrimitiveFloat();
JPrimitiveType tDouble = program.getTypePrimitiveDouble();
- JType fromType = x.getExpression().getType();
+ JType fromType = x.getExpr().getType();
if (tByte == fromType) {
if (tChar == toType) {
narrow = true;
@@ -432,62 +430,46 @@
}
}
- ChangeList myChangeList;
if (narrow || round) {
+ // Replace the expression with a call to the narrow or round method
String methodName = "Cast." + (narrow ? "narrow_" : "round_")
+ toType.getName();
- myChangeList = new ChangeList("Replace '" + x + "' with a call to "
- + methodName);
JMethod castMethod = program.getSpecialMethod(methodName);
- JMethodCall call = new JMethodCall(program, null, castMethod);
- myChangeList.addExpression(x.expr, call.args);
- myChangeList.replaceExpression(m, call);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ castMethod);
+ call.getArgs().add(x.getExpr());
+ replaceExpr = call;
} else {
- myChangeList = new ChangeList("Remove the cast from '" + x + "'");
- myChangeList.replaceExpression(m, x.expr);
+ // Just remove the cast
+ replaceExpr = x.getExpr();
}
- changeList.add(myChangeList);
}
+ ctx.replaceMe(replaceExpr);
}
// @Override
- public void endVisit(JInstanceOf x, Mutator m) {
- JType argType = x.getExpression().getType();
+ public void endVisit(JInstanceOf x, Context ctx) {
+ JType argType = x.getExpr().getType();
if (argType instanceof JClassType
&& program.typeOracle.canTriviallyCast((JClassType) argType,
- x.testType)) {
- // trivially true if non-null
+ x.getTestType())) {
+ // trivially true if non-null; replace with a null test
JNullLiteral nullLit = program.getLiteralNull();
- JBinaryOperation eq = new JBinaryOperation(program,
- program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, nullLit,
- nullLit);
- ChangeList myChangeList = new ChangeList("Replace '" + x
- + "' with a simple null test.");
- myChangeList.replaceExpression(eq.lhs, x.expr);
- myChangeList.replaceExpression(m, eq);
- changeList.add(myChangeList);
+ JBinaryOperation eq = new JBinaryOperation(program, x.getSourceInfo(),
+ program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ,
+ x.getExpr(), nullLit);
+ ctx.replaceMe(eq);
} else {
JMethod method = program.getSpecialMethod("Cast.instanceOf");
- JMethodCall call = new JMethodCall(program, null, method);
- replaceCast(call, x.testType, m, x.expr);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ method);
+ Integer boxedInt = (Integer) queryIds.get(x.getTestType());
+ JIntLiteral qId = program.getLiteralInt(boxedInt.intValue());
+ call.getArgs().add(x.getExpr());
+ call.getArgs().add(qId);
+ ctx.replaceMe(call);
}
}
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- private void replaceCast(JMethodCall call, JReferenceType type,
- Mutator dest, Mutator arg) {
- Integer boxedInt = (Integer) queryIds.get(type);
- JIntLiteral qId = program.getLiteralInt(boxedInt.intValue());
- ChangeList myChangeList = new ChangeList("Replace '" + dest.get()
- + " with a call to " + call.getTarget().getName());
- myChangeList.addExpression(arg, call.args);
- myChangeList.addExpression(qId, call.args);
- myChangeList.replaceExpression(dest, call);
- changeList.add(myChangeList);
- }
}
public static void exec(JProgram program) {
@@ -505,32 +487,20 @@
private void execImpl() {
{
ConcatVisitor visitor = new ConcatVisitor();
- program.traverse(visitor);
- ChangeList changes = visitor.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ visitor.accept(program);
}
{
DivVisitor visitor = new DivVisitor();
- program.traverse(visitor);
- ChangeList changes = visitor.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ visitor.accept(program);
}
{
AssignTypeIdsVisitor assigner = new AssignTypeIdsVisitor();
- program.traverse(assigner);
+ assigner.accept(program);
assigner.computeTypeIds();
}
{
ReplaceTypeChecksVisitor replacer = new ReplaceTypeChecksVisitor();
- program.traverse(replacer);
- ChangeList changes = replacer.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ replacer.accept(program);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java
index 36ae6e1..517e037 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CastOptimizer.java
@@ -15,20 +15,19 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JInstanceOf;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JTypeOracle;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
/**
* Optimizer that will remove all trivially computable casts and instanceof
@@ -36,20 +35,20 @@
*/
public class CastOptimizer {
- private class ReplaceTrivialCastsVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Replace all trivially computable casts and instanceof operations.");
+ /**
+ * Replaces all trivially computable casts and instanceof operations.
+ */
+ private class ReplaceTrivialCastsVisitor extends JModVisitor {
// @Override
- public void endVisit(JCastOperation x, Mutator m) {
- JType argType = x.getExpression().getType();
- if (!(x.castType instanceof JReferenceType)
+ public void endVisit(JCastOperation x, Context ctx) {
+ JType argType = x.getExpr().getType();
+ if (!(x.getCastType() instanceof JReferenceType)
|| !(argType instanceof JReferenceType)) {
return;
}
- JReferenceType toType = (JReferenceType) x.castType;
+ JReferenceType toType = (JReferenceType) x.getCastType();
JReferenceType fromType = (JReferenceType) argType;
boolean triviallyTrue = false;
@@ -66,7 +65,7 @@
if (triviallyTrue) {
// remove the cast operation
- changeList.replaceExpression(m, x.expr);
+ ctx.replaceMe(x.getExpr());
} else if (triviallyFalse) {
// throw a ClassCastException unless the argument is null
JMethod method = program.getSpecialMethod("Cast.throwClassCastExceptionUnlessNull");
@@ -75,31 +74,31 @@
* will proceedeth forth from this cast operation. Assuredly, if the
* call completes normally it will return null.
*/
- JMethodCall call = new JMethodCall(program, null, method,
- program.getTypeNull());
- ChangeList myChangeList = new ChangeList("Replace '" + x
- + "' with a call to throwClassCastExceptionUnlessNull().");
- myChangeList.addExpression(x.expr, call.args);
- myChangeList.replaceExpression(m, call);
- changeList.add(myChangeList);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(), null,
+ method, program.getTypeNull());
+ call.getArgs().add(x.getExpr());
+ ctx.replaceMe(call);
}
}
// @Override
- public void endVisit(JInstanceOf x, Mutator m) {
- JType argType = x.getExpression().getType();
+ public void endVisit(JInstanceOf x, Context ctx) {
+ JType argType = x.getExpr().getType();
if (!(argType instanceof JReferenceType)) {
return;
}
- JReferenceType toType = x.testType;
+ JReferenceType toType = x.getTestType();
JReferenceType fromType = (JReferenceType) argType;
boolean triviallyTrue = false;
boolean triviallyFalse = false;
JTypeOracle typeOracle = program.typeOracle;
- if (typeOracle.canTriviallyCast(fromType, toType)) {
+ if (fromType == program.getTypeNull()) {
+ // null is never instanceOf anything
+ triviallyFalse = true;
+ } else if (typeOracle.canTriviallyCast(fromType, toType)) {
triviallyTrue = true;
} else if (!typeOracle.isInstantiatedType(toType)) {
triviallyFalse = true;
@@ -108,30 +107,17 @@
}
if (triviallyTrue) {
- if (fromType == program.getTypeNull()) {
- // replace with a true literal
- changeList.replaceExpression(m, program.getLiteralBoolean(true));
- } else {
- // replace with a simple null test
- JNullLiteral nullLit = program.getLiteralNull();
- JBinaryOperation eq = new JBinaryOperation(program,
- program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ, nullLit,
- nullLit);
- ChangeList myChangeList = new ChangeList("Replace '" + x
- + "' with a simple null test.");
- myChangeList.replaceExpression(eq.lhs, x.expr);
- myChangeList.replaceExpression(m, eq);
- changeList.add(myChangeList);
- }
+ // replace with a simple null test
+ JNullLiteral nullLit = program.getLiteralNull();
+ JBinaryOperation neq = new JBinaryOperation(program, x.getSourceInfo(),
+ program.getTypePrimitiveBoolean(), JBinaryOperator.NEQ,
+ x.getExpr(), nullLit);
+ ctx.replaceMe(neq);
} else if (triviallyFalse) {
// replace with a false literal
- changeList.replaceExpression(m, program.getLiteralBoolean(false));
+ ctx.replaceMe(program.getLiteralBoolean(false));
}
}
-
- public ChangeList getChangeList() {
- return changeList;
- }
}
public static boolean exec(JProgram program) {
@@ -146,12 +132,7 @@
private boolean execImpl() {
ReplaceTrivialCastsVisitor replacer = new ReplaceTrivialCastsVisitor();
- program.traverse(replacer);
- ChangeList changes = replacer.getChangeList();
- if (changes.empty()) {
- return false;
- }
- changes.apply();
- return true;
+ replacer.accept(program);
+ return replacer.didChange();
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
index aadfdbd..064fa81 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CatchBlockNormalizer.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
@@ -24,13 +25,13 @@
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JThrowStatement;
import com.google.gwt.dev.jjs.ast.JTryStatement;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
import java.util.ArrayList;
import java.util.List;
@@ -41,33 +42,34 @@
*/
public class CatchBlockNormalizer {
- private class CollapseCatchBlocks extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Collapse all multi-catch blocks into a single catch block.");
+ /**
+ * Collapses all multi-catch blocks into a single catch block.
+ */
+ private class CollapseCatchBlocks extends JModVisitor {
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
clearLocals();
currentMethod = null;
}
// @Override
- public void endVisit(JTryStatement x) {
- if (x.catchBlocks.isEmpty()) {
+ public void endVisit(JTryStatement x, Context ctx) {
+ if (x.getCatchBlocks().isEmpty()) {
return;
}
- ChangeList myChangeList = new ChangeList("Merge " + x.catchBlocks.size()
- + " catch blocks.");
+ JSourceInfo catchInfo = ((JBlock) x.getCatchBlocks().get(0)).getSourceInfo();
+
JLocal exObj = popTempLocal();
- JLocalRef exRef = new JLocalRef(program, exObj);
- JBlock newCatchBlock = new JBlock(program);
+ JLocalRef exRef = new JLocalRef(program, catchInfo, exObj);
+ JBlock newCatchBlock = new JBlock(program, catchInfo);
// $e = Exceptions.caught($e)
JMethod caughtMethod = program.getSpecialMethod("Exceptions.caught");
- JMethodCall call = new JMethodCall(program, null, caughtMethod);
- call.args.add(exRef);
- JExpressionStatement asg = program.createAssignmentStmt(exRef, call);
+ JMethodCall call = new JMethodCall(program, catchInfo, null, caughtMethod);
+ call.getArgs().add(exRef);
+ JExpressionStatement asg = program.createAssignmentStmt(catchInfo, exRef,
+ call);
newCatchBlock.statements.add(asg);
/*
@@ -77,41 +79,40 @@
* Go backwards so we can nest the else statements in the correct order!
*/
// rethrow the current exception if no one caught it
- JStatement cur = new JThrowStatement(program, exRef);
- for (int i = x.catchBlocks.size() - 1; i >= 0; --i) {
- JBlock block = (JBlock) x.catchBlocks.get(i);
- JLocalRef arg = (JLocalRef) x.catchArgs.get(i);
+ JStatement cur = new JThrowStatement(program, null, exRef);
+ for (int i = x.getCatchBlocks().size() - 1; i >= 0; --i) {
+ JBlock block = (JBlock) x.getCatchBlocks().get(i);
+ JLocalRef arg = (JLocalRef) x.getCatchArgs().get(i);
+ catchInfo = block.getSourceInfo();
JReferenceType argType = (JReferenceType) arg.getType();
// if ($e instanceof Argtype) { userVar = $e; <user code> }
- JExpression ifTest = new JInstanceOf(program, argType, exRef);
- asg = program.createAssignmentStmt(arg, exRef);
- myChangeList.addStatement(asg, 0, block);
+ JExpression ifTest = new JInstanceOf(program, catchInfo, argType, exRef);
+ asg = program.createAssignmentStmt(catchInfo, arg, exRef);
+ if (!block.statements.isEmpty()) {
+ // Only bother adding the assingment if the block is non-empty
+ block.statements.add(0, asg);
+ }
// nest the previous as an else for me
- cur = new JIfStatement(program, ifTest, block, cur);
+ cur = new JIfStatement(program, catchInfo, ifTest, block, cur);
}
newCatchBlock.statements.add(cur);
- myChangeList.clear(x.catchArgs);
- myChangeList.clear(x.catchBlocks);
- myChangeList.addNode(exRef, 0, x.catchArgs);
- myChangeList.addNode(newCatchBlock, 0, x.catchBlocks);
- changeList.add(myChangeList);
- }
-
- public ChangeList getChangeList() {
- return changeList;
+ x.getCatchArgs().clear();
+ x.getCatchArgs().add(exRef);
+ x.getCatchBlocks().clear();
+ x.getCatchBlocks().add(newCatchBlock);
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
clearLocals();
return true;
}
// @Override
- public boolean visit(JTryStatement x) {
- if (!x.catchBlocks.isEmpty()) {
+ public boolean visit(JTryStatement x, Context ctx) {
+ if (!x.getCatchBlocks().isEmpty()) {
pushTempLocal();
}
return true;
@@ -123,12 +124,9 @@
}
private JMethod currentMethod;
-
- private final List/* <JLocal> */tempLocals = new ArrayList/* <JLocal> */();
-
private int localIndex;
-
private final JProgram program;
+ private final List/* <JLocal> */tempLocals = new ArrayList/* <JLocal> */();
private CatchBlockNormalizer(JProgram program) {
this.program = program;
@@ -140,14 +138,8 @@
}
private void execImpl() {
- {
- CollapseCatchBlocks collapser = new CollapseCatchBlocks();
- program.traverse(collapser);
- ChangeList changes = collapser.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
- }
+ CollapseCatchBlocks collapser = new CollapseCatchBlocks();
+ collapser.accept(program);
}
private JLocal popTempLocal() {
@@ -156,8 +148,9 @@
private void pushTempLocal() {
if (localIndex == tempLocals.size()) {
- JLocal newTemp = program.createLocal(("$e" + localIndex).toCharArray(),
- program.getTypeJavaLangObject(), false, currentMethod);
+ JLocal newTemp = program.createLocal(null,
+ ("$e" + localIndex).toCharArray(), program.getTypeJavaLangObject(),
+ false, currentMethod);
tempLocals.add(newTemp);
}
++localIndex;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
index c2fcc16..a4abe8a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/CompoundAssignmentNormalizer.java
@@ -15,21 +15,20 @@
*/
package com.google.gwt.dev.jjs.impl;
-import com.google.gwt.dev.jjs.ast.Holder;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JBinaryOperator;
+import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JFieldRef;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNullLiteral;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JThisRef;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import java.util.ArrayList;
@@ -42,19 +41,20 @@
*/
public class CompoundAssignmentNormalizer {
- private class BreakupAssignOpsVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Break apart certain complex assignments.");
+ /**
+ * Breaks apart certain complex assignments.
+ */
+ private class BreakupAssignOpsVisitor extends JModVisitor {
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
/*
* Convert to a normal divide operation so we can cast the result. Since
* the left hand size must be computed twice, we have to replace any
* left-hand side expressions that could have side effects with
* temporaries, so that they are only run once.
*/
- if (x.op == JBinaryOperator.ASG_DIV
+ if (x.getOp() == JBinaryOperator.ASG_DIV
&& x.getType() != program.getTypePrimitiveFloat()
&& x.getType() != program.getTypePrimitiveDouble()) {
@@ -65,57 +65,49 @@
* temporaries, so that they are only run once.
*/
final int pushUsedLocals = localIndex;
- JMultiExpression multi = new JMultiExpression(program);
+ JMultiExpression multi = new JMultiExpression(program,
+ x.getSourceInfo());
ReplaceSideEffectsInLvalue replacer = new ReplaceSideEffectsInLvalue(
multi);
- x.lhs.traverse(replacer);
+ JExpression newLhs = replacer.accept(x.getLhs());
localIndex = pushUsedLocals;
JNullLiteral litNull = program.getLiteralNull();
JBinaryOperation operation = new JBinaryOperation(program,
- x.getLhs().getType(), JBinaryOperator.DIV, litNull, litNull);
- JBinaryOperation asg = new JBinaryOperation(program,
- x.getLhs().getType(), JBinaryOperator.ASG, litNull, operation);
+ x.getSourceInfo(), newLhs.getType(), JBinaryOperator.DIV, newLhs,
+ x.getRhs());
+ JBinaryOperation asg = new JBinaryOperation(program, x.getSourceInfo(),
+ newLhs.getType(), JBinaryOperator.ASG, newLhs, operation);
- ChangeList myChangeList = new ChangeList("Break '" + x
- + "' into two operations.");
-
- myChangeList.replaceExpression(operation.lhs, x.lhs);
- myChangeList.replaceExpression(operation.rhs, x.rhs);
- myChangeList.replaceExpression(asg.lhs, x.lhs);
-
- if (replacer.getChangeList().empty()) {
- myChangeList.replaceExpression(m, asg);
+ JMultiExpression multiExpr = replacer.getMultiExpr();
+ if (multiExpr.exprs.isEmpty()) {
+ // just use the split assignment expression
+ ctx.replaceMe(asg);
} else {
- myChangeList.add(replacer.getChangeList());
- myChangeList.addExpression(asg, multi.exprs);
- myChangeList.replaceExpression(m, multi);
+ // add the assignment as the last item in the multi
+ multi.exprs.add(asg);
+ ctx.replaceMe(multi);
}
-
- changeList.add(myChangeList);
}
}
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
clearLocals();
currentMethod = null;
}
- public ChangeList getChangeList() {
- return changeList;
- }
-
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
clearLocals();
return true;
}
}
- private class ReplaceSideEffectsInLvalue extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Replace side effects in lvalue.");
+ /**
+ * Replaces side effects in lvalue.
+ */
+ private class ReplaceSideEffectsInLvalue extends JModVisitor {
private final JMultiExpression multi;
@@ -123,56 +115,65 @@
this.multi = multi;
}
- public ChangeList getChangeList() {
- return changeList;
+ public JMultiExpression getMultiExpr() {
+ return multi;
}
// @Override
- public boolean visit(JArrayRef x, Mutator m) {
- possiblyReplace(x.instance);
- possiblyReplace(x.indexExpr);
- return false;
- }
-
- // @Override
- public boolean visit(JFieldRef x, Mutator m) {
- if (x.getInstance() != null) {
- possiblyReplace(x.instance);
+ public boolean visit(JArrayRef x, Context ctx) {
+ JExpression newInstance = possiblyReplace(x.getInstance());
+ JExpression newIndexExpr = possiblyReplace(x.getIndexExpr());
+ if (newInstance != x.getInstance() || newIndexExpr != x.getIndexExpr()) {
+ JArrayRef newExpr = new JArrayRef(program, x.getSourceInfo(),
+ newInstance, newIndexExpr);
+ ctx.replaceMe(newExpr);
}
return false;
}
// @Override
- public boolean visit(JLocalRef x, Mutator m) {
+ public boolean visit(JFieldRef x, Context ctx) {
+ if (x.getInstance() != null) {
+ JExpression newInstance = possiblyReplace(x.getInstance());
+ if (newInstance != x.getInstance()) {
+ JFieldRef newExpr = new JFieldRef(program, x.getSourceInfo(),
+ newInstance, x.getField(), x.getEnclosingType());
+ ctx.replaceMe(newExpr);
+ }
+ }
return false;
}
// @Override
- public boolean visit(JParameterRef x, Mutator m) {
+ public boolean visit(JLocalRef x, Context ctx) {
return false;
}
// @Override
- public boolean visit(JThisRef x, Mutator m) {
+ public boolean visit(JParameterRef x, Context ctx) {
return false;
}
- private void possiblyReplace(Holder x) {
- if (!x.get().hasSideEffects()) {
- return;
+ // @Override
+ public boolean visit(JThisRef x, Context ctx) {
+ return false;
+ }
+
+ private JExpression possiblyReplace(JExpression x) {
+ if (!x.hasSideEffects()) {
+ return x;
}
// Create a temp local
JLocal tempLocal = getTempLocal();
// Create an assignment for this temp and add it to multi.
- JLocalRef tempRef = new JLocalRef(program, tempLocal);
- JBinaryOperation asg = new JBinaryOperation(program, x.get().getType(),
- JBinaryOperator.ASG, tempRef, program.getLiteralNull());
- changeList.replaceExpression(asg.rhs, x);
- changeList.addExpression(asg, multi.exprs);
+ JLocalRef tempRef = new JLocalRef(program, x.getSourceInfo(), tempLocal);
+ JBinaryOperation asg = new JBinaryOperation(program, x.getSourceInfo(),
+ x.getType(), JBinaryOperator.ASG, tempRef, x);
+ multi.exprs.add(asg);
// Update me with the temp
- changeList.replaceExpression(x, tempRef);
+ return tempRef;
}
}
@@ -181,12 +182,9 @@
}
private JMethod currentMethod;
-
- private final List/* <JLocal> */tempLocals = new ArrayList/* <JLocal> */();
-
private int localIndex;
-
private final JProgram program;
+ private final List/* <JLocal> */tempLocals = new ArrayList/* <JLocal> */();
private CompoundAssignmentNormalizer(JProgram program) {
this.program = program;
@@ -199,19 +197,16 @@
private void execImpl() {
BreakupAssignOpsVisitor breaker = new BreakupAssignOpsVisitor();
- program.traverse(breaker);
- ChangeList changes = breaker.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ breaker.accept(program);
}
private JLocal getTempLocal() {
if (localIndex < tempLocals.size()) {
return (JLocal) tempLocals.get(localIndex++);
}
- JLocal newTemp = program.createLocal(("$t" + localIndex++).toCharArray(),
- program.getTypeVoid(), false, currentMethod);
+ JLocal newTemp = program.createLocal(null,
+ ("$t" + localIndex++).toCharArray(), program.getTypeVoid(), false,
+ currentMethod);
tempLocals.add(newTemp);
return newTemp;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
new file mode 100644
index 0000000..7b5311a
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/DeadCodeElimination.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2006 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jjs.impl;
+
+import com.google.gwt.dev.jjs.ast.Context;
+import com.google.gwt.dev.jjs.ast.JBinaryOperation;
+import com.google.gwt.dev.jjs.ast.JBinaryOperator;
+import com.google.gwt.dev.jjs.ast.JBlock;
+import com.google.gwt.dev.jjs.ast.JBooleanLiteral;
+import com.google.gwt.dev.jjs.ast.JBreakStatement;
+import com.google.gwt.dev.jjs.ast.JContinueStatement;
+import com.google.gwt.dev.jjs.ast.JDoStatement;
+import com.google.gwt.dev.jjs.ast.JExpression;
+import com.google.gwt.dev.jjs.ast.JForStatement;
+import com.google.gwt.dev.jjs.ast.JIfStatement;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
+import com.google.gwt.dev.jjs.ast.JPrefixOperation;
+import com.google.gwt.dev.jjs.ast.JProgram;
+import com.google.gwt.dev.jjs.ast.JStatement;
+import com.google.gwt.dev.jjs.ast.JTryStatement;
+import com.google.gwt.dev.jjs.ast.JUnaryOperator;
+import com.google.gwt.dev.jjs.ast.JVisitor;
+import com.google.gwt.dev.jjs.ast.JWhileStatement;
+
+/**
+ * Attempts to remove dead code.
+ */
+public class DeadCodeElimination {
+
+ /**
+ * Eliminates dead or unreachable code when possible.
+ */
+ public class DeadCodeVisitor extends JModVisitor {
+
+ /**
+ * Short circuit boolean AND or OR expressions when possible.
+ */
+ public void endVisit(JBinaryOperation x, Context ctx) {
+ if (x.getOp() == JBinaryOperator.AND) {
+ // simplify short circuit AND expressions
+ if (x.getLhs() instanceof JBooleanLiteral) {
+ // eg: if (false && isWhatever()) -> if (false)
+ // eg: if (true && isWhatever()) -> if (isWhatever())
+ JBooleanLiteral booleanLiteral = (JBooleanLiteral) x.getLhs();
+ if (booleanLiteral.getValue()) {
+ ctx.replaceMe(x.getRhs());
+ } else {
+ ctx.replaceMe(x.getLhs());
+ }
+
+ } else if (x.getRhs() instanceof JBooleanLiteral) {
+ // eg: if (isWhatever() && true) -> if (isWhatever())
+ JBooleanLiteral booleanLiteral = (JBooleanLiteral) x.getRhs();
+ if (booleanLiteral.getValue()) {
+ ctx.replaceMe(x.getLhs());
+ }
+ }
+
+ } else if (x.getOp() == JBinaryOperator.OR) {
+ // simplify short circuit OR expressions
+ if (x.getLhs() instanceof JBooleanLiteral) {
+ // eg: if (true || isWhatever()) -> if (true)
+ // eg: if (false || isWhatever()) -> if (isWhatever())
+ JBooleanLiteral booleanLiteral = (JBooleanLiteral) x.getLhs();
+ if (booleanLiteral.getValue()) {
+ ctx.replaceMe(x.getLhs());
+ } else {
+ ctx.replaceMe(x.getRhs());
+ }
+
+ } else if (x.getRhs() instanceof JBooleanLiteral) {
+ // eg: if (isWhatever() || false) -> if (isWhatever())
+ JBooleanLiteral booleanLiteral = (JBooleanLiteral) x.getRhs();
+ if (!booleanLiteral.getValue()) {
+ ctx.replaceMe(x.getLhs());
+ }
+ }
+ }
+ }
+
+ /**
+ * Prune empty blocks.
+ */
+ public void endVisit(JBlock x, Context ctx) {
+ if (x.statements.size() == 0) {
+ if (ctx.canRemove()) {
+ ctx.removeMe();
+ }
+ }
+ }
+
+ /**
+ * Convert do { } while (false); into a block.
+ */
+ public void endVisit(JDoStatement x, Context ctx) {
+ final JExpression expression = x.getTestExpr();
+ if (expression instanceof JBooleanLiteral) {
+ final JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;
+
+ // If false, replace do with do's body
+ if (!booleanLiteral.getValue()) {
+ // Unless it contains break/continue statements
+ FindBreakContinueStatementsVisitor visitor = new FindBreakContinueStatementsVisitor();
+ visitor.accept(x.getBody());
+ if (!visitor.hasBreakContinueStatements()) {
+ ctx.replaceMe(x.getBody());
+ }
+ }
+ }
+ }
+
+ /**
+ * Prune for (X; false; Y) statements, but make sure X is run.
+ */
+ public void endVisit(JForStatement x, Context ctx) {
+ final JExpression expression = x.getTestExpr();
+ if (expression instanceof JBooleanLiteral) {
+ final JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;
+
+ // If false, replace the for statement with its initializers
+ if (!booleanLiteral.getValue()) {
+ JBlock block = new JBlock(program, x.getSourceInfo());
+ block.statements.addAll(x.getInitializers());
+ ctx.replaceMe(block);
+ }
+ }
+ }
+
+ /**
+ * Prune "if (false)" statements.
+ */
+ public void endVisit(JIfStatement x, Context ctx) {
+ final JExpression expression = x.getIfExpr();
+ if (expression instanceof JBooleanLiteral) {
+ final JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;
+
+ if (booleanLiteral.getValue()) {
+ // If true, replace myself with then statement
+ ctx.replaceMe(x.getThenStmt());
+ } else if (x.getElseStmt() != null) {
+ // If false, replace myself with else statement
+ ctx.replaceMe(x.getElseStmt());
+ } else {
+ // just prune me
+ removeMe(x, ctx);
+ }
+ }
+ }
+
+ /**
+ * Resolve "!true" into "false" and vice versa.
+ */
+ public void endVisit(JPrefixOperation x, Context ctx) {
+ if (x.getOp() == JUnaryOperator.NOT) {
+ if (x.getArg() instanceof JBooleanLiteral) {
+ JBooleanLiteral booleanLiteral = (JBooleanLiteral) x.getArg();
+ ctx.replaceMe(program.getLiteralBoolean(!booleanLiteral.getValue()));
+ }
+ }
+ }
+
+ /**
+ * Prune try statements with no body. Hoist up try statements with no
+ * catches and an empty finally.
+ */
+ public void endVisit(JTryStatement x, Context ctx) {
+ boolean noTry = x.getTryBlock().statements.isEmpty();
+ // TODO: normalize finally block handling
+ boolean noFinally = (x.getFinallyBlock() == null)
+ || x.getFinallyBlock().statements.isEmpty();
+ boolean noCatch = x.getCatchArgs().size() == 0;
+
+ if (noTry) {
+ // If the try block is empty, just remove it
+ removeMe(x, ctx);
+ } else if (noCatch && noFinally) {
+ // If there's no catch or finally, there's no point in this even being
+ // a try statement, replace myself with the try block
+ ctx.replaceMe(x.getTryBlock());
+ }
+ }
+
+ /**
+ * Prune while (false) statements.
+ */
+ public void endVisit(JWhileStatement x, Context ctx) {
+ final JExpression expression = x.getTestExpr();
+ if (expression instanceof JBooleanLiteral) {
+ final JBooleanLiteral booleanLiteral = (JBooleanLiteral) expression;
+
+ // If false, prune the while statement
+ if (!booleanLiteral.getValue()) {
+ removeMe(x, ctx);
+ }
+ }
+ }
+
+ private void removeMe(JStatement stmt, Context ctx) {
+ if (ctx.canRemove()) {
+ ctx.removeMe();
+ } else {
+ // empty block statement
+ ctx.replaceMe(new JBlock(program, stmt.getSourceInfo()));
+ }
+ }
+ }
+
+ /**
+ * Examines code to find out whether it contains any break or continue
+ * statements.
+ */
+ public static class FindBreakContinueStatementsVisitor extends JVisitor {
+ private boolean hasBreakContinueStatements = false;
+
+ public void endVisit(JBreakStatement x, Context ctx) {
+ hasBreakContinueStatements = true;
+ }
+
+ public void endVisit(JContinueStatement x, Context ctx) {
+ hasBreakContinueStatements = true;
+ }
+
+ protected boolean hasBreakContinueStatements() {
+ return hasBreakContinueStatements;
+ }
+ }
+
+ public static boolean exec(JProgram program) {
+ return new DeadCodeElimination(program).execImpl();
+ }
+
+ private final JProgram program;
+
+ public DeadCodeElimination(JProgram program) {
+ this.program = program;
+ }
+
+ private boolean execImpl() {
+ boolean madeChanges = false;
+ while (true) {
+ DeadCodeVisitor deadCodeVisitor = new DeadCodeVisitor();
+ deadCodeVisitor.accept(program);
+ if (!deadCodeVisitor.didChange()) {
+ break;
+ }
+ madeChanges = true;
+ }
+ return madeChanges;
+ }
+}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
index d733368..c903926 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaAST.java
@@ -18,7 +18,6 @@
import com.google.gwt.dev.jjs.ast.CanBeStatic;
import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.HasName;
-import com.google.gwt.dev.jjs.ast.HolderList;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JAssertStatement;
@@ -63,6 +62,7 @@
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JSwitchStatement;
@@ -79,10 +79,12 @@
import com.google.gwt.dev.js.JsAbstractVisitorWithAllVisits;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsNameRef;
+import com.google.gwt.dev.js.ast.JsSourceInfo;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.ArrayAllocationExpression;
@@ -134,7 +136,6 @@
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.ast.WhileStatement;
-import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
import org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.eclipse.jdt.internal.compiler.impl.ByteConstant;
import org.eclipse.jdt.internal.compiler.impl.CharConstant;
@@ -183,7 +184,7 @@
/**
* Comparator for <code>HasName</code> instances.
*/
- public static class HasNameSort implements Comparator/* <HasName> */ {
+ public static class HasNameSort implements Comparator {
public int compare(Object o1, Object o2) {
HasName h1 = (HasName) o1;
HasName h2 = (HasName) o2;
@@ -203,6 +204,12 @@
* {@link org.eclipse.jdt.internal.compiler.ast.ASTNode} we'd have to override
* every single method and explicitly throw an exception to get the same
* behavior.
+ *
+ * NOTE ON JDT FORCED OPTIMIZATIONS - If JDT statically determines that a
+ * section of code in unreachable, it won't fully resolve that section of
+ * code. This invalid-state code causes us major problems. As a result, we
+ * have to optimize out those dead blocks early and never try to translate
+ * them to our AST.
*/
private static class JavaASTGenerationVisitor {
@@ -224,18 +231,22 @@
private ClassScope currentClassScope;
+ private String currentFileName;
+
private JMethod currentMethod;
private MethodScope currentMethodScope;
+ private int[] currentSeparatorPositions;
+
private final Map/* <JMethod, Map<String, JLabel>> */labelMap = new IdentityHashMap();
private Class[] params = new Class[1];
- private final TypeMap typeMap;
-
private final JProgram program;
+ private final TypeMap typeMap;
+
public JavaASTGenerationVisitor(TypeMap typeMap) {
this.typeMap = typeMap;
program = this.typeMap.getProgram();
@@ -249,6 +260,8 @@
public void processType(TypeDeclaration x) {
currentClass = (JReferenceType) typeMap.get(x.binding);
currentClassScope = x.scope;
+ currentSeparatorPositions = x.compilationResult.lineSeparatorPositions;
+ currentFileName = String.valueOf(x.compilationResult.fileName);
if (x.fields != null) {
// Process fields
@@ -292,6 +305,8 @@
currentClassScope = null;
currentClass = null;
+ currentSeparatorPositions = null;
+ currentFileName = null;
}
/**
@@ -304,23 +319,35 @@
}
try {
- params[0] = child.getClass();
- Method method = getClass().getDeclaredMethod(name, params);
- args[0] = child;
- return (JNode) method.invoke(this, args);
- } catch (SecurityException e) {
- throw new InternalCompilerException("Error during dispatch", e);
- } catch (NoSuchMethodException e) {
- String s = params[0].getName();
- throw new InternalCompilerException("Expecting: private void " + name
- + "(" + s.substring(s.lastIndexOf('.') + 1) + " x) { }", e);
- } catch (IllegalArgumentException e) {
- throw new InternalCompilerException("Error during dispatch", e);
- } catch (IllegalAccessException e) {
- throw new InternalCompilerException("Error during dispatch", e);
- } catch (InvocationTargetException e) {
- throw new InternalCompilerException("Error during dispatch",
- e.getTargetException());
+ try {
+ params[0] = child.getClass();
+ Method method = getClass().getDeclaredMethod(name, params);
+ args[0] = child;
+ return (JNode) method.invoke(this, args);
+ } catch (SecurityException e) {
+ throw new InternalCompilerException("Error during dispatch", e);
+ } catch (NoSuchMethodException e) {
+ String s = params[0].getName();
+ throw new InternalCompilerException("Expecting: private void " + name
+ + "(" + s.substring(s.lastIndexOf('.') + 1) + " x) { }", e);
+ } catch (IllegalArgumentException e) {
+ throw new InternalCompilerException("Error during dispatch", e);
+ } catch (IllegalAccessException e) {
+ throw new InternalCompilerException("Error during dispatch", e);
+ } catch (InvocationTargetException e) {
+ Throwable target = e.getTargetException();
+ if (target instanceof InternalCompilerException) {
+ throw (InternalCompilerException) target;
+ } else {
+ throw new InternalCompilerException(
+ "Error during AST construction", target);
+ }
+ }
+ } catch (InternalCompilerException ice) {
+ if (child instanceof ASTNode) {
+ ice.addNode((ASTNode) child);
+ }
+ throw ice;
}
}
@@ -351,7 +378,7 @@
if (expr == null) {
return null;
}
- stmt = new JExpressionStatement(program, expr);
+ stmt = new JExpressionStatement(program, makeSourceInfo(x), expr);
} else {
stmt = (JStatement) dispatch("processStatement", x);
}
@@ -422,6 +449,7 @@
*/
void processConstructor(ConstructorDeclaration x) {
JMethod ctor = (JMethod) typeMap.get(x.binding);
+ JSourceInfo info = ctor.body.getSourceInfo();
currentMethod = ctor;
currentMethodScope = x.scope;
@@ -444,8 +472,10 @@
// Call clinit; $clinit is always in position 0.
JMethod clinitMethod = (JMethod) enclosingType.methods.get(0);
- JMethodCall clinitCall = new JMethodCall(program, null, clinitMethod);
- ctor.body.statements.add(new JExpressionStatement(program, clinitCall));
+ JMethodCall clinitCall = new JMethodCall(program, info, null,
+ clinitMethod);
+ ctor.body.statements.add(new JExpressionStatement(program, info,
+ clinitCall));
/*
* All synthetic fields must be assigned, unless we have an explicit this
@@ -462,8 +492,9 @@
JParameter param = (JParameter) paramIt.next();
if (arg.matchingField != null) {
JField field = (JField) typeMap.get(arg);
- ctor.body.statements.add(program.createAssignmentStmt(
- createVariableRef(field), createVariableRef(param)));
+ ctor.body.statements.add(program.createAssignmentStmt(info,
+ createVariableRef(info, field), createVariableRef(info,
+ param)));
}
}
}
@@ -473,8 +504,9 @@
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
JParameter param = (JParameter) paramIt.next();
JField field = (JField) typeMap.get(arg);
- ctor.body.statements.add(program.createAssignmentStmt(
- createVariableRef(field), createVariableRef(param)));
+ ctor.body.statements.add(program.createAssignmentStmt(info,
+ createVariableRef(info, field),
+ createVariableRef(info, param)));
}
}
}
@@ -482,10 +514,11 @@
// optional this or super constructor call
if (call != null) {
- ctor.body.statements.add(new JExpressionStatement(program, call));
+ ctor.body.statements.add(new JExpressionStatement(program,
+ makeSourceInfo(ctorCall), call));
}
- JExpression thisRef = createThisRef(enclosingType);
+ JExpression thisRef = createThisRef(info, enclosingType);
/*
* Call the synthetic instance initializer method, unless we have an
@@ -494,8 +527,10 @@
if (!hasExplicitThis) {
// $init is always in position 1 (clinit is in 0)
JMethod initMethod = (JMethod) enclosingType.methods.get(1);
- JMethodCall initCall = new JMethodCall(program, thisRef, initMethod);
- ctor.body.statements.add(new JExpressionStatement(program, initCall));
+ JMethodCall initCall = new JMethodCall(program, info, thisRef,
+ initMethod);
+ ctor.body.statements.add(new JExpressionStatement(program, info,
+ initCall));
}
// user code (finally!)
@@ -513,10 +548,11 @@
currentMethod = null;
// synthesize a return statement to emulate returning the new object
- ctor.body.statements.add(new JReturnStatement(program, thisRef));
+ ctor.body.statements.add(new JReturnStatement(program, null, thisRef));
}
JExpression processExpression(AllocationExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
SourceTypeBinding typeBinding = (SourceTypeBinding) x.resolvedType;
if (typeBinding.constantPoolName() == null) {
/*
@@ -558,10 +594,10 @@
throw new InternalCompilerException(
"String constructor error; no matching implementation.");
}
- call = new JMethodCall(program, null, targetMethod);
+ call = new JMethodCall(program, makeSourceInfo(x), null, targetMethod);
} else {
- JNewInstance newInstance = new JNewInstance(program, newType);
- call = new JMethodCall(program, newInstance, ctor);
+ JNewInstance newInstance = new JNewInstance(program, info, newType);
+ call = new JMethodCall(program, info, newInstance, ctor);
}
// Synthetic args for inner classes
@@ -573,7 +609,7 @@
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
JClassType syntheticThisType = (JClassType) typeMap.get(arg.type);
- call.args.add(createThisRef(syntheticThisType));
+ call.getArgs().add(createThisRef(info, syntheticThisType));
}
}
// Synthetic locals for local classes
@@ -581,8 +617,8 @@
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable);
- call.args.add(createVariableRef(variable,
- arg.actualOuterLocalVariable));
+ call.getArgs().add(
+ createVariableRef(info, variable, arg.actualOuterLocalVariable));
}
}
}
@@ -590,7 +626,7 @@
// Plain old regular user arguments
if (x.arguments != null) {
for (int i = 0, n = x.arguments.length; i < n; ++i) {
- call.args.add(dispProcessExpression(x.arguments[i]));
+ call.getArgs().add(dispProcessExpression(x.arguments[i]));
}
}
@@ -599,15 +635,18 @@
JExpression processExpression(AND_AND_Expression x) {
JType type = (JType) typeMap.get(x.resolvedType);
- return processBinaryOperation(JBinaryOperator.AND, type, x.left, x.right);
+ JSourceInfo info = makeSourceInfo(x);
+ return processBinaryOperation(info, JBinaryOperator.AND, type, x.left,
+ x.right);
}
JExpression processExpression(ArrayAllocationExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
- JNewArray newArray = new JNewArray(program, type);
+ JNewArray newArray = new JNewArray(program, info, type);
if (x.initializer != null) {
- newArray.initializers = new HolderList();
+ newArray.initializers = new ArrayList();
if (x.initializer.expressions != null) {
for (int i = 0; i < x.initializer.expressions.length; i++) {
Expression expression = x.initializer.expressions[i];
@@ -615,7 +654,7 @@
}
}
} else {
- newArray.dims = new HolderList();
+ newArray.dims = new ArrayList();
for (int i = 0; i < x.dimensions.length; i++) {
Expression dimension = x.dimensions[i];
// can be null if index expression was empty
@@ -631,10 +670,11 @@
}
JExpression processExpression(ArrayInitializer x) {
+ JSourceInfo info = makeSourceInfo(x);
JArrayType type = (JArrayType) typeMap.get(x.resolvedType);
- JNewArray newArray = new JNewArray(program, type);
+ JNewArray newArray = new JNewArray(program, info, type);
- newArray.initializers = new HolderList();
+ newArray.initializers = new ArrayList();
if (x.expressions != null) {
for (int i = 0; i < x.expressions.length; i++) {
Expression expression = x.expressions[i];
@@ -646,14 +686,16 @@
}
JExpression processExpression(ArrayReference x) {
- JArrayRef arrayRef = new JArrayRef(program,
+ JSourceInfo info = makeSourceInfo(x);
+ JArrayRef arrayRef = new JArrayRef(program, info,
dispProcessExpression(x.receiver), dispProcessExpression(x.position));
return arrayRef;
}
JExpression processExpression(Assignment x) {
JType type = (JType) typeMap.get(x.resolvedType);
- return processBinaryOperation(JBinaryOperator.ASG, type, x.lhs,
+ JSourceInfo info = makeSourceInfo(x);
+ return processBinaryOperation(info, JBinaryOperator.ASG, type, x.lhs,
x.expression);
}
@@ -713,12 +755,14 @@
}
JType type = (JType) typeMap.get(x.resolvedType);
- return processBinaryOperation(op, type, x.left, x.right);
+ JSourceInfo info = makeSourceInfo(x);
+ return processBinaryOperation(info, op, type, x.left, x.right);
}
JExpression processExpression(CastExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JType type = (JType) typeMap.get(x.resolvedType);
- JCastOperation cast = new JCastOperation(program, type,
+ JCastOperation cast = new JCastOperation(program, info, type,
dispProcessExpression(x.expression));
return cast;
}
@@ -771,15 +815,17 @@
}
JType type = (JType) typeMap.get(x.resolvedType);
- return processBinaryOperation(op, type, x.lhs, x.expression);
+ JSourceInfo info = makeSourceInfo(x);
+ return processBinaryOperation(info, op, type, x.lhs, x.expression);
}
JExpression processExpression(ConditionalExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JType type = (JType) typeMap.get(x.resolvedType);
JExpression ifTest = dispProcessExpression(x.condition);
JExpression thenExpr = dispProcessExpression(x.valueIfTrue);
JExpression elseExpr = dispProcessExpression(x.valueIfFalse);
- JConditional conditional = new JConditional(program, type, ifTest,
+ JConditional conditional = new JConditional(program, info, type, ifTest,
thenExpr, elseExpr);
return conditional;
}
@@ -799,7 +845,8 @@
}
JType type = (JType) typeMap.get(x.resolvedType);
- return processBinaryOperation(op, type, x.left, x.right);
+ JSourceInfo info = makeSourceInfo(x);
+ return processBinaryOperation(info, op, type, x.left, x.right);
}
/**
@@ -815,6 +862,7 @@
}
JExpression processExpression(FieldReference x) {
+ JSourceInfo info = makeSourceInfo(x);
FieldBinding fieldBinding = x.binding;
JField field;
if (fieldBinding.declaringClass == null) {
@@ -827,18 +875,20 @@
field = (JField) typeMap.get(fieldBinding);
}
JExpression instance = dispProcessExpression(x.receiver);
- JExpression fieldRef = new JFieldRef(program, instance, field,
+ JExpression fieldRef = new JFieldRef(program, info, instance, field,
currentClass);
return fieldRef;
}
JExpression processExpression(InstanceOfExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JExpression expr = dispProcessExpression(x.expression);
JReferenceType testType = (JReferenceType) typeMap.get(x.type.resolvedType);
- return new JInstanceOf(program, testType, expr);
+ return new JInstanceOf(program, info, testType, expr);
}
JExpression processExpression(MessageSend x) {
+ JSourceInfo info = makeSourceInfo(x);
JType type = (JType) typeMap.get(x.resolvedType);
JMethod method = (JMethod) typeMap.get(x.binding);
assert (type == method.getType());
@@ -847,7 +897,7 @@
if (x.receiver instanceof ThisReference) {
if (method.isStatic()) {
// don't bother qualifying it, it's a no-op
- // TODO: this may be handled by later optimizations now
+ // TODO(???): this may be handled by later optimizations now
qualifier = null;
} else if (x.receiver instanceof QualifiedThisReference) {
// do nothing, the qualifier is correct
@@ -857,11 +907,11 @@
* actually be the wrong type, if the target method is in an enclosing
* class. We have to sythensize our own ref of the correct type.
*/
- qualifier = createThisRef(method.getEnclosingType());
+ qualifier = createThisRef(info, method.getEnclosingType());
}
}
- JMethodCall call = new JMethodCall(program, qualifier, method);
+ JMethodCall call = new JMethodCall(program, info, qualifier, method);
boolean isSuperRef = x.receiver instanceof SuperReference;
if (isSuperRef) {
call.setStaticDispatchOnly();
@@ -870,7 +920,7 @@
// The arguments come first...
if (x.arguments != null) {
for (int i = 0, n = x.arguments.length; i < n; ++i) {
- call.args.add(dispProcessExpression(x.arguments[i]));
+ call.getArgs().add(dispProcessExpression(x.arguments[i]));
}
}
@@ -883,10 +933,13 @@
JExpression processExpression(OR_OR_Expression x) {
JType type = (JType) typeMap.get(x.resolvedType);
- return processBinaryOperation(JBinaryOperator.OR, type, x.left, x.right);
+ JSourceInfo info = makeSourceInfo(x);
+ return processBinaryOperation(info, JBinaryOperator.OR, type, x.left,
+ x.right);
}
JExpression processExpression(PostfixExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JUnaryOperator op;
switch (x.operator) {
@@ -902,12 +955,13 @@
throw new InternalCompilerException("Unexpected postfix operator");
}
- JPostfixOperation postOp = new JPostfixOperation(program, op,
+ JPostfixOperation postOp = new JPostfixOperation(program, info, op,
dispProcessExpression(x.lhs));
return postOp;
}
JExpression processExpression(PrefixExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JUnaryOperator op;
switch (x.operator) {
@@ -923,7 +977,7 @@
throw new InternalCompilerException("Unexpected prefix operator");
}
- JPrefixOperation preOp = new JPrefixOperation(program, op,
+ JPrefixOperation preOp = new JPrefixOperation(program, info, op,
dispProcessExpression(x.lhs));
return preOp;
}
@@ -942,11 +996,12 @@
return processExpression((AllocationExpression) x);
}
+ JSourceInfo info = makeSourceInfo(x);
MethodBinding b = x.binding;
JMethod ctor = (JMethod) typeMap.get(b);
JClassType enclosingType = (JClassType) ctor.getEnclosingType();
- JNewInstance newInstance = new JNewInstance(program, enclosingType);
- JMethodCall call = new JMethodCall(program, newInstance, ctor);
+ JNewInstance newInstance = new JNewInstance(program, info, enclosingType);
+ JMethodCall call = new JMethodCall(program, info, newInstance, ctor);
JExpression qualifier = dispProcessExpression(x.enclosingInstance);
// Synthetic args for inner classes
@@ -958,7 +1013,7 @@
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.enclosingInstances[i];
JClassType syntheticThisType = (JClassType) typeMap.get(arg.type);
- call.args.add(createThisRef(syntheticThisType, qualifier));
+ call.getArgs().add(createThisRef(syntheticThisType, qualifier));
}
}
// Synthetic locals for local classes
@@ -966,8 +1021,8 @@
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
SyntheticArgumentBinding arg = nestedBinding.outerLocalVariables[i];
JVariable variable = (JVariable) typeMap.get(arg.actualOuterLocalVariable);
- call.args.add(createVariableRef(variable,
- arg.actualOuterLocalVariable));
+ call.getArgs().add(
+ createVariableRef(info, variable, arg.actualOuterLocalVariable));
}
}
}
@@ -975,7 +1030,7 @@
// Plain old regular arguments
if (x.arguments != null) {
for (int i = 0, n = x.arguments.length; i < n; ++i) {
- call.args.add(dispProcessExpression(x.arguments[i]));
+ call.getArgs().add(dispProcessExpression(x.arguments[i]));
}
}
@@ -983,6 +1038,7 @@
}
JExpression processExpression(QualifiedNameReference x) {
+ JSourceInfo info = makeSourceInfo(x);
Binding binding = x.binding;
JNode node = typeMap.get(binding);
if (!(node instanceof JVariable)) {
@@ -990,7 +1046,7 @@
}
JVariable variable = (JVariable) node;
- JExpression curRef = createVariableRef(variable, binding);
+ JExpression curRef = createVariableRef(info, variable, binding);
/*
* Wackiness: JDT represents multiple field access as an array of fields,
@@ -1011,7 +1067,7 @@
} else {
field = (JField) typeMap.get(fieldBinding);
}
- curRef = new JFieldRef(program, curRef, field, currentClass);
+ curRef = new JFieldRef(program, info, curRef, field, currentClass);
}
}
@@ -1020,6 +1076,7 @@
JExpression processExpression(QualifiedSuperReference x) {
JClassType type = (JClassType) typeMap.get(x.resolvedType);
+ JSourceInfo info = makeSourceInfo(x);
/*
* WEIRD: If a superref is qualified with the EXACT type of the innermost
* type (in other words, a needless qualifier), it must refer to that
@@ -1031,14 +1088,15 @@
* compatible type), so we must create a reference to some outer type.
*/
if (type == currentClass) {
- return createSuperRef(type);
+ return createSuperRef(info, type);
} else {
- return createQualifiedSuperRef(type);
+ return createQualifiedSuperRef(info, type);
}
}
JExpression processExpression(QualifiedThisReference x) {
JClassType type = (JClassType) typeMap.get(x.resolvedType);
+ JSourceInfo info = makeSourceInfo(x);
/*
* WEIRD: If a thisref is qualified with the EXACT type of the innermost
* type (in other words, a needless qualifier), it must refer to that
@@ -1050,13 +1108,14 @@
* compatible type), so we must create a reference to some outer type.
*/
if (type == currentClass) {
- return createThisRef(type);
+ return createThisRef(info, type);
} else {
- return createQualifiedThisRef(type);
+ return createQualifiedThisRef(info, type);
}
}
JExpression processExpression(SingleNameReference x) {
+ JSourceInfo info = makeSourceInfo(x);
Binding binding = x.binding;
Object target = typeMap.get(binding);
if (!(target instanceof JVariable)) {
@@ -1073,29 +1132,32 @@
if (x.syntheticAccessors != null) {
JField field = (JField) variable;
if (!field.isStatic()) {
- JExpression instance = createThisRef(field.getEnclosingType());
- return new JFieldRef(program, instance, field, currentClass);
+ JExpression instance = createThisRef(info, field.getEnclosingType());
+ return new JFieldRef(program, info, instance, field, currentClass);
}
}
- return createVariableRef(variable, binding);
+ return createVariableRef(info, variable, binding);
}
JExpression processExpression(SuperReference x) {
JClassType type = (JClassType) typeMap.get(x.resolvedType);
assert (type == currentClass.extnds);
- JExpression superRef = createSuperRef(type);
+ JSourceInfo info = makeSourceInfo(x);
+ JExpression superRef = createSuperRef(info, type);
return superRef;
}
JExpression processExpression(ThisReference x) {
JClassType type = (JClassType) typeMap.get(x.resolvedType);
assert (type == currentClass);
- JExpression thisRef = createThisRef(type);
+ JSourceInfo info = makeSourceInfo(x);
+ JExpression thisRef = createThisRef(info, type);
return thisRef;
}
JExpression processExpression(UnaryExpression x) {
+ JSourceInfo info = makeSourceInfo(x);
JUnaryOperator op;
int operator = ((x.bits & UnaryExpression.OperatorMASK) >> UnaryExpression.OperatorSHIFT);
@@ -1121,7 +1183,7 @@
"Unexpected operator for unary expression");
}
- JPrefixOperation preOp = new JPrefixOperation(program, op,
+ JPrefixOperation preOp = new JPrefixOperation(program, info, op,
dispProcessExpression(x.expression));
return preOp;
}
@@ -1144,8 +1206,9 @@
if (initializer instanceof JLiteral) {
field.constInitializer = (JLiteral) initializer;
} else if (initializer != null) {
- JStatement assignStmt = program.createAssignmentStmt(
- createVariableRef(field), initializer);
+ JSourceInfo info = makeSourceInfo(declaration);
+ JStatement assignStmt = program.createAssignmentStmt(info,
+ createVariableRef(info, field), initializer);
// will either be init or clinit
currentMethod.body.statements.add(assignStmt);
@@ -1158,11 +1221,6 @@
currentMethod.body.statements.add(block);
}
- // // 5.0
- // JStatement processStatement(ForeachStatement x) {
- // return null;
- // }
-
void processMethod(AbstractMethodDeclaration x) {
MethodBinding b = x.binding;
JMethod method = (JMethod) typeMap.get(b);
@@ -1192,6 +1250,11 @@
currentMethod = null;
}
+ // // 5.0
+ // JStatement processStatement(ForeachStatement x) {
+ // return null;
+ // }
+
void processNativeMethod(AbstractMethodDeclaration x,
JsniMethod nativeMethod) {
@@ -1214,10 +1277,11 @@
for (int i = 0; i < nameRefs.size(); ++i) {
JsNameRef nameRef = (JsNameRef) nameRefs.get(i);
+ JSourceInfo info = translateInfo(nameRef.getInfo());
String ident = nameRef.getName().getIdent();
HasEnclosingType node = (HasEnclosingType) program.jsniMap.get(ident);
if (node == null) {
- node = parseJsniRef(x, ident);
+ node = parseJsniRef(info, x, ident);
if (node == null) {
continue; // already reported error
}
@@ -1229,12 +1293,13 @@
boolean isField = node instanceof JField;
assert (isField || node instanceof JMethod);
if (canBeStatic.isStatic() && nameRef.getQualifier() != null) {
- reportJsniError(x, "Cannot make a qualified reference to the static "
- + (isField ? "field " : "method ") + hasName.getName(), 0);
+ reportJsniError(info, x,
+ "Cannot make a qualified reference to the static "
+ + (isField ? "field " : "method ") + hasName.getName());
} else if (!canBeStatic.isStatic() && nameRef.getQualifier() == null) {
- reportJsniError(x,
+ reportJsniError(info, x,
"Cannot make an unqualified reference to the instance "
- + (isField ? "field " : "method ") + hasName.getName(), 0);
+ + (isField ? "field " : "method ") + hasName.getName());
}
if (isField) {
@@ -1243,20 +1308,22 @@
* from JSNI with the literal value of the field.
*/
JField field = (JField) node;
- JsniFieldRef fieldRef = new JsniFieldRef(program, field, currentClass);
+ JsniFieldRef fieldRef = new JsniFieldRef(program, info, field,
+ currentClass);
nativeMethod.jsniFieldRefs.add(fieldRef);
} else {
JMethod method = (JMethod) node;
- JsniMethodRef methodRef = new JsniMethodRef(program, method);
+ JsniMethodRef methodRef = new JsniMethodRef(program, info, method);
nativeMethod.jsniMethodRefs.add(methodRef);
}
}
}
JStatement processStatement(AssertStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
JExpression expr = dispProcessExpression(x.assertExpression);
JExpression arg = dispProcessExpression(x.exceptionArgument);
- return new JAssertStatement(program, expr, arg);
+ return new JAssertStatement(program, info, expr, arg);
}
JBlock processStatement(Block x) {
@@ -1264,7 +1331,8 @@
return null;
}
- JBlock block = new JBlock(program);
+ JSourceInfo info = makeSourceInfo(x);
+ JBlock block = new JBlock(program, info);
if (x.statements != null) {
for (int i = 0, n = x.statements.length; i < n; ++i) {
JStatement jstmt = dispProcessStatement(x.statements[i]);
@@ -1277,32 +1345,28 @@
}
JStatement processStatement(BreakStatement x) {
- return new JBreakStatement(program, getOrCreateLabel(currentMethod,
- x.label));
+ JSourceInfo info = makeSourceInfo(x);
+ return new JBreakStatement(program, info, getOrCreateLabel(info,
+ currentMethod, x.label));
}
JStatement processStatement(CaseStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
JExpression expression = dispProcessExpression(x.constantExpression);
- return new JCaseStatement(program, (JLiteral) expression);
+ return new JCaseStatement(program, info, (JLiteral) expression);
}
JStatement processStatement(ContinueStatement x) {
- return new JContinueStatement(program, getOrCreateLabel(currentMethod,
- x.label));
+ JSourceInfo info = makeSourceInfo(x);
+ return new JContinueStatement(program, info, getOrCreateLabel(info,
+ currentMethod, x.label));
}
JStatement processStatement(DoStatement x) {
- // If false, just return the body
- // do { x } while (false) => x
- Constant cst = x.condition.optimizedBooleanConstant();
- if (cst != Constant.NotAConstant) {
- if (!cst.booleanValue()) {
- return dispProcessStatement(x.action);
- }
- }
+ JSourceInfo info = makeSourceInfo(x);
JExpression loopTest = dispProcessExpression(x.condition);
JStatement loopBody = dispProcessStatement(x.action);
- JDoStatement stmt = new JDoStatement(program, loopTest, loopBody);
+ JDoStatement stmt = new JDoStatement(program, info, loopTest, loopBody);
return stmt;
}
@@ -1311,13 +1375,15 @@
}
JStatement processStatement(ForStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
+ // SEE NOTE ON JDT FORCED OPTIMIZATIONS
// If false, just return the initializers
// for (init; false; inc) { x } => { init }
if (x.condition != null) {
Constant cst = x.condition.optimizedBooleanConstant();
if (cst != Constant.NotAConstant) {
if (!cst.booleanValue()) {
- JBlock block = new JBlock(program);
+ JBlock block = new JBlock(program, info);
block.statements = processStatements(x.initializations);
return block;
}
@@ -1328,10 +1394,11 @@
JExpression expr = dispProcessExpression(x.condition);
List/* <JExpressionStatement> */incr = processStatements(x.increments);
JStatement body = dispProcessStatement(x.action);
- return new JForStatement(program, init, expr, incr, body);
+ return new JForStatement(program, info, init, expr, incr, body);
}
JStatement processStatement(IfStatement x) {
+ // SEE NOTE ON JDT FORCED OPTIMIZATIONS
// If constant, just return the appropriate case
// if (true) x; else y; => x
// if (false) x; else y; => y
@@ -1346,10 +1413,12 @@
}
}
+ JSourceInfo info = makeSourceInfo(x);
JExpression expr = dispProcessExpression(x.condition);
JStatement thenStmt = dispProcessStatement(x.thenStatement);
JStatement elseStmt = dispProcessStatement(x.elseStatement);
- JIfStatement ifStmt = new JIfStatement(program, expr, thenStmt, elseStmt);
+ JIfStatement ifStmt = new JIfStatement(program, info, expr, thenStmt,
+ elseStmt);
return ifStmt;
}
@@ -1358,18 +1427,22 @@
if (body == null) {
return null;
}
- return new JLabeledStatement(program, getOrCreateLabel(currentMethod,
- x.label), body);
+ JSourceInfo info = makeSourceInfo(x);
+ return new JLabeledStatement(program, info, getOrCreateLabel(info,
+ currentMethod, x.label), body);
}
JStatement processStatement(LocalDeclaration x) {
+ JSourceInfo info = makeSourceInfo(x);
JLocal local = (JLocal) typeMap.get(x.binding);
- JLocalRef localRef = new JLocalRef(program, local);
+ JLocalRef localRef = new JLocalRef(program, info, local);
JExpression initializer = dispProcessExpression(x.initialization);
- return new JLocalDeclarationStatement(program, localRef, initializer);
+ return new JLocalDeclarationStatement(program, info, localRef,
+ initializer);
}
JStatement processStatement(ReturnStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
if (currentMethodScope.referenceContext instanceof ConstructorDeclaration) {
/*
* Special: constructors are implemented as instance methods that return
@@ -1378,47 +1451,52 @@
*/
JClassType enclosingType = (JClassType) currentMethod.getEnclosingType();
assert (x.expression == null);
- return new JReturnStatement(program, createThisRef(enclosingType));
+ return new JReturnStatement(program, info, createThisRef(info,
+ enclosingType));
} else {
- return new JReturnStatement(program,
+ return new JReturnStatement(program, info,
dispProcessExpression(x.expression));
}
}
JStatement processStatement(SwitchStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
JExpression expression = dispProcessExpression(x.expression);
- JBlock block = new JBlock(program);
+ JBlock block = new JBlock(program, info);
block.statements = processStatements(x.statements);
- return new JSwitchStatement(program, expression, block);
+ return new JSwitchStatement(program, info, expression, block);
}
JStatement processStatement(SynchronizedStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
JBlock block = processStatement(x.block);
JExpression expr = dispProcessExpression(x.expression);
- block.statements.add(0, new JExpressionStatement(program, expr));
+ block.statements.add(0, new JExpressionStatement(program, info, expr));
return block;
}
JStatement processStatement(ThrowStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
JExpression toThrow = dispProcessExpression(x.exception);
- return new JThrowStatement(program, toThrow);
+ return new JThrowStatement(program, info, toThrow);
}
JStatement processStatement(TryStatement x) {
+ JSourceInfo info = makeSourceInfo(x);
JBlock tryBlock = processStatement(x.tryBlock);
List/* <JLocalRef> */catchArgs = new ArrayList/* <JLocalRef> */();
List/* <JBlock> */catchBlocks = new ArrayList/* <JBlock> */();
if (x.catchBlocks != null) {
for (int i = 0, c = x.catchArguments.length; i < c; ++i) {
JLocal local = (JLocal) typeMap.get(x.catchArguments[i].binding);
- catchArgs.add(createVariableRef(local));
+ catchArgs.add(createVariableRef(info, local));
}
for (int i = 0, c = x.catchBlocks.length; i < c; ++i) {
catchBlocks.add(processStatement(x.catchBlocks[i]));
}
}
JBlock finallyBlock = processStatement(x.finallyBlock);
- return new JTryStatement(program, tryBlock, catchArgs, catchBlocks,
+ return new JTryStatement(program, info, tryBlock, catchArgs, catchBlocks,
finallyBlock);
}
@@ -1428,6 +1506,7 @@
}
JStatement processStatement(WhileStatement x) {
+ // SEE NOTE ON JDT FORCED OPTIMIZATIONS
// If false, just return nothing
// while (false) { x } => ;
Constant cst = x.condition.optimizedBooleanConstant();
@@ -1436,9 +1515,11 @@
return null;
}
}
+ JSourceInfo info = makeSourceInfo(x);
JExpression loopTest = dispProcessExpression(x.condition);
JStatement loopBody = dispProcessStatement(x.action);
- JWhileStatement stmt = new JWhileStatement(program, loopTest, loopBody);
+ JWhileStatement stmt = new JWhileStatement(program, info, loopTest,
+ loopBody);
return stmt;
}
@@ -1456,9 +1537,10 @@
}
JMethodCall processSuperConstructorCall(ExplicitConstructorCall x) {
+ JSourceInfo info = makeSourceInfo(x);
JMethod ctor = (JMethod) typeMap.get(x.binding);
- JExpression trueQualifier = createThisRef(currentClass);
- JMethodCall call = new JMethodCall(program, trueQualifier, ctor);
+ JExpression trueQualifier = createThisRef(info, currentClass);
+ JMethodCall call = new JMethodCall(program, info, trueQualifier, ctor);
// We have to find and pass through any synthetics our supertype needs
ReferenceBinding superClass = x.binding.declaringClass;
@@ -1484,11 +1566,12 @@
List/* <JExpression> */workList = new ArrayList/* <JExpression> */();
Iterator/* <JParameter> */paramIt = currentMethod.params.iterator();
for (int i = 0; i < myBinding.enclosingInstances.length; ++i) {
- workList.add(createVariableRef((JParameter) paramIt.next()));
+ workList.add(createVariableRef(info,
+ (JParameter) paramIt.next()));
}
- call.args.add(createThisRef(classType, workList));
+ call.getArgs().add(createThisRef(classType, workList));
} else {
- call.args.add(createThisRef(classType, qualifier));
+ call.getArgs().add(createThisRef(classType, qualifier));
}
}
}
@@ -1512,14 +1595,14 @@
throw new InternalCompilerException(
"Could not find matching local arg for explicit super ctor call.");
}
- call.args.add(createVariableRef(param));
+ call.getArgs().add(createVariableRef(info, param));
}
}
}
if (x.arguments != null) {
for (int i = 0, n = x.arguments.length; i < n; ++i) {
- call.args.add(dispProcessExpression(x.arguments[i]));
+ call.getArgs().add(dispProcessExpression(x.arguments[i]));
}
}
@@ -1527,9 +1610,10 @@
}
JMethodCall processThisConstructorCall(ExplicitConstructorCall x) {
+ JSourceInfo info = makeSourceInfo(x);
JMethod ctor = (JMethod) typeMap.get(x.binding);
- JExpression trueQualifier = createThisRef(currentClass);
- JMethodCall call = new JMethodCall(program, trueQualifier, ctor);
+ JExpression trueQualifier = createThisRef(info, currentClass);
+ JMethodCall call = new JMethodCall(program, info, trueQualifier, ctor);
// All synthetics must be passed through to the target ctor
ReferenceBinding declaringClass = x.binding.declaringClass;
@@ -1538,12 +1622,14 @@
NestedTypeBinding nestedBinding = (NestedTypeBinding) declaringClass;
if (nestedBinding.enclosingInstances != null) {
for (int i = 0; i < nestedBinding.enclosingInstances.length; ++i) {
- call.args.add(createVariableRef((JParameter) paramIt.next()));
+ call.getArgs().add(
+ createVariableRef(info, (JParameter) paramIt.next()));
}
}
if (nestedBinding.outerLocalVariables != null) {
for (int i = 0; i < nestedBinding.outerLocalVariables.length; ++i) {
- call.args.add(createVariableRef((JParameter) paramIt.next()));
+ call.getArgs().add(
+ createVariableRef(info, (JParameter) paramIt.next()));
}
}
}
@@ -1551,7 +1637,7 @@
assert (x.qualification == null);
if (x.arguments != null) {
for (int i = 0, n = x.arguments.length; i < n; ++i) {
- call.args.add(dispProcessExpression(x.arguments[i]));
+ call.getArgs().add(dispProcessExpression(x.arguments[i]));
}
}
@@ -1563,7 +1649,8 @@
if (classType.fields.size() > 0) {
JField field = (JField) classType.fields.get(0);
if (field.getName().startsWith("this$")) {
- list.add(new JFieldRef(program, expr, field, currentClass));
+ list.add(new JFieldRef(program, expr.getSourceInfo(), expr, field,
+ currentClass));
}
}
}
@@ -1596,9 +1683,10 @@
* access) of the appropriate type. Always use this method instead of
* creating a naked JThisRef or you won't get the synthetic accesses right.
*/
- private JExpression createQualifiedSuperRef(JClassType targetType) {
+ private JExpression createQualifiedSuperRef(JSourceInfo info,
+ JClassType targetType) {
assert (currentClass instanceof JClassType);
- JExpression expr = program.getExpressionThisRef((JClassType) currentClass);
+ JExpression expr = program.getExprThisRef(info, (JClassType) currentClass);
List/* <JExpression> */list = new ArrayList();
addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass);
return createSuperRef(targetType, list);
@@ -1609,9 +1697,10 @@
* access) of the appropriate type. Always use this method instead of
* creating a naked JThisRef or you won't get the synthetic accesses right.
*/
- private JExpression createQualifiedThisRef(JClassType targetType) {
+ private JExpression createQualifiedThisRef(JSourceInfo info,
+ JClassType targetType) {
assert (currentClass instanceof JClassType);
- JExpression expr = program.getExpressionThisRef((JClassType) currentClass);
+ JExpression expr = program.getExprThisRef(info, (JClassType) currentClass);
List/* <JExpression> */list = new ArrayList();
addAllOuterThisRefsPlusSuperChain(list, expr, (JClassType) currentClass);
return createThisRef(targetType, list);
@@ -1622,19 +1711,6 @@
* access) of the appropriate type. Always use this method instead of
* creating a naked JThisRef or you won't get the synthetic accesses right.
*/
- private JExpression createSuperRef(JClassType targetType) {
- assert (currentClass instanceof JClassType);
- JExpression expr = program.getExpressionThisRef((JClassType) currentClass);
- List/* <JExpression> */list = new ArrayList();
- list.add(expr);
- return createSuperRef(targetType, list);
- }
-
- /**
- * Helper to create a "super" ref (really a this ref or synthetic this field
- * access) of the appropriate type. Always use this method instead of
- * creating a naked JThisRef or you won't get the synthetic accesses right.
- */
private JExpression createSuperRef(JClassType targetType,
List/* <JExpression> */list) {
assert (currentClass instanceof JClassType);
@@ -1655,14 +1731,16 @@
}
/**
- * Helper to creates this ref (or maybe a synthetic this field access) of
- * the appropriate type. Always use this method instead of creating a naked
- * JThisRef or you won't get the synthetic accesses right.
+ * Helper to create a "super" ref (really a this ref or synthetic this field
+ * access) of the appropriate type. Always use this method instead of
+ * creating a naked JThisRef or you won't get the synthetic accesses right.
*/
- private JExpression createThisRef(JReferenceType targetType) {
+ private JExpression createSuperRef(JSourceInfo info, JClassType targetType) {
assert (currentClass instanceof JClassType);
- return createThisRef(targetType,
- program.getExpressionThisRef((JClassType) currentClass));
+ JExpression expr = program.getExprThisRef(info, (JClassType) currentClass);
+ List/* <JExpression> */list = new ArrayList();
+ list.add(expr);
+ return createSuperRef(targetType, list);
}
/**
@@ -1719,37 +1797,49 @@
}
/**
+ * Helper to creates this ref (or maybe a synthetic this field access) of
+ * the appropriate type. Always use this method instead of creating a naked
+ * JThisRef or you won't get the synthetic accesses right.
+ */
+ private JExpression createThisRef(JSourceInfo info,
+ JReferenceType targetType) {
+ assert (currentClass instanceof JClassType);
+ return createThisRef(targetType, program.getExprThisRef(info,
+ (JClassType) currentClass));
+ }
+
+ /**
* Creates an appropriate JVariableRef for the polymorphic type of the
* requested JVariable.
*/
- private JVariableRef createVariableRef(JVariable variable) {
+ private JVariableRef createVariableRef(JSourceInfo info, JVariable variable) {
if (variable instanceof JLocal) {
JLocal local = (JLocal) variable;
if (local.getEnclosingMethod() != currentMethod) {
throw new InternalCompilerException(
"LocalRef referencing local in a different method.");
}
- return new JLocalRef(program, local);
+ return new JLocalRef(program, info, local);
} else if (variable instanceof JParameter) {
JParameter parameter = (JParameter) variable;
if (parameter.getEnclosingMethod() != currentMethod) {
throw new InternalCompilerException(
"ParameterRef referencing param in a different method.");
}
- return new JParameterRef(program, parameter);
+ return new JParameterRef(program, info, parameter);
} else if (variable instanceof JField) {
JField field = (JField) variable;
JExpression instance = null;
if (!field.isStatic()) {
JClassType fieldEnclosingType = (JClassType) field.getEnclosingType();
- instance = createThisRef(fieldEnclosingType);
+ instance = createThisRef(info, fieldEnclosingType);
if (!program.typeOracle.canTriviallyCast(
(JClassType) instance.getType(), fieldEnclosingType)) {
throw new InternalCompilerException(
"FieldRef referencing field in a different type.");
}
}
- return new JFieldRef(program, instance, field, currentClass);
+ return new JFieldRef(program, info, instance, field, currentClass);
}
throw new InternalCompilerException("Unknown JVariable subclass.");
}
@@ -1758,7 +1848,8 @@
* Creates an appropriate JVariableRef for the polymorphic type of the
* requested JVariable.
*/
- private JVariableRef createVariableRef(JVariable variable, Binding binding) {
+ private JVariableRef createVariableRef(JSourceInfo info,
+ JVariable variable, Binding binding) {
// Fix up the reference if it's to an outer local/param
variable = possiblyReferenceOuterLocal(variable, binding);
if (variable == null) {
@@ -1770,14 +1861,15 @@
*/
return null;
}
- return createVariableRef(variable);
+ return createVariableRef(info, variable);
}
/**
* Get a new label of a particular name, or create a new one if it doesn't
* exist already.
*/
- private JLabel getOrCreateLabel(JMethod enclosingMethod, char[] name) {
+ private JLabel getOrCreateLabel(JSourceInfo info, JMethod enclosingMethod,
+ char[] name) {
if (name == null) {
return null;
}
@@ -1789,21 +1881,28 @@
}
JLabel jlabel = (JLabel) lblMap.get(sname);
if (jlabel == null) {
- jlabel = new JLabel(program, sname);
+ jlabel = new JLabel(program, info, sname);
lblMap.put(sname, jlabel);
}
return jlabel;
}
- private HasEnclosingType parseJsniRef(AbstractMethodDeclaration x,
- String ident) {
+ private JSourceInfo makeSourceInfo(Statement x) {
+ int startLine = ProblemHandler.searchLineNumber(
+ currentSeparatorPositions, x.sourceStart);
+ return new JSourceInfo(x.sourceStart, x.sourceEnd, startLine,
+ currentFileName);
+ }
+
+ private HasEnclosingType parseJsniRef(JSourceInfo info,
+ AbstractMethodDeclaration x, String ident) {
String[] parts = ident.substring(1).split("::");
assert (parts.length == 2);
String className = parts[0];
JReferenceType type = program.getFromTypeMap(className);
if (type == null) {
- reportJsniError(x, "Unresolvable native reference to type '"
- + className + "'", 0);
+ reportJsniError(info, x, "Unresolvable native reference to type '"
+ + className + "'");
return null;
}
String rhs = parts[1];
@@ -1817,8 +1916,8 @@
}
}
- reportJsniError(x, "Unresolvable native reference to field '" + rhs
- + "' in type '" + className + "'", 0);
+ reportJsniError(info, x, "Unresolvable native reference to field '"
+ + rhs + "' in type '" + className + "'");
} else {
// look for a method
String methodName = rhs.substring(0, parenPos);
@@ -1838,12 +1937,12 @@
}
if (almostMatches == null) {
- reportJsniError(x, "Unresolvable native reference to method '"
- + methodName + "' in type '" + className + "'", 0);
+ reportJsniError(info, x, "Unresolvable native reference to method '"
+ + methodName + "' in type '" + className + "'");
} else {
- reportJsniError(x, "Unresolvable native reference to method '"
+ reportJsniError(info, x, "Unresolvable native reference to method '"
+ methodName + "' in type '" + className + "' (did you mean "
- + almostMatches + "?)", 0);
+ + almostMatches + "?)");
}
}
return null;
@@ -1906,12 +2005,12 @@
* look for the specific operators that we think should match each JDT node,
* and throw an error if there's a mismatch.
*/
- private JExpression processBinaryOperation(JBinaryOperator op, JType type,
- Expression arg1, Expression arg2) {
+ private JExpression processBinaryOperation(JSourceInfo info,
+ JBinaryOperator op, JType type, Expression arg1, Expression arg2) {
JExpression exprArg1 = dispProcessExpression(arg1);
JExpression exprArg2 = dispProcessExpression(arg2);
- JBinaryOperation binaryOperation = new JBinaryOperation(program, type,
- op, exprArg1, exprArg2);
+ JBinaryOperation binaryOperation = new JBinaryOperation(program, info,
+ type, op, exprArg1, exprArg2);
return binaryOperation;
}
@@ -1920,14 +2019,14 @@
* overrides/implements.
*/
private void tryFindUpRefs(JMethod method, MethodBinding binding) {
- tryFindUpRefsRecurive(method, binding, binding.declaringClass);
+ tryFindUpRefsRecursive(method, binding, binding.declaringClass);
}
/**
* For a given method(and method binding), recursively try to find all
* methods that it overrides/implements.
*/
- private void tryFindUpRefsRecurive(JMethod method, MethodBinding binding,
+ private void tryFindUpRefsRecursive(JMethod method, MethodBinding binding,
ReferenceBinding searchThisType) {
// See if this class has any uprefs, unless this class is myself
@@ -1947,14 +2046,14 @@
// recurse super class
if (searchThisType.superclass() != null) {
- tryFindUpRefsRecurive(method, binding, searchThisType.superclass());
+ tryFindUpRefsRecursive(method, binding, searchThisType.superclass());
}
// recurse super interfaces
if (searchThisType.superInterfaces() != null) {
for (int i = 0; i < searchThisType.superInterfaces().length; i++) {
ReferenceBinding intf = searchThisType.superInterfaces()[i];
- tryFindUpRefsRecurive(method, binding, intf);
+ tryFindUpRefsRecursive(method, binding, intf);
}
}
}
@@ -1973,16 +2072,19 @@
Collections.sort(jprogram.getDeclaredTypes(), new HasNameSort());
}
- public static void reportJsniError(
- AbstractMethodDeclaration methodDeclaration, String message,
- int offsetFromStart) {
+ public static void reportJsniError(JSourceInfo info,
+ AbstractMethodDeclaration methodDeclaration, String message) {
CompilationResult compResult = methodDeclaration.compilationResult();
- ICompilationUnit compUnit = compResult.getCompilationUnit();
- offsetFromStart += methodDeclaration.bodyStart;
- DefaultProblem problem = new DefaultProblem(compUnit.getFileName(),
- message, IProblem.Unclassified, null, ProblemSeverities.Error,
- offsetFromStart, offsetFromStart, ProblemHandler.searchLineNumber(
- compResult.lineSeparatorPositions, offsetFromStart));
+ DefaultProblem problem = new DefaultProblem(
+ info.getFileName().toCharArray(), message, IProblem.Unclassified, null,
+ ProblemSeverities.Error, info.getStartPos(), info.getEndPos(),
+ info.getStartLine());
compResult.record(problem, methodDeclaration);
}
+
+ public static JSourceInfo translateInfo(JsSourceInfo info) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
index ce0738e..804a097 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/GenerateJavaScriptAST.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasEnclosingType;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
@@ -73,7 +74,6 @@
import com.google.gwt.dev.jjs.ast.JUnaryOperator;
import com.google.gwt.dev.jjs.ast.JVisitor;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
-import com.google.gwt.dev.jjs.ast.Mutator;
import com.google.gwt.dev.jjs.ast.js.JClassSeed;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniMethod;
@@ -149,12 +149,12 @@
private final Stack/* <JsScope> */scopeStack = new Stack();
// @Override
- public void endVisit(JClassType x) {
+ public void endVisit(JClassType x, Context ctx) {
pop();
}
// @Override
- public void endVisit(JField x) {
+ public void endVisit(JField x, Context ctx) {
String name = x.getName();
String mangleName = mangleName(x);
if (x.isStatic()) {
@@ -165,12 +165,12 @@
}
// @Override
- public void endVisit(JInterfaceType x) {
+ public void endVisit(JInterfaceType x, Context ctx) {
pop();
}
// @Override
- public void endVisit(JLabel x) {
+ public void endVisit(JLabel x, Context ctx) {
if (getName(x) != null) {
return;
}
@@ -178,7 +178,7 @@
}
// @Override
- public void endVisit(JLocal x) {
+ public void endVisit(JLocal x, Context ctx) {
// locals can conflict, that's okay just reuse the same variable
JsScope scope = peek();
JsName jsName = scope.getOrCreateObfuscatableName(x.getName());
@@ -186,17 +186,17 @@
}
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
pop();
}
// @Override
- public void endVisit(JParameter x) {
+ public void endVisit(JParameter x, Context ctx) {
names.put(x, peek().createUniqueObfuscatableName(x.getName()));
}
// @Override
- public void endVisit(JProgram x) {
+ public void endVisit(JProgram x, Context ctx) {
// visit special things that may have been culled
JField field = x.getSpecialField("Object.typeId");
names.put(field, objectScope.getOrCreateObfuscatableName(
@@ -230,12 +230,12 @@
}
// @Override
- public void endVisit(JsniMethod x) {
+ public void endVisit(JsniMethod x, Context ctx) {
// didn't push anything
}
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
// have I already been visited as a supertype?
JsScope myScope = (JsScope) classScopes.get(x);
if (myScope != null) {
@@ -254,7 +254,7 @@
JsScope parentScope = (JsScope) classScopes.get(x.extnds);
// Run my superclass first!
if (parentScope == null) {
- x.extnds.traverse(this);
+ accept(x.extnds);
}
parentScope = (JsScope) classScopes.get(x.extnds);
assert (parentScope != null);
@@ -276,14 +276,14 @@
}
// @Override
- public boolean visit(JInterfaceType x) {
+ public boolean visit(JInterfaceType x, Context ctx) {
// interfaces have no name at run time
push(interfaceScope);
return true;
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
// my polymorphic name
String name = x.getName();
@@ -321,7 +321,7 @@
}
// @Override
- public boolean visit(JsniMethod x) {
+ public boolean visit(JsniMethod x, Context ctx) {
// my polymorphic name
String name = x.getName();
if (!x.isStatic()) {
@@ -363,19 +363,19 @@
private final JsName globalTemp = rootScope.getOrCreateUnobfuscatableName("_");
+ private final Stack/* <JsNode> */nodeStack = new Stack/* <JsNode> */();
+
private final JsName prototype = objectScope.getOrCreateUnobfuscatableName("prototype");
private final JsName window = rootScope.getOrCreateUnobfuscatableName("window");
- private final Stack/* <JsNode> */nodeStack = new Stack/* <JsNode> */();
-
// @Override
- public void endVisit(JAbsentArrayDimension x, Mutator m) {
+ public void endVisit(JAbsentArrayDimension x, Context ctx) {
throw new InternalCompilerException("Should not get here.");
}
// @Override
- public void endVisit(JArrayRef x, Mutator m) {
+ public void endVisit(JArrayRef x, Context ctx) {
JsArrayAccess jsArrayAccess = new JsArrayAccess();
jsArrayAccess.setIndexExpr((JsExpression) pop());
jsArrayAccess.setArrayExpr((JsExpression) pop());
@@ -383,8 +383,8 @@
}
// @Override
- public void endVisit(JAssertStatement x) {
- // TODO: implement assert
+ public void endVisit(JAssertStatement x, Context ctx) {
+ // TODO(later): implement assert
if (x.getArg() != null) {
pop(); // arg
}
@@ -393,10 +393,10 @@
}
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
JsExpression rhs = (JsExpression) pop(); // rhs
JsExpression lhs = (JsExpression) pop(); // lhs
- JsBinaryOperator myOp = JavaToJsOperatorMap.get(x.op);
+ JsBinaryOperator myOp = JavaToJsOperatorMap.get(x.getOp());
/*
* Use === and !== on reference types, or else you can get wrong answers
@@ -416,7 +416,7 @@
}
// @Override
- public void endVisit(JBlock x) {
+ public void endVisit(JBlock x, Context ctx) {
JsBlock jsBlock = new JsBlock();
JsStatements stmts = jsBlock.getStatements();
popList(stmts, x.statements.size()); // stmts
@@ -431,14 +431,15 @@
}
// @Override
- public void endVisit(JBooleanLiteral x, Mutator m) {
- push(x.value ? jsProgram.getTrueLiteral() : jsProgram.getFalseLiteral());
+ public void endVisit(JBooleanLiteral x, Context ctx) {
+ push(x.getValue() ? jsProgram.getTrueLiteral()
+ : jsProgram.getFalseLiteral());
}
// @Override
- public void endVisit(JBreakStatement x) {
+ public void endVisit(JBreakStatement x, Context ctx) {
JsNameRef labelRef = null;
- if (x.label != null) {
+ if (x.getLabel() != null) {
JsLabel label = (JsLabel) pop(); // label
labelRef = label.getName().makeRef();
}
@@ -446,8 +447,8 @@
}
// @Override
- public void endVisit(JCaseStatement x) {
- if (x.getExpression() == null) {
+ public void endVisit(JCaseStatement x, Context ctx) {
+ if (x.getExpr() == null) {
push(new JsDefault());
} else {
JsCase jsCase = new JsCase();
@@ -457,31 +458,31 @@
}
// @Override
- public void endVisit(JCastOperation x, Mutator m) {
+ public void endVisit(JCastOperation x, Context ctx) {
throw new InternalCompilerException("Should not get here.");
}
// @Override
- public void endVisit(JCharLiteral x, Mutator m) {
- push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.value)));
+ public void endVisit(JCharLiteral x, Context ctx) {
+ push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.getValue())));
}
// @Override
- public void endVisit(JClassLiteral x, Mutator m) {
+ public void endVisit(JClassLiteral x, Context ctx) {
// My seed function name
- String nameString = x.refType.getJavahSignatureName() + "_classlit";
+ String nameString = x.getRefType().getJavahSignatureName() + "_classlit";
JsName classLit = rootScope.getOrCreateObfuscatableName(nameString);
- classLits.put(x.refType, classLit);
+ classLits.put(x.getRefType(), classLit);
push(classLit.makeRef());
}
// @Override
- public void endVisit(JClassSeed x, Mutator m) {
- push(getName(x.refType).makeRef());
+ public void endVisit(JClassSeed x, Context ctx) {
+ push(getName(x.getRefType()).makeRef());
}
// @Override
- public void endVisit(JClassType x) {
+ public void endVisit(JClassType x, Context ctx) {
if (alreadyRan.contains(x)) {
return;
}
@@ -612,7 +613,7 @@
}
// @Override
- public void endVisit(JConditional x, Mutator m) {
+ public void endVisit(JConditional x, Context ctx) {
JsExpression elseExpr = (JsExpression) pop(); // elseExpr
JsExpression thenExpr = (JsExpression) pop(); // thenExpr
JsExpression ifTest = (JsExpression) pop(); // ifTest
@@ -620,9 +621,9 @@
}
// @Override
- public void endVisit(JContinueStatement x) {
+ public void endVisit(JContinueStatement x, Context ctx) {
JsNameRef labelRef = null;
- if (x.label != null) {
+ if (x.getLabel() != null) {
JsLabel label = (JsLabel) pop(); // label
labelRef = label.getName().makeRef();
}
@@ -630,9 +631,9 @@
}
// @Override
- public void endVisit(JDoStatement x) {
+ public void endVisit(JDoStatement x, Context ctx) {
JsDoWhile stmt = new JsDoWhile();
- if (x.body != null) {
+ if (x.getBody() != null) {
stmt.setBody((JsStatement) pop()); // body
} else {
stmt.setBody(jsProgram.getEmptyStmt());
@@ -642,14 +643,14 @@
}
// @Override
- public void endVisit(JDoubleLiteral x, Mutator m) {
- push(jsProgram.getDecimalLiteral(String.valueOf(x.value)));
+ public void endVisit(JDoubleLiteral x, Context ctx) {
+ push(jsProgram.getDecimalLiteral(String.valueOf(x.getValue())));
}
// @Override
- public void endVisit(JExpressionStatement x) {
+ public void endVisit(JExpressionStatement x, Context ctx) {
JsExpression expr = (JsExpression) pop(); // expr
- if (x.getExpression().hasSideEffects()) {
+ if (x.getExpr().hasSideEffects()) {
push(expr.makeStmt());
} else {
push(jsProgram.getEmptyStmt());
@@ -657,7 +658,7 @@
}
// @Override
- public void endVisit(JField x) {
+ public void endVisit(JField x, Context ctx) {
if (x.hasInitializer() && x.constInitializer == null) {
// do nothing
push(null);
@@ -666,9 +667,9 @@
// if we need an initial value, create an assignment
if (x.constInitializer != null) {
- x.constInitializer.traverse(this);
+ accept(x.constInitializer);
} else {
- x.getType().getDefaultValue().traverse(this);
+ accept(x.getType().getDefaultValue());
}
JsNameRef fieldRef = getName(x).makeRef();
@@ -680,8 +681,8 @@
}
// @Override
- public void endVisit(JFieldRef x, Mutator m) {
- JsName jsFieldName = getName(x.field);
+ public void endVisit(JFieldRef x, Context ctx) {
+ JsName jsFieldName = getName(x.getField());
JsNameRef nameRef = jsFieldName.makeRef();
JsExpression qualifier = null;
@@ -700,16 +701,16 @@
}
// @Override
- public void endVisit(JFloatLiteral x, Mutator m) {
- push(jsProgram.getDecimalLiteral(String.valueOf(x.value)));
+ public void endVisit(JFloatLiteral x, Context ctx) {
+ push(jsProgram.getDecimalLiteral(String.valueOf(x.getValue())));
}
// @Override
- public void endVisit(JForStatement x) {
+ public void endVisit(JForStatement x, Context ctx) {
JsFor jsFor = new JsFor();
// body
- if (x.body != null) {
+ if (x.getBody() != null) {
jsFor.setBody((JsStatement) pop());
} else {
jsFor.setBody(jsProgram.getEmptyStmt());
@@ -746,14 +747,14 @@
}
// @Override
- public void endVisit(JIfStatement x) {
+ public void endVisit(JIfStatement x, Context ctx) {
JsIf stmt = new JsIf();
- if (x.elseStmt != null) {
+ if (x.getElseStmt() != null) {
stmt.setElseStmt((JsStatement) pop()); // elseStmt
}
- if (x.thenStmt != null) {
+ if (x.getThenStmt() != null) {
stmt.setThenStmt((JsStatement) pop()); // thenStmt
} else {
stmt.setThenStmt(jsProgram.getEmptyStmt());
@@ -764,12 +765,12 @@
}
// @Override
- public void endVisit(JInstanceOf x, Mutator m) {
+ public void endVisit(JInstanceOf x, Context ctx) {
throw new InternalCompilerException("Should not get here.");
}
// @Override
- public void endVisit(JInterfaceType x) {
+ public void endVisit(JInterfaceType x, Context ctx) {
List/* <JsFunction> */jsFuncs = popList(x.methods.size()); // methods
List/* <JsStatement> */jsFields = popList(x.fields.size()); // fields
@@ -789,17 +790,17 @@
}
// @Override
- public void endVisit(JIntLiteral x, Mutator m) {
- push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.value)));
+ public void endVisit(JIntLiteral x, Context ctx) {
+ push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.getValue())));
}
// @Override
- public void endVisit(JLabel x) {
+ public void endVisit(JLabel x, Context ctx) {
push(new JsLabel(getName(x)));
}
// @Override
- public void endVisit(JLabeledStatement x) {
+ public void endVisit(JLabeledStatement x, Context ctx) {
JsStatement body = (JsStatement) pop(); // body
JsLabel label = (JsLabel) pop(); // label
label.setStmt(body);
@@ -807,12 +808,12 @@
}
// @Override
- public void endVisit(JLocal x) {
+ public void endVisit(JLocal x, Context ctx) {
push(getName(x).makeRef());
}
// @Override
- public void endVisit(JLocalDeclarationStatement x) {
+ public void endVisit(JLocalDeclarationStatement x, Context ctx) {
if (x.getInitializer() == null) {
pop(); // localRef
@@ -834,17 +835,17 @@
}
// @Override
- public void endVisit(JLocalRef x, Mutator m) {
+ public void endVisit(JLocalRef x, Context ctx) {
push(getName(x.getTarget()).makeRef());
}
// @Override
- public void endVisit(JLongLiteral x, Mutator m) {
- push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.value)));
+ public void endVisit(JLongLiteral x, Context ctx) {
+ push(jsProgram.getIntegralLiteral(BigInteger.valueOf(x.getValue())));
}
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
JsBlock body = (JsBlock) pop();
List/* <JsNameRef> */locals = popList(x.locals.size()); // locals
@@ -864,10 +865,28 @@
jsParams.add(param);
}
+ /*
+ * Emit a statement to declare the method's complete set of local
+ * variables. JavaScript doesn't have the same concept of lexical scoping
+ * as Java, so it's okay to just predeclare all local vars at the top of
+ * the function, which saves us having to use the "var" keyword over and
+ * over.
+ *
+ * Note: it's fine to use the same JS ident to represent two different
+ * Java locals of the same name since they could never conflict with each
+ * other in Java. We use the alreadySeen set to make sure we don't declare
+ * the same-named local var twice.
+ */
JsVars vars = new JsVars();
+ Set alreadySeen = new HashSet();
for (int i = 0; i < locals.size(); ++i) {
JsNameRef localRef = (JsNameRef) locals.get(i);
- vars.add(new JsVar(localRef.getName()));
+ JsName name = localRef.getName();
+ String ident = name.getIdent();
+ if (!alreadySeen.contains(ident)) {
+ alreadySeen.add(ident);
+ vars.add(new JsVar(name));
+ }
}
if (vars.iterator().hasNext()) {
@@ -884,11 +903,11 @@
}
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
JsInvocation jsInvocation = new JsInvocation();
- popList(jsInvocation.getArguments(), x.args.size()); // args
+ popList(jsInvocation.getArguments(), x.getArgs().size()); // args
JsNameRef qualifier;
JsExpression unnecessaryQualifier = null;
@@ -922,7 +941,7 @@
}
// @Override
- public void endVisit(JMultiExpression x, Mutator m) {
+ public void endVisit(JMultiExpression x, Context ctx) {
List/* <JsExpression> */exprs = popList(x.exprs.size());
JsExpression cur = null;
for (int i = 0; i < exprs.size(); ++i) {
@@ -933,12 +952,12 @@
}
// @Override
- public void endVisit(JNewArray x, Mutator m) {
+ public void endVisit(JNewArray x, Context ctx) {
throw new InternalCompilerException("Should not get here.");
}
// @Override
- public void endVisit(JNewInstance x, Mutator m) {
+ public void endVisit(JNewInstance x, Context ctx) {
JsNew newOp = new JsNew();
JsNameRef nameRef = getName(x.getType()).makeRef();
newOp.setConstructorExpression(nameRef);
@@ -946,34 +965,34 @@
}
// @Override
- public void endVisit(JNullLiteral x, Mutator m) {
+ public void endVisit(JNullLiteral x, Context ctx) {
push(jsProgram.getNullLiteral());
}
// @Override
- public void endVisit(JParameter x) {
+ public void endVisit(JParameter x, Context ctx) {
push(new JsParameter(getName(x)));
}
// @Override
- public void endVisit(JParameterRef x, Mutator m) {
+ public void endVisit(JParameterRef x, Context ctx) {
push(getName(x.getTarget()).makeRef());
}
// @Override
- public void endVisit(JPostfixOperation x, Mutator m) {
- push(new JsPostfixOperation(JavaToJsOperatorMap.get(x.op),
+ public void endVisit(JPostfixOperation x, Context ctx) {
+ push(new JsPostfixOperation(JavaToJsOperatorMap.get(x.getOp()),
(JsExpression) pop())); // arg
}
// @Override
- public void endVisit(JPrefixOperation x, Mutator m) {
- push(new JsPrefixOperation(JavaToJsOperatorMap.get(x.op),
+ public void endVisit(JPrefixOperation x, Context ctx) {
+ push(new JsPrefixOperation(JavaToJsOperatorMap.get(x.getOp()),
(JsExpression) pop())); // arg
}
// @Override
- public void endVisit(JProgram x) {
+ public void endVisit(JProgram x, Context ctx) {
JsStatements globalStmts = jsProgram.getGlobalBlock().getStatements();
// types don't push
@@ -1043,7 +1062,7 @@
JsArrayLiteral arrayLit = new JsArrayLiteral();
for (int i = 0; i < program.getJsonTypeTable().size(); ++i) {
JsonObject jsonObject = (JsonObject) program.getJsonTypeTable().get(i);
- jsonObject.traverse(this);
+ accept(jsonObject);
arrayLit.getExpressions().add((JsExpression) pop());
}
JsExpression asg = createAssignment(fieldRef, arrayLit);
@@ -1071,8 +1090,8 @@
}
// @Override
- public void endVisit(JReturnStatement x) {
- if (x.getExpression() != null) {
+ public void endVisit(JReturnStatement x, Context ctx) {
+ if (x.getExpr() != null) {
push(new JsReturn((JsExpression) pop())); // expr
} else {
push(new JsReturn());
@@ -1080,7 +1099,7 @@
}
// @Override
- public void endVisit(JsniMethod x) {
+ public void endVisit(JsniMethod x, Context ctx) {
JsFunction jsFunc = x.getFunc();
// replace all jsni idents with a real JsName now that we know it
@@ -1131,51 +1150,54 @@
}
// @Override
- public void endVisit(JsonArray x, Mutator m) {
+ public void endVisit(JsonArray x, Context ctx) {
JsArrayLiteral jsArrayLiteral = new JsArrayLiteral();
popList(jsArrayLiteral.getExpressions(), x.exprs.size());
push(jsArrayLiteral);
}
// @Override
- public void endVisit(JsonObject x, Mutator mutator) {
+ public void endVisit(JsonObject x, Context ctx) {
JsObjectLiteral jsObjectLiteral = new JsObjectLiteral();
popList(jsObjectLiteral.getPropertyInitializers(), x.propInits.size());
push(jsObjectLiteral);
}
// @Override
- public void endVisit(JsonPropInit init) {
+ public void endVisit(JsonPropInit init, Context ctx) {
JsExpression valueExpr = (JsExpression) pop();
JsExpression labelExpr = (JsExpression) pop();
push(new JsPropertyInitializer(labelExpr, valueExpr));
}
// @Override
- public void endVisit(JStringLiteral x, Mutator m) {
- push(jsProgram.getStringLiteral(x.value));
+ public void endVisit(JStringLiteral x, Context ctx) {
+ push(jsProgram.getStringLiteral(x.getValue()));
}
// @Override
- public void endVisit(JThisRef x, Mutator m) {
+ public void endVisit(JThisRef x, Context ctx) {
push(new JsThisRef());
}
// @Override
- public void endVisit(JThrowStatement x) {
+ public void endVisit(JThrowStatement x, Context ctx) {
push(new JsThrow((JsExpression) pop())); // expr
}
// @Override
- public void endVisit(JTryStatement x) {
+ public void endVisit(JTryStatement x, Context ctx) {
JsTry jsTry = new JsTry();
- if (x.finallyBlock != null) {
- jsTry.setFinallyBlock((JsBlock) pop()); // finallyBlock
+ if (x.getFinallyBlock() != null) {
+ JsBlock finallyBlock = (JsBlock) pop(); // finallyBlock
+ if (finallyBlock.getStatements().size() > 0) {
+ jsTry.setFinallyBlock(finallyBlock);
+ }
}
- int size = x.catchArgs.size();
- assert (size < 2 && size == x.catchBlocks.size());
+ int size = x.getCatchArgs().size();
+ assert (size < 2 && size == x.getCatchBlocks().size());
if (size == 1) {
JsBlock catchBlock = (JsBlock) pop(); // catchBlocks
JsNameRef arg = (JsNameRef) pop(); // catchArgs
@@ -1190,9 +1212,9 @@
}
// @Override
- public void endVisit(JWhileStatement x) {
+ public void endVisit(JWhileStatement x, Context ctx) {
JsWhile stmt = new JsWhile();
- if (x.body != null) {
+ if (x.getBody() != null) {
stmt.setBody((JsStatement) pop()); // body
} else {
stmt.setBody(jsProgram.getEmptyStmt());
@@ -1202,7 +1224,7 @@
}
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
if (alreadyRan.contains(x)) {
return false;
}
@@ -1210,20 +1232,20 @@
// force supertype to generate code first, this is required for prototype
// chaining to work properly
if (x.extnds != null && !alreadyRan.contains(x)) {
- x.extnds.traverse(this);
+ accept(x.extnds);
}
return true;
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
return true;
}
// @Override
- public boolean visit(JProgram x) {
+ public boolean visit(JProgram x, Context ctx) {
// handle null method
// return 'window' so that fields can be referenced
JsReturn jsReturn = new JsReturn(window.makeRef());
@@ -1236,26 +1258,26 @@
}
// @Override
- public boolean visit(JsniMethod x) {
+ public boolean visit(JsniMethod x, Context ctx) {
currentMethod = x;
return false;
}
- public boolean visit(JSwitchStatement x) {
+ public boolean visit(JSwitchStatement x, Context ctx) {
/*
* What a pain.. JSwitchStatement and JsSwitch are modelled completely
* differently. Here we try to resolve those differences.
*/
JsSwitch jsSwitch = new JsSwitch();
- x.getExpression().traverse(this);
+ accept(x.getExpr());
jsSwitch.setExpr((JsExpression) pop()); // expr
- List/* <JStatement> */bodyStmts = x.body.statements;
+ List/* <JStatement> */bodyStmts = x.getBody().statements;
if (bodyStmts.size() > 0) {
JsStatements curStatements = null;
for (int i = 0; i < bodyStmts.size(); ++i) {
JStatement stmt = (JStatement) bodyStmts.get(i);
- stmt.traverse(this);
+ accept(stmt);
if (stmt instanceof JCaseStatement) {
// create a new switch member
JsSwitchMember switchMember = (JsSwitchMember) pop(); // stmt
@@ -1450,19 +1472,19 @@
private final JsScope interfaceScope;
- private JsName nullMethodName;
-
- private final JsScope objectScope;
-
- private final JsScope rootScope;
-
private final JsProgram jsProgram;
private final Map/* <JMethod, JsFunction> */methodMap = new IdentityHashMap();
private final Map/* <HasName, JsName> */names = new IdentityHashMap();
+
+ private JsName nullMethodName;
+
+ private final JsScope objectScope;
+
private final Map/* <JMethod, JsName> */polymorphicNames = new IdentityHashMap();
private final JProgram program;
+ private final JsScope rootScope;
private final JTypeOracle typeOracle;
private GenerateJavaScriptAST(JProgram program, JsProgram jsProgram) {
@@ -1507,9 +1529,9 @@
private void execImpl() {
CreateNamesAndScopesVisitor creator = new CreateNamesAndScopesVisitor();
- program.traverse(creator);
+ creator.accept(program);
GenerateJavaScriptVisitor generator = new GenerateJavaScriptVisitor();
- program.traverse(generator);
+ generator.accept(program);
}
private JsName getName(HasName x) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java b/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java
index c93e1f5..29d3f35 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/InternalCompilerException.java
@@ -15,6 +15,10 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.JNode;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+
/**
* Indicates the compiler encountered an unexpected and unsupported state of
* operation.
@@ -28,4 +32,13 @@
public InternalCompilerException(String message, Throwable cause) {
super(message, cause);
}
+
+ public void addNode(ASTNode node) {
+ // TODO Auto-generated method stub
+ }
+
+ public void addNode(JNode node) {
+ // TODO Auto-generated method stub
+ }
+
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java
index ad86e58..927e3b1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaPrecedenceVisitor.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -41,7 +42,6 @@
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
/**
* See the Java Programming Language, 4th Edition, p. 750, Table 2. I just
@@ -54,7 +54,7 @@
public static int exec(JExpression expression) {
JavaPrecedenceVisitor visitor = new JavaPrecedenceVisitor();
- expression.traverse(visitor);
+ visitor.accept(expression);
if (visitor.answer < 0) {
throw new InternalCompilerException("Precedence must be >= 0!");
}
@@ -67,145 +67,145 @@
}
// @Override
- public boolean visit(JAbsentArrayDimension x, Mutator m) {
+ public boolean visit(JAbsentArrayDimension x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JArrayRef x, Mutator m) {
+ public boolean visit(JArrayRef x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JBinaryOperation operation, Mutator mutator) {
- answer = operation.op.getPrecedence();
+ public boolean visit(JBinaryOperation operation, Context ctx) {
+ answer = operation.getOp().getPrecedence();
return false;
}
// @Override
- public boolean visit(JBooleanLiteral x, Mutator m) {
+ public boolean visit(JBooleanLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JCastOperation operation, Mutator mutator) {
+ public boolean visit(JCastOperation operation, Context ctx) {
answer = 2;
return false;
}
// @Override
- public boolean visit(JCharLiteral x, Mutator m) {
+ public boolean visit(JCharLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JClassLiteral x, Mutator m) {
+ public boolean visit(JClassLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JConditional conditional, Mutator mutator) {
+ public boolean visit(JConditional conditional, Context ctx) {
answer = 13;
return false;
}
// @Override
- public boolean visit(JDoubleLiteral x, Mutator m) {
+ public boolean visit(JDoubleLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JFieldRef x, Mutator m) {
+ public boolean visit(JFieldRef x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JFloatLiteral x, Mutator m) {
+ public boolean visit(JFloatLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JInstanceOf of, Mutator mutator) {
+ public boolean visit(JInstanceOf of, Context ctx) {
answer = 6;
return false;
}
// @Override
- public boolean visit(JIntLiteral x, Mutator m) {
+ public boolean visit(JIntLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JLocalRef x, Mutator m) {
+ public boolean visit(JLocalRef x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JLongLiteral x, Mutator m) {
+ public boolean visit(JLongLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JMethodCall x, Mutator m) {
+ public boolean visit(JMethodCall x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JNewArray array, Mutator mutator) {
+ public boolean visit(JNewArray array, Context ctx) {
answer = 2;
return false;
}
// @Override
- public boolean visit(JNewInstance instance, Mutator mutator) {
+ public boolean visit(JNewInstance instance, Context ctx) {
answer = 2;
return false;
}
// @Override
- public boolean visit(JNullLiteral x, Mutator m) {
+ public boolean visit(JNullLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JParameterRef x, Mutator m) {
+ public boolean visit(JParameterRef x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JPostfixOperation operation, Mutator mutator) {
+ public boolean visit(JPostfixOperation operation, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JPrefixOperation operation, Mutator mutator) {
+ public boolean visit(JPrefixOperation operation, Context ctx) {
answer = 1;
return false;
}
// @Override
- public boolean visit(JStringLiteral x, Mutator m) {
+ public boolean visit(JStringLiteral x, Context ctx) {
answer = 0;
return false;
}
// @Override
- public boolean visit(JThisRef x, Mutator m) {
+ public boolean visit(JThisRef x, Context ctx) {
answer = 0;
return false;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java
index f34e52c..dd43d91 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/JavaScriptObjectCaster.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
import com.google.gwt.dev.jjs.ast.JCastOperation;
import com.google.gwt.dev.jjs.ast.JConditional;
@@ -22,102 +23,124 @@
import com.google.gwt.dev.jjs.ast.JLocalDeclarationStatement;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
/**
* Replace cast and instanceof operations with calls to the Cast class.
*/
public class JavaScriptObjectCaster {
- private class AssignmentVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Synthesize casts from JavaScriptObjects to trigger wrapping.");
+ /**
+ * Synthesize casts from JavaScriptObjects to trigger wrapping.
+ */
+ private class AssignmentVisitor extends JModVisitor {
private JMethod currentMethod;
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
if (x.isAssignment()) {
- checkAndReplaceJso(x.rhs, x.getLhs().getType());
+ JType lhsType = x.getLhs().getType();
+ JExpression newRhs = checkAndReplaceJso(x.getRhs(), lhsType);
+ if (newRhs != x.getRhs()) {
+ JBinaryOperation asg = new JBinaryOperation(program,
+ x.getSourceInfo(), lhsType, x.getOp(), x.getLhs(), newRhs);
+ ctx.replaceMe(asg);
+ }
}
}
// @Override
- public void endVisit(JConditional x, Mutator m) {
- checkAndReplaceJso(x.thenExpr, x.getType());
- checkAndReplaceJso(x.elseExpr, x.getType());
- }
-
- // @Override
- public void endVisit(JLocalDeclarationStatement x) {
- JExpression initializer = x.getInitializer();
- if (initializer != null) {
- checkAndReplaceJso(x.initializer, x.getLocalRef().getType());
+ public void endVisit(JConditional x, Context ctx) {
+ JExpression newThen = checkAndReplaceJso(x.getThenExpr(), x.getType());
+ JExpression newElse = checkAndReplaceJso(x.getElseExpr(), x.getType());
+ if (newThen != x.getThenExpr() || newElse != x.getElseExpr()) {
+ JConditional newCond = new JConditional(program, x.getSourceInfo(),
+ x.getType(), x.getIfTest(), newThen, newElse);
+ ctx.replaceMe(newCond);
}
}
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JLocalDeclarationStatement x, Context ctx) {
+ JExpression newInst = x.getInitializer();
+ if (newInst != null) {
+ newInst = checkAndReplaceJso(newInst, x.getLocalRef().getType());
+ if (newInst != x.getInitializer()) {
+ JLocalDeclarationStatement newStmt = new JLocalDeclarationStatement(
+ program, x.getSourceInfo(), x.getLocalRef(), newInst);
+ ctx.replaceMe(newStmt);
+ }
+ }
+ }
+
+ // @Override
+ public void endVisit(JMethod x, Context ctx) {
currentMethod = null;
}
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
- if (!x.getTarget().isStatic()) {
- // for polymorphic calls, force wrapping
- checkAndReplaceJso(x.instance, program.getTypeJavaLangObject());
- }
+ public void endVisit(JMethodCall x, Context ctx) {
for (int i = 0; i < x.getTarget().params.size(); ++i) {
JParameter param = (JParameter) x.getTarget().params.get(i);
- checkAndReplaceJso(x.args.getMutator(i), param.getType());
+ JExpression newArg = checkAndReplaceJso(
+ (JExpression) x.getArgs().get(i), param.getType());
+ x.getArgs().set(i, newArg);
+ }
+ if (!x.getTarget().isStatic()) {
+ // for polymorphic calls, force wrapping
+ JExpression newInst = checkAndReplaceJso(x.getInstance(),
+ program.getTypeJavaLangObject());
+ if (newInst != x.getInstance()) {
+ JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
+ newInst, x.getTarget(), x.isStaticDispatchOnly());
+ newCall.getArgs().addAll(x.getArgs());
+ ctx.replaceMe(newCall);
+ }
}
}
// @Override
- public void endVisit(JReturnStatement x) {
- if (x.getExpression() != null) {
- checkAndReplaceJso(x.expr, currentMethod.getType());
+ public void endVisit(JReturnStatement x, Context ctx) {
+ if (x.getExpr() != null) {
+ JExpression newExpr = checkAndReplaceJso(x.getExpr(),
+ currentMethod.getType());
+ if (newExpr != x.getExpr()) {
+ JReturnStatement newStmt = new JReturnStatement(program,
+ x.getSourceInfo(), newExpr);
+ ctx.replaceMe(newStmt);
+ }
}
}
- public ChangeList getChangeList() {
- return changeList;
- }
-
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
return true;
}
- private void checkAndReplaceJso(Mutator arg, JType targetType) {
- JType argType = arg.get().getType();
+ private JExpression checkAndReplaceJso(JExpression arg, JType targetType) {
+ JType argType = arg.getType();
if (argType == targetType) {
- return;
+ return arg;
}
if (!(targetType instanceof JReferenceType)) {
- return;
+ return arg;
}
if (!program.isJavaScriptObject(argType)) {
- return;
+ return arg;
}
- JCastOperation cast = new JCastOperation(program, targetType,
- program.getLiteralNull());
- ChangeList myChangeList = new ChangeList("Synthesize a cast from '"
- + argType + "' to '" + targetType + "'.");
- myChangeList.replaceExpression(cast.expr, arg);
- myChangeList.replaceExpression(arg, cast);
- changeList.add(myChangeList);
+ // Synthesize a cast to the target type
+ JCastOperation cast = new JCastOperation(program, arg.getSourceInfo(),
+ targetType, arg);
+ return cast;
}
}
@@ -132,14 +155,8 @@
}
private void execImpl() {
- {
- AssignmentVisitor visitor = new AssignmentVisitor();
- program.traverse(visitor);
- ChangeList changes = visitor.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
- }
+ AssignmentVisitor visitor = new AssignmentVisitor();
+ visitor.accept(program);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
index 40c8071..477387a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MakeCallsStatic.java
@@ -15,12 +15,14 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
import com.google.gwt.dev.jjs.ast.JLocal;
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JProgram;
@@ -29,11 +31,12 @@
import com.google.gwt.dev.jjs.ast.JThisRef;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
+import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
+import java.util.Set;
/**
* This is an interesting "optimization". It's not really an optimization in and
@@ -47,116 +50,132 @@
* reduces use of the long "this" keyword in the resulting JavaScript, and in
* most cases the polymorphic version can be pruned later.
*
- * TODO: make this work on JSNI methods!
+ * TODO(later): make this work on JSNI methods!
*/
public class MakeCallsStatic {
/**
- * For any instance methods that are called in a non-polymorphic manner, move
- * the contents of the method to a static method, and have the instance method
- * delegate to it. Sometimes the instance method can be pruned later since we
- * update all non-polymorphic call sites.
+ * For all methods that should be made static, move the contents of the method
+ * to a new static method, and have the original (instance) method delegate to
+ * it. Sometimes the instance method can be pruned later since we update all
+ * non-polymorphic call sites.
*/
- private class CreateStaticMethodVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Create static impls for instance methods");
+ private class CreateStaticImplsVisitor extends JModVisitor {
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
- JMethod oldMethod = x.getTarget();
+ public boolean visit(JMethod x, Context ctx) {
+ if (!toBeMadeStatic.contains(x)) {
+ return false;
+ }
+
+ // Let's do it!
+ JClassType enclosingType = (JClassType) x.getEnclosingType();
+ JType oldReturnType = x.getType();
+
+ // Create the new static method
+ String newName = "$" + x.getName();
+
+ /*
+ * Don't use the JProgram helper because it auto-adds the new method to
+ * its enclosing class, which will break iteration.
+ */
+ JMethod newMethod = new JMethod(program, x.getSourceInfo(), newName,
+ enclosingType, oldReturnType, false, true, true, x.isPrivate());
+
+ // Setup all params and locals; map from the old method to the new method
+ JParameter thisParam = program.createParameter(null,
+ "this$static".toCharArray(), enclosingType, true, newMethod);
+ Map/* <JVariable, JVariable> */varMap = new IdentityHashMap();
+ for (int i = 0; i < x.params.size(); ++i) {
+ JParameter oldVar = (JParameter) x.params.get(i);
+ JParameter newVar = program.createParameter(oldVar.getSourceInfo(),
+ oldVar.getName().toCharArray(), oldVar.getType(), oldVar.isFinal(),
+ newMethod);
+ varMap.put(oldVar, newVar);
+ }
+ newMethod.freezeParamTypes();
+
+ // Copy all locals over to the new method
+ for (int i = 0; i < x.locals.size(); ++i) {
+ JLocal oldVar = (JLocal) x.locals.get(i);
+ JLocal newVar = program.createLocal(oldVar.getSourceInfo(),
+ oldVar.getName().toCharArray(), oldVar.getType(), oldVar.isFinal(),
+ newMethod);
+ varMap.put(oldVar, newVar);
+ }
+ x.locals.clear();
+
+ // Move the body of the instance method to the static method
+ newMethod.body.statements.addAll(x.body.statements);
+ x.body.statements.clear();
+
+ /*
+ * Rewrite the method body. Update all thisRefs to paramrefs. Update
+ * paramRefs and localRefs to target the params/locals in the new method.
+ */
+ RewriteMethodBody rewriter = new RewriteMethodBody(thisParam, varMap);
+ rewriter.accept(newMethod);
+
+ JSourceInfo bodyInfo = x.body.getSourceInfo();
+ // delegate from the instance method to the static method
+ JMethodCall newCall = new JMethodCall(program, bodyInfo, null, newMethod);
+ newCall.getArgs().add(program.getExprThisRef(bodyInfo, enclosingType));
+ for (int i = 0; i < x.params.size(); ++i) {
+ JParameter param = (JParameter) x.params.get(i);
+ newCall.getArgs().add(new JParameterRef(program, bodyInfo, param));
+ }
+ JStatement statement;
+ if (oldReturnType == program.getTypeVoid()) {
+ statement = new JExpressionStatement(program, bodyInfo, newCall);
+ } else {
+ statement = new JReturnStatement(program, bodyInfo, newCall);
+ }
+ x.body.statements.add(statement);
+
+ // Add the new method as a static impl of the old method
+ program.putStaticImpl(x, newMethod);
+ assert (ctx.canInsert());
+ ctx.insertAfter(newMethod);
+ return false;
+ }
+ }
+
+ /**
+ * Look for any places where instance methods are called in a static manner.
+ * Record this fact so we can create static dispatch implementations.
+ */
+ private class FindStaticDispatchSitesVisitor extends JVisitor {
+
+ // @Override
+ public void endVisit(JMethodCall x, Context ctx) {
+ JMethod method = x.getTarget();
+
+ // Did we already do this one?
+ if (program.getStaticImpl(method) != null
+ || toBeMadeStatic.contains(method)) {
+ return;
+ }
// Must be instance and final
if (x.canBePolymorphic()) {
return;
}
- if (oldMethod.isStatic()) {
+ if (method.isStatic()) {
return;
}
- if (oldMethod.isAbstract()) {
+ if (method.isAbstract()) {
return;
}
- if (oldMethod.isNative()) {
+ if (method.isNative()) {
return;
}
- if (oldMethod == program.getNullMethod()) {
+ if (method == program.getNullMethod()) {
// Special case: we don't make calls to this method static.
return;
}
- // Did we already do this one?
- if (program.getStaticImpl(oldMethod) != null) {
- return;
- }
-
- JClassType enclosingType = (JClassType) oldMethod.getEnclosingType();
- JType oldReturnType = oldMethod.getType();
-
- // Create the new static method
- String newName = "$" + oldMethod.getName();
-
- /*
- * Don't use thie JProgram helper because it auto-adds the new method to
- * its enclosing class, which will break iteration.
- */
- JMethod newMethod = new JMethod(program, newName, enclosingType,
- oldReturnType, false, true, true, oldMethod.isPrivate());
-
- // Setup all params and locals; map from the old method to the new method
- JParameter thisParam = program.createParameter(
- "this$static".toCharArray(), enclosingType, true, newMethod);
- Map/* <JVariable, JVariable> */varMap = new IdentityHashMap();
- for (int i = 0; i < oldMethod.params.size(); ++i) {
- JParameter oldVar = (JParameter) oldMethod.params.get(i);
- JParameter newVar = program.createParameter(
- oldVar.getName().toCharArray(), oldVar.getType(), oldVar.isFinal(),
- newMethod);
- varMap.put(oldVar, newVar);
- }
-
- newMethod.freezeParamTypes();
- for (int i = 0; i < oldMethod.locals.size(); ++i) {
- JLocal oldVar = (JLocal) oldMethod.locals.get(i);
- JLocal newVar = program.createLocal(oldVar.getName().toCharArray(),
- oldVar.getType(), oldVar.isFinal(), newMethod);
- varMap.put(oldVar, newVar);
- }
- ChangeList myChangeList = new ChangeList("Create a new static method '"
- + newMethod + "' for instance method '" + oldMethod + "'");
- myChangeList.addMethod(newMethod);
- program.putStaticImpl(oldMethod, newMethod);
-
- // rewrite the method body to update all thisRefs to instance refs
- ChangeList subChangeList = new ChangeList(
- "Update thisrefs as paramrefs; update paramrefs and localrefs to target this method.");
- RewriteMethodBody rewriter = new RewriteMethodBody(thisParam, varMap,
- subChangeList);
- oldMethod.traverse(rewriter);
- myChangeList.add(subChangeList);
-
- // Move the body of the instance method to the static method
- myChangeList.clear(oldMethod.locals);
- myChangeList.moveBody(oldMethod, newMethod);
-
- // delegate from the instance method to the static method
- JMethodCall newCall = new JMethodCall(program, null, newMethod);
- newCall.args.add(program.getExpressionThisRef(enclosingType));
- for (int i = 0; i < oldMethod.params.size(); ++i) {
- JParameter param = (JParameter) oldMethod.params.get(i);
- newCall.args.add(new JParameterRef(program, param));
- }
- JStatement statement;
- if (oldReturnType == program.getTypeVoid()) {
- statement = new JExpressionStatement(program, newCall);
- } else {
- statement = new JReturnStatement(program, newCall);
- }
- myChangeList.addStatement(statement, oldMethod.body);
- changeList.add(myChangeList);
- }
-
- public ChangeList getChangeList() {
- return changeList;
+ // Let's do it!
+ toBeMadeStatic.add(method);
}
}
@@ -165,10 +184,7 @@
* CreateStaticMethodVisitor, go and rewrite the call sites to call the static
* method instead.
*/
- private class RewriteCallSites extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Rewrite calls to final instance methods as calls to static impl methods.");
+ private class RewriteCallSites extends JModVisitor {
/*
* In cases where callers are directly referencing (effectively) final
@@ -176,33 +192,24 @@
* static method instead.
*/
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JMethodCall x, Context ctx) {
JMethod oldMethod = x.getTarget();
JMethod newMethod = program.getStaticImpl(oldMethod);
if (newMethod == null || x.canBePolymorphic()) {
return;
}
- ChangeList changes = new ChangeList("Replace '" + x
- + "' with a static call");
-
// Update the call site
- JMethodCall newCall = new JMethodCall(program, null, newMethod);
- changes.replaceExpression(m, newCall);
+ JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(), null,
+ newMethod);
// The qualifier becomes the first arg
- changes.addExpression(x.instance, newCall.args);
+ newCall.getArgs().add(x.getInstance());
// Copy the rest of the args
- for (int i = 0; i < x.args.size(); ++i) {
- Mutator arg = x.args.getMutator(i);
- changes.addExpression(arg, newCall.args);
+ for (int i = 0; i < x.getArgs().size(); ++i) {
+ newCall.getArgs().add(x.getArgs().get(i));
}
-
- changeList.add(changes);
- }
-
- public ChangeList getChangeList() {
- return changeList;
+ ctx.replaceMe(newCall);
}
}
@@ -210,37 +217,37 @@
* When code is moved from an instance method to a static method, all this
* refs must be replaced with param refs to the synthetic this param.
*/
- private class RewriteMethodBody extends JVisitor {
+ private class RewriteMethodBody extends JModVisitor {
- private final ChangeList changeList;
private final JParameter thisParam;
private final Map/* <JVariable, JVariable> */varMap;
public RewriteMethodBody(JParameter thisParam,
- Map/* <JVariable, JVariable> */varMap, ChangeList changeList) {
- this.changeList = changeList;
+ Map/* <JVariable, JVariable> */varMap) {
this.thisParam = thisParam;
this.varMap = varMap;
}
// @Override
- public void endVisit(JLocalRef x, Mutator m) {
+ public void endVisit(JLocalRef x, Context ctx) {
JLocal local = (JLocal) varMap.get(x.getTarget());
- JLocalRef localRef = new JLocalRef(program, local);
- changeList.replaceExpression(m, localRef);
+ JLocalRef localRef = new JLocalRef(program, x.getSourceInfo(), local);
+ ctx.replaceMe(localRef);
}
// @Override
- public void endVisit(JParameterRef x, Mutator m) {
+ public void endVisit(JParameterRef x, Context ctx) {
JParameter param = (JParameter) varMap.get(x.getTarget());
- JParameterRef paramRef = new JParameterRef(program, param);
- changeList.replaceExpression(m, paramRef);
+ JParameterRef paramRef = new JParameterRef(program, x.getSourceInfo(),
+ param);
+ ctx.replaceMe(paramRef);
}
// @Override
- public void endVisit(JThisRef x, Mutator m) {
- JParameterRef paramRef = new JParameterRef(program, thisParam);
- changeList.replaceExpression(m, paramRef);
+ public void endVisit(JThisRef x, Context ctx) {
+ JParameterRef paramRef = new JParameterRef(program, x.getSourceInfo(),
+ thisParam);
+ ctx.replaceMe(paramRef);
}
}
@@ -248,6 +255,8 @@
return new MakeCallsStatic(program).execImpl();
}
+ public Set toBeMadeStatic = new HashSet();
+
private final JProgram program;
private MakeCallsStatic(JProgram program) {
@@ -255,24 +264,21 @@
}
private boolean execImpl() {
- {
- CreateStaticMethodVisitor creator = new CreateStaticMethodVisitor();
- program.traverse(creator);
- ChangeList changes = creator.getChangeList();
- if (changes.empty()) {
- return false;
- }
- changes.apply();
+ FindStaticDispatchSitesVisitor finder = new FindStaticDispatchSitesVisitor();
+ finder.accept(program);
+ if (toBeMadeStatic.isEmpty()) {
+ return false;
}
- {
- RewriteCallSites rewriter = new RewriteCallSites();
- program.traverse(rewriter);
- ChangeList changes = rewriter.getChangeList();
- assert (!changes.empty());
- changes.apply();
+ CreateStaticImplsVisitor creator = new CreateStaticImplsVisitor();
+ creator.accept(program);
+ if (!creator.didChange()) {
+ return false;
}
+ RewriteCallSites rewriter = new RewriteCallSites();
+ rewriter.accept(program);
+ assert (rewriter.didChange());
return true;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java
index a2ded14..950b5c1 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodAndClassFinalizer.java
@@ -15,13 +15,13 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
import com.google.gwt.dev.jjs.ast.js.JsniMethod;
import java.util.HashSet;
@@ -46,45 +46,46 @@
*/
private class FinalizeVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Finalize effectively final methods and types.");
+ private boolean didChange = false;
- public ChangeList getChangeList() {
- return changeList;
+ public boolean didChange() {
+ return didChange;
}
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
if (!x.isFinal() && !isSubclassed.contains(x)) {
- changeList.makeFinal(x);
+ x.setFinal(true);
+ didChange = true;
}
for (int i = 0; i < x.methods.size(); ++i) {
JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
+ accept(method);
}
return false;
}
// @Override
- public boolean visit(JInterfaceType x) {
+ public boolean visit(JInterfaceType x, Context ctx) {
for (int i = 0; i < x.methods.size(); ++i) {
JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
+ accept(method);
}
return false;
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
if (!x.isFinal() && !isOverriden.contains(x)) {
- changeList.makeFinal(x);
+ x.setFinal(true);
+ didChange = true;
}
return false;
}
// @Override
- public boolean visit(JsniMethod x) {
- return visit((JMethod) x);
+ public boolean visit(JsniMethod x, Context ctx) {
+ return visit((JMethod) x, ctx);
}
}
/**
@@ -93,29 +94,29 @@
private class MarkVisitor extends JVisitor {
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
if (x.extnds != null) {
isSubclassed.add(x.extnds);
}
for (int i = 0; i < x.methods.size(); ++i) {
JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
+ accept(method);
}
return false;
}
// @Override
- public boolean visit(JInterfaceType x) {
+ public boolean visit(JInterfaceType x, Context ctx) {
for (int i = 0; i < x.methods.size(); ++i) {
JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
+ accept(method);
}
return false;
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
for (int i = 0; i < x.overrides.size(); ++i) {
JMethod it = (JMethod) x.overrides.get(i);
isOverriden.add(it);
@@ -124,17 +125,17 @@
}
// @Override
- public boolean visit(JProgram x) {
+ public boolean visit(JProgram x, Context ctx) {
for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
- type.traverse(this);
+ accept(type);
}
return false;
}
// @Override
- public boolean visit(JsniMethod x) {
- return visit((JMethod) x);
+ public boolean visit(JsniMethod x, Context ctx) {
+ return visit((JMethod) x, ctx);
}
}
@@ -142,24 +143,20 @@
return new MethodAndClassFinalizer().execImpl(program);
}
- private final Set/* <JClassType> */isSubclassed = new HashSet/* <JClassType> */();
-
private final Set/* <JMethod> */isOverriden = new HashSet/* <JMethod> */();
+ private final Set/* <JClassType> */isSubclassed = new HashSet/* <JClassType> */();
+
private MethodAndClassFinalizer() {
}
private boolean execImpl(JProgram program) {
MarkVisitor marker = new MarkVisitor();
- program.traverse(marker);
+ marker.accept(program);
+
FinalizeVisitor finalizer = new FinalizeVisitor();
- program.traverse(finalizer);
- ChangeList changes = finalizer.getChangeList();
- if (changes.empty()) {
- return false;
- }
- changes.apply();
- return true;
+ finalizer.accept(program);
+ return finalizer.didChange();
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
index 141460d..1b002ec 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodCallTightener.java
@@ -15,19 +15,18 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
/**
* Update polymorphic method calls to tighter bindings based on the type of the
@@ -43,12 +42,10 @@
* Updates polymorphic method calls to tighter bindings based on the type of
* the qualifier.
*/
- public class MethodCallTighteningVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Update polymorphic method calls to tighter bindings based on the type of the qualifier.");
+ public class MethodCallTighteningVisitor extends JModVisitor {
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
JExpression instance = x.getInstance();
@@ -100,30 +97,14 @@
return;
}
- ChangeList changes = new ChangeList("Replace call '" + x + "' to type '"
- + enclosingType + "' with a call to type '"
- + foundMethod.getEnclosingType() + "'");
-
- // Update the call site
- JMethodCall call = new JMethodCall(program, null, foundMethod);
- changes.replaceExpression(m, call);
-
- // Copy the qualifier
- changes.replaceExpression(call.instance, x.instance);
-
- // Copy the args
- for (int i = 0; i < x.args.size(); ++i) {
- Mutator arg = x.args.getMutator(i);
- changes.addExpression(arg, call.args);
- }
-
- changeList.add(changes);
-
- return;
- }
-
- public ChangeList getChangeList() {
- return changeList;
+ /*
+ * Replace the call to the original method with a call to the same method
+ * on the tighter type.
+ */
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(),
+ x.getInstance(), foundMethod);
+ call.getArgs().addAll(x.getArgs());
+ ctx.replaceMe(call);
}
}
@@ -139,14 +120,8 @@
private boolean execImpl() {
MethodCallTighteningVisitor tightener = new MethodCallTighteningVisitor();
- program.traverse(tightener);
- ChangeList changes = tightener.getChangeList();
- if (changes.empty()) {
- return false;
- }
-
- changes.apply();
- return true;
+ tightener.accept(program);
+ return tightener.didChange();
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
index 3cce0f6..26f9e97 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/MethodInliner.java
@@ -15,8 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
-import com.google.gwt.dev.jjs.ast.Holder;
-import com.google.gwt.dev.jjs.ast.HolderList;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JBlock;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JExpressionStatement;
@@ -25,16 +24,18 @@
import com.google.gwt.dev.jjs.ast.JLiteral;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JParameterRef;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JReturnStatement;
import com.google.gwt.dev.jjs.ast.JStatement;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
+import com.google.gwt.dev.jjs.ast.JSourceInfo;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -47,55 +48,61 @@
/**
* Flattens <code>JMultiExpressions</code> where possible.
+ *
+ * TODO: make this a JModVisitor
*/
public class FlattenMultiVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Flatten multis where possible.");
- // @Override
- public void endVisit(JMultiExpression x, Mutator m) {
- HolderList exprs = x.exprs;
+ private boolean didChange = false;
- // do all adds FIRST or the indices will be wrong
- for (int i = 0; i < exprs.size(); ++i) {
- JExpression expr = exprs.getExpr(i);
- if (expr instanceof JMultiExpression) {
- JMultiExpression sub = (JMultiExpression) expr;
- changeList.addAll(sub.exprs, i, exprs);
- }
- }
-
- // now remove the old multi
- for (int i = 0; i < exprs.size(); ++i) {
- JExpression expr = exprs.getExpr(i);
- if (expr instanceof JMultiExpression) {
- changeList.removeNode(exprs.getMutator(i), exprs);
- }
- }
+ public boolean didChange() {
+ return didChange;
}
- public ChangeList getChangeList() {
- return changeList;
+ // @Override
+ public void endVisit(JMultiExpression x, Context ctx) {
+ ArrayList exprs = x.exprs;
+
+ /*
+ * Add the contents of all nested multis into the top multi, in place. We
+ * are in fact iterating over nodes we've just added, but that should be
+ * okay as the children will already be flattened.
+ */
+ for (int i = 0; i < exprs.size(); ++i) {
+ JExpression expr = (JExpression) exprs.get(i);
+ if (expr instanceof JMultiExpression) {
+ JMultiExpression sub = (JMultiExpression) expr;
+ exprs.addAll(i + 1, sub.exprs);
+ didChange = true;
+ }
+ }
+
+ // now remove the old multis
+ for (Iterator it = exprs.iterator(); it.hasNext();) {
+ JExpression expr = (JExpression) it.next();
+ if (expr instanceof JMultiExpression) {
+ it.remove();
+ didChange = true;
+ }
+ }
}
}
/**
* Method inlining visitor.
*/
- public class InliningVisitor extends JVisitor {
+ public class InliningVisitor extends JModVisitor {
/**
* Resets with each new visitor, which is good since things that couldn't be
* inlined before might become inlineable.
*/
Set/* <JMethod> */cannotInline = new HashSet/* <JMethod> */();
- private final ChangeList changeList = new ChangeList("Inline methods.");
-
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
currentMethod = null;
}
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
// The method call must be known statically
@@ -110,12 +117,16 @@
List/* <JStatement> */stmts = method.body.statements;
boolean possibleToInline = false;
if (stmts.isEmpty()) {
- possibleToInline = inlineEmptyMethodCall(x, m, method);
+ inlineEmptyMethodCall(x, ctx);
+ possibleToInline = true;
} else if (stmts.size() == 1) {
JStatement stmt = (JStatement) stmts.get(0);
if (stmt instanceof JReturnStatement) {
- possibleToInline = tryInlineSimpleMethodCall(x, m, method,
- (JReturnStatement) stmt);
+ possibleToInline = tryInlineExpression(x, ctx,
+ ((JReturnStatement) stmt).getExpr());
+ } else if (stmt instanceof JExpressionStatement) {
+ possibleToInline = tryInlineExpression(x, ctx,
+ ((JExpressionStatement) stmt).getExpr());
}
}
@@ -124,11 +135,7 @@
}
}
- public ChangeList getChangeList() {
- return changeList;
- }
-
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
return true;
}
@@ -148,10 +155,10 @@
* should be inlinable, but we have to first examine the field reference and
* then recursively determine that the qualifier is inlinable.
*/
- private Mutator canInlineResultExpression(JExpression targetReturnExpr,
- List/* <JParameter> */params, HolderList args, int[] magicArg,
- ChangeList changes) {
- if (targetReturnExpr instanceof JLiteral) {
+ private JExpression canInlineExpression(JSourceInfo info,
+ JExpression targetExpr, List/* <JParameter> */params, ArrayList args,
+ int[] magicArg) {
+ if (targetExpr instanceof JLiteral) {
// just reference the same JLiteral
/*
* hackish: pretend there is an arg that is returned which comes after
@@ -159,29 +166,27 @@
* tryInlineSimpleMethodCall to succeed
*/
magicArg[0] = args.size();
- return new Holder(targetReturnExpr);
- } else if (targetReturnExpr instanceof JParameterRef) {
+ return targetExpr;
+ } else if (targetExpr instanceof JParameterRef) {
// translate the param ref into the appropriate arg
- int i = params.indexOf(((JParameterRef) targetReturnExpr).getTarget());
+ int i = params.indexOf(((JParameterRef) targetExpr).getTarget());
assert (i >= 0);
magicArg[0] = i;
- return args.getMutator(i);
- } else if (targetReturnExpr instanceof JFieldRef) {
- JFieldRef oldFieldRef = (JFieldRef) targetReturnExpr;
+ return (JExpression) args.get(i);
+ } else if (targetExpr instanceof JFieldRef) {
+ JFieldRef oldFieldRef = (JFieldRef) targetExpr;
JField field = oldFieldRef.getField();
JExpression instance = oldFieldRef.getInstance();
- JFieldRef newFieldRef = new JFieldRef(program, null, field,
- currentMethod.getEnclosingType());
if (instance != null) {
// If an instance field, we have to be able to inline the qualifier
- Mutator instanceMutator = canInlineResultExpression(instance, params,
- args, magicArg, changes);
- if (instanceMutator == null) {
+ instance = canInlineExpression(info, instance, params, args, magicArg);
+ if (instance == null) {
return null;
}
- changes.replaceExpression(newFieldRef.instance, instanceMutator);
}
- return new Holder(newFieldRef);
+ JFieldRef newFieldRef = new JFieldRef(program, info, instance, field,
+ currentMethod.getEnclosingType());
+ return newFieldRef;
} else {
/*
* For now, only inline REALLY trivial stuff since we have no way of
@@ -191,42 +196,38 @@
}
}
- private boolean inlineEmptyMethodCall(JMethodCall x, Mutator m,
- JMethod method) {
- ChangeList changes = new ChangeList("Inline a call to empty method '"
- + method + "'");
- JMultiExpression multi = new JMultiExpression(program);
+ /**
+ * Inlines a call to an empty method.
+ */
+ private void inlineEmptyMethodCall(JMethodCall x, Context ctx) {
+ JMultiExpression multi = new JMultiExpression(program, x.getSourceInfo());
JExpression instance = x.getInstance();
if (instance != null && instance.hasSideEffects()) {
- changes.addExpression(x.instance, multi.exprs);
+ multi.exprs.add(x.getInstance());
}
- for (int i = 0, c = x.args.size(); i < c; ++i) {
- if (x.args.getExpr(i).hasSideEffects()) {
- changes.addExpression(x.args.getMutator(i), multi.exprs);
+ for (int i = 0, c = x.getArgs().size(); i < c; ++i) {
+ if (((JExpression) x.getArgs().get(i)).hasSideEffects()) {
+ multi.exprs.add(x.getArgs().get(i));
}
}
-
- changes.replaceExpression(m, multi);
- changeList.add(changes);
- return true;
+ ctx.replaceMe(multi);
}
- private boolean tryInlineSimpleMethodCall(JMethodCall x, Mutator m,
- JMethod method, JReturnStatement returnStmt) {
- List/* <JParameter> */params = method.params;
- HolderList args = x.args;
-
- ChangeList changes = new ChangeList("Inline a call to simple method '"
- + method + "'");
+ /**
+ * Inline a call to a method that contains only a return statement.
+ */
+ private boolean tryInlineExpression(JMethodCall x, Context ctx,
+ JExpression targetExpr) {
+ List/* <JParameter> */params = x.getTarget().params;
+ ArrayList args = x.getArgs();
// the expression returned by the inlined method, if any
- Mutator resultExpression;
+ JExpression resultExpression;
// the argument that is returned by the inlined method, if any
int magicArg[] = new int[1];
- JExpression targetReturnExpr = returnStmt.getExpression();
- resultExpression = canInlineResultExpression(targetReturnExpr, params,
- args, magicArg, changes);
+ resultExpression = canInlineExpression(x.getSourceInfo(), targetExpr,
+ params, args, magicArg);
if (resultExpression == null) {
return false; // cannot inline
@@ -235,20 +236,20 @@
// the argument that is returned by the inlined method
int iMagicArg = magicArg[0];
- JMultiExpression multi = new JMultiExpression(program);
+ JMultiExpression multi = new JMultiExpression(program, x.getSourceInfo());
// Evaluate the instance argument (we can have one even with static calls)
JExpression instance = x.getInstance();
if (instance != null && instance.hasSideEffects()) {
- changes.addExpression(x.instance, multi.exprs);
+ multi.exprs.add(x.getInstance());
}
// Now evaluate any side-effect args that aren't the magic arg.
for (int i = 0; i < params.size(); ++i) {
- if (args.getExpr(i).hasSideEffects()) {
+ if (((JExpression) args.get(i)).hasSideEffects()) {
if (i < iMagicArg) {
// evaluate this arg inside of the multi
- changes.addExpression(args.getMutator(i), multi.exprs);
+ multi.exprs.add(args.get(i));
} else if (i == iMagicArg) {
// skip this arg, we'll do it below as the final one
} else {
@@ -268,9 +269,8 @@
}
// add in the result expression as the last item in the multi
- changes.addExpression(resultExpression, multi.exprs);
- changes.replaceExpression(m, multi);
- changeList.add(changes);
+ multi.exprs.add(resultExpression);
+ ctx.replaceMe(multi);
return true;
}
}
@@ -278,13 +278,26 @@
/**
* Reduces <code>JMultiExpression</code> where possible.
*/
- public class ReduceMultiVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Reduce multis where possible.");
+ public class ReduceMultiVisitor extends JModVisitor {
// @Override
- public void endVisit(JMultiExpression x, Mutator m) {
- HolderList exprs = x.exprs;
+ public void endVisit(JBlock x, Context ctx) {
+ for (Iterator it = x.statements.iterator(); it.hasNext();) {
+ JStatement stmt = (JStatement) it.next();
+ // If we're a JExprStmt with no side effects, just remove me
+ if (stmt instanceof JExpressionStatement) {
+ JExpression expr = ((JExpressionStatement) stmt).getExpr();
+ if (!expr.hasSideEffects()) {
+ it.remove();
+ didChange = true;
+ }
+ }
+ }
+ }
+
+ // @Override
+ public void endVisit(JMultiExpression x, Context ctx) {
+ ArrayList exprs = x.exprs;
final int c = exprs.size();
if (c == 0) {
@@ -293,42 +306,28 @@
int countSideEffectsBeforeLast = 0;
for (int i = 0; i < c - 1; ++i) {
- JExpression expr = exprs.getExpr(i);
+ JExpression expr = (JExpression) exprs.get(i);
if (expr.hasSideEffects()) {
++countSideEffectsBeforeLast;
}
}
if (countSideEffectsBeforeLast == 0) {
- changeList.replaceExpression(m, x.exprs.getMutator(c - 1));
+ ctx.replaceMe((JExpression) x.exprs.get(c - 1));
} else {
+ JMultiExpression newMulti = new JMultiExpression(program,
+ x.getSourceInfo());
for (int i = 0; i < c - 1; ++i) {
- JExpression expr = exprs.getExpr(i);
- if (!expr.hasSideEffects()) {
- changeList.removeNode(x.exprs.getMutator(i), exprs);
+ JExpression expr = (JExpression) exprs.get(i);
+ if (expr.hasSideEffects()) {
+ newMulti.exprs.add(expr);
}
}
- }
- }
-
- public ChangeList getChangeList() {
- return changeList;
- }
-
- // @Override
- public boolean visit(JBlock x) {
- for (int i = 0; i < x.statements.size(); ++i) {
- JStatement stmt = (JStatement) x.statements.get(i);
- stmt.traverse(this);
- // If we're a JExprStmt with no side effects, just remove me
- if (stmt instanceof JExpressionStatement) {
- JExpression expr = ((JExpressionStatement) stmt).getExpression();
- if (!expr.hasSideEffects()) {
- changeList.removeNode(stmt, x.statements);
- }
+ newMulti.exprs.add(x.exprs.get(c - 1));
+ if (newMulti.exprs.size() < x.exprs.size()) {
+ ctx.replaceMe(newMulti);
}
}
- return false;
}
}
@@ -346,34 +345,18 @@
private boolean execImpl() {
boolean madeChanges = false;
while (true) {
- {
- InliningVisitor inliner = new InliningVisitor();
- program.traverse(inliner);
- ChangeList changes = inliner.getChangeList();
- if (changes.empty()) {
- break;
- }
- changes.apply();
- madeChanges = true;
+ InliningVisitor inliner = new InliningVisitor();
+ inliner.accept(program);
+ if (!inliner.didChange()) {
+ break;
}
+ madeChanges = true;
- {
- FlattenMultiVisitor flattener = new FlattenMultiVisitor();
- program.traverse(flattener);
- ChangeList changes = flattener.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
- }
+ FlattenMultiVisitor flattener = new FlattenMultiVisitor();
+ flattener.accept(program);
- {
- ReduceMultiVisitor reducer = new ReduceMultiVisitor();
- program.traverse(reducer);
- ChangeList changes = reducer.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
- }
+ ReduceMultiVisitor reducer = new ReduceMultiVisitor();
+ reducer.accept(program);
}
return madeChanges;
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
index a9c22a4..4291e55 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/Pruner.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -35,14 +36,13 @@
import com.google.gwt.dev.jjs.ast.JStringLiteral;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
import com.google.gwt.dev.jjs.ast.js.JsniMethod;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -63,6 +63,8 @@
* failures at compile time.
*
* TODO(later): prune params and locals
+ *
+ * TODO(later): make RescueVisitor use less stack?
*/
public class Pruner {
@@ -72,31 +74,33 @@
*/
private class PruneVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Prune unreferenced methods, fields, and types.");
+ private boolean didChange = false;
- public ChangeList getChangeList() {
- return changeList;
+ public boolean didChange() {
+ return didChange;
}
// @Override
- public boolean visit(JClassType type) {
+ public boolean visit(JClassType type, Context ctx) {
assert (referencedTypes.contains(type));
boolean isInstantiated = program.typeOracle.isInstantiatedType(type);
- for (int i = 0; i < type.fields.size(); ++i) {
- JField it = (JField) type.fields.get(i);
- if (!referencedNonTypes.contains(it)
- || pruneViaNoninstantiability(isInstantiated, it)) {
- changeList.removeField(it);
+ for (Iterator it = type.fields.iterator(); it.hasNext();) {
+ JField field = (JField) it.next();
+ if (!referencedNonTypes.contains(field)
+ || pruneViaNoninstantiability(isInstantiated, field)) {
+ it.remove();
+ didChange = true;
}
}
- for (int i = 0; i < type.methods.size(); ++i) {
- JMethod it = (JMethod) type.methods.get(i);
- if (!methodIsReferenced(it)
- || pruneViaNoninstantiability(isInstantiated, it)) {
- changeList.removeMethod(it);
+
+ for (Iterator it = type.methods.iterator(); it.hasNext();) {
+ JMethod method = (JMethod) it.next();
+ if (!methodIsReferenced(method)
+ || pruneViaNoninstantiability(isInstantiated, method)) {
+ it.remove();
+ didChange = true;
}
}
@@ -104,23 +108,30 @@
}
// @Override
- public boolean visit(JInterfaceType type) {
+ public boolean visit(JInterfaceType type, Context ctx) {
boolean isReferenced = referencedTypes.contains(type);
boolean isInstantiated = program.typeOracle.isInstantiatedType(type);
- for (int i = 0; i < type.fields.size(); ++i) {
- JField it = (JField) type.fields.get(i);
+ for (Iterator it = type.fields.iterator(); it.hasNext();) {
+ JField field = (JField) it.next();
// all interface fields are static and final
- if (!isReferenced || !referencedNonTypes.contains(it)) {
- changeList.removeField(it);
+ if (!isReferenced || !referencedNonTypes.contains(field)) {
+ it.remove();
+ didChange = true;
}
}
- // start at index 1; never prune clinit directly out of the interface
- for (int i = 1; i < type.methods.size(); ++i) {
- JMethod it = (JMethod) type.methods.get(i);
+
+ Iterator it = type.methods.iterator();
+ if (it.hasNext()) {
+ // start at index 1; never prune clinit directly out of the interface
+ it.next();
+ }
+ while (it.hasNext()) {
+ JMethod method = (JMethod) it.next();
// all other interface methods are instance and abstract
- if (!isInstantiated || !methodIsReferenced(it)) {
- changeList.removeMethod(it);
+ if (!isInstantiated || !methodIsReferenced(method)) {
+ it.remove();
+ didChange = true;
}
}
@@ -128,14 +139,15 @@
}
// @Override
- public boolean visit(JProgram program) {
+ public boolean visit(JProgram program, Context ctx) {
for (int i = 0; i < program.getDeclaredTypes().size(); ++i) {
JReferenceType type = (JReferenceType) program.getDeclaredTypes().get(i);
if (referencedTypes.contains(type)
|| program.typeOracle.isInstantiatedType(type)) {
- type.traverse(this);
+ accept(type);
} else {
- changeList.removeType(type);
+ program.getDeclaredTypes().remove(type);
+ didChange = true;
}
}
return false;
@@ -175,6 +187,7 @@
return (!isInstantiated && (!it.isStatic() || program.isStaticImpl(it)));
}
}
+
/**
* Marks as "referenced" any types, methods, and fields that are reachable.
* Also marks as "instantiable" any the classes and interfaces that can
@@ -189,9 +202,9 @@
}
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
// special string concat handling
- if (x.op == JBinaryOperator.ADD
+ if (x.getOp() == JBinaryOperator.ADD
&& x.getType() == program.getTypeJavaLangString()) {
rescueByConcat(x.getLhs().getType());
rescueByConcat(x.getRhs().getType());
@@ -199,7 +212,7 @@
}
// @Override
- public boolean visit(JArrayType type) {
+ public boolean visit(JArrayType type, Context ctx) {
assert (referencedTypes.contains(type));
boolean isInstantiated = instantiatedTypes.contains(type);
@@ -225,7 +238,7 @@
}
// @Override
- public boolean visit(JClassLiteral literal, Mutator mutator) {
+ public boolean visit(JClassLiteral literal, Context ctx) {
// rescue and instantiate java.lang.Class
// JLS 12.4.1: do not rescue the target type
rescue(program.getTypeJavaLangClass(), true, true);
@@ -233,7 +246,7 @@
}
// @Override
- public boolean visit(JClassType type) {
+ public boolean visit(JClassType type, Context ctx) {
assert (referencedTypes.contains(type));
boolean isInstantiated = instantiatedTypes.contains(type);
@@ -266,7 +279,7 @@
}
// @Override
- public boolean visit(JFieldRef ref, Mutator mutator) {
+ public boolean visit(JFieldRef ref, Context ctx) {
JField target = ref.getField();
// JLS 12.4.1: references to static, non-final, or
@@ -281,7 +294,7 @@
}
// @Override
- public boolean visit(JInterfaceType type) {
+ public boolean visit(JInterfaceType type, Context ctx) {
boolean isReferenced = referencedTypes.contains(type);
boolean isInstantiated = instantiatedTypes.contains(type);
assert (isReferenced || isInstantiated);
@@ -301,14 +314,14 @@
// visit any field initializers
for (int i = 0; i < type.fields.size(); ++i) {
JField it = (JField) type.fields.get(i);
- it.traverse(this);
+ accept(it);
}
return false;
}
// @Override
- public boolean visit(JMethodCall call, Mutator mutator) {
+ public boolean visit(JMethodCall call, Context ctx) {
JMethod target = call.getTarget();
// JLS 12.4.1: references to static methods rescue the enclosing class
if (target.isStatic()) {
@@ -319,12 +332,12 @@
}
// @Override
- public boolean visit(JNewArray newArray, Mutator mutator) {
+ public boolean visit(JNewArray newArray, Context ctx) {
// rescue and instantiate the array type
JArrayType arrayType = newArray.getArrayType();
if (newArray.dims != null) {
// rescue my type and all the implicitly nested types (with fewer dims)
- int nDims = arrayType.dims;
+ int nDims = arrayType.getDims();
JType leafType = arrayType.getLeafType();
assert (newArray.dims.size() == nDims);
for (int i = 0; i < nDims; ++i) {
@@ -344,28 +357,28 @@
}
// @Override
- public boolean visit(JNewInstance newInstance, Mutator mutator) {
+ public boolean visit(JNewInstance newInstance, Context ctx) {
// rescue and instantiate the target class!
rescue(newInstance.getClassType(), true, true);
return true;
}
// @Override
- public boolean visit(JsniFieldRef x) {
+ public boolean visit(JsniFieldRef x, Context ctx) {
/*
* SPECIAL: this could be an assignment that passes a value from
* JavaScript into Java.
*
- * TODO: technically we only need to do this if the field is being
+ * TODO(later): technically we only need to do this if the field is being
* assigned to.
*/
maybeRescueJavaScriptObjectPassingIntoJava(x.getField().getType());
// JsniFieldRef rescues as JFieldRef
- return visit(/* (JFieldRef) */x, null);
+ return visit((JFieldRef) x, ctx);
}
// @Override
- public boolean visit(JsniMethodRef x) {
+ public boolean visit(JsniMethodRef x, Context ctx) {
/*
* SPECIAL: each argument of the call passes a value from JavaScript into
* Java.
@@ -376,11 +389,11 @@
maybeRescueJavaScriptObjectPassingIntoJava(param.getType());
}
// JsniMethodRef rescues as JMethodCall
- return visit(/* (JMethodCall) */x, null);
+ return visit((JMethodCall) x, ctx);
}
// @Override
- public boolean visit(JStringLiteral literal, Mutator mutator) {
+ public boolean visit(JStringLiteral literal, Context ctx) {
// rescue and instantiate java.lang.String
rescue(program.getTypeJavaLangString(), true, true);
return true;
@@ -406,60 +419,51 @@
}
}
- private boolean rescue(JField field) {
- if (field == null) {
- return false;
+ private void rescue(JField field) {
+ if (field != null) {
+ if (!referencedNonTypes.contains(field)) {
+ referencedNonTypes.add(field);
+ }
}
-
- if (!referencedNonTypes.contains(field)) {
- referencedNonTypes.add(field);
- return true;
- }
- return true;
}
private boolean rescue(JMethod method) {
- if (method == null) {
- return false;
- }
-
- if (!referencedNonTypes.contains(method)) {
- referencedNonTypes.add(method);
- method.traverse(this);
- if (method instanceof JsniMethod) {
- /*
- * SPECIAL: returning from this method passes a value from JavaScript
- * into Java.
- */
- maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
+ if (method != null) {
+ if (!referencedNonTypes.contains(method)) {
+ referencedNonTypes.add(method);
+ accept(method);
+ if (method instanceof JsniMethod) {
+ /*
+ * SPECIAL: returning from this method passes a value from
+ * JavaScript into Java.
+ */
+ maybeRescueJavaScriptObjectPassingIntoJava(method.getType());
+ }
+ return true;
}
- return true;
}
return false;
}
- private boolean rescue(JReferenceType type, boolean isReferenced,
+ private void rescue(JReferenceType type, boolean isReferenced,
boolean isInstantiated) {
- if (type == null) {
- return false;
- }
+ if (type != null) {
- boolean doVisit = false;
- if (isInstantiated && !instantiatedTypes.contains(type)) {
- instantiatedTypes.add(type);
- doVisit = true;
- }
+ boolean doVisit = false;
+ if (isInstantiated && !instantiatedTypes.contains(type)) {
+ instantiatedTypes.add(type);
+ doVisit = true;
+ }
- if (isReferenced && !referencedTypes.contains(type)) {
- referencedTypes.add(type);
- doVisit = true;
- }
+ if (isReferenced && !referencedTypes.contains(type)) {
+ referencedTypes.add(type);
+ doVisit = true;
+ }
- if (doVisit) {
- type.traverse(this);
+ if (doVisit) {
+ accept(type);
+ }
}
-
- return doVisit;
}
/**
@@ -517,7 +521,7 @@
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
if (referencedNonTypes.contains(x)) {
return false;
}
@@ -539,14 +543,14 @@
}
// @Override
- public boolean visit(JProgram x) {
+ public boolean visit(JProgram x, Context ctx) {
didRescue = false;
return true;
}
// @Override
- public boolean visit(JsniMethod x) {
- return visit((JMethod) x);
+ public boolean visit(JsniMethod x, Context ctx) {
+ return visit((JMethod) x, ctx);
}
}
@@ -573,12 +577,10 @@
boolean madeChanges = false;
while (true) {
RescueVisitor rescuer = new RescueVisitor();
-
for (int i = 0; i < program.specialTypes.size(); ++i) {
JReferenceType type = (JReferenceType) program.specialTypes.get(i);
rescuer.rescue(type, true, noSpecialTypes);
}
-
for (int i = 0; i < program.entryMethods.size(); ++i) {
JMethod method = (JMethod) program.entryMethods.get(i);
rescuer.rescue(method);
@@ -587,17 +589,14 @@
UpRefVisitor upRefer = new UpRefVisitor(rescuer);
do {
rescuer.commitInstantiatedTypes();
- program.traverse(upRefer);
+ upRefer.accept(program);
} while (upRefer.didRescue());
PruneVisitor pruner = new PruneVisitor();
- program.traverse(pruner);
-
- ChangeList changes = pruner.getChangeList();
- if (changes.empty()) {
+ pruner.accept(program);
+ if (!pruner.didChange()) {
break;
}
- changes.apply();
referencedTypes.clear();
referencedNonTypes.clear();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
index e54a836..9c4b99d 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ReplaceRebinds.java
@@ -15,17 +15,15 @@
*/
package com.google.gwt.dev.jjs.impl;
-import com.google.gwt.dev.jjs.ast.Holder;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassLiteral;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JExpression;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNewInstance;
import com.google.gwt.dev.jjs.ast.JProgram;
-import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
/**
* Replaces any "GWT.create()" calls with a new expression for the actual result
@@ -33,26 +31,22 @@
*/
public class ReplaceRebinds {
- private class RebindVisitor extends JVisitor {
-
- private final ChangeList changeList = new ChangeList(
- "Replace GWT.create() with new expressions.");
+ private class RebindVisitor extends JModVisitor {
// @Override
- public void endVisit(JMethodCall x, Mutator mutator) {
+ public void endVisit(JMethodCall x, Context ctx) {
JMethod method = x.getTarget();
if (method == program.getRebindCreateMethod()) {
- assert (x.args.size() == 1);
- JExpression arg = x.args.getExpr(0);
+ assert (x.getArgs().size() == 1);
+ JExpression arg = (JExpression) x.getArgs().get(0);
assert (arg instanceof JClassLiteral);
JClassLiteral classLiteral = (JClassLiteral) arg;
- JClassType classType = program.rebind(classLiteral.refType);
+ JClassType classType = program.rebind(classLiteral.getRefType());
/*
* Find the appropriate (noArg) constructor. In our AST, constructors
* are instance methods that should be qualified with a new expression.
*/
-
JMethod noArgCtor = null;
for (int i = 0; i < classType.methods.size(); ++i) {
JMethod ctor = (JMethod) classType.methods.get(i);
@@ -64,15 +58,13 @@
}
assert (noArgCtor != null);
// Call it, using a new expression as a qualifier
- JNewInstance newInstance = new JNewInstance(program, classType);
- JMethodCall call = new JMethodCall(program, newInstance, noArgCtor);
- changeList.replaceExpression(mutator, new Holder(call));
+ JNewInstance newInstance = new JNewInstance(program, x.getSourceInfo(),
+ classType);
+ JMethodCall call = new JMethodCall(program, x.getSourceInfo(),
+ newInstance, noArgCtor);
+ ctx.replaceMe(call);
}
}
-
- public ChangeList getChangeList() {
- return changeList;
- }
}
public static boolean exec(JProgram program) {
@@ -87,13 +79,8 @@
private boolean execImpl() {
RebindVisitor rebinder = new RebindVisitor();
- program.traverse(rebinder);
- ChangeList changes = rebinder.getChangeList();
- if (changes.empty()) {
- return false;
- }
- changes.apply();
- return true;
+ rebinder.accept(program);
+ return rebinder.didChange();
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
index 4d07ac4..b61953a 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/SourceGenerationVisitor.java
@@ -16,6 +16,7 @@
package com.google.gwt.dev.jjs.impl;
import com.google.gwt.dev.jjs.ast.CanBeFinal;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
@@ -50,25 +51,25 @@
}
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
// All classes are deemed "static" so the monolithic compile results can be
// copy/pasted into a single enclosing class.
print(CHARS_STATIC);
- super.visit(x);
+ super.visit(x, ctx);
openBlock();
for (int i = 0; i < x.fields.size(); ++i) {
JField it = (JField) x.fields.get(i);
- it.traverse(this);
+ accept(it);
newline();
newline();
}
for (int i = 0; i < x.methods.size(); ++i) {
JMethod it = (JMethod) x.methods.get(i);
if (!isEmptyInitializer(it)) {
- it.traverse(this);
+ accept(it);
newline();
newline();
}
@@ -78,32 +79,32 @@
return false;
}
- public boolean visit(JField x) {
- super.visit(x);
+ public boolean visit(JField x, Context ctx) {
+ super.visit(x, ctx);
if (x.constInitializer != null) {
print(" = ");
- x.constInitializer.traverse(this);
+ accept(x.constInitializer);
}
semi();
return false;
}
// @Override
- public boolean visit(JInterfaceType x) {
- super.visit(x);
+ public boolean visit(JInterfaceType x, Context ctx) {
+ super.visit(x, ctx);
openBlock();
for (int i = 0; i < x.fields.size(); ++i) {
JField field = (JField) x.fields.get(i);
- field.traverse(this);
+ accept(field);
newline();
newline();
}
for (int i = 0; i < x.methods.size(); ++i) {
JMethod method = (JMethod) x.methods.get(i);
- method.traverse(this);
+ accept(method);
newline();
newline();
}
@@ -113,21 +114,21 @@
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
// special: transcribe clinit and init as if they were initializer blocks
if (isInitializer(x)) {
if (x.isStatic()) {
print(CHARS_STATIC);
}
- x.body.traverse(this);
+ accept(x.body);
} else {
- super.visit(x);
+ super.visit(x, ctx);
if (x.isAbstract()) {
semi();
} else {
space();
- x.body.traverse(this);
+ accept(x.body);
}
}
@@ -135,16 +136,16 @@
}
// @Override
- public boolean visit(JProgram x) {
+ public boolean visit(JProgram x, Context ctx) {
for (int i = 0; i < x.entryMethods.size(); ++i) {
JMethod method = (JMethod) x.entryMethods.get(i);
- method.traverse(this);
+ accept(method);
newline();
newline();
}
for (int i = 0; i < x.getDeclaredTypes().size(); ++i) {
JReferenceType type = (JReferenceType) x.getDeclaredTypes().get(i);
- type.traverse(this);
+ accept(type);
newline();
newline();
}
@@ -152,8 +153,8 @@
}
// @Override
- public boolean visit(JsniMethod x) {
- super.visit(x);
+ public boolean visit(JsniMethod x, Context ctx) {
+ super.visit(x, ctx);
space();
print(CHARS_SLASHSTAR);
String jsniCode = x.getFunc().getBody().toString();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
index dd3028d..ae9351e 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ToStringGenerationVisitor.java
@@ -19,6 +19,7 @@
import com.google.gwt.dev.jjs.ast.CanBeFinal;
import com.google.gwt.dev.jjs.ast.CanBeNative;
import com.google.gwt.dev.jjs.ast.CanBeStatic;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.HasName;
import com.google.gwt.dev.jjs.ast.HasType;
import com.google.gwt.dev.jjs.ast.JAbsentArrayDimension;
@@ -77,7 +78,6 @@
import com.google.gwt.dev.jjs.ast.JTryStatement;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.jjs.ast.JWhileStatement;
-import com.google.gwt.dev.jjs.ast.Mutator;
import com.google.gwt.dev.jjs.ast.js.JMultiExpression;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
import com.google.gwt.dev.jjs.ast.js.JsniMethod;
@@ -147,70 +147,70 @@
}
// @Override
- public boolean visit(JAbsentArrayDimension x, Mutator h) {
+ public boolean visit(JAbsentArrayDimension x, Context ctx) {
// nothing to print, parent prints []
return false;
}
// @Override
- public boolean visit(JArrayRef x, Mutator h) {
+ public boolean visit(JArrayRef x, Context ctx) {
JExpression instance = x.getInstance();
parenPush(x, instance);
- instance.traverse(this);
+ accept(instance);
parenPop(x, instance);
print('[');
- x.getIndexExpr().traverse(this);
+ accept(x.getIndexExpr());
print(']');
return false;
}
// @Override
- public boolean visit(JArrayType x) {
- x.leafType.traverse(this);
- for (int i = 0, c = x.dims; i < c; ++i) {
+ public boolean visit(JArrayType x, Context ctx) {
+ accept(x.getLeafType());
+ for (int i = 0, c = x.getDims(); i < c; ++i) {
print("[]");
}
return false;
}
// @Override
- public boolean visit(JAssertStatement x) {
+ public boolean visit(JAssertStatement x, Context ctx) {
print(CHARS_ASSERT);
- x.getTestExpr().traverse(this);
+ accept(x.getTestExpr());
if (x.getArg() != null) {
print(" : ");
- x.getArg().traverse(this);
+ accept(x.getArg());
}
return false;
}
// @Override
- public boolean visit(JBinaryOperation x, Mutator h) {
+ public boolean visit(JBinaryOperation x, Context ctx) {
// TODO(later): associativity
JExpression arg1 = x.getLhs();
parenPush(x, arg1);
- arg1.traverse(this);
+ accept(arg1);
parenPop(x, arg1);
space();
- print(x.op.getSymbol());
+ print(x.getOp().getSymbol());
space();
JExpression arg2 = x.getRhs();
parenPush(x, arg2);
- arg2.traverse(this);
+ accept(arg2);
parenPop(x, arg2);
return false;
}
// @Override
- public boolean visit(JBlock x) {
+ public boolean visit(JBlock x, Context ctx) {
openBlock();
for (int i = 0; i < x.statements.size(); ++i) {
JStatement statement = (JStatement) x.statements.get(i);
needSemi = true;
- statement.traverse(this);
+ accept(statement);
if (needSemi) {
semi();
}
@@ -222,26 +222,26 @@
}
// @Override
- public boolean visit(JBooleanLiteral x, Mutator h) {
- printBooleanLiteral(x.value);
+ public boolean visit(JBooleanLiteral x, Context ctx) {
+ printBooleanLiteral(x.getValue());
return false;
}
// @Override
- public boolean visit(JBreakStatement x) {
+ public boolean visit(JBreakStatement x, Context ctx) {
print(CHARS_BREAK);
- if (x.label != null) {
+ if (x.getLabel() != null) {
space();
- x.label.traverse(this);
+ accept(x.getLabel());
}
return false;
}
// @Override
- public boolean visit(JCaseStatement x) {
- if (x.getExpression() != null) {
+ public boolean visit(JCaseStatement x, Context ctx) {
+ if (x.getExpr() != null) {
print(CHARS_CASE);
- x.getExpression().traverse(this);
+ accept(x.getExpr());
} else {
print(CHARS_DEFAULT);
}
@@ -252,34 +252,34 @@
}
// @Override
- public boolean visit(JCastOperation x, Mutator h) {
+ public boolean visit(JCastOperation x, Context ctx) {
lparen();
printType(x);
rparen();
space();
- JExpression expr = x.getExpression();
+ JExpression expr = x.getExpr();
parenPush(x, expr);
- expr.traverse(this);
+ accept(expr);
parenPop(x, expr);
return false;
}
// @Override
- public boolean visit(JCharLiteral x, Mutator h) {
- printCharLiteral(x.value);
+ public boolean visit(JCharLiteral x, Context ctx) {
+ printCharLiteral(x.getValue());
return false;
}
// @Override
- public boolean visit(JClassLiteral x, Mutator h) {
- printTypeName(x.refType);
+ public boolean visit(JClassLiteral x, Context ctx) {
+ printTypeName(x.getRefType());
print(CHARS_DOTCLASS);
return false;
}
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
printAbstractFlag(x);
printFinalFlag(x);
print(CHARS_CLASS);
@@ -306,47 +306,47 @@
}
// @Override
- public boolean visit(JConditional x, Mutator h) {
+ public boolean visit(JConditional x, Context ctx) {
// TODO(later): associativity
JExpression ifTest = x.getIfTest();
parenPush(x, ifTest);
- ifTest.traverse(this);
+ accept(ifTest);
parenPop(x, ifTest);
print(" ? ");
JExpression thenExpr = x.getThenExpr();
parenPush(x, thenExpr);
- thenExpr.traverse(this);
+ accept(thenExpr);
parenPop(x, thenExpr);
print(" : ");
JExpression elseExpr = x.getElseExpr();
parenPush(x, elseExpr);
- elseExpr.traverse(this);
+ accept(elseExpr);
parenPop(x, elseExpr);
return false;
}
// @Override
- public boolean visit(JContinueStatement x) {
+ public boolean visit(JContinueStatement x, Context ctx) {
print(CHARS_CONTINUE);
- if (x.label != null) {
+ if (x.getLabel() != null) {
space();
- x.label.traverse(this);
+ accept(x.getLabel());
}
return false;
}
// @Override
- public boolean visit(JDoStatement x) {
+ public boolean visit(JDoStatement x, Context ctx) {
print(CHARS_DO);
- if (x.body != null) {
- nestedStatementPush(x.body);
- x.body.traverse(this);
- nestedStatementPop(x.body);
+ if (x.getBody() != null) {
+ nestedStatementPush(x.getBody());
+ accept(x.getBody());
+ nestedStatementPop(x.getBody());
}
if (needSemi) {
semi();
@@ -357,25 +357,25 @@
}
print(CHARS_WHILE);
lparen();
- x.getTestExpr().traverse(this);
+ accept(x.getTestExpr());
rparen();
return false;
}
// @Override
- public boolean visit(JDoubleLiteral x, Mutator h) {
- printDoubleLiteral(x.value);
+ public boolean visit(JDoubleLiteral x, Context ctx) {
+ printDoubleLiteral(x.getValue());
return false;
}
// @Override
- public boolean visit(JExpressionStatement x) {
- x.getExpression().traverse(this);
+ public boolean visit(JExpressionStatement x, Context ctx) {
+ accept(x.getExpr());
return false;
}
// @Override
- public boolean visit(JField x) {
+ public boolean visit(JField x, Context ctx) {
// Due to our wacky construction model, only constant fields may be final
// when generating source
if (x.constInitializer != null) {
@@ -392,48 +392,48 @@
}
// @Override
- public boolean visit(JFieldRef x, Mutator h) {
+ public boolean visit(JFieldRef x, Context ctx) {
JExpression instance = x.getInstance();
if (instance != null) {
parenPush(x, instance);
- instance.traverse(this);
+ accept(instance);
parenPop(x, instance);
} else {
- printTypeName(x.field.enclosingType);
+ printTypeName(x.getField().getEnclosingType());
}
print('.');
- printUniqueName(x.field);
+ printUniqueName(x.getField());
return false;
}
// @Override
- public boolean visit(JFloatLiteral x, Mutator h) {
- printFloatLiteral(x.value);
+ public boolean visit(JFloatLiteral x, Context ctx) {
+ printFloatLiteral(x.getValue());
return false;
}
// @Override
- public boolean visit(JForStatement x) {
+ public boolean visit(JForStatement x, Context ctx) {
print(CHARS_FOR);
lparen();
Iterator/* <JStatement> */iter = x.getInitializers().iterator();
if (iter.hasNext()) {
JStatement stmt = (JStatement) iter.next();
- stmt.traverse(this);
+ accept(stmt);
}
suppressType = true;
while (iter.hasNext()) {
print(CHARS_COMMA);
JStatement stmt = (JStatement) iter.next();
- stmt.traverse(this);
+ accept(stmt);
}
suppressType = false;
semi();
space();
if (x.getTestExpr() != null) {
- x.getTestExpr().traverse(this);
+ accept(x.getTestExpr());
}
semi();
@@ -441,28 +441,28 @@
visitCollectionWithCommas(x.getIncrements().iterator());
rparen();
- if (x.body != null) {
- nestedStatementPush(x.body);
- x.body.traverse(this);
- nestedStatementPop(x.body);
+ if (x.getBody() != null) {
+ nestedStatementPush(x.getBody());
+ accept(x.getBody());
+ nestedStatementPop(x.getBody());
}
return false;
}
// @Override
- public boolean visit(JIfStatement x) {
+ public boolean visit(JIfStatement x, Context ctx) {
print(CHARS_IF);
lparen();
- x.getIfExpr().traverse(this);
+ accept(x.getIfExpr());
rparen();
- if (x.thenStmt != null) {
- nestedStatementPush(x.thenStmt);
- x.thenStmt.traverse(this);
- nestedStatementPop(x.thenStmt);
+ if (x.getThenStmt() != null) {
+ nestedStatementPush(x.getThenStmt());
+ accept(x.getThenStmt());
+ nestedStatementPop(x.getThenStmt());
}
- if (x.elseStmt != null) {
+ if (x.getElseStmt() != null) {
if (needSemi) {
semi();
newline();
@@ -471,15 +471,15 @@
needSemi = true;
}
print(CHARS_ELSE);
- boolean elseIf = x.elseStmt instanceof JIfStatement;
+ boolean elseIf = x.getElseStmt() instanceof JIfStatement;
if (!elseIf) {
- nestedStatementPush(x.elseStmt);
+ nestedStatementPush(x.getElseStmt());
} else {
space();
}
- x.elseStmt.traverse(this);
+ accept(x.getElseStmt());
if (!elseIf) {
- nestedStatementPop(x.elseStmt);
+ nestedStatementPop(x.getElseStmt());
}
}
@@ -487,18 +487,18 @@
}
// @Override
- public boolean visit(JInstanceOf x, Mutator h) {
- JExpression expr = x.getExpression();
+ public boolean visit(JInstanceOf x, Context ctx) {
+ JExpression expr = x.getExpr();
parenPush(x, expr);
- expr.traverse(this);
+ accept(expr);
parenPop(x, expr);
print(CHARS_INSTANCEOF);
- printTypeName(x.testType);
+ printTypeName(x.getTestType());
return false;
}
// @Override
- public boolean visit(JInterfaceType x) {
+ public boolean visit(JInterfaceType x, Context ctx) {
print(CHARS_INTERFACE);
printTypeName(x);
space();
@@ -518,27 +518,27 @@
}
// @Override
- public boolean visit(JIntLiteral x, Mutator h) {
- print(Integer.toString(x.value).toCharArray());
+ public boolean visit(JIntLiteral x, Context ctx) {
+ print(Integer.toString(x.getValue()).toCharArray());
return false;
}
// @Override
- public boolean visit(JLabel x) {
+ public boolean visit(JLabel x, Context ctx) {
printName(x);
return false;
}
// @Override
- public boolean visit(JLabeledStatement x) {
- x.label.traverse(this);
+ public boolean visit(JLabeledStatement x, Context ctx) {
+ accept(x.getLabel());
print(" : ");
- x.body.traverse(this);
+ accept(x.getBody());
return false;
}
// @Override
- public boolean visit(JLocal x) {
+ public boolean visit(JLocal x, Context ctx) {
printFinalFlag(x);
printType(x);
space();
@@ -547,44 +547,44 @@
}
// @Override
- public boolean visit(JLocalDeclarationStatement x) {
+ public boolean visit(JLocalDeclarationStatement x, Context ctx) {
if (!suppressType) {
- x.getLocalRef().getTarget().traverse(this);
+ accept(x.getLocalRef().getTarget());
} else {
- x.getLocalRef().traverse(this);
+ accept(x.getLocalRef());
}
JExpression initializer = x.getInitializer();
if (initializer != null) {
print(" = ");
- initializer.traverse(this);
+ accept(initializer);
}
return false;
}
// @Override
- public boolean visit(JLocalRef x, Mutator h) {
- printName(x.local);
+ public boolean visit(JLocalRef x, Context ctx) {
+ printName(x.getLocal());
return false;
}
// @Override
- public boolean visit(JLongLiteral x, Mutator h) {
- printLongLiteral(x.value);
+ public boolean visit(JLongLiteral x, Context ctx) {
+ printLongLiteral(x.getValue());
return false;
}
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
return printMethodHeader(x);
}
// @Override
- public boolean visit(JMethodCall x, Mutator h) {
+ public boolean visit(JMethodCall x, Context ctx) {
JExpression instance = x.getInstance();
JMethod target = x.getTarget();
if (instance != null) {
parenPush(x, instance);
- instance.traverse(this);
+ accept(instance);
parenPop(x, instance);
} else {
printTypeName(target.getEnclosingType());
@@ -596,13 +596,13 @@
printName(target);
}
lparen();
- visitCollectionWithCommas(x.args.iterator());
+ visitCollectionWithCommas(x.getArgs().iterator());
rparen();
return false;
}
// @Override
- public boolean visit(JMultiExpression x, Mutator m) {
+ public boolean visit(JMultiExpression x, Context ctx) {
lparen();
visitCollectionWithCommas(x.exprs.iterator());
rparen();
@@ -610,18 +610,18 @@
}
// @Override
- public boolean visit(JNewArray x, Mutator h) {
+ public boolean visit(JNewArray x, Context ctx) {
print(CHARS_NEW);
- printTypeName(x.getArrayType().leafType);
+ printTypeName(x.getArrayType().getLeafType());
if (x.initializers != null) {
print('{');
visitCollectionWithCommas(x.initializers.iterator());
print('}');
} else {
for (int i = 0; i < x.dims.size(); ++i) {
- JExpression expr = x.dims.getExpr(i);
+ JExpression expr = (JExpression) x.dims.get(i);
print('[');
- expr.traverse(this);
+ accept(expr);
print(']');
}
}
@@ -629,7 +629,7 @@
}
// @Override
- public boolean visit(JNewInstance x, Mutator h) {
+ public boolean visit(JNewInstance x, Context ctx) {
print(CHARS_NEW);
printType(x);
lparen();
@@ -638,19 +638,19 @@
}
// @Override
- public boolean visit(JNullLiteral x, Mutator h) {
+ public boolean visit(JNullLiteral x, Context ctx) {
print(CHARS_NULL);
return false;
}
// @Override
- public boolean visit(JNullType x) {
+ public boolean visit(JNullType x, Context ctx) {
printTypeName(x);
return false;
}
// @Override
- public boolean visit(JParameter x) {
+ public boolean visit(JParameter x, Context ctx) {
printType(x);
space();
printName(x);
@@ -658,72 +658,72 @@
}
// @Override
- public boolean visit(JParameterRef x, Mutator h) {
+ public boolean visit(JParameterRef x, Context ctx) {
printName(x.getTarget());
return false;
}
// @Override
- public boolean visit(JPostfixOperation x, Mutator h) {
+ public boolean visit(JPostfixOperation x, Context ctx) {
// TODO(later): associativity
JExpression arg = x.getArg();
parenPush(x, arg);
- arg.traverse(this);
+ accept(arg);
parenPop(x, arg);
- print(x.op.getSymbol());
+ print(x.getOp().getSymbol());
return false;
}
// @Override
- public boolean visit(JPrefixOperation x, Mutator h) {
+ public boolean visit(JPrefixOperation x, Context ctx) {
// TODO(later): associativity
- print(x.op.getSymbol());
+ print(x.getOp().getSymbol());
JExpression arg = x.getArg();
parenPush(x, arg);
- arg.traverse(this);
+ accept(arg);
parenPop(x, arg);
return false;
}
// @Override
- public boolean visit(JPrimitiveType x) {
+ public boolean visit(JPrimitiveType x, Context ctx) {
printTypeName(x);
return false;
}
// @Override
- public boolean visit(JProgram x) {
+ public boolean visit(JProgram x, Context ctx) {
print("<JProgram>");
return false;
}
// @Override
- public boolean visit(JReturnStatement x) {
+ public boolean visit(JReturnStatement x, Context ctx) {
print(CHARS_RETURN);
- if (x.getExpression() != null) {
+ if (x.getExpr() != null) {
space();
- x.getExpression().traverse(this);
+ accept(x.getExpr());
}
return false;
}
// @Override
- public boolean visit(JsniFieldRef x) {
- return visit(x.getField());
+ public boolean visit(JsniFieldRef x, Context ctx) {
+ return visit(x.getField(), ctx);
}
// @Override
- public boolean visit(JsniMethod x) {
+ public boolean visit(JsniMethod x, Context ctx) {
return printMethodHeader(x);
}
// @Override
- public boolean visit(JsniMethodRef x) {
+ public boolean visit(JsniMethodRef x, Context ctx) {
return printMethodHeader(x.getTarget());
}
// @Override
- public boolean visit(JsonArray x, Mutator m) {
+ public boolean visit(JsonArray x, Context ctx) {
print('[');
visitCollectionWithCommas(x.exprs.iterator());
print(']');
@@ -731,7 +731,7 @@
}
// @Override
- public boolean visit(JsonObject x, Mutator m) {
+ public boolean visit(JsonObject x, Context ctx) {
print('{');
visitCollectionWithCommas(x.propInits.iterator());
print('}');
@@ -739,79 +739,79 @@
}
// @Override
- public boolean visit(JsonPropInit x) {
- x.labelExpr.traverse(this);
+ public boolean visit(JsonPropInit x, Context ctx) {
+ accept(x.labelExpr);
print(':');
- x.valueExpr.traverse(this);
+ accept(x.valueExpr);
return false;
}
// @Override
- public boolean visit(JStringLiteral x, Mutator h) {
- printStringLiteral(x.value);
+ public boolean visit(JStringLiteral x, Context ctx) {
+ printStringLiteral(x.getValue());
return false;
}
// @Override
- public boolean visit(JSwitchStatement x) {
+ public boolean visit(JSwitchStatement x, Context ctx) {
print(CHARS_SWITCH);
lparen();
- x.getExpression().traverse(this);
+ accept(x.getExpr());
rparen();
space();
- nestedStatementPush(x.body);
- x.body.traverse(this);
- nestedStatementPop(x.body);
+ nestedStatementPush(x.getBody());
+ accept(x.getBody());
+ nestedStatementPop(x.getBody());
return false;
}
// @Override
- public boolean visit(JThisRef x, Mutator h) {
+ public boolean visit(JThisRef x, Context ctx) {
print(CHARS_THIS);
return false;
}
// @Override
- public boolean visit(JThrowStatement x) {
+ public boolean visit(JThrowStatement x, Context ctx) {
print(CHARS_THROW);
- if (x.getExpression() != null) {
+ if (x.getExpr() != null) {
space();
- x.getExpression().traverse(this);
+ accept(x.getExpr());
}
return false;
}
// @Override
- public boolean visit(JTryStatement x) {
+ public boolean visit(JTryStatement x, Context ctx) {
print(CHARS_TRY);
- x.tryBlock.traverse(this);
- for (int i = 0, c = x.catchArgs.size(); i < c; ++i) {
+ accept(x.getTryBlock());
+ for (int i = 0, c = x.getCatchArgs().size(); i < c; ++i) {
print(CHARS_CATCH);
lparen();
- JLocalRef localRef = (JLocalRef) x.catchArgs.get(i);
- localRef.getTarget().traverse(this);
+ JLocalRef localRef = (JLocalRef) x.getCatchArgs().get(i);
+ accept(localRef.getTarget());
rparen();
space();
- JBlock block = (JBlock) x.catchBlocks.get(i);
- block.traverse(this);
+ JBlock block = (JBlock) x.getCatchBlocks().get(i);
+ accept(block);
}
- if (x.finallyBlock != null) {
+ if (x.getFinallyBlock() != null) {
print(CHARS_FINALLY);
- x.finallyBlock.traverse(this);
+ accept(x.getFinallyBlock());
}
return false;
}
// @Override
- public boolean visit(JWhileStatement x) {
+ public boolean visit(JWhileStatement x, Context ctx) {
print(CHARS_WHILE);
lparen();
- x.getTestExpr().traverse(this);
+ accept(x.getTestExpr());
rparen();
- if (x.body != null) {
- nestedStatementPush(x.body);
- x.body.traverse(this);
- nestedStatementPop(x.body);
+ if (x.getBody() != null) {
+ nestedStatementPush(x.getBody());
+ accept(x.getBody());
+ nestedStatementPop(x.getBody());
}
return false;
}
@@ -1061,12 +1061,12 @@
protected void visitCollectionWithCommas(Iterator/* <? extends JNode> */iter) {
if (iter.hasNext()) {
JNode node = (JNode) iter.next();
- node.traverse(this);
+ accept(node);
}
while (iter.hasNext()) {
print(CHARS_COMMA);
JNode node = (JNode) iter.next();
- node.traverse(this);
+ accept(node);
}
}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
index 8136f94..9ecd657 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/TypeTightener.java
@@ -15,6 +15,7 @@
*/
package com.google.gwt.dev.jjs.impl;
+import com.google.gwt.dev.jjs.ast.Context;
import com.google.gwt.dev.jjs.ast.JArrayRef;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JBinaryOperation;
@@ -28,6 +29,7 @@
import com.google.gwt.dev.jjs.ast.JLocalRef;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JMethodCall;
+import com.google.gwt.dev.jjs.ast.JModVisitor;
import com.google.gwt.dev.jjs.ast.JNewArray;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JParameter;
@@ -40,8 +42,6 @@
import com.google.gwt.dev.jjs.ast.JVariable;
import com.google.gwt.dev.jjs.ast.JVariableRef;
import com.google.gwt.dev.jjs.ast.JVisitor;
-import com.google.gwt.dev.jjs.ast.Mutator;
-import com.google.gwt.dev.jjs.ast.change.ChangeList;
import com.google.gwt.dev.jjs.ast.js.JsniFieldRef;
import com.google.gwt.dev.jjs.ast.js.JsniMethod;
import com.google.gwt.dev.jjs.ast.js.JsniMethodRef;
@@ -89,45 +89,45 @@
/**
* Replaces dangling null references with dummy calls.
*/
- public class FixDanglingRefsVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Replace dangling null references with dummy calls.");
+ public class FixDanglingRefsVisitor extends JModVisitor {
// @Override
- public void endVisit(JArrayRef x, Mutator m) {
+ public void endVisit(JArrayRef x, Context ctx) {
JExpression instance = x.getInstance();
if (instance.getType() == typeNull) {
if (!instance.hasSideEffects()) {
instance = program.getLiteralNull();
}
- JArrayRef arrayRef = new JArrayRef(program, instance,
- program.getLiteralInt(0));
- changeList.replaceExpression(m, arrayRef);
+ JArrayRef arrayRef = new JArrayRef(program, x.getSourceInfo(),
+ instance, program.getLiteralInt(0));
+ ctx.replaceMe(arrayRef);
}
}
// @Override
- public void endVisit(JFieldRef x, Mutator m) {
+ public void endVisit(JFieldRef x, Context ctx) {
JExpression instance = x.getInstance();
boolean isStatic = x.getField().isStatic();
if (isStatic && instance != null) {
// this doesn't really belong here, but while we're here let's remove
// non-side-effect qualifiers to statics
if (!instance.hasSideEffects()) {
- changeList.replaceExpression(x.instance, (JExpression) null);
+ JFieldRef fieldRef = new JFieldRef(program, x.getSourceInfo(), null,
+ x.getField(), x.getEnclosingType());
+ ctx.replaceMe(fieldRef);
}
} else if (!isStatic && instance.getType() == typeNull) {
if (!instance.hasSideEffects()) {
instance = program.getLiteralNull();
}
- JFieldRef fieldRef = new JFieldRef(program, instance,
- program.getNullField(), null);
- changeList.replaceExpression(m, fieldRef);
+ JFieldRef fieldRef = new JFieldRef(program, x.getSourceInfo(),
+ instance, program.getNullField(), null);
+ ctx.replaceMe(fieldRef);
}
}
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JMethodCall x, Context ctx) {
JExpression instance = x.getInstance();
JMethod method = x.getTarget();
boolean isStatic = method.isStatic();
@@ -136,30 +136,31 @@
// this doesn't really belong here, but while we're here let's remove
// non-side-effect qualifiers to statics
if (!instance.hasSideEffects()) {
- changeList.replaceExpression(x.instance, (JExpression) null);
+ JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
+ null, x.getTarget());
+ newCall.getArgs().addAll(x.getArgs());
+ ctx.replaceMe(newCall);
}
} else if (!isStatic && instance.getType() == typeNull) {
+ // bind null instance calls to the null method
if (!instance.hasSideEffects()) {
instance = program.getLiteralNull();
}
- JMethodCall call = new JMethodCall(program, instance,
- program.getNullMethod());
- changeList.replaceExpression(m, call);
- } else if (isStaticImpl && x.args.size() > 0
- && x.args.getExpr(0).getType() == typeNull) {
- instance = x.args.getExpr(0);
+ JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
+ instance, program.getNullMethod());
+ ctx.replaceMe(newCall);
+ } else if (isStaticImpl && x.getArgs().size() > 0
+ && ((JExpression) x.getArgs().get(0)).getType() == typeNull) {
+ // bind null instance calls to the null method for static impls
+ instance = (JExpression) x.getArgs().get(0);
if (!instance.hasSideEffects()) {
instance = program.getLiteralNull();
}
- JMethodCall call = new JMethodCall(program, instance,
- program.getNullMethod());
- changeList.replaceExpression(m, call);
+ JMethodCall newCall = new JMethodCall(program, x.getSourceInfo(),
+ instance, program.getNullMethod());
+ ctx.replaceMe(newCall);
}
}
-
- public ChangeList getChangeList() {
- return changeList;
- }
}
/**
* Record "type flow" information. Variables receive type flow via assignment.
@@ -180,7 +181,7 @@
private JMethod currentMethod;
// @Override
- public void endVisit(JBinaryOperation x, Mutator m) {
+ public void endVisit(JBinaryOperation x, Context ctx) {
if (x.isAssignment() && (x.getType() instanceof JReferenceType)) {
JExpression lhs = x.getLhs();
if (lhs instanceof JVariableRef) {
@@ -190,7 +191,7 @@
}
// @Override
- public void endVisit(JClassType x) {
+ public void endVisit(JClassType x, Context ctx) {
for (JClassType cur = x; cur != null; cur = cur.extnds) {
addImplementor(cur, x);
for (Iterator it = cur.implments.iterator(); it.hasNext();) {
@@ -201,7 +202,7 @@
}
// @Override
- public void endVisit(JField x) {
+ public void endVisit(JField x, Context ctx) {
if (x.constInitializer != null) {
addAssignment(x, x.constInitializer);
}
@@ -209,7 +210,7 @@
}
// @Override
- public void endVisit(JLocalDeclarationStatement x) {
+ public void endVisit(JLocalDeclarationStatement x, Context ctx) {
JExpression initializer = x.getInitializer();
if (initializer != null) {
addAssignment(x.getLocalRef().getTarget(), initializer);
@@ -217,7 +218,7 @@
}
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
for (int i = 0; i < x.overrides.size(); ++i) {
JMethod method = (JMethod) x.overrides.get(i);
addOverrider(method, x);
@@ -231,10 +232,10 @@
}
// @Override
- public void endVisit(JMethodCall x, Mutator m) {
+ public void endVisit(JMethodCall x, Context ctx) {
// All of the params in the target method are considered to be assigned by
// the arguments from the caller
- Iterator/* <JExpression> */argIt = x.args.iterator();
+ Iterator/* <JExpression> */argIt = x.getArgs().iterator();
ArrayList params = x.getTarget().params;
for (int i = 0; i < params.size(); ++i) {
JParameter param = (JParameter) params.get(i);
@@ -246,26 +247,26 @@
}
// @Override
- public void endVisit(JReturnStatement x) {
+ public void endVisit(JReturnStatement x, Context ctx) {
if (currentMethod.getType() instanceof JReferenceType) {
- addReturn(currentMethod, x.getExpression());
+ addReturn(currentMethod, x.getExpr());
}
}
// @Override
- public void endVisit(JsniFieldRef x) {
+ public void endVisit(JsniFieldRef x, Context ctx) {
// If this happens in JSNI, we can't make any type-tightening assumptions
// Fake an assignment-to-self to prevent tightening
addAssignment(x.getTarget(), x);
}
// @Override
- public void endVisit(JsniMethod x) {
- endVisit((JMethod) x);
+ public void endVisit(JsniMethod x, Context ctx) {
+ endVisit((JMethod) x, ctx);
}
// @Override
- public void endVisit(JsniMethodRef x) {
+ public void endVisit(JsniMethodRef x, Context ctx) {
// If this happens in JSNI, we can't make any type-tightening assumptions
// Fake an assignment-to-self on all args to prevent tightening
@@ -273,16 +274,16 @@
for (int i = 0; i < method.params.size(); ++i) {
JParameter param = (JParameter) method.params.get(i);
- addAssignment(param, new JParameterRef(program, param));
+ addAssignment(param, new JParameterRef(program, null, param));
}
}
// @Override
- public void endVisit(JTryStatement x) {
+ public void endVisit(JTryStatement x, Context ctx) {
// Never tighten args to catch blocks
// Fake an assignment-to-self to prevent tightening
- for (int i = 0; i < x.catchArgs.size(); ++i) {
- JLocalRef arg = (JLocalRef) x.catchArgs.get(i);
+ for (int i = 0; i < x.getCatchArgs().size(); ++i) {
+ JLocalRef arg = (JLocalRef) x.getCatchArgs().get(i);
addAssignment(arg.getTarget(), arg);
}
}
@@ -292,7 +293,7 @@
* param type in an overriding method if the declaring method is looser.
*/
// @Override
- public boolean visit(JMethod x) {
+ public boolean visit(JMethod x, Context ctx) {
currentMethod = x;
List/* <JMethod> */overrides = x.overrides;
@@ -374,16 +375,20 @@
* on it.
*/
public class TightenTypesVisitor extends JVisitor {
- private final ChangeList changeList = new ChangeList(
- "Tighten types on fields, locals, params, methods.");
+
+ private boolean didChange = false;
+
+ public boolean didChange() {
+ return didChange;
+ }
// @Override
- public void endVisit(JField x) {
+ public void endVisit(JField x, Context ctx) {
tighten(x);
}
// @Override
- public void endVisit(JLocal x) {
+ public void endVisit(JLocal x, Context ctx) {
tighten(x);
}
@@ -391,7 +396,7 @@
* Tighten based on return types and overrides.
*/
// @Override
- public void endVisit(JMethod x) {
+ public void endVisit(JMethod x, Context ctx) {
if (!(x.getType() instanceof JReferenceType)) {
return;
@@ -404,7 +409,8 @@
// tighten based on non-instantiability
if (!program.typeOracle.isInstantiatedType(refType)) {
- changeList.changeType(x, typeNull);
+ x.setType(typeNull);
+ didChange = true;
return;
}
@@ -436,34 +442,32 @@
JReferenceType resultType = program.generalizeTypes(typeList);
resultType = program.strongerType(refType, resultType);
if (refType != resultType) {
- changeList.changeType(x, resultType);
+ x.setType(resultType);
+ didChange = true;
}
}
// @Override
- public void endVisit(JNewArray x, Mutator m) {
+ public void endVisit(JNewArray x, Context ctx) {
// tighten leaf type based on non-instantiability
JArrayType arrayType = x.getArrayType();
JType leafType = arrayType.getLeafType();
if (leafType instanceof JReferenceType) {
if (!program.typeOracle.isInstantiatedType((JReferenceType) leafType)) {
arrayType = program.getTypeArray(typeNull, arrayType.getDims());
- changeList.changeType(x, arrayType);
+ x.setType(arrayType);
+ didChange = true;
}
}
}
// @Override
- public void endVisit(JParameter x) {
+ public void endVisit(JParameter x, Context ctx) {
tighten(x);
}
- public ChangeList getChangeList() {
- return changeList;
- }
-
// @Override
- public boolean visit(JClassType x) {
+ public boolean visit(JClassType x, Context ctx) {
// don't mess with classes used in code gen
if (program.specialTypes.contains(x)) {
return false;
@@ -471,7 +475,7 @@
return true;
}
- public boolean visit(JsniMethod x) {
+ public boolean visit(JsniMethod x, Context ctx) {
/*
* Explicitly NOT visiting native methods since we can't infer type
* information.
@@ -496,7 +500,8 @@
// tighten based on non-instantiability
if (!program.typeOracle.isInstantiatedType(refType)) {
- changeList.changeType(x, typeNull);
+ x.setType(typeNull);
+ didChange = true;
return;
}
@@ -545,7 +550,8 @@
JReferenceType resultType = program.generalizeTypes(typeList);
resultType = program.strongerType(refType, resultType);
if (refType != resultType) {
- changeList.changeType(x, resultType);
+ x.setType(resultType);
+ didChange = true;
}
}
}
@@ -578,26 +584,21 @@
}
private boolean execImpl() {
- boolean madeChanges = false;
RecordVisitor recorder = new RecordVisitor();
- program.traverse(recorder);
+ recorder.accept(program);
+ boolean madeChanges = false;
while (true) {
TightenTypesVisitor tightener = new TightenTypesVisitor();
- program.traverse(tightener);
- ChangeList changes = tightener.getChangeList();
- if (changes.empty()) {
- return madeChanges;
+ tightener.accept(program);
+ if (!tightener.didChange()) {
+ break;
}
- changes.apply();
madeChanges = true;
FixDanglingRefsVisitor fixer = new FixDanglingRefsVisitor();
- program.traverse(fixer);
- changes = fixer.getChangeList();
- if (!changes.empty()) {
- changes.apply();
- }
+ fixer.accept(program);
}
+ return madeChanges;
}
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java
index 8f20d8a..49580f9 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNode.java
@@ -25,6 +25,11 @@
*/
public abstract class JsNode implements JsVisitable {
+ public JsSourceInfo getInfo() {
+ // TODO: make this real
+ return null;
+ }
+
// @Override
public String toString() {
// no obfuscation
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/change/Change.java b/dev/core/src/com/google/gwt/dev/js/ast/JsSourceInfo.java
similarity index 66%
rename from dev/core/src/com/google/gwt/dev/jjs/ast/change/Change.java
rename to dev/core/src/com/google/gwt/dev/js/ast/JsSourceInfo.java
index ac79b3c..f159495 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/ast/change/Change.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsSourceInfo.java
@@ -13,18 +13,10 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.dev.jjs.ast.change;
-
-import com.google.gwt.core.ext.TreeLogger;
+package com.google.gwt.dev.js.ast;
/**
- * Interface implemented by classes that apply changes to a set of statements.
+ * Tracks file and line information for AST nodes.
*/
-public interface Change {
-
- void describe(TreeLogger logger, TreeLogger.Type type);
-
- void apply();
- // void undo();
- // void verify();
+public class JsSourceInfo {
}
diff --git a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
index d4659e4..08a923b 100644
--- a/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
+++ b/user/test/com/google/gwt/dev/jjs/test/CompilerTest.java
@@ -15,47 +15,47 @@
private static interface Fruit {
}
- private static class Granny extends Apple {
- }
-
private static class Fuji extends Apple {
}
- private static class SideEffectCauser {
- private static Object instance = new Object();
-
- public static Object causeClinitSideEffect() {
- return instance;
- }
-
- static {
- CompilerTest.sideEffectChecker++;
- }
- }
-
- private static class SideEffectCauser2 {
- public static Object causeClinitSideEffect() {
- return null;
- }
-
- static {
- CompilerTest.sideEffectChecker++;
- }
+ private static class Granny extends Apple {
}
private static class NonSideEffectCauser {
public static final String NOT_A_COMPILE_TIME_CONSTANT = null;
}
+ private static class SideEffectCauser {
+ private static Object instance = new Object();
+
+ static {
+ CompilerTest.sideEffectChecker++;
+ }
+
+ public static Object causeClinitSideEffect() {
+ return instance;
+ }
+ }
+
+ private static class SideEffectCauser2 {
+ static {
+ CompilerTest.sideEffectChecker++;
+ }
+
+ public static Object causeClinitSideEffect() {
+ return null;
+ }
+ }
+
private static final class UninstantiableType {
+ public Object field;
+
private UninstantiableType() {
}
public Object returnNull() {
return null;
}
-
- public Object field;
}
private static int sideEffectChecker;
@@ -137,6 +137,39 @@
assertEquals(null, checkRescued);
}
+ public void testDeadCode() {
+ while (returnFalse()) {
+ break;
+ }
+
+ do {
+ break;
+ } while (false);
+
+ do {
+ break;
+ } while (returnFalse());
+
+ for (; returnFalse();) {
+ }
+
+ boolean check = false;
+ for (check = true; returnFalse(); fail()) {
+ fail();
+ }
+ assertTrue(check);
+
+ if (returnFalse()) {
+ fail();
+ } else {
+ }
+
+ if (!returnFalse()) {
+ } else {
+ fail();
+ }
+ }
+
public void testDeadTypes() {
if (false) {
new Object() {
@@ -339,11 +372,23 @@
final String bar = cannotOptimize() ? "bar" : "foo";
String result = new Object() {
+ private String a = foo;
+
+ {
+ a = foo;
+ }
+
public String toString() {
return new Object() {
private static final String constantString = "wallawalla";
+ private String ai = foo;
+
+ {
+ ai = foo;
+ }
+
public String toString() {
// this line used to cause ICE due to no synthetic path to bar
bar.valueOf(false);
@@ -352,21 +397,9 @@
return foo + a + ai;
}
- {
- ai = foo;
- }
-
- private String ai = foo;
-
}.toString() + a;
}
- {
- a = foo;
- }
-
- private String a = foo;
-
}.toString();
assertEquals(result, "foofoofoofoo");
}
@@ -429,20 +462,10 @@
new B();
}
- public void testSwitchStatement() {
- switch (0) {
- case 0:
- int test; // used to cause an ICE
- break;
- }
- }
-
- public void testSubclassStaticInnerAndClinitOrdering() {
- new CheckSubclassStaticInnerAndClinitOrdering();
- }
-
public void testReturnStatementInCtor() {
class Foo {
+ int i;
+
Foo(int i) {
this.i = i;
if (i == 0)
@@ -451,20 +474,34 @@
return;
return;
}
-
- int i;
}
assertEquals(new Foo(0).i, 0);
assertEquals(new Foo(1).i, 1);
assertEquals(new Foo(2).i, 2);
}
+ public void testSubclassStaticInnerAndClinitOrdering() {
+ new CheckSubclassStaticInnerAndClinitOrdering();
+ }
+
+ public void testSwitchStatement() {
+ switch (0) {
+ case 0:
+ int test; // used to cause an ICE
+ break;
+ }
+ }
+
public void testUnaryPlus() {
int x, y = -7;
x = +y;
assertEquals(-7, x);
}
+ private boolean returnFalse() {
+ return false;
+ }
+
}
class A {
@@ -479,13 +516,11 @@
}
}
-class Outer {
- public static class StaticInner {
- }
-}
-
// This construct used to cause an ICE
class CheckSubclassStaticInnerAndClinitOrdering extends Outer.StaticInner {
+ private static class Foo {
+ }
+
private static final Foo FOO = new Foo();
public CheckSubclassStaticInnerAndClinitOrdering() {
@@ -496,7 +531,9 @@
// This used to be null due to clinit ordering issues
Assert.assertNotNull(foo);
}
+}
- private static class Foo {
+class Outer {
+ public static class StaticInner {
}
}