001    /*
002     * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.comp;
027    
028    import com.sun.tools.javac.tree.*;
029    import java.util.Iterator;
030    import java.util.NoSuchElementException;
031    import com.sun.tools.javac.util.List;
032    import static com.sun.tools.javac.tree.JCTree.*;
033    
034    /* for SEPARABLE */
035    import static com.sun.tools.javac.code.Flags.*;
036    
037    /** A class for environments, instances of which are passed as
038     *  arguments to tree visitors.  Environments refer to important ancestors
039     *  of the subtree that's currently visited, such as the enclosing method,
040     *  the enclosing class, or the enclosing toplevel node. They also contain
041     *  a generic component, represented as a type parameter, to carry further
042     *  information specific to individual passes.
043     *
044     *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
045     *  you write code that depends on this, you do so at your own risk.
046     *  This code and its internal interfaces are subject to change or
047     *  deletion without notice.</b>
048     */
049    public class Env<A> implements Iterable<Env<A>> {
050    
051        /** The next enclosing environment.
052         */
053        public Env<A> next;
054    
055        /** The environment enclosing the current class.
056         */
057        public Env<A> outer;
058    
059        /** The tree with which this environment is associated.
060         */
061        public JCTree tree;
062    
063        /** The enclosing toplevel tree.
064         */
065        public JCTree.JCCompilationUnit toplevel;
066    
067        /** The next enclosing class definition.
068         */
069        public JCTree.JCClassDecl enclClass;
070    
071        /** The next enclosing method definition.
072         */
073        public JCTree.JCMethodDecl enclMethod;
074    
075        // emw4: staging additions
076    
077        /** A list of all enclosing brackets, innermost to outermost
078         */
079        public List<JCExpression> enclBrackets;
080    
081        /** The escape under which we are operating, or null if there was no escape
082          * or if we entered a bracket inside an escape. */
083        public JCTree escape = null;
084        public int escapeCount = 0;
085        
086        /** A generic field for further information.
087         */
088        public A info;
089    
090        /** Is this an environment for evaluating a base clause?
091         */
092        public boolean baseClause = false;
093    
094        /** Create an outermost environment for a given (toplevel)tree,
095         *  with a given info field.
096         */
097        public Env(JCTree tree, A info) {
098            this.next = null;
099            this.outer = null;
100            this.tree = tree;
101            this.toplevel = null;
102            this.enclClass = null;
103            this.enclMethod = null;
104            this.enclBrackets = List.nil ();
105            this.escape = null;
106            this.escapeCount = 0;
107            this.info = info;
108        }
109    
110        /** Duplicate this environment, updating with given tree and info,
111         *  and copying all other fields.
112         */
113        public Env<A> dup(JCTree tree, A info) {
114            return dupto(new Env<A>(tree, info));
115        }
116    
117        /** Duplicate this environment into a given Environment,
118         *  using its tree and info, and copying all other fields.
119         */
120        public Env<A> dupto(Env<A> that) {
121            that.next = this;
122            that.outer = this.outer;
123            that.toplevel = this.toplevel;
124            that.enclClass = this.enclClass;
125            that.enclMethod = this.enclMethod;
126            that.enclBrackets = this.enclBrackets;
127            that.escape = this.escape; 
128            that.escapeCount = this.escapeCount;
129            return that;
130        }
131    
132        /** Duplicate this environment, updating with given tree,
133         *  and copying all other fields.
134         */
135        public Env<A> dup(JCTree tree) {
136            return dup(tree, this.info);
137        }
138    
139        // emw4: staging additions
140    
141        /** Duplicate this environment, updating with given tree and info
142         *  and adding a new bracket to enclBrackets, copying all other fields.
143         */
144        public Env<A> dupBracket(JCTree tree, A info, JCExpression bracket) {
145            Env <A> env = dup(tree, info);
146            env.enclBrackets = this.enclBrackets.prepend (bracket);
147            env.escape = null;
148            return env;
149        }
150    
151        /** Duplicate this environment, updating with given tree
152         *  and adding a new bracket to enclBrackets, copying all other fields.
153         */
154        public Env<A> dupBracket(JCTree tree, JCExpression bracket) {
155            return dupBracket (tree, this.info, bracket);
156        }
157    
158        /** Duplicate this environment, updating with given tree and info
159         *  and removing the most recent bracket from enclBrackets, copying all other fields.
160         */
161        public Env<A> dupEscape(JCTree tree, A info) {
162            Env <A> env = dup(tree, info);
163            assert (! enclBrackets.isEmpty ());
164            env.enclBrackets = this.enclBrackets.tail;
165            env.escape = tree;
166            env.escapeCount++;
167            return env;
168        }
169        
170        /** Duplicate this environment, updating with given tree
171         *  and removing the most recent bracket from enclBrackets,
172         *  copying all other fields.
173         */
174        public Env<A> dupEscape(JCTree tree) {
175            return dupEscape(tree, info);
176        }
177        
178        public int getLevel() {
179            return enclBrackets.size();
180        }
181    
182        /* FIXME: this should really find the most recent enclosing tree that is
183        ** - a method, in which case return true iff SEPARABLE is set
184        ** - an escape, in which case always return true
185        ** - a bracket, in which case return the safe field of that bracket
186        */
187        public boolean isEscapeSafe () {
188            boolean currentMethodEscapeSafe =
189                (enclMethod != null && (enclMethod.sym.flags() & SEPARABLE)!=0);
190            return ((currentMethodEscapeSafe && getLevel() == 0) || escape!=null);
191        }
192    
193        /** Return closest enclosing environment which points to a tree with given tag.
194         */
195        public Env<A> enclosing(int tag) {
196            Env<A> env1 = this;
197            while (env1 != null && env1.tree.getTag() != tag) env1 = env1.next;
198            return env1;
199        }
200    
201        public String toString() {
202            StringBuilder sb = new StringBuilder("Env[");
203            String[] lines;
204            sb.append(info);
205            sb.append("\n  escape=");
206            sb.append(escape);
207            sb.append("\n  escapeCount=");
208            sb.append(escapeCount);
209            sb.append("\n  brackets=");
210            for(JCExpression b: enclBrackets) {
211                lines = b.toString().split("\n");
212                for(String l: lines) {
213                    sb.append("\n    ");
214                    sb.append(l);
215                }
216            }
217            lines = tree.toString().split("\n");
218            for(String l: lines) {
219                sb.append("\n    ");
220                sb.append(l);
221            }
222            if (outer!=null) {
223                sb.append("\n  outer=");
224                lines = outer.toString().split("\n");
225                for(String l: lines) {
226                    sb.append("\n    ");
227                    sb.append(l);
228                }
229            }
230            sb.append("]");
231            return sb.toString();
232        }
233    
234        public Iterator<Env<A>> iterator() {
235            return new Iterator<Env<A>>() {
236                Env<A> next = Env.this;
237                public boolean hasNext() {
238                    return next.outer != null;
239                }
240                public Env<A> next() {
241                    if (hasNext()) {
242                        Env<A> current = next;
243                        next = current.outer;
244                        return current;
245                    }
246                    throw new NoSuchElementException();
247    
248                }
249                public void remove() {
250                    throw new UnsupportedOperationException();
251                }
252            };
253        }
254    }