From: <zy...@us...> - 2009-01-20 13:56:50
|
Revision: 5949 http://jython.svn.sourceforge.net/jython/?rev=5949&view=rev Author: zyasoft Date: 2009-01-20 13:56:46 +0000 (Tue, 20 Jan 2009) Log Message: ----------- Initial commit. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyFrame.java branches/pbcvm/src/org/python/core/PyFunction.java branches/pbcvm/src/org/python/core/PyTableCode.java Added Paths: ----------- branches/pbcvm/src/org/python/core/Opcode.java branches/pbcvm/src/org/python/core/PyBaseCode.java branches/pbcvm/src/org/python/core/PyBytecode.java Added: branches/pbcvm/src/org/python/core/Opcode.java =================================================================== --- branches/pbcvm/src/org/python/core/Opcode.java (rev 0) +++ branches/pbcvm/src/org/python/core/Opcode.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -0,0 +1,172 @@ +package org.python.core; + +// derived from CPython 2.5.2 Include/opcode.h + +public class Opcode { + + public static final int POP_TOP = 1; + public static final int ROT_TWO = 2; + public static final int ROT_THREE = 3; + public static final int DUP_TOP = 4; + public static final int ROT_FOUR = 5; + public static final int NOP = 9; + public static final int UNARY_POSITIVE = 10; + public static final int UNARY_NEGATIVE = 11; + public static final int UNARY_NOT = 12; + public static final int UNARY_CONVERT = 13; + public static final int UNARY_INVERT = 15; + public static final int LIST_APPEND = 18; + public static final int BINARY_POWER = 19; + public static final int BINARY_MULTIPLY = 20; + public static final int BINARY_DIVIDE = 21; + public static final int BINARY_MODULO = 22; + public static final int BINARY_ADD = 23; + public static final int BINARY_SUBTRACT = 24; + public static final int BINARY_SUBSCR = 25; + public static final int BINARY_FLOOR_DIVIDE = 26; + public static final int BINARY_TRUE_DIVIDE = 27; + public static final int INPLACE_FLOOR_DIVIDE = 28; + public static final int INPLACE_TRUE_DIVIDE = 29; + public static final int SLICE = 30; + /* Also uses 31-33 */ + public static final int STORE_SLICE = 40; + /* Also uses 41-43 */ + public static final int DELETE_SLICE = 50; + /* Also uses 51-53 */ + public static final int INPLACE_ADD = 55; + public static final int INPLACE_SUBTRACT = 56; + public static final int INPLACE_MULTIPLY = 57; + public static final int INPLACE_DIVIDE = 58; + public static final int INPLACE_MODULO = 59; + public static final int STORE_SUBSCR = 60; + public static final int DELETE_SUBSCR = 61; + public static final int BINARY_LSHIFT = 62; + public static final int BINARY_RSHIFT = 63; + public static final int BINARY_AND = 64; + public static final int BINARY_XOR = 65; + public static final int BINARY_OR = 66; + public static final int INPLACE_POWER = 67; + public static final int GET_ITER = 68; + public static final int PRINT_EXPR = 70; + public static final int PRINT_ITEM = 71; + public static final int PRINT_NEWLINE = 72; + public static final int PRINT_ITEM_TO = 73; + public static final int PRINT_NEWLINE_TO = 74; + public static final int INPLACE_LSHIFT = 75; + public static final int INPLACE_RSHIFT = 76; + public static final int INPLACE_AND = 77; + public static final int INPLACE_XOR = 78; + public static final int INPLACE_OR = 79; + public static final int BREAK_LOOP = 80; + public static final int WITH_CLEANUP = 81; + public static final int LOAD_LOCALS = 82; + public static final int RETURN_VALUE = 83; + public static final int IMPORT_STAR = 84; + public static final int EXEC_STMT = 85; + public static final int YIELD_VALUE = 86; + public static final int POP_BLOCK = 87; + public static final int END_FINALLY = 88; + public static final int BUILD_CLASS = 89; + public static final int HAVE_ARGUMENT = 90; /* Opcodes from here have an argument: */ + + public static final int STORE_NAME = 90; /* Index in name list */ + + public static final int DELETE_NAME = 91; /* "" */ + + public static final int UNPACK_SEQUENCE = 92; /* Number of sequence items */ + + public static final int FOR_ITER = 93; + public static final int STORE_ATTR = 95; /* Index in name list */ + + public static final int DELETE_ATTR = 96; /* "" */ + + public static final int STORE_GLOBAL = 97; /* "" */ + + public static final int DELETE_GLOBAL = 98; /* "" */ + + public static final int DUP_TOPX = 99; /* number of items to duplicate */ + + public static final int LOAD_CONST = 100; /* Index in const list */ + + public static final int LOAD_NAME = 101; /* Index in name list */ + + public static final int BUILD_TUPLE = 102; /* Number of tuple items */ + + public static final int BUILD_LIST = 103; /* Number of list items */ + + public static final int BUILD_MAP = 104; /* Always zero for now */ + + public static final int LOAD_ATTR = 105; /* Index in name list */ + + public static final int COMPARE_OP = 106; /* Comparison operator */ + + public static final int IMPORT_NAME = 107; /* Index in name list */ + + public static final int IMPORT_FROM = 108; /* Index in name list */ + + public static final int JUMP_FORWARD = 110; /* Number of bytes to skip */ + + public static final int JUMP_IF_FALSE = 111; /* "" */ + + public static final int JUMP_IF_TRUE = 112; /* "" */ + + public static final int JUMP_ABSOLUTE = 113; /* Target byte offset from beginning of code */ + + public static final int LOAD_GLOBAL = 116; /* Index in name list */ + + public static final int CONTINUE_LOOP = 119; /* Start of loop (absolute) */ + + public static final int SETUP_LOOP = 120; /* Target address (absolute) */ + + public static final int SETUP_EXCEPT = 121; /* "" */ + + public static final int SETUP_FINALLY = 122; /* "" */ + + public static final int LOAD_FAST = 124; /* Local variable number */ + + public static final int STORE_FAST = 125; /* Local variable number */ + + public static final int DELETE_FAST = 126; /* Local variable number */ + + public static final int RAISE_VARARGS = 130; /* Number of raise arguments (1, 2 or 3) */ + /* CALL_FUNCTION_XXX opcodes defined below depend on this definition */ + + public static final int CALL_FUNCTION = 131; /* #args + (#kwargs<<8) */ + + public static final int MAKE_FUNCTION = 132; /* #defaults */ + + public static final int BUILD_SLICE = 133; /* Number of items */ + + public static final int MAKE_CLOSURE = 134; /* #free vars */ + + public static final int LOAD_CLOSURE = 135; /* Load free variable from closure */ + + public static final int LOAD_DEREF = 136; /* Load and dereference from closure cell */ + + public static final int STORE_DEREF = 137; /* Store into cell */ + + /* The next 3 opcodes must be contiguous and satisfy + (CALL_FUNCTION_VAR - CALL_FUNCTION) & 3 == 1 */ + public static final int CALL_FUNCTION_VAR = 140; /* #args + (#kwargs<<8) */ + + public static final int CALL_FUNCTION_KW = 141; /* #args + (#kwargs<<8) */ + + public static final int CALL_FUNCTION_VAR_KW = 142; /* #args + (#kwargs<<8) */ + + /* Support for opargs more than 16 bits long */ + public static final int EXTENDED_ARG = 143; + + // comparison opcodes (on the oparg), just put in this class too + public static final int PyCmp_LT = 0; + public static final int PyCmp_LE = 1; + public static final int PyCmp_EQ = 2; + public static final int PyCmp_NE = 3; + public static final int PyCmp_GT = 4; + public static final int PyCmp_GE = 5; + public static final int PyCmp_IN = 6; + public static final int PyCmp_NOT_IN = 7; + public static final int PyCmp_IS = 8; + public static final int PyCmp_IS_NOT = 9; + public static final int PyCmp_EXC_MATCH = 10; + +} Added: branches/pbcvm/src/org/python/core/PyBaseCode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBaseCode.java (rev 0) +++ branches/pbcvm/src/org/python/core/PyBaseCode.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -0,0 +1,314 @@ +// Copyright (c) Corporation for National Research Initiatives +package org.python.core; + +import org.python.modules._systemrestart; + +public abstract class PyBaseCode extends PyCode { + + public int co_argcount; + int nargs; + public int co_firstlineno = -1; + public String co_varnames[]; + public String co_cellvars[]; + public int jy_npurecell; // internal: jython specific + public String co_freevars[]; + public String co_filename; + public int co_flags; + public int co_nlocals; + public boolean varargs, varkwargs; + + final public static int CO_OPTIMIZED = 0x0001; + //final public static int CO_NEWLOCALS = 0x0002 + final public static int CO_VARARGS = 0x0004; + final public static int CO_VARKEYWORDS = 0x0008; + final public static int CO_GENERATOR = 0x0020; + + // these are defined in __future__.py + final public static int CO_NESTED = 0x0010; + final public static int CO_GENERATOR_ALLOWED = 0x0; + final public static int CO_FUTUREDIVISION = 0x2000; + final public static int CO_FUTURE_ABSOLUTE_IMPORT = 0x4000; + final public static int CO_WITH_STATEMENT = 0x8000; + + //XXX: I'm not positive that this is the right place for these constants. + final public static int PyCF_SOURCE_IS_UTF8 = 0x0100; + final public static int PyCF_DONT_IMPLY_DEDENT = 0x0200; + final public static int PyCF_ONLY_AST = 0x0400; + + final public static int CO_ALL_FEATURES = PyCF_DONT_IMPLY_DEDENT|PyCF_ONLY_AST| + PyCF_SOURCE_IS_UTF8|CO_NESTED| + CO_GENERATOR_ALLOWED| CO_FUTUREDIVISION| + CO_FUTURE_ABSOLUTE_IMPORT|CO_WITH_STATEMENT; + + + public boolean hasFreevars() { + return co_freevars != null && co_freevars.length > 0; + } + + public PyObject call(PyFrame frame, PyObject closure) { +// System.err.println("tablecode call: "+co_name); + ThreadState ts = Py.getThreadState(); + 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 = interpret(frame); + } 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 (Thread.currentThread().isInterrupted()) { + throw new PyException(_systemrestart.SystemRestart); + } + return ret; + } + + public PyObject call(PyObject globals, PyObject[] defaults, + PyObject closure) + { + if (co_argcount != 0 || varargs || varkwargs) + return call(Py.EmptyObjects, Py.NoKeywords, globals, defaults, + closure); + PyFrame frame = new PyFrame(this, globals); + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject arg1, PyObject globals, PyObject[] defaults, + PyObject closure) + { + if (co_argcount != 1 || varargs || varkwargs) + return call(new PyObject[] {arg1}, + Py.NoKeywords, globals, defaults, closure); + PyFrame frame = new PyFrame(this, globals); + frame.f_fastlocals[0] = arg1; + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject arg1, PyObject arg2, PyObject globals, + PyObject[] defaults, PyObject closure) + { + if (co_argcount != 2 || varargs || varkwargs) + return call(new PyObject[] {arg1, arg2}, + Py.NoKeywords, globals, defaults, closure); + PyFrame frame = new PyFrame(this, globals); + frame.f_fastlocals[0] = arg1; + frame.f_fastlocals[1] = arg2; + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject arg1, PyObject arg2, PyObject arg3, + PyObject globals, PyObject[] defaults, + PyObject closure) + { + if (co_argcount != 3 || varargs || varkwargs) + return call(new PyObject[] {arg1, arg2, arg3}, + Py.NoKeywords, globals, defaults, closure); + PyFrame frame = new PyFrame(this, globals); + frame.f_fastlocals[0] = arg1; + frame.f_fastlocals[1] = arg2; + frame.f_fastlocals[2] = arg3; + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public PyObject call(PyObject self, PyObject args[], + String keywords[], PyObject globals, + PyObject[] defaults, PyObject closure) + { + PyObject[] os = new PyObject[args.length+1]; + os[0] = self; + System.arraycopy(args, 0, os, 1, args.length); + return call(os, keywords, globals, defaults, closure); + } + + public PyObject call(PyObject args[], String kws[], PyObject globals, PyObject[] defs, + PyObject closure) { + PyFrame frame = new PyFrame(this, globals); + int argcount = args.length - kws.length; + int defcount = defs != null ? defs.length : 0; + PyObject[] fastlocals = frame.f_fastlocals; + + if (co_argcount > 0 || (varargs || varkwargs)) { + int i; + int n = argcount; + PyObject kwdict = null; + if (varkwargs) { + kwdict = new PyDictionary(); + i = co_argcount; + if (varargs) { + i++; + } + fastlocals[i] = kwdict; + } + if (argcount > co_argcount) { + if (!varargs) { + String msg = String.format("%.200s() takes %s %d %sargument%s (%d given)", + co_name, + defcount > 0 ? "at most" : "exactly", + co_argcount, + kws.length > 0 ? "non-keyword " : "", + co_argcount == 1 ? "" : "s", + argcount); + throw Py.TypeError(msg); + } + n = co_argcount; + } + + System.arraycopy(args, 0, fastlocals, 0, n); + + if (varargs) { + PyObject[] u = new PyObject[argcount - n]; + System.arraycopy(args, n, u, 0, argcount - n); + PyObject uTuple = new PyTuple(u); + fastlocals[co_argcount] = uTuple; + } + for (i = 0; i < kws.length; i++) { + String keyword = kws[i]; + PyObject value = args[i + argcount]; + int j; + // XXX: keywords aren't PyObjects, can't ensure strings + //if (keyword == null || keyword.getClass() != PyString.class) { + // throw Py.TypeError(String.format("%.200s() keywords must be strings", + // co_name)); + //} + for (j = 0; j < co_argcount; j++) { + if (co_varnames[j].equals(keyword)) { + break; + } + } + if (j >= co_argcount) { + if (kwdict == null) { + throw Py.TypeError(String.format("%.200s() got an unexpected keyword " + + "argument '%.400s'", + co_name, keyword)); + } + kwdict.__setitem__(keyword, value); + } else { + if (fastlocals[j] != null) { + throw Py.TypeError(String.format("%.200s() got multiple values for " + + "keyword argument '%.400s'", + co_name, keyword)); + } + fastlocals[j] = value; + } + } + if (argcount < co_argcount) { + int m = co_argcount - defcount; + for (i = argcount; i < m; i++) { + if (fastlocals[i] == null) { + String msg = + String.format("%.200s() takes %s %d %sargument%s (%d given)", + co_name, (varargs || defcount > 0) ? + "at least" : "exactly", + m, kws.length > 0 ? "non-keyword " : "", + m == 1 ? "" : "s", i); + throw Py.TypeError(msg); + } + } + if (n > m) { + i = n - m; + } else { + i = 0; + } + for (; i < defcount; i++) { + if (fastlocals[m + i] == null) { + fastlocals[m + i] = defs[i]; + } + } + } + } else if (argcount > 0) { + throw Py.TypeError(String.format("%.200s() takes no arguments (%d given)", + co_name, argcount)); + } + + if ((co_flags & CO_GENERATOR) != 0) { + return new PyGenerator(frame, closure); + } + return call(frame, closure); + } + + public String toString() { + return String.format("<code object %.100s at %s, file \"%.300s\", line %d>", + co_name, Py.idstr(this), co_filename, co_firstlineno); + } + + protected PyObject interpret(PyFrame f) { + throw new UnsupportedOperationException("interpret not supported"); + } +} Added: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java (rev 0) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -0,0 +1,1129 @@ +package org.python.core; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class PyBytecode extends PyBaseCode { + + // for debugging + static int count = 0; // total number of opcodes run + final static int maxCount = 900; // less than my buffer on iterm + static PyObject opname; + + static synchronized PyObject getOpname() { + if (opname == null) { + opname = __builtin__.__import__("dis").__getattr__("opname"); + } + return opname; + } + // end debugging + + public final char[] co_code; // to avoid sign issues + public final PyObject[] co_consts; + public final String[] co_names; + public final int co_stacksize; // ignored, probably shouldn't be + public final PyObject[] co_lnotab; // ignored + + // follows new.code's interface + public PyBytecode(int argcount, int nlocals, int stacksize, int flags, + String codestring, PyObject[] constants, String[] names, String varnames[], + String filename, String name, int firstlineno, PyObject[] lnotab) { + this(argcount, nlocals, stacksize, flags, codestring, + constants, names, varnames, filename, name, firstlineno, lnotab, + null, null); + } + + public PyBytecode(int argcount, int nlocals, int stacksize, int flags, + String codestring, PyObject[] constants, String[] names, String varnames[], + String filename, String name, int firstlineno, PyObject[] lnotab, + String[] cellvars, String[] freevars) { + co_argcount = nargs = argcount; + co_varnames = varnames; + co_nlocals = nlocals; // maybe assert = varnames.length; + co_filename = filename; + co_firstlineno = firstlineno; + co_cellvars = cellvars; + co_freevars = freevars; + co_name = name; + +// need to look at how this is used, since it's not part of the standard new.code interface +// this.varargs = varargs; +// if (varargs) { +// co_argcount -= 1; +// co_flags |= CO_VARARGS; +// } +// this.varkwargs = varkwargs; +// if (varkwargs) { +// co_argcount -= 1; +// co_flags |= CO_VARKEYWORDS; +// } + co_flags |= flags; + + co_stacksize = stacksize; + co_consts = constants; + co_names = names; + co_code = codestring.toCharArray(); + co_lnotab = lnotab; + } + private static final String[] __members__ = { + "co_name", "co_argcount", + "co_varnames", "co_filename", "co_firstlineno", + "co_flags", "co_cellvars", "co_freevars", "co_nlocals", + "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); + } + return super.__findattr_ex__(name); + } + + enum Why { + + NOT, /* No error */ + EXCEPTION, /* Exception occurred */ + RERAISE, /* Exception re-raised by 'finally' */ + RETURN, /* 'return' statement */ + BREAK, /* 'break' statement */ + CONTINUE, /* 'continue' statement */ + YIELD /* 'yield' operator */ + + }; + + private Why do_raise() { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private Why do_raise(PyObject type) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private Why do_raise(PyObject type, PyObject value) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private Why do_raise(PyObject type, PyObject value, PyObject traceback) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + protected PyObject interpret(PyFrame f) { + final PyStack stack = new PyStack(); + int next_instr = -1; + int opcode; /* Current opcode */ + int oparg = 0; /* Current opcode argument, if any */ + Why why = Why.NOT; + PyObject retval = null; + + while (count < maxCount) { // XXX - replace with while(true) + + f.f_lasti = next_instr++; // should have no worries about needing co_lnotab, just keep this current + opcode = co_code[next_instr]; + if (opcode > Opcode.HAVE_ARGUMENT) { + next_instr += 2; + oparg = (co_code[next_instr] << 8) + co_code[next_instr - 1]; + System.err.println(count + "," + next_instr + "> opcode: " + getOpname().__getitem__(Py.newInteger(opcode)) + ", oparg: " + oparg + ", stack: " + stack.toString()); + } else { + System.err.println(count + "," + next_instr + "> opcode: " + getOpname().__getitem__(Py.newInteger(opcode)) + ", stack: " + stack.toString()); + } + count += 1; + + try { + switch (opcode) { + case Opcode.NOP: + break; + + case Opcode.LOAD_FAST: + stack.push(f.getlocal(oparg)); + break; + + case Opcode.LOAD_CONST: + stack.push(co_consts[oparg]); + break; + + case Opcode.STORE_FAST: + f.setlocal(oparg, stack.pop()); + break; + + case Opcode.POP_TOP: + stack.pop(); + break; + + case Opcode.ROT_TWO: + stack.rotN(2); + break; + + case Opcode.ROT_THREE: + stack.rotN(3); + break; + + case Opcode.ROT_FOUR: + stack.rotN(4); + break; + + case Opcode.DUP_TOP: + stack.dup(); + break; + + case Opcode.DUP_TOPX: + if (oparg == 2 || oparg == 3) { + stack.dupN(oparg); + } else { + throw Py.RuntimeError("invalid argument to DUP_TOPX" + + " (bytecode corruption?)"); + } + break; + + case Opcode.UNARY_POSITIVE: + stack.push(stack.pop().__pos__()); + break; + + case Opcode.UNARY_NEGATIVE: + stack.push(stack.pop().__neg__()); + break; + + case Opcode.UNARY_NOT: + stack.push(stack.pop().__not__()); + break; + + case Opcode.UNARY_CONVERT: + stack.push(stack.pop().__repr__()); + break; + + case Opcode.UNARY_INVERT: + stack.push(stack.pop().__invert__()); + break; + + case Opcode.BINARY_POWER: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__pow__(b)); + break; + } + + case Opcode.BINARY_MULTIPLY: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__mul__(b)); + break; + } + + case Opcode.BINARY_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + + if ((co_flags & CO_FUTUREDIVISION) == 0) { + stack.push(a.__div__(b)); + } else { + stack.push(a.__truediv__(b)); + } + break; + } + + case Opcode.BINARY_TRUE_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__truediv__(b)); + break; + } + + case Opcode.BINARY_FLOOR_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__floordiv__(b)); + break; + } + + case Opcode.BINARY_MODULO: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__mod__(b)); + break; + } + + case Opcode.BINARY_ADD: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__add__(b)); + break; + } + + case Opcode.BINARY_SUBTRACT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__sub__(b)); + break; + } + + case Opcode.BINARY_SUBSCR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__getitem__(b)); + break; + } + + case Opcode.BINARY_LSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__lshift__(b)); + break; + } + + case Opcode.BINARY_RSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__rshift__(b)); + break; + } + + case Opcode.BINARY_AND: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__and__(b)); + break; + } + + + case Opcode.BINARY_XOR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__xor__(b)); + break; + } + + case Opcode.BINARY_OR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__or__(b)); + break; + } + + case Opcode.LIST_APPEND: { + PyObject b = stack.pop(); + PyList a = (PyList) (stack.pop()); + a.append(b); + break; + } + + case Opcode.INPLACE_POWER: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ipow__(b)); + break; + } + + case Opcode.INPLACE_MULTIPLY: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__imul__(b)); + break; + } + + case Opcode.INPLACE_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + if ((co_flags & CO_FUTUREDIVISION) == 0) { + stack.push(a.__idiv__(b)); + } else { + stack.push(a.__itruediv__(b)); + } + break; + } + + case Opcode.INPLACE_TRUE_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__itruediv__(b)); + break; + } + + case Opcode.INPLACE_FLOOR_DIVIDE: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ifloordiv__(b)); + break; + } + + case Opcode.INPLACE_MODULO: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__imod__(b)); + break; + } + + case Opcode.INPLACE_ADD: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__iadd__(b)); + break; + } + + case Opcode.INPLACE_SUBTRACT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__isub__(b)); + break; + } + + case Opcode.INPLACE_LSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ilshift__(b)); + break; + } + + case Opcode.INPLACE_RSHIFT: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__irshift__(b)); + break; + } + + case Opcode.INPLACE_AND: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__iand__(b)); + break; + } + + case Opcode.INPLACE_XOR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ixor__(b)); + break; + } + + case Opcode.INPLACE_OR: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + stack.push(a.__ior__(b)); + break; + } + +// +// case SLICE+0: +// case SLICE+1: +// case SLICE+2: +// case SLICE+3: +// if ((opcode-SLICE) & 2) +// w = POP(); +// else +// w = NULL; +// if ((opcode-SLICE) & 1) +// v = POP(); +// else +// v = NULL; +// u = TOP(); +// x = apply_slice(u, v, w); +// Py_DECREF(u); +// Py_XDECREF(v); +// Py_XDECREF(w); +// SET_TOP(x); +// if (x != NULL) continue; +// break; +// +// case Opcode.STORE_SLICE+0: +// case Opcode.STORE_SLICE+1: +// case Opcode.STORE_SLICE+2: +// case Opcode.STORE_SLICE+3: +// if (((opcode - Opcode.STORE_SLICE) & 2) !=0) { +// +// } +// w = POP(); +// else +// w = NULL; +// if ((opcode-STORE_SLICE) & 1) +// v = POP(); +// else +// v = NULL; +// u = POP(); +// t = POP(); +// err = assign_slice(u, v, w, t); /* u[v:w] = t */ +// Py_DECREF(t); +// Py_DECREF(u); +// Py_XDECREF(v); +// Py_XDECREF(w); +// if (err == 0) continue; +// break; +// +// case DELETE_SLICE+0: +// case DELETE_SLICE+1: +// case DELETE_SLICE+2: +// case DELETE_SLICE+3: +// if ((opcode-DELETE_SLICE) & 2) +// w = POP(); +// else +// w = NULL; +// if ((opcode-DELETE_SLICE) & 1) +// v = POP(); +// else +// v = NULL; +// u = POP(); +// err = assign_slice(u, v, w, (PyObject *)NULL); +// /* del u[v:w] */ +// Py_DECREF(u); +// Py_XDECREF(v); +// Py_XDECREF(w); +// if (err == 0) continue; +// break; +// + case Opcode.STORE_SUBSCR: { + PyObject key = stack.pop(); + PyObject obj = stack.pop(); + PyObject value = stack.pop(); + obj.__setitem__(key, value); + break; + } + + case Opcode.DELETE_SUBSCR: { + PyObject key = stack.pop(); + PyObject obj = stack.pop(); + obj.__delitem__(key); + break; + } + + case Opcode.PRINT_EXPR: + PySystemState.displayhook(stack.pop()); + break; + + case Opcode.PRINT_ITEM_TO: + Py.printComma(stack.pop(), stack.pop()); + break; + + case Opcode.PRINT_ITEM: + Py.printComma(stack.pop()); + break; + + case Opcode.PRINT_NEWLINE_TO: + Py.printlnv(stack.pop()); + break; + + case Opcode.PRINT_NEWLINE: + Py.println(); + break; + + case Opcode.RAISE_VARARGS: + + switch (oparg) { + case 3: { + PyObject tb = stack.pop(); + PyObject value = stack.pop(); + PyObject type = stack.pop(); + why = do_raise(type, value, tb); + break; + } + case 2: { + PyObject value = stack.pop(); + PyObject type = stack.pop(); + why = do_raise(type, value); + break; + } + case 1: { + PyObject type = stack.pop(); + why = do_raise(type); + break; + } + case 0: + why = do_raise(); + break; + default: + throw Py.SystemError("bad RAISE_VARARGS oparg"); + } + break; + + case Opcode.LOAD_LOCALS: + stack.push(f.f_locals); + break; + + case Opcode.RETURN_VALUE: + retval = stack.pop(); + why = Why.RETURN; + break; + + case Opcode.YIELD_VALUE: + retval = stack.pop(); + why = Why.YIELD; + break; + + case Opcode.EXEC_STMT: { + PyObject locals = stack.pop(); + PyObject globals = stack.pop(); + PyObject code = stack.pop(); + + if ((locals == null || locals == Py.None) && + (globals == null || globals == Py.None)) { + throw Py.SystemError("globals and locals cannot be NULL"); + } + Py.exec(code, globals, locals); + + if (!(globals.__finditem__("__builtins__").__nonzero__())) { + globals.__setitem__("__builtins__", f.f_builtins); + } + break; + } + +// case POP_BLOCK: +// { +// PyTryBlock *b = PyFrame_BlockPop(f); +// while (STACK_LEVEL() > b->b_level) { +// v = POP(); +// Py_DECREF(v); +// } +// } +// continue; +// +// case END_FINALLY: +// v = POP(); +// if (PyInt_Check(v)) { +// why = (enum why_code) PyInt_AS_LONG(v); +// assert(why != WHY_YIELD); +// if (why == WHY_RETURN || +// why == WHY_CONTINUE) +// retval = POP(); +// } +// else if (PyExceptionClass_Check(v) || PyString_Check(v)) { +// w = POP(); +// u = POP(); +// PyErr_Restore(v, w, u); +// why = WHY_RERAISE; +// break; +// } +// else if (v != Py_None) { +// PyErr_SetString(PyExc_SystemError, +// "'finally' pops bad exception"); +// why = WHY_EXCEPTION; +// } +// Py_DECREF(v); +// break; +// + case Opcode.BUILD_CLASS: { + PyObject methods = stack.pop(); + PyObject bases[] = (new PyTuple(stack.pop())).getArray(); + String name = stack.pop().toString(); + stack.push(Py.makeClass(name, bases, methods)); + break; + } + + case Opcode.STORE_NAME: + f.setlocal(oparg, stack.pop()); + break; + + case Opcode.DELETE_NAME: + f.dellocal(oparg); + break; + + case Opcode.UNPACK_SEQUENCE: { + PyObject v = stack.pop(); + int i = 0; + PyObject items[] = new PyObject[oparg]; + for (PyObject item : v.asIterable()) { + items[i++] = item; + if (i > oparg) { + break; + } + } + for (i = i - 1; i >= 0; i--) { + stack.push(items[i]); + } + break; + } + + case Opcode.STORE_ATTR: { + PyObject obj = stack.pop(); + PyObject v = stack.pop(); + obj.__setattr__(co_names[oparg], v); + break; + } + + case Opcode.DELETE_ATTR: + stack.pop().__delattr__(co_names[oparg]); + break; + + case Opcode.STORE_GLOBAL: + f.setglobal(co_names[oparg], stack.pop()); + break; + + case Opcode.DELETE_GLOBAL: + f.delglobal(co_names[oparg]); + break; + + case Opcode.LOAD_NAME: + stack.push(f.getname(co_names[oparg])); + break; + + case Opcode.LOAD_GLOBAL: + stack.push(f.getglobal(co_names[oparg])); + break; + + case Opcode.DELETE_FAST: + f.dellocal(oparg); + break; + + case Opcode.LOAD_CLOSURE: + stack.push(f.getclosure(oparg)); + break; + + case Opcode.LOAD_DEREF: + stack.push(f.getderef(oparg)); + break; + + case Opcode.STORE_DEREF: + f.setderef(oparg, stack.pop()); + break; + + case Opcode.BUILD_TUPLE: + stack.push(new PyTuple(stack.popN(oparg))); + break; + + case Opcode.BUILD_LIST: + stack.push(new PyList(stack.popN(oparg))); + break; + + case Opcode.BUILD_MAP: + stack.push(new PyDictionary()); + + case Opcode.LOAD_ATTR: + stack.push(stack.pop().__getattr__(co_names[oparg])); + break; + + case Opcode.COMPARE_OP: { + PyObject b = stack.pop(); + PyObject a = stack.pop(); + + switch (oparg) { + + case Opcode.PyCmp_LT: + stack.push(a._lt(b)); + break; + case Opcode.PyCmp_LE: + stack.push(a._le(b)); + break; + case Opcode.PyCmp_EQ: + stack.push(a._eq(b)); + break; + case Opcode.PyCmp_NE: + stack.push(a._ne(b)); + break; + case Opcode.PyCmp_GT: + stack.push(a._gt(b)); + break; + case Opcode.PyCmp_GE: + stack.push(a._ge(b)); + break; + case Opcode.PyCmp_IN: + stack.push(a._in(b)); + break; + case Opcode.PyCmp_NOT_IN: + stack.push(a._notin(b)); + break; + case Opcode.PyCmp_IS: + stack.push(a._is(b)); + break; + case Opcode.PyCmp_IS_NOT: + stack.push(a._isnot(b)); + break; + case Opcode.PyCmp_EXC_MATCH: + stack.push(Py.newBoolean(Py.matchException(new PyException(a), b))); + break; + + } + break; + } + + case Opcode.IMPORT_NAME: { + PyObject __import__ = f.f_builtins.__finditem__("__import__"); + if (__import__ == null) { + throw Py.ImportError("__import__ not found"); + } + PyString name = Py.newString(co_names[oparg]); + PyObject fromlist = stack.pop(); + PyObject level = stack.pop(); + + if (level.asInt() != -1) { + stack.push(__import__.__call__(new PyObject[]{name, f.f_globals, f.f_locals, fromlist, level})); + } else { + stack.push(__import__.__call__(new PyObject[]{name, f.f_globals, f.f_locals, fromlist})); + } + break; + } + + case Opcode.IMPORT_STAR: { + String module = stack.pop().toString(); + imp.importAll(module, f); + break; + } + + case Opcode.IMPORT_FROM: + String name = co_names[oparg]; + try { + stack.push(stack.pop().__getattr__(name)); + + } catch (PyException pye) { + if (Py.matchException(pye, Py.AttributeError)) { + throw Py.ImportError(String.format("cannot import name %.230s", name)); + } else { + throw pye; + } + } + break; + + case Opcode.JUMP_FORWARD: + next_instr += oparg; + break; + + case Opcode.JUMP_IF_FALSE: + if (!stack.top().__nonzero__()) { + next_instr += oparg; + } + break; + + case Opcode.JUMP_IF_TRUE: + if (stack.top().__nonzero__()) { + next_instr += oparg; + } + break; + + case Opcode.JUMP_ABSOLUTE: + next_instr = oparg; + break; + + case Opcode.GET_ITER: { + PyObject it = stack.top().__iter__(); + if (it != null) { + stack.set_top(it); + } + break; + } + + case Opcode.FOR_ITER: { + PyObject it = stack.pop(); + try { + PyObject x = it.__iternext__(); + if (x != null) { + stack.push(x); + } + } catch (PyException pye) { + if (!Py.matchException(pye, Py.StopIteration)) { + throw pye; + } + } + next_instr += oparg; + break; + } + + case Opcode.BREAK_LOOP: + why = Why.BREAK; + break; + + case Opcode.CONTINUE_LOOP: + retval = Py.newInteger(oparg); + if (retval.__nonzero__()) { + why = Why.CONTINUE; + } + break; +// +// case SETUP_LOOP: +// case SETUP_EXCEPT: +// case SETUP_FINALLY: +// /* NOTE: If you add any new block-setup opcodes that are not try/except/finally +// handlers, you may need to update the PyGen_NeedsFinalizing() function. */ +// +// PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, +// STACK_LEVEL()); +// continue; +// +// case WITH_CLEANUP: +// { +// /* TOP is the context.__exit__ bound method. +// Below that are 1-3 values indicating how/why +// we entered the finally clause: +// - SECOND = None +// - (SECOND, THIRD) = (WHY_{RETURN,CONTINUE}), retval +// - SECOND = WHY_*; no retval below it +// - (SECOND, THIRD, FOURTH) = exc_info() +// In the last case, we must call +// TOP(SECOND, THIRD, FOURTH) +// otherwise we must call +// TOP(None, None, None) +// +// In addition, if the stack represents an exception, +// *and* the function call returns a 'true' value, we +// "zap" this information, to prevent END_FINALLY from +// re-raising the exception. (But non-local gotos +// should still be resumed.) +// */ +// +// x = TOP(); +// u = SECOND(); +// if (PyInt_Check(u) || u == Py_None) { +// u = v = w = Py_None; +// } +// else { +// v = THIRD(); +// w = FOURTH(); +// } +// /* XXX Not the fastest way to call it... */ +// x = PyObject_CallFunctionObjArgs(x, u, v, w, NULL); +// if (x == NULL) +// break; /* Go to error exit */ +// if (u != Py_None && PyObject_IsTrue(x)) { +// /* There was an exception and a true return */ +// Py_DECREF(x); +// x = TOP(); /* Again */ +// STACKADJ(-3); +// Py_INCREF(Py_None); +// SET_TOP(Py_None); +// Py_DECREF(x); +// Py_DECREF(u); +// Py_DECREF(v); +// Py_DECREF(w); +// } else { +// /* Let END_FINALLY do its thing */ +// Py_DECREF(x); +// x = POP(); +// Py_DECREF(x); +// } +// break; +// } +// + case Opcode.CALL_FUNCTION: { + int na = oparg & 0xff; + int nk = (oparg >> 8) & 0xff; + int n = na + 2 * nk; + + PyObject args[] = stack.popN(na); + PyObject callable = stack.pop(); + System.err.println("__call__:" + callable + "," + Arrays.toString(args)); + stack.push(callable.__call__(args)); + break; + } + +// +// case CALL_FUNCTION_VAR: +// case CALL_FUNCTION_KW: +// case CALL_FUNCTION_VAR_KW: +// { +// int na = oparg & 0xff; +// int nk = (oparg>>8) & 0xff; +// int flags = (opcode - CALL_FUNCTION) & 3; +// int n = na + 2 * nk; +// PyObject **pfunc, *func, **sp; +// PCALL(PCALL_ALL); +// if (flags & CALL_FLAG_VAR) +// n++; +// if (flags & CALL_FLAG_KW) +// n++; +// pfunc = stack_pointer - n - 1; +// func = *pfunc; +// +// if (PyMethod_Check(func) +// && PyMethod_GET_SELF(func) != NULL) { +// PyObject *self = PyMethod_GET_SELF(func); +// Py_INCREF(self); +// func = PyMethod_GET_FUNCTION(func); +// Py_INCREF(func); +// Py_DECREF(*pfunc); +// *pfunc = self; +// na++; +// n++; +// } else +// Py_INCREF(func); +// sp = stack_pointer; +// READ_TIMESTAMP(intr0); +// x = ext_do_call(func, &sp, flags, na, nk); +// READ_TIMESTAMP(intr1); +// stack_pointer = sp; +// Py_DECREF(func); +// +// while (stack_pointer > pfunc) { +// w = POP(); +// Py_DECREF(w); +// } +// PUSH(x); +// if (x != NULL) +// continue; +// break; +// } +// + case Opcode.MAKE_FUNCTION: { + PyCode code = (PyCode) stack.pop(); + PyObject[] defaults = stack.popN(oparg); + PyFunction func = new PyFunction(f.f_globals, defaults, code); + stack.push(func); + break; + } + + case Opcode.MAKE_CLOSURE: { + PyCode code = (PyCode) stack.pop(); + PyObject[] closure_cells = new PyTuple(stack.pop()).getArray(); + PyObject[] defaults = stack.popN(oparg); + PyFunction func = new PyFunction(f.f_globals, defaults, code, closure_cells); + stack.push(func); + break; + } + +// case BUILD_SLICE: +// if (oparg == 3) +// w = POP(); +// else +// w = NULL; +// v = POP(); +// u = TOP(); +// x = PySlice_New(u, v, w); +// Py_DECREF(u); +// Py_DECREF(v); +// Py_XDECREF(w); +// SET_TOP(x); +// if (x != NULL) continue; +// break; +// + case Opcode.EXTENDED_ARG: + opcode = co_code[next_instr++]; + next_instr += 2; + oparg = oparg << 16 | ((co_code[next_instr - 1] << 8) + (co_code[next_instr - 2])); + break; + + default: + Py.print(Py.getSystemState().stderr, + Py.newString( + String.format("XXX lineno: %d, opcode: %d\n", + f.f_lasti, opcode))); + throw Py.SystemError("unknown opcode"); + + + } // end switch + } // end try + catch (Throwable t) { + // wrap so we can consume with our try block handling + PyException pye = Py.JavaError(t); + // XXX - but since that hasn't been written, for now just rethrow in wrapped form + throw pye; + } + + + // process why, blocks + switch (why) { + case RETURN: + return retval; + default: + break; + } + } // end while + return Py.None; // should never get here, just for debugging + } + + // XXX - perhaps add support for max stack size (presumably from co_stacksize) + // and capacity hints + class PyStack { + + final List<PyObject> stack; + + PyStack() { + stack = new ArrayList<PyObject>(); + } + + PyObject top() { + return stack.get(stack.size() - 1); + } + + PyObject pop() { + return stack.remove(stack.size() - 1); + } + + void push(PyObject v) { + stack.add(v); + } + + void set_top(PyObject v) { + stack.set(stack.size() - 1, v); + } + + void dup() { + stack.add(top()); + } + + void dupN(int n) { + PyObject v = top(); + for (int i = 0; i < n; i++) { + stack.add(v); + } + } + + PyObject[] popN(int n) { + int end = stack.size(); // exclusive + PyObject ret[] = new PyObject[n]; + List<PyObject> lastN = stack.subList(end - n, end); + lastN.toArray(ret); + lastN.clear(); + return ret; + } + + void rotN(int n) { + int end = stack.size(); + List<PyObject> lastN = stack.subList(end - n, end); + Collections.rotate(lastN, n); + } + + @Override + public String toString() { + return stack.toString(); + } + } +} + + Modified: branches/pbcvm/src/org/python/core/PyFrame.java =================================================================== --- branches/pbcvm/src/org/python/core/PyFrame.java 2009-01-20 13:47:20 UTC (rev 5948) +++ branches/pbcvm/src/org/python/core/PyFrame.java 2009-01-20 13:56:46 UTC (rev 5949) @@ -8,7 +8,7 @@ { public PyFrame f_... [truncated message content] |