Added lvalue tracking based on context to the JS AST. Simplified JsInliner to use this.
Review by: bobv.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2223 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/js/JsInliner.java b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
index fedde1f..c0f3123 100644
--- a/dev/core/src/com/google/gwt/dev/js/JsInliner.java
+++ b/dev/core/src/com/google/gwt/dev/js/JsInliner.java
@@ -25,7 +25,6 @@
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContext;
-import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
@@ -40,6 +39,7 @@
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsNullLiteral;
+import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
@@ -52,7 +52,6 @@
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsSwitchMember;
import com.google.gwt.dev.js.ast.JsThisRef;
-import com.google.gwt.dev.js.ast.JsUnaryOperation;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVisitor;
import com.google.gwt.dev.js.ast.JsWhile;
@@ -1068,57 +1067,21 @@
this.parameterNames = parameterNames;
}
- /**
- * Disallow inlining if the left-hand side of an assignment is a parameter.
- */
@Override
- public void endVisit(JsBinaryOperation x, JsContext<JsExpression> ctx) {
- JsBinaryOperator op = x.getOperator();
-
- // Don't allow assignments to the left-hand side.
- if (op.isAssignment() && isParameter(x.getArg1())) {
+ public void endVisit(JsNameRef x, JsContext<JsExpression> ctx) {
+ if (ctx.isLvalue() && isParameter(x)) {
lvalue = true;
}
}
-
- /**
- * Delegates to {@link #checkUnaryOperation(JsUnaryOperation)}.
- */
- @Override
- public void endVisit(JsPostfixOperation x, JsContext<JsExpression> ctx) {
- checkUnaryOperation(x);
- }
-
- /**
- * Delegates to {@link #checkUnaryOperation(JsUnaryOperation)}.
- */
- @Override
- public void endVisit(JsPrefixOperation x, JsContext<JsExpression> ctx) {
- checkUnaryOperation(x);
- }
-
+
public boolean parameterAsLValue() {
return lvalue;
}
/**
- * Disallow modification of parameters via unary operations.
- */
- private void checkUnaryOperation(JsUnaryOperation x) {
- if (x.getOperator().isModifying() && isParameter(x.getArg())) {
- lvalue = true;
- }
- }
-
- /**
* Determine if a JsExpression is a JsNameRef that refers to a parameter.
*/
- private boolean isParameter(JsExpression e) {
- if (!(e instanceof JsNameRef)) {
- return false;
- }
-
- JsNameRef ref = (JsNameRef) e;
+ private boolean isParameter(JsNameRef ref) {
if (ref.getQualifier() != null) {
return false;
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java
index 3181b61..ce14a46 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsBinaryOperation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -103,7 +103,11 @@
public void traverse(JsVisitor v, JsContext<JsExpression> ctx) {
if (v.visit(this, ctx)) {
- arg1 = v.accept(arg1);
+ if (op.isAssignment()) {
+ arg1 = v.acceptLvalue(arg1);
+ } else {
+ arg1 = v.accept(arg1);
+ }
arg2 = v.accept(arg2);
}
v.endVisit(this, ctx);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java b/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java
index 2d90665..4d63cd1 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -32,6 +32,8 @@
void insertBefore(T node);
+ boolean isLvalue();
+
void removeMe();
void replaceMe(T node);
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
index 2e6d7dd1..61aa765 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsModVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -50,6 +50,10 @@
didChange = true;
}
+ public boolean isLvalue() {
+ return false;
+ }
+
public void removeMe() {
checkState();
collection.remove(index--);
@@ -85,6 +89,13 @@
}
}
+ private class LvalueContext extends NodeContext<JsExpression> {
+ @Override
+ public boolean isLvalue() {
+ return true;
+ }
+ }
+
private class NodeContext<T extends JsVisitable<T>> implements JsContext<T> {
private T node;
private boolean replaced;
@@ -105,6 +116,10 @@
throw new UnsupportedOperationException();
}
+ public boolean isLvalue() {
+ return false;
+ }
+
public void removeMe() {
throw new UnsupportedOperationException();
}
@@ -156,6 +171,10 @@
}
}
+ protected JsExpression doAcceptLvalue(JsExpression expr) {
+ return new LvalueContext().traverse(expr);
+ }
+
@Override
protected <T extends JsVisitable<T>> void doAcceptWithInsertRemove(
List<T> collection) {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java b/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java
index d28d897..6358f15 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsUnaryOperation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -51,7 +51,15 @@
}
public void traverse(JsVisitor v, JsContext<JsExpression> ctx) {
- arg = v.accept(arg);
+ if (op.isModifying()) {
+ /*
+ * The delete operator is practically like an assignment of undefined, so
+ * for practical purposes we're treating it as an lvalue.
+ */
+ arg = v.acceptLvalue(arg);
+ } else {
+ arg = v.accept(arg);
+ }
}
}
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
index b939349..a5a78fe 100644
--- a/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/js/ast/JsVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Google Inc.
+ * Copyright 2008 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
@@ -28,6 +28,37 @@
@SuppressWarnings("unused")
public class JsVisitor {
+ protected static final JsContext<JsExpression> LVALUE_CONTEXT = new JsContext<JsExpression>() {
+
+ public boolean canInsert() {
+ return false;
+ }
+
+ public boolean canRemove() {
+ return false;
+ }
+
+ public void insertAfter(JsExpression node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void insertBefore(JsExpression node) {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isLvalue() {
+ return true;
+ }
+
+ public void removeMe() {
+ throw new UnsupportedOperationException();
+ }
+
+ public void replaceMe(JsExpression node) {
+ throw new UnsupportedOperationException();
+ }
+ };
+
protected static final JsContext UNMODIFIABLE_CONTEXT = new JsContext() {
public boolean canInsert() {
@@ -46,6 +77,10 @@
throw new UnsupportedOperationException();
}
+ public boolean isLvalue() {
+ return false;
+ }
+
public void removeMe() {
throw new UnsupportedOperationException();
}
@@ -63,6 +98,10 @@
doAcceptList(collection);
}
+ public JsExpression acceptLvalue(JsExpression expr) {
+ return doAcceptLvalue(expr);
+ }
+
public final <T extends JsVisitable<T>> void acceptWithInsertRemove(
List<T> collection) {
doAcceptWithInsertRemove(collection);
@@ -372,6 +411,11 @@
}
}
+ protected JsExpression doAcceptLvalue(JsExpression expr) {
+ doTraverse(expr, LVALUE_CONTEXT);
+ return expr;
+ }
+
protected <T extends JsVisitable<T>> void doAcceptWithInsertRemove(
List<T> collection) {
for (Iterator<T> it = collection.iterator(); it.hasNext();) {