// Copyright (c) Corporation for National Research Initiatives package org.python.core; /** * An implementation of PyCode where the actual executable content * is stored as a PyFunctionTable instance and an integer index. */ import org.python.modules._systemrestart; public class PyTableCode extends PyBaseCode { PyFunctionTable funcs; int func_id; public String co_code = ""; // only used by inspect public PyTableCode(int argcount, String varnames[], String filename, String name, int firstlineno, boolean varargs, boolean varkwargs, PyFunctionTable funcs, int func_id) { this(argcount, varnames, filename, name, firstlineno, varargs, varkwargs, funcs, func_id, null, null, 0, 0); } public PyTableCode(int argcount, String varnames[], String filename, String name, int firstlineno, boolean varargs, boolean varkwargs, PyFunctionTable funcs, int func_id, String[] cellvars, String[] freevars, int npurecell, int moreflags) // may change { co_argcount = nargs = argcount; co_varnames = varnames; co_nlocals = varnames.length; co_filename = filename; co_firstlineno = firstlineno; co_cellvars = cellvars; co_freevars = freevars; this.jy_npurecell = npurecell; this.varargs = varargs; co_name = name; if (varargs) { co_argcount -= 1; co_flags.setFlag(CodeFlag.CO_VARARGS); } this.varkwargs = varkwargs; if (varkwargs) { co_argcount -= 1; co_flags.setFlag(CodeFlag.CO_VARKEYWORDS); } co_flags = new CompilerFlags(co_flags.toBits() | moreflags); this.funcs = funcs; this.func_id = func_id; } private static final String[] __members__ = { "co_name", "co_argcount", "co_varnames", "co_filename", "co_firstlineno", "co_flags","co_cellvars","co_freevars","co_nlocals" // not supported: co_code, co_consts, co_names, // co_lnotab, co_stacksize }; 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) { // no writable attributes throwReadonly(name); } public void __delattr__(String name) { throwReadonly(name); } private static PyTuple toPyStringTuple(String[] ar) { if (ar == null) return Py.EmptyTuple; int sz = ar.length; PyString[] pystr = new PyString[sz]; for (int i = 0; i < sz; i++) { pystr[i] = new PyString(ar[i]); } return new PyTuple(pystr); } public PyObject __findattr_ex__(String name) { // have to craft co_varnames specially if (name == "co_varnames") { return toPyStringTuple(co_varnames); } if (name == "co_cellvars") { return toPyStringTuple(co_cellvars); } if (name == "co_freevars") { return toPyStringTuple(co_freevars); } if (name == "co_filename") { return new PyString(co_filename); } if (name == "co_name") { return new PyString(co_name); } if (name == "co_flags") { return Py.newInteger(co_flags.toBits()); } return super.__findattr_ex__(name); } @Override public PyObject call(ThreadState ts, PyFrame frame, PyObject closure) { // System.err.println("tablecode call: "+co_name); if (ts.systemState == null) { ts.systemState = Py.defaultSystemState; } //System.err.println("got ts: "+ts+", "+ts.systemState); // Cache previously defined exception PyException previous_exception = ts.exception; // Push frame frame.f_back = ts.frame; if (frame.f_builtins == null) { if (frame.f_back != null) { frame.f_builtins = frame.f_back.f_builtins; } else { //System.err.println("ts: "+ts); //System.err.println("ss: "+ts.systemState); frame.f_builtins = PySystemState.builtins; } } // nested scopes: setup env with closure // this should only be done once, so let the frame take care of it frame.setupEnv((PyTuple)closure); ts.frame = frame; // Handle trace function for debugging if (ts.tracefunc != null) { frame.f_lineno = co_firstlineno; frame.tracefunc = ts.tracefunc.traceCall(frame); } // Handle trace function for profiling if (ts.profilefunc != null) { ts.profilefunc.traceCall(frame); } PyObject ret; try { ret = funcs.call_function(func_id, frame, ts); } catch (Throwable t) { // Convert exceptions that occured in Java code to PyExceptions PyException pye = Py.JavaError(t); pye.tracebackHere(frame); frame.f_lasti = -1; if (frame.tracefunc != null) { frame.tracefunc.traceException(frame, pye); } if (ts.profilefunc != null) { ts.profilefunc.traceException(frame, pye); } // Rethrow the exception to the next stack frame ts.exception = previous_exception; ts.frame = ts.frame.f_back; throw pye; } if (frame.tracefunc != null) { frame.tracefunc.traceReturn(frame, ret); } // Handle trace function for profiling if (ts.profilefunc != null) { ts.profilefunc.traceReturn(frame, ret); } // Restore previously defined exception ts.exception = previous_exception; ts.frame = ts.frame.f_back; // Check for interruption, which is used for restarting the interpreter // on Jython if (ts.systemState._systemRestart && Thread.currentThread().isInterrupted()) { throw new PyException(_systemrestart.SystemRestart); } return ret; } @Override protected PyObject interpret(PyFrame f, ThreadState ts) { throw new UnsupportedOperationException("Inlined interpret to improve call performance (may want to reconsider in the future)."); } }