// Copyright (c) Corporation for National Research Initiatives package org.python.core; /** * A python frame object. */ final public class PyFrame extends PyObject { public PyFrame f_back; public PyTableCode f_code; public PyObject f_locals; public PyObject f_globals; public int f_lineno; public PyObject f_builtins; public PyObject[] f_fastlocals; public PyCell[] f_env; // nested scopes: cell + free env public int f_ncells; public int f_nfreevars; public int f_lasti; public Object[] f_savedlocals; // an interface to functions suitable for tracing, e.g. via sys.settrace() public TraceFunction tracefunc; private static final String[] __members__ = { "f_back", "f_code", "f_locals", "f_globals", "f_lineno", "f_builtins", "f_trace" }; public PyFrame(PyTableCode code, PyObject locals, PyObject globals, PyObject builtins) { f_code = code; f_locals = locals; f_globals = globals; f_builtins = builtins; // This needs work to be efficient with multiple interpreter states if (locals == null && code != null) { // ! f_fastlocals needed for arg passing too if ((code.co_flags & PyTableCode.CO_OPTIMIZED) != 0 || code.nargs > 0) { if (code.co_nlocals > 0) { // internal: may change f_fastlocals = new PyObject[code.co_nlocals - code.jy_npurecell]; } } else f_locals = new PyStringMap(); } if (code != null) { // reserve space for env int env_sz = 0; if (code.co_freevars != null) env_sz += (f_nfreevars = code.co_freevars.length); if (code.co_cellvars != null) env_sz += (f_ncells = code.co_cellvars.length); if (env_sz > 0) f_env = new PyCell[env_sz]; } } public PyFrame(PyTableCode code, PyObject globals) { this(code, null, globals, null); } public String toString() { if (f_code == null) { return "<frame (unknown code) at line " + f_lineno + ">"; } else { return "<frame in \"" + f_code.co_name + "\" at line " + f_lineno + ">"; } } public PyObject __dir__() { PyString members[] = new PyString[__members__.length]; for (int i = 0; i < __members__.length; i++) members[i] = new PyString(__members__[i]); return new PyList(members); } private void throwReadonly(String name) { for (int i = 0; i < __members__.length; i++) if (__members__[i] == name) throw Py.TypeError("readonly attribute"); throw Py.AttributeError(name); } public void __setattr__(String name, PyObject value) { // In CPython, some of the frame's attributes are read/writeable if (name == "f_trace") tracefunc = new PythonTraceFunction(value); // not yet implemented: // f_exc_type // f_exc_value // f_exc_traceback else throwReadonly(name); } public void __delattr__(String name) { if (name == "f_trace") tracefunc = null; // not yet implemented: // f_exc_type // f_exc_value // f_exc_traceback else throwReadonly(name); } public PyObject __findattr__(String name) { if (name == "f_locals") return getf_locals(); else if (name == "f_trace") { if (tracefunc instanceof PythonTraceFunction) { return ((PythonTraceFunction) tracefunc).tracefunc; } return Py.None; } return super.__findattr__(name); } public PyObject getf_locals() { if (f_locals == null) f_locals = new PyStringMap(); if (f_code != null && (f_code.co_nlocals > 0 || f_nfreevars > 0)) { int i; if (f_fastlocals != null) { for (i = 0; i < f_fastlocals.length; i++) { PyObject o = f_fastlocals[i]; if (o != null) f_locals.__setitem__(f_code.co_varnames[i], o); } if ((f_code.co_flags & PyTableCode.CO_OPTIMIZED) == 0) f_fastlocals = null; } int j = 0; for (i = 0; i < f_ncells; i++, j++) { PyObject v = f_env[j].ob_ref; if (v != null) f_locals.__setitem__(f_code.co_cellvars[i], v); } for (i = 0; i < f_nfreevars; i++, j++) { PyObject v = f_env[j].ob_ref; if (v != null) f_locals.__setitem__(f_code.co_freevars[i], v); } } return f_locals; } public void setline(int line) { f_lineno = line; if (tracefunc != null) tracefunc = tracefunc.traceLine(this, line); } public int getline() { return f_lineno; } public PyObject getlocal(int index) { if (f_fastlocals != null) { PyObject ret = f_fastlocals[index]; if (ret != null) return ret; } return getlocal(f_code.co_varnames[index]); } public PyObject getlocal(String index) { // System.err.println("getlocal: "+index); if (f_locals == null) getf_locals(); PyObject ret = f_locals.__finditem__(index); if (ret != null) return ret; throw Py.UnboundLocalError("local: '" + index + "'"); //return getglobal(index); } public PyObject getname(String index) { if (f_locals == null) getf_locals(); if (f_locals == f_globals) return getglobal(index); PyObject ret = f_locals.__finditem__(index); if (ret != null) return ret; return getglobal(index); } public PyObject getglobal(String index) { PyObject ret = f_globals.__finditem__(index); if (ret != null) { return ret; } // Set up f_builtins if not already set if (f_builtins == null) { f_builtins = Py.getSystemState().builtins; } ret = f_builtins.__finditem__(index); if (ret != null) return ret; throw Py.NameError(index); } public void setlocal(int index, PyObject value) { if (f_fastlocals != null) f_fastlocals[index] = value; else setlocal(f_code.co_varnames[index], value); } public void setlocal(String index, PyObject value) { if (f_locals == null) getf_locals(); f_locals.__setitem__(index, value); } public void setglobal(String index, PyObject value) { f_globals.__setitem__(index, value); } public void dellocal(int index) { if (f_fastlocals != null) { if (f_fastlocals[index] == null) { throw Py.UnboundLocalError("local: '" + f_code.co_varnames[index] + "'"); } f_fastlocals[index] = null; } else dellocal(f_code.co_varnames[index]); } public void dellocal(String index) { if (f_locals == null) getf_locals(); try { f_locals.__delitem__(index); } catch (PyException e) { if (!Py.matchException(e, Py.KeyError)) throw e; throw Py.UnboundLocalError("local: '" + index + "'"); } } public void delglobal(String index) { f_globals.__delitem__(index); } // nested scopes helpers public PyObject getclosure(int index) { return f_env[index]; } public PyObject getderef(int index) { PyObject obj = f_env[index].ob_ref; if (obj != null) return obj; String name; if (index >= f_ncells) name = f_code.co_freevars[index - f_ncells]; else name = f_code.co_cellvars[index]; throw Py.UnboundLocalError("local: '" + name + "'"); } public void setderef(int index, PyObject value) { f_env[index].ob_ref = value; } public void to_cell(int parm_index, int env_index) { f_env[env_index].ob_ref = f_fastlocals[parm_index]; } }