src/jdk/nashorn/internal/ir/ForNode.java

Thu, 11 Jul 2013 18:33:33 +0200

author
attila
date
Thu, 11 Jul 2013 18:33:33 +0200
changeset 430
2c007a8bb0e7
parent 290
6fc7b51e83d6
child 952
6d5471a497fb
child 962
ac62e33a99b0
permissions
-rw-r--r--

8013925: Remove symbol fields from nodes that don't need them
Reviewed-by: jlaskey, lagergren

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.ir;
    28 import jdk.nashorn.internal.ir.annotations.Immutable;
    29 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    31 /**
    32  * IR representing a FOR statement.
    33  */
    34 @Immutable
    35 public final class ForNode extends LoopNode {
    36     /** Initialize expression. */
    37     private final Expression init;
    39     /** Test expression. */
    40     private final Expression modify;
    42     /** Iterator symbol. */
    43     private Symbol iterator;
    45     /** Is this a normal for loop? */
    46     public static final int IS_FOR      = 1 << 0;
    48     /** Is this a normal for in loop? */
    49     public static final int IS_FOR_IN   = 1 << 1;
    51     /** Is this a normal for each in loop? */
    52     public static final int IS_FOR_EACH = 1 << 2;
    54     private final int flags;
    56     /**
    57      * Constructor
    58      *
    59      * @param lineNumber line number
    60      * @param token      token
    61      * @param finish     finish
    62      * @param init       initialization expression
    63      * @param test       test
    64      * @param body       body
    65      * @param modify     modify
    66      * @param flags      flags
    67      */
    68     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) {
    69         super(lineNumber, token, finish, test, body, false);
    70         this.init   = init;
    71         this.modify = modify;
    72         this.flags  = flags;
    73     }
    75     private ForNode(final ForNode forNode, final Expression init, final Expression test, final Block body, final Expression modify, final int flags, final boolean controlFlowEscapes) {
    76         super(forNode, test, body, controlFlowEscapes);
    77         this.init   = init;
    78         this.modify = modify;
    79         this.flags  = flags;
    80         this.iterator = forNode.iterator; //TODO is this acceptable? symbols are never cloned, just copied as references
    81     }
    83     @Override
    84     public Node ensureUniqueLabels(LexicalContext lc) {
    85         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
    86     }
    88     @Override
    89     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
    90         if (visitor.enterForNode(this)) {
    91             return visitor.leaveForNode(
    92                 setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
    93                 setTest(lc, test == null ? null : (Expression)test.accept(visitor)).
    94                 setModify(lc, modify == null ? null : (Expression)modify.accept(visitor)).
    95                 setBody(lc, (Block)body.accept(visitor)));
    96         }
    98         return this;
    99     }
   101     @Override
   102     public void toString(final StringBuilder sb) {
   103         sb.append("for (");
   105         if (isForIn()) {
   106             init.toString(sb);
   107             sb.append(" in ");
   108             modify.toString(sb);
   109         } else {
   110             if (init != null) {
   111                 init.toString(sb);
   112             }
   113             sb.append("; ");
   114             if (test != null) {
   115                 test.toString(sb);
   116             }
   117             sb.append("; ");
   118             if (modify != null) {
   119                 modify.toString(sb);
   120             }
   121         }
   123         sb.append(')');
   124     }
   126     @Override
   127     public boolean hasGoto() {
   128         return !isForIn() && test == null;
   129     }
   131     @Override
   132     public boolean mustEnter() {
   133         if (isForIn()) {
   134             return false; //may be an empty set to iterate over, then we skip the loop
   135         }
   136         return test == null;
   137     }
   139     /**
   140      * Get the initialization expression for this for loop
   141      * @return the initialization expression
   142      */
   143     public Expression getInit() {
   144         return init;
   145     }
   147     /**
   148      * Reset the initialization expression for this for loop
   149      * @param lc lexical context
   150      * @param init new initialization expression
   151      * @return new for node if changed or existing if not
   152      */
   153     public ForNode setInit(final LexicalContext lc, final Expression init) {
   154         if (this.init == init) {
   155             return this;
   156         }
   157         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
   158     }
   160     /**
   161      * Is this a for in construct rather than a standard init;condition;modification one
   162      * @return true if this is a for in constructor
   163      */
   164     public boolean isForIn() {
   165         return (flags & IS_FOR_IN) != 0;
   166     }
   168     /**
   169      * Flag this to be a for in construct
   170      * @param lc lexical context
   171      * @return new for node if changed or existing if not
   172      */
   173     public ForNode setIsForIn(final LexicalContext lc) {
   174         return setFlags(lc, flags | IS_FOR_IN);
   175     }
   177     /**
   178      * Is this a for each construct, known from e.g. Rhino. This will be a for of construct
   179      * in ECMAScript 6
   180      * @return true if this is a for each construct
   181      */
   182     public boolean isForEach() {
   183         return (flags & IS_FOR_EACH) != 0;
   184     }
   186     /**
   187      * Flag this to be a for each construct
   188      * @param lc lexical context
   189      * @return new for node if changed or existing if not
   190      */
   191     public ForNode setIsForEach(final LexicalContext lc) {
   192         return setFlags(lc, flags | IS_FOR_EACH);
   193     }
   195     /**
   196      * If this is a for in or for each construct, there is an iterator symbol
   197      * @return the symbol for the iterator to be used, or null if none exists
   198      */
   199     public Symbol getIterator() {
   200         return iterator;
   201     }
   203     /**
   204      * Assign an iterator symbol to this ForNode. Used for for in and for each constructs
   205      * @param iterator the iterator symbol
   206      */
   207     public void setIterator(final Symbol iterator) {
   208         this.iterator = iterator;
   209     }
   211     /**
   212      * Get the modification expression for this ForNode
   213      * @return the modification expression
   214      */
   215     public Expression getModify() {
   216         return modify;
   217     }
   219     /**
   220      * Reset the modification expression for this ForNode
   221      * @param lc lexical context
   222      * @param modify new modification expression
   223      * @return new for node if changed or existing if not
   224      */
   225     public ForNode setModify(final LexicalContext lc, final Expression modify) {
   226         if (this.modify == modify) {
   227             return this;
   228         }
   229         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
   230     }
   232     @Override
   233     public Expression getTest() {
   234         return test;
   235     }
   237     @Override
   238     public ForNode setTest(final LexicalContext lc, final Expression test) {
   239         if (this.test == test) {
   240             return this;
   241         }
   242         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
   243     }
   245     @Override
   246     public Block getBody() {
   247         return body;
   248     }
   250     @Override
   251     public ForNode setBody(final LexicalContext lc, final Block body) {
   252         if (this.body == body) {
   253             return this;
   254         }
   255         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
   256     }
   258     @Override
   259     public ForNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes) {
   260         if (this.controlFlowEscapes == controlFlowEscapes) {
   261             return this;
   262         }
   263         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
   264     }
   266     private ForNode setFlags(final LexicalContext lc, final int flags) {
   267         if (this.flags == flags) {
   268             return this;
   269         }
   270         return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
   271     }
   273 }

mercurial