nashorn/src/jdk/nashorn/internal/ir/ForNode.java
changeset 24751 ccbd9cd3f720
parent 18867 bc91e3fcc5ba
child 24759 31aed7d9c02a
--- a/nashorn/src/jdk/nashorn/internal/ir/ForNode.java	Mon May 05 14:17:20 2014 +0200
+++ b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java	Tue May 13 11:30:40 2014 +0200
@@ -33,11 +33,12 @@
  */
 @Immutable
 public final class ForNode extends LoopNode {
-    /** Initialize expression. */
+    /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a
+     * for-in statement. */
     private final Expression init;
 
-    /** Test expression. */
-    private final Expression modify;
+    /** Modify expression for an ordinary statement, or the source of the iterator in the for-in statement. */
+    private final JoinPredecessorExpression modify;
 
     /** Iterator symbol. */
     private Symbol iterator;
@@ -59,30 +60,30 @@
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param init       initialization expression
-     * @param test       test
      * @param body       body
-     * @param modify     modify
      * @param flags      flags
      */
-    public ForNode(final int lineNumber, final long token, final int finish, final Expression init, final Expression test, final Block body, final Expression modify, final int flags) {
-        super(lineNumber, token, finish, test, body, false);
+    public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags) {
+        super(lineNumber, token, finish, body, false);
+        this.flags  = flags;
+        this.init = null;
+        this.modify = null;
+    }
+
+    private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
+            final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, LocalVariableConversion conversion) {
+        super(forNode, test, body, controlFlowEscapes, conversion);
         this.init   = init;
         this.modify = modify;
         this.flags  = flags;
-    }
-
-    private ForNode(final ForNode forNode, final Expression init, final Expression test, final Block body, final Expression modify, final int flags, final boolean controlFlowEscapes) {
-        super(forNode, test, body, controlFlowEscapes);
-        this.init   = init;
-        this.modify = modify;
-        this.flags  = flags;
-        this.iterator = forNode.iterator; //TODO is this acceptable? symbols are never cloned, just copied as references
+        // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally
+        // is executed.
+        this.iterator = forNode.iterator;
     }
 
     @Override
     public Node ensureUniqueLabels(LexicalContext lc) {
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -90,8 +91,8 @@
         if (visitor.enterForNode(this)) {
             return visitor.leaveForNode(
                 setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
-                setTest(lc, test == null ? null : (Expression)test.accept(visitor)).
-                setModify(lc, modify == null ? null : (Expression)modify.accept(visitor)).
+                setTest(lc, test == null ? null : (JoinPredecessorExpression)test.accept(visitor)).
+                setModify(lc, modify == null ? null : (JoinPredecessorExpression)modify.accept(visitor)).
                 setBody(lc, (Block)body.accept(visitor)));
         }
 
@@ -100,7 +101,8 @@
 
     @Override
     public void toString(final StringBuilder sb) {
-        sb.append("for (");
+        sb.append("for");
+        LocalVariableConversion.toString(conversion, sb).append(' ');
 
         if (isForIn()) {
             init.toString(sb);
@@ -154,7 +156,7 @@
         if (this.init == init) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     /**
@@ -212,7 +214,7 @@
      * Get the modification expression for this ForNode
      * @return the modification expression
      */
-    public Expression getModify() {
+    public JoinPredecessorExpression getModify() {
         return modify;
     }
 
@@ -222,24 +224,19 @@
      * @param modify new modification expression
      * @return new for node if changed or existing if not
      */
-    public ForNode setModify(final LexicalContext lc, final Expression modify) {
+    public ForNode setModify(final LexicalContext lc, final JoinPredecessorExpression modify) {
         if (this.modify == modify) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
-    public Expression getTest() {
-        return test;
-    }
-
-    @Override
-    public ForNode setTest(final LexicalContext lc, final Expression test) {
+    public ForNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) {
         if (this.test == test) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -252,7 +249,7 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -260,14 +257,18 @@
         if (this.controlFlowEscapes == controlFlowEscapes) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     private ForNode setFlags(final LexicalContext lc, final int flags) {
         if (this.flags == flags) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
+    @Override
+    JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+    }
 }