< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java

Print this page




  34 @Immutable
  35 public final class ForNode extends LoopNode {
  36     private static final long serialVersionUID = 1L;
  37 
  38     /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a
  39      * for-in statement. */
  40     private final Expression init;
  41 
  42     /** Modify expression for an ordinary statement, or the source of the iterator in the for-in statement. */
  43     private final JoinPredecessorExpression modify;
  44 
  45     /** Iterator symbol. */
  46     private final Symbol iterator;
  47 
  48     /** Is this a normal for in loop? */
  49     public static final int IS_FOR_IN           = 1 << 0;
  50 
  51     /** Is this a normal for each in loop? */
  52     public static final int IS_FOR_EACH         = 1 << 1;
  53 



  54     /** Does this loop need a per-iteration scope because its init contain a LET declaration? */
  55     public static final int PER_ITERATION_SCOPE = 1 << 2;
  56 
  57     private final int flags;
  58 
  59     /**
  60      * Constructs a ForNode
  61      *
  62      * @param lineNumber The line number of header
  63      * @param token      The for token
  64      * @param finish     The last character of the for node
  65      * @param body       The body of the for node
  66      * @param flags      The flags
  67      */
  68     public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags){
  69         this(lineNumber, token, finish, body, flags, null, null, null);
  70     }
  71 
  72     /**
  73      * Constructor
  74      *
  75      * @param lineNumber The line number of header


 110         if (visitor.enterForNode(this)) {
 111             return visitor.leaveForNode(
 112                 setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
 113                 setTest(lc, test == null ? null : (JoinPredecessorExpression)test.accept(visitor)).
 114                 setModify(lc, modify == null ? null : (JoinPredecessorExpression)modify.accept(visitor)).
 115                 setBody(lc, (Block)body.accept(visitor)));
 116         }
 117 
 118         return this;
 119     }
 120 
 121     @Override
 122     public void toString(final StringBuilder sb, final boolean printTypes) {
 123         sb.append("for");
 124         LocalVariableConversion.toString(conversion, sb).append(' ');
 125 
 126         if (isForIn()) {
 127             init.toString(sb, printTypes);
 128             sb.append(" in ");
 129             modify.toString(sb, printTypes);




 130         } else {
 131             if (init != null) {
 132                 init.toString(sb, printTypes);
 133             }
 134             sb.append("; ");
 135             if (test != null) {
 136                 test.toString(sb, printTypes);
 137             }
 138             sb.append("; ");
 139             if (modify != null) {
 140                 modify.toString(sb, printTypes);
 141             }
 142         }
 143 
 144         sb.append(')');
 145     }
 146 
 147     @Override
 148     public boolean hasGoto() {
 149         return !isForIn() && test == null;
 150     }
 151 
 152     @Override
 153     public boolean mustEnter() {
 154         if (isForIn()) {
 155             return false; //may be an empty set to iterate over, then we skip the loop
 156         }
 157         return test == null;
 158     }
 159 
 160     /**
 161      * Get the initialization expression for this for loop
 162      * @return the initialization expression
 163      */
 164     public Expression getInit() {
 165         return init;
 166     }
 167 
 168     /**
 169      * Reset the initialization expression for this for loop
 170      * @param lc lexical context
 171      * @param init new initialization expression
 172      * @return new for node if changed or existing if not
 173      */
 174     public ForNode setInit(final LexicalContext lc, final Expression init) {
 175         if (this.init == init) {
 176             return this;
 177         }
 178         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
 179     }
 180 
 181     /**
 182      * Is this a for in construct rather than a standard init;condition;modification one
 183      * @return true if this is a for in constructor
 184      */
 185     public boolean isForIn() {
 186         return (flags & IS_FOR_IN) != 0;
 187     }

















 188     /**
 189      * Is this a for each construct, known from e.g. Rhino. This will be a for of construct
 190      * in ECMAScript 6
 191      * @return true if this is a for each construct
 192      */
 193     public boolean isForEach() {
 194         return (flags & IS_FOR_EACH) != 0;
 195     }
 196 
 197     /**
 198      * If this is a for in or for each construct, there is an iterator symbol
 199      * @return the symbol for the iterator to be used, or null if none exists
 200      */
 201     public Symbol getIterator() {
 202         return iterator;
 203     }
 204 
 205     /**
 206      * Assign an iterator symbol to this ForNode. Used for for in and for each constructs
 207      * @param lc the current lexical context


 266     }
 267 
 268     @Override
 269     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
 270         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
 271     }
 272 
 273     @Override
 274     public boolean hasPerIterationScope() {
 275         return (flags & PER_ITERATION_SCOPE) != 0;
 276     }
 277 
 278     /**
 279      * Returns true if this for-node needs the scope creator of its containing block to create
 280      * per-iteration scope. This is only true for for-in loops with lexical declarations.
 281      *
 282      * @see Block#providesScopeCreator()
 283      * @return true if the containing block's scope object creator is required in codegen
 284      */
 285     public boolean needsScopeCreator() {
 286         return isForIn() && hasPerIterationScope();
 287     }
 288 }


  34 @Immutable
  35 public final class ForNode extends LoopNode {
  36     private static final long serialVersionUID = 1L;
  37 
  38     /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a
  39      * for-in statement. */
  40     private final Expression init;
  41 
  42     /** Modify expression for an ordinary statement, or the source of the iterator in the for-in statement. */
  43     private final JoinPredecessorExpression modify;
  44 
  45     /** Iterator symbol. */
  46     private final Symbol iterator;
  47 
  48     /** Is this a normal for in loop? */
  49     public static final int IS_FOR_IN           = 1 << 0;
  50 
  51     /** Is this a normal for each in loop? */
  52     public static final int IS_FOR_EACH         = 1 << 1;
  53 
  54     /** Is this a ES6 for-of loop? */
  55     public static final int IS_FOR_OF           = 1 << 2;
  56 
  57     /** Does this loop need a per-iteration scope because its init contain a LET declaration? */
  58     public static final int PER_ITERATION_SCOPE = 1 << 3;
  59 
  60     private final int flags;
  61 
  62     /**
  63      * Constructs a ForNode
  64      *
  65      * @param lineNumber The line number of header
  66      * @param token      The for token
  67      * @param finish     The last character of the for node
  68      * @param body       The body of the for node
  69      * @param flags      The flags
  70      */
  71     public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags){
  72         this(lineNumber, token, finish, body, flags, null, null, null);
  73     }
  74 
  75     /**
  76      * Constructor
  77      *
  78      * @param lineNumber The line number of header


 113         if (visitor.enterForNode(this)) {
 114             return visitor.leaveForNode(
 115                 setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
 116                 setTest(lc, test == null ? null : (JoinPredecessorExpression)test.accept(visitor)).
 117                 setModify(lc, modify == null ? null : (JoinPredecessorExpression)modify.accept(visitor)).
 118                 setBody(lc, (Block)body.accept(visitor)));
 119         }
 120 
 121         return this;
 122     }
 123 
 124     @Override
 125     public void toString(final StringBuilder sb, final boolean printTypes) {
 126         sb.append("for");
 127         LocalVariableConversion.toString(conversion, sb).append(' ');
 128 
 129         if (isForIn()) {
 130             init.toString(sb, printTypes);
 131             sb.append(" in ");
 132             modify.toString(sb, printTypes);
 133         } else if (isForOf()) {
 134             init.toString(sb, printTypes);
 135             sb.append(" of ");
 136             modify.toString(sb, printTypes);
 137         } else {
 138             if (init != null) {
 139                 init.toString(sb, printTypes);
 140             }
 141             sb.append("; ");
 142             if (test != null) {
 143                 test.toString(sb, printTypes);
 144             }
 145             sb.append("; ");
 146             if (modify != null) {
 147                 modify.toString(sb, printTypes);
 148             }
 149         }
 150 
 151         sb.append(')');
 152     }
 153 
 154     @Override
 155     public boolean hasGoto() {
 156         return !isForInOrOf() && test == null;
 157     }
 158 
 159     @Override
 160     public boolean mustEnter() {
 161         if (isForInOrOf()) {
 162             return false; //may be an empty set to iterate over, then we skip the loop
 163         }
 164         return test == null;
 165     }
 166 
 167     /**
 168      * Get the initialization expression for this for loop
 169      * @return the initialization expression
 170      */
 171     public Expression getInit() {
 172         return init;
 173     }
 174 
 175     /**
 176      * Reset the initialization expression for this for loop
 177      * @param lc lexical context
 178      * @param init new initialization expression
 179      * @return new for node if changed or existing if not
 180      */
 181     public ForNode setInit(final LexicalContext lc, final Expression init) {
 182         if (this.init == init) {
 183             return this;
 184         }
 185         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
 186     }
 187 
 188     /**
 189      * Is this a for in construct rather than a standard init;condition;modification one
 190      * @return true if this is a for in constructor
 191      */
 192     public boolean isForIn() {
 193         return (flags & IS_FOR_IN) != 0;
 194     }
 195 
 196     /**
 197      * Is this a for-of loop?
 198      * @return true if this is a for-of loop
 199      */
 200     public boolean isForOf() {
 201         return (flags & IS_FOR_OF) != 0;
 202     }
 203 
 204     /**
 205      * Is this a for-in or for-of statement?
 206      * @return true if this is a for-in or for-of loop
 207      */
 208     public boolean isForInOrOf() {
 209         return isForIn() || isForOf();
 210     }
 211 
 212     /**
 213      * Is this a for each construct, known from e.g. Rhino. This will be a for of construct
 214      * in ECMAScript 6
 215      * @return true if this is a for each construct
 216      */
 217     public boolean isForEach() {
 218         return (flags & IS_FOR_EACH) != 0;
 219     }
 220 
 221     /**
 222      * If this is a for in or for each construct, there is an iterator symbol
 223      * @return the symbol for the iterator to be used, or null if none exists
 224      */
 225     public Symbol getIterator() {
 226         return iterator;
 227     }
 228 
 229     /**
 230      * Assign an iterator symbol to this ForNode. Used for for in and for each constructs
 231      * @param lc the current lexical context


 290     }
 291 
 292     @Override
 293     JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
 294         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion, iterator));
 295     }
 296 
 297     @Override
 298     public boolean hasPerIterationScope() {
 299         return (flags & PER_ITERATION_SCOPE) != 0;
 300     }
 301 
 302     /**
 303      * Returns true if this for-node needs the scope creator of its containing block to create
 304      * per-iteration scope. This is only true for for-in loops with lexical declarations.
 305      *
 306      * @see Block#providesScopeCreator()
 307      * @return true if the containing block's scope object creator is required in codegen
 308      */
 309     public boolean needsScopeCreator() {
 310         return isForInOrOf() && hasPerIterationScope();
 311     }
 312 }
< prev index next >