001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: /**
005: * A python frame object.
006: */
007:
008: public class PyFrame extends PyObject {
009: public PyFrame f_back;
010: public PyTableCode f_code;
011: public PyObject f_locals;
012: public PyObject f_globals;
013: public int f_lineno;
014: public PyObject f_builtins;
015: public PyObject[] f_fastlocals;
016: public PyCell[] f_env; // nested scopes: cell + free env
017: public int f_ncells;
018: public int f_nfreevars;
019: public int f_lasti;
020: public Object[] f_savedlocals;
021:
022: // an interface to functions suitable for tracing, e.g. via sys.settrace()
023: public TraceFunction tracefunc;
024:
025: private static final String[] __members__ = { "f_back", "f_code",
026: "f_locals", "f_globals", "f_lineno", "f_builtins",
027: "f_trace" };
028:
029: public PyFrame(PyTableCode code, PyObject locals, PyObject globals,
030: PyObject builtins) {
031: f_code = code;
032: f_locals = locals;
033: f_globals = globals;
034: f_builtins = builtins;
035: // This needs work to be efficient with multiple interpreter states
036: if (locals == null && code != null) {
037: // ! f_fastlocals needed for arg passing too
038: if ((code.co_flags & PyTableCode.CO_OPTIMIZED) != 0
039: || code.nargs > 0) {
040: if (code.co_nlocals > 0) {
041: // internal: may change
042: f_fastlocals = new PyObject[code.co_nlocals
043: - code.jy_npurecell];
044: }
045: } else
046: f_locals = new PyStringMap();
047: }
048: if (code != null) { // reserve space for env
049: int env_sz = 0;
050: if (code.co_freevars != null)
051: env_sz += (f_nfreevars = code.co_freevars.length);
052: if (code.co_cellvars != null)
053: env_sz += (f_ncells = code.co_cellvars.length);
054: if (env_sz > 0)
055: f_env = new PyCell[env_sz];
056: }
057: }
058:
059: public PyFrame(PyTableCode code, PyObject globals) {
060: this (code, null, globals, null);
061: }
062:
063: public String toString() {
064: if (f_code == null) {
065: return "<frame (unknown code) at line " + f_lineno + ">";
066: } else {
067: return "<frame in \"" + f_code.co_name + "\" at line "
068: + f_lineno + ">";
069: }
070: }
071:
072: public PyObject __dir__() {
073: PyString members[] = new PyString[__members__.length];
074: for (int i = 0; i < __members__.length; i++)
075: members[i] = new PyString(__members__[i]);
076: return new PyList(members);
077: }
078:
079: private void throwReadonly(String name) {
080: for (int i = 0; i < __members__.length; i++)
081: if (__members__[i] == name)
082: throw Py.TypeError("readonly attribute");
083: throw Py.AttributeError(name);
084: }
085:
086: public void __setattr__(String name, PyObject value) {
087: // In CPython, some of the frame's attributes are read/writeable
088: if (name == "f_trace")
089: tracefunc = new PythonTraceFunction(value);
090: // not yet implemented:
091: // f_exc_type
092: // f_exc_value
093: // f_exc_traceback
094: else
095: throwReadonly(name);
096: }
097:
098: public void __delattr__(String name) {
099: if (name == "f_trace")
100: tracefunc = null;
101: // not yet implemented:
102: // f_exc_type
103: // f_exc_value
104: // f_exc_traceback
105: else
106: throwReadonly(name);
107: }
108:
109: public PyObject __findattr__(String name) {
110: if (name == "f_locals")
111: return getf_locals();
112: else if (name == "f_trace") {
113: if (tracefunc instanceof PythonTraceFunction) {
114: return ((PythonTraceFunction) tracefunc).tracefunc;
115: }
116: return Py.None;
117: }
118: return super .__findattr__(name);
119: }
120:
121: public PyObject getf_locals() {
122: if (f_locals == null)
123: f_locals = new PyStringMap();
124: if (f_code != null
125: && (f_code.co_nlocals > 0 || f_nfreevars > 0)) {
126: int i;
127: if (f_fastlocals != null) {
128: for (i = 0; i < f_fastlocals.length; i++) {
129: PyObject o = f_fastlocals[i];
130: if (o != null)
131: f_locals.__setitem__(f_code.co_varnames[i], o);
132: }
133: if ((f_code.co_flags & PyTableCode.CO_OPTIMIZED) == 0)
134: f_fastlocals = null;
135: }
136: int j = 0;
137: for (i = 0; i < f_ncells; i++, j++) {
138: PyObject v = f_env[j].ob_ref;
139: if (v != null)
140: f_locals.__setitem__(f_code.co_cellvars[i], v);
141: }
142: for (i = 0; i < f_nfreevars; i++, j++) {
143: PyObject v = f_env[j].ob_ref;
144: if (v != null)
145: f_locals.__setitem__(f_code.co_freevars[i], v);
146: }
147: }
148: return f_locals;
149: }
150:
151: public void setline(int line) {
152: f_lineno = line;
153: if (tracefunc != null)
154: tracefunc = tracefunc.traceLine(this , line);
155: }
156:
157: public int getline() {
158: return f_lineno;
159: }
160:
161: public PyObject getlocal(int index) {
162: if (f_fastlocals != null) {
163: PyObject ret = f_fastlocals[index];
164: if (ret != null)
165: return ret;
166: }
167: return getlocal(f_code.co_varnames[index]);
168: }
169:
170: public PyObject getlocal(String index) {
171: // System.err.println("getlocal: "+index);
172: if (f_locals == null)
173: getf_locals();
174: PyObject ret = f_locals.__finditem__(index);
175: if (ret != null)
176: return ret;
177:
178: throw Py.UnboundLocalError("local: '" + index + "'");
179: //return getglobal(index);
180: }
181:
182: public PyObject getname(String index) {
183: if (f_locals == null)
184: getf_locals();
185: if (f_locals == f_globals)
186: return getglobal(index);
187:
188: PyObject ret = f_locals.__finditem__(index);
189: if (ret != null)
190: return ret;
191: return getglobal(index);
192: }
193:
194: public PyObject getglobal(String index) {
195: PyObject ret = f_globals.__finditem__(index);
196: if (ret != null) {
197: return ret;
198: }
199:
200: // Set up f_builtins if not already set
201: if (f_builtins == null) {
202: f_builtins = Py.getSystemState().builtins;
203: }
204: ret = f_builtins.__finditem__(index);
205: if (ret != null)
206: return ret;
207:
208: throw Py.NameError(index);
209: }
210:
211: public void setlocal(int index, PyObject value) {
212: if (f_fastlocals != null)
213: f_fastlocals[index] = value;
214: else
215: setlocal(f_code.co_varnames[index], value);
216: }
217:
218: public void setlocal(String index, PyObject value) {
219: if (f_locals == null)
220: getf_locals();
221: f_locals.__setitem__(index, value);
222: }
223:
224: public void setglobal(String index, PyObject value) {
225: f_globals.__setitem__(index, value);
226: }
227:
228: public void dellocal(int index) {
229: if (f_fastlocals != null) {
230: if (f_fastlocals[index] == null) {
231: throw Py.UnboundLocalError("local: '"
232: + f_code.co_varnames[index] + "'");
233: }
234: f_fastlocals[index] = null;
235: } else
236: dellocal(f_code.co_varnames[index]);
237: }
238:
239: public void dellocal(String index) {
240: if (f_locals == null)
241: getf_locals();
242: try {
243: f_locals.__delitem__(index);
244: } catch (PyException e) {
245: if (!Py.matchException(e, Py.KeyError))
246: throw e;
247: throw Py.UnboundLocalError("local: '" + index + "'");
248: }
249: }
250:
251: public void delglobal(String index) {
252: f_globals.__delitem__(index);
253: }
254:
255: // nested scopes helpers
256:
257: public PyObject getclosure(int index) {
258: return f_env[index];
259: }
260:
261: public PyObject getderef(int index) {
262: PyObject obj = f_env[index].ob_ref;
263: if (obj != null)
264: return obj;
265: String name;
266: if (index >= f_ncells)
267: name = f_code.co_freevars[index - f_ncells];
268: else
269: name = f_code.co_cellvars[index];
270: throw Py.UnboundLocalError("local: '" + name + "'");
271: }
272:
273: public void setderef(int index, PyObject value) {
274: f_env[index].ob_ref = value;
275: }
276:
277: public void to_cell(int parm_index, int env_index) {
278: f_env[env_index].ob_ref = f_fastlocals[parm_index];
279: }
280: }
|