001: // (C) Copyright 2001 Samuele Pedroni
002:
003: package org.python.compiler;
004:
005: import org.python.parser.*;
006: import org.python.parser.ast.*;
007: import java.util.*;
008:
009: public class ScopesCompiler extends Visitor implements ScopeConstants {
010:
011: private CompilationContext code_compiler;
012:
013: private Stack scopes;
014: private ScopeInfo cur = null;
015: private Hashtable nodeScopes;
016:
017: private int level = 0;
018: private int func_level = 0;
019:
020: public ScopesCompiler(CompilationContext code_compiler,
021: Hashtable nodeScopes) {
022: this .code_compiler = code_compiler;
023: this .nodeScopes = nodeScopes;
024: scopes = new Stack();
025: }
026:
027: public void beginScope(String name, int kind, SimpleNode node,
028: ArgListCompiler ac) {
029: if (cur != null) {
030: scopes.push(cur);
031: }
032: if (kind == FUNCSCOPE)
033: func_level++;
034: cur = new ScopeInfo(name, node, level++, kind, func_level, ac);
035: nodeScopes.put(node, cur);
036: }
037:
038: public void endScope() throws Exception {
039: if (cur.kind == FUNCSCOPE)
040: func_level--;
041: level--;
042: ScopeInfo up = (!scopes.empty()) ? (ScopeInfo) scopes.pop()
043: : null;
044: //Go into the stack to find a non class containing scope to use making the closure
045: //See PEP 227
046: int dist = 1;
047: ScopeInfo referenceable = up;
048: for (int i = scopes.size() - 1; i >= 0
049: && referenceable.kind == CLASSSCOPE; i--, dist++) {
050: referenceable = ((ScopeInfo) scopes.get(i));
051: }
052: cur.cook(referenceable, dist, code_compiler);
053: cur.dump(); // dbg
054: cur = up;
055: }
056:
057: public void parse(SimpleNode node) throws Exception {
058: try {
059: visit(node);
060: } catch (Throwable t) {
061: throw org.python.core.parser.fixParseError(null, t,
062: code_compiler.getFilename());
063: }
064: }
065:
066: public Object visitInteractive(Interactive node) throws Exception {
067: beginScope("<single-top>", TOPSCOPE, node, null);
068: suite(node.body);
069: endScope();
070: return null;
071: }
072:
073: public Object visitModule(org.python.parser.ast.Module node)
074: throws Exception {
075: beginScope("<file-top>", TOPSCOPE, node, null);
076: suite(node.body);
077: endScope();
078: return null;
079: }
080:
081: public Object visitExpression(Expression node) throws Exception {
082: beginScope("<eval-top>", TOPSCOPE, node, null);
083: visit(new Return(node.body));
084: endScope();
085: return null;
086: }
087:
088: private void def(String name) {
089: cur.addBound(name);
090: }
091:
092: public Object visitFunctionDef(FunctionDef node) throws Exception {
093: def(node.name);
094: ArgListCompiler ac = new ArgListCompiler();
095: ac.visitArgs(node.args);
096:
097: exprType[] defaults = ac.getDefaults();
098: int defc = defaults.length;
099: for (int i = 0; i < defc; i++) {
100: visit(defaults[i]);
101: }
102:
103: beginScope(node.name, FUNCSCOPE, node, ac);
104: int n = ac.names.size();
105: for (int i = 0; i < n; i++) {
106: cur.addParam((String) ac.names.elementAt(i));
107: }
108: for (int i = 0; i < ac.init_code.size(); i++) {
109: visit((stmtType) ac.init_code.elementAt(i));
110: }
111: cur.markFromParam();
112: suite(node.body);
113: endScope();
114: return null;
115: }
116:
117: public Object visitLambda(Lambda node) throws Exception {
118: ArgListCompiler ac = new ArgListCompiler();
119: ac.visitArgs(node.args);
120:
121: SimpleNode[] defaults = ac.getDefaults();
122: int defc = defaults.length;
123: for (int i = 0; i < defc; i++) {
124: visit(defaults[i]);
125: }
126:
127: beginScope("<lambda>", FUNCSCOPE, node, ac);
128: int n = ac.names.size();
129: for (int i = 0; i < n; i++) {
130: cur.addParam((String) ac.names.elementAt(i));
131: }
132: for (int i = 0; i < ac.init_code.size(); i++)
133: visit((stmtType) ac.init_code.elementAt(i));
134: cur.markFromParam();
135: visit(node.body);
136: endScope();
137: return null;
138: }
139:
140: public void suite(stmtType[] stmts) throws Exception {
141: int n = stmts.length;
142: for (int i = 0; i < n; i++)
143: visit(stmts[i]);
144: }
145:
146: public Object visitImport(Import node) throws Exception {
147: int n = node.names.length;
148: for (int i = 0; i < n; i++) {
149: if (node.names[i].asname != null)
150: cur.addBound(node.names[i].asname);
151: else {
152: String name = node.names[i].name;
153: if (name.indexOf('.') > 0)
154: name = name.substring(0, name.indexOf('.'));
155: cur.addBound(name);
156: }
157: }
158: return null;
159: }
160:
161: public Object visitImportFrom(ImportFrom node) throws Exception {
162: Future.checkFromFuture(node); // future stmt support
163: int n = node.names.length;
164: if (n == 0) {
165: cur.from_import_star = true;
166: return null;
167: }
168: for (int i = 0; i < n; i++) {
169: if (node.names[i].asname != null)
170: cur.addBound(node.names[i].asname);
171: else
172: cur.addBound(node.names[i].name);
173: }
174: return null;
175: }
176:
177: public Object visitGlobal(Global node) throws Exception {
178: int n = node.names.length;
179: for (int i = 0; i < n; i++) {
180: String name = node.names[i];
181: int prev = cur.addGlobal(name);
182: if (prev >= 0) {
183: if ((prev & FROM_PARAM) != 0)
184: code_compiler.error("name '" + name
185: + "' is local and global", true, node);
186: if ((prev & GLOBAL) != 0)
187: continue;
188: String what;
189: if ((prev & BOUND) != 0)
190: what = "assignment";
191: else
192: what = "use";
193: code_compiler.error("name '" + name
194: + "' declared global after " + what, false,
195: node);
196: }
197: }
198: return null;
199: }
200:
201: public Object visitExec(Exec node) throws Exception {
202: cur.exec = true;
203: if (node.globals == null && node.locals == null)
204: cur.unqual_exec = true;
205: traverse(node);
206: return null;
207: }
208:
209: /*
210: private static void illassign(SimpleNode node) throws Exception {
211: String target = "operator";
212: if (node.id == PythonGrammarTreeConstants.JJTCALL_OP) {
213: target = "function call";
214: } else if ((node.id == PythonGrammarTreeConstants.JJTFOR_STMT)) {
215: target = "list comprehension";
216: }
217: throw new ParseException("can't assign to "+target,node);
218: }
219: */
220:
221: public Object visitClassDef(ClassDef node) throws Exception {
222: def(node.name);
223: int n = node.bases.length;
224: for (int i = 0; i < n; i++)
225: visit(node.bases[i]);
226: beginScope(node.name, CLASSSCOPE, node, null);
227: suite(node.body);
228: endScope();
229: return null;
230: }
231:
232: public Object visitName(Name node) throws Exception {
233: String name = node.id;
234: if (node.ctx != expr_contextType.Load) {
235: if (name.equals("__debug__"))
236: code_compiler.error("can not assign to __debug__",
237: true, node);
238: cur.addBound(name);
239: } else
240: cur.addUsed(name);
241: return null;
242: }
243:
244: public Object visitListComp(ListComp node) throws Exception {
245: String tmp = "_[" + (++cur.list_comprehension_count) + "]";
246: cur.addBound(tmp);
247: traverse(node);
248: return null;
249: }
250:
251: public Object visitYield(Yield node) throws Exception {
252: cur.generator = true;
253: cur.yield_count++;
254: traverse(node);
255: return null;
256: }
257: }
|