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 }