From: <zy...@us...> - 2009-01-21 05:02:31
|
Revision: 5952 http://jython.svn.sourceforge.net/jython/?rev=5952&view=rev Author: zyasoft Date: 2009-01-21 05:02:29 +0000 (Wed, 21 Jan 2009) Log Message: ----------- Fixed binary and inplace bytecodes to use the proper methods. Added block support to support iteration. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-20 19:29:17 UTC (rev 5951) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-21 05:02:29 UTC (rev 5952) @@ -4,7 +4,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Map; public class PyBytecode extends PyBaseCode { @@ -20,7 +19,7 @@ return opname; } // end debugging - + public final static int CO_MAXBLOCKS = 20; // same as in CPython public final char[] co_code; // to avoid sign issues public final PyObject[] co_consts; public final String[] co_names; @@ -83,6 +82,7 @@ return new PyList(members); } + private void throwReadonly(String name) { for (int i = 0; i < __members__.length; i++) { if (__members__[i] == name) { @@ -161,6 +161,23 @@ throw new UnsupportedOperationException("Not yet implemented"); } + private static String stringify_blocks(PyFrame f) { + if (f.f_exits == null) return "[]"; + StringBuilder buf = new StringBuilder(); + for (int i = 0; i < f.f_blockstate[0]; i++) { + buf.append(f.f_exits[i].toString()); + } + return buf.toString(); + } + + private static void print_debug(int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { + System.err.println(count + "," + f.f_lasti + "> opcode: " + + getOpname().__getitem__(Py.newInteger(opcode)) + + (opcode > Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + + ", stack: " + stack.toString() + + ", blocks: " + stringify_blocks(f)); + } + @Override protected PyObject interpret(PyFrame f) { final PyStack stack = new PyStack(); @@ -172,15 +189,15 @@ 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 + next_instr += 1; + 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()); } + print_debug(next_instr, opcode, oparg, stack, f); + count += 1; try { @@ -252,14 +269,14 @@ case Opcode.BINARY_POWER: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__pow__(b)); + stack.push(a._pow(b)); break; } case Opcode.BINARY_MULTIPLY: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__mul__(b)); + stack.push(a._mul(b)); break; } @@ -268,9 +285,9 @@ PyObject a = stack.pop(); if ((co_flags & CO_FUTUREDIVISION) == 0) { - stack.push(a.__div__(b)); + stack.push(a._div(b)); } else { - stack.push(a.__truediv__(b)); + stack.push(a._truediv(b)); } break; } @@ -278,35 +295,35 @@ case Opcode.BINARY_TRUE_DIVIDE: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__truediv__(b)); + stack.push(a._truediv(b)); break; } case Opcode.BINARY_FLOOR_DIVIDE: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__floordiv__(b)); + stack.push(a._floordiv(b)); break; } case Opcode.BINARY_MODULO: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__mod__(b)); + stack.push(a._mod(b)); break; } case Opcode.BINARY_ADD: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__add__(b)); + stack.push(a._add(b)); break; } case Opcode.BINARY_SUBTRACT: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__sub__(b)); + stack.push(a._sub(b)); break; } @@ -320,21 +337,21 @@ case Opcode.BINARY_LSHIFT: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__lshift__(b)); + stack.push(a._lshift(b)); break; } case Opcode.BINARY_RSHIFT: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__rshift__(b)); + stack.push(a._rshift(b)); break; } case Opcode.BINARY_AND: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__and__(b)); + stack.push(a._and(b)); break; } @@ -342,14 +359,14 @@ case Opcode.BINARY_XOR: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__xor__(b)); + stack.push(a._xor(b)); break; } case Opcode.BINARY_OR: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__or__(b)); + stack.push(a._or(b)); break; } @@ -370,7 +387,7 @@ case Opcode.INPLACE_MULTIPLY: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__imul__(b)); + stack.push(a._imul(b)); break; } @@ -378,9 +395,9 @@ PyObject b = stack.pop(); PyObject a = stack.pop(); if ((co_flags & CO_FUTUREDIVISION) == 0) { - stack.push(a.__idiv__(b)); + stack.push(a._idiv(b)); } else { - stack.push(a.__itruediv__(b)); + stack.push(a._itruediv(b)); } break; } @@ -388,70 +405,70 @@ case Opcode.INPLACE_TRUE_DIVIDE: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__itruediv__(b)); + stack.push(a._itruediv(b)); break; } case Opcode.INPLACE_FLOOR_DIVIDE: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__ifloordiv__(b)); + stack.push(a._ifloordiv(b)); break; } case Opcode.INPLACE_MODULO: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__imod__(b)); + stack.push(a._imod(b)); break; } case Opcode.INPLACE_ADD: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__iadd__(b)); + stack.push(a._iadd(b)); break; } case Opcode.INPLACE_SUBTRACT: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__isub__(b)); + stack.push(a._isub(b)); break; } case Opcode.INPLACE_LSHIFT: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__ilshift__(b)); + stack.push(a._ilshift(b)); break; } case Opcode.INPLACE_RSHIFT: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__irshift__(b)); + stack.push(a._irshift(b)); break; } case Opcode.INPLACE_AND: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__iand__(b)); + stack.push(a._iand(b)); break; } case Opcode.INPLACE_XOR: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__ixor__(b)); + stack.push(a._ixor(b)); break; } case Opcode.INPLACE_OR: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__ior__(b)); + stack.push(a._ior(b)); break; } @@ -597,6 +614,16 @@ case Opcode.YIELD_VALUE: retval = stack.pop(); + // need to implement something like this when we reenter after a yield +// code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj); +// code.dup(); +// code.instanceof_("org/python/core/PyException"); +// Label done2 = new Label(); +// code.ifeq(done2); +// code.checkcast("java/lang/Throwable"); +// code.athrow(); +// code.label(done2); +// code.checkcast("org/python/core/PyObject"); why = Why.YIELD; break; @@ -617,15 +644,14 @@ break; } -// case POP_BLOCK: -// { -// PyTryBlock *b = PyFrame_BlockPop(f); -// while (STACK_LEVEL() > b->b_level) { -// v = POP(); -// Py_DECREF(v); -// } -// } -// continue; + case Opcode.POP_BLOCK: + { + PyTryBlock b = (PyTryBlock) (f.f_exits[--f.f_blockstate[0]]); + while (stack.size() > b.b_level) { + stack.pop(); + } + } + break; // // case END_FINALLY: // v = POP(); @@ -839,7 +865,7 @@ break; case Opcode.JUMP_ABSOLUTE: - next_instr = oparg; + next_instr = oparg - 1; // XXX - continue to a label is probably much better break; case Opcode.GET_ITER: { @@ -855,7 +881,9 @@ try { PyObject x = it.__iternext__(); if (x != null) { + stack.push(it); stack.push(x); + break; } } catch (PyException pye) { if (!Py.matchException(pye, Py.StopIteration)) { @@ -876,17 +904,18 @@ why = Why.CONTINUE; } break; + + case Opcode.SETUP_LOOP: + case Opcode.SETUP_EXCEPT: + case Opcode.SETUP_FINALLY: { + if (f.f_exits == null) { // allocate in the frame where they can fit! consider supporting directly in the frame + f.f_exits = new PyObject[CO_MAXBLOCKS]; // f_blockstack in CPython - a simple ArrayList might be best + f.f_blockstate = new int[]{0}; // f_iblock in CPython + } + f.f_exits[f.f_blockstate[0]++] = new PyTryBlock(opcode, next_instr + oparg, stack.size()); + 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. @@ -1069,7 +1098,7 @@ // XXX - perhaps add support for max stack size (presumably from co_stacksize) // and capacity hints - class PyStack { + private class PyStack { final List<PyObject> stack; @@ -1119,11 +1148,37 @@ Collections.rotate(lastN, n); } + int size() { + return stack.size(); + } + @Override public String toString() { return stack.toString(); } } + + private class PyTryBlock extends PyObject { // purely to sit on top of the existing PyFrame in f_exits!!! + + int b_type; /* what kind of block this is */ + + int b_handler; /* where to jump to find handler */ + + int b_level; /* value stack level to pop to */ + + + PyTryBlock(int type, int handler, int level) { + b_type = type; + b_handler = handler; + b_level = level; + } + + @Override + public String toString() { + return "[" + getOpname().__getitem__(Py.newInteger(b_type)) + "," + + b_handler + "," + b_level + "]"; + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-23 04:40:32
|
Revision: 5962 http://jython.svn.sourceforge.net/jython/?rev=5962&view=rev Author: zyasoft Date: 2009-01-23 04:40:26 +0000 (Fri, 23 Jan 2009) Log Message: ----------- Added support for try/except and try/finally blocks (and their combination). Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-23 01:03:39 UTC (rev 5961) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-23 04:40:26 UTC (rev 5962) @@ -82,7 +82,6 @@ return new PyList(members); } - private void throwReadonly(String name) { for (int i = 0; i < __members__.length; i++) { if (__members__[i] == name) { @@ -145,24 +144,48 @@ }; - private Why do_raise() { - throw new UnsupportedOperationException("Not yet implemented"); - } + // to enable why's to be stored on a PyStack + private class PyStackWhy extends PyObject { - private Why do_raise(PyObject type) { - throw new UnsupportedOperationException("Not yet implemented"); + Why why; + + PyStackWhy(Why why) { + this.why = why; + } + + @Override + public String toString() { + return why.toString(); + } } - private Why do_raise(PyObject type, PyObject value) { - throw new UnsupportedOperationException("Not yet implemented"); + private class PyStackException extends PyObject { + + PyException exception; + + PyStackException(PyException exception) { + this.exception = exception; + } + + @Override + public String toString() { + return exception.toString(); + } } - private Why do_raise(PyObject type, PyObject value, PyObject traceback) { - throw new UnsupportedOperationException("Not yet implemented"); + private static Why do_raise(ThreadState ts, PyObject type, PyObject value, PyTraceback traceback) { + PyException pye = type == null ? ts.exception : new PyException(type, value, traceback); + if (traceback == null) { + return Why.EXCEPTION; + } else { + return Why.RERAISE; + } } private static String stringify_blocks(PyFrame f) { - if (f.f_exits == null) return "[]"; + if (f.f_exits == null || f.f_blockstate[0] == 0) { + return "[]"; + } StringBuilder buf = new StringBuilder(); for (int i = 0; i < f.f_blockstate[0]; i++) { buf.append(f.f_exits[i].toString()); @@ -175,9 +198,29 @@ getOpname().__getitem__(Py.newInteger(opcode)) + (opcode > Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + ", stack: " + stack.toString() + - ", blocks: " + stringify_blocks(f)); + ", blocks: " + stringify_blocks(f)); } + private static PyTryBlock popBlock(PyFrame f) { + return (PyTryBlock) (f.f_exits[--f.f_blockstate[0]]); + } + + private static void pushBlock(PyFrame f, PyTryBlock block) { + if (f.f_exits == null) { // allocate in the frame where they can fit! consider supporting directly in the frame + f.f_exits = new PyObject[CO_MAXBLOCKS]; // f_blockstack in CPython - a simple ArrayList might be best + f.f_blockstate = new int[]{0}; // f_iblock in CPython - f_blockstate is likely go away soon + } + f.f_exits[f.f_blockstate[0]++] = block; + } + + private boolean blocksLeft(PyFrame f) { + if (f.f_exits != null) { + return f.f_blockstate[0] > 0; + } else { + return false; + } + } + @Override protected PyObject interpret(PyFrame f) { final PyStack stack = new PyStack(); @@ -186,10 +229,19 @@ int oparg = 0; /* Current opcode argument, if any */ Why why = Why.NOT; PyObject retval = null; + ThreadState ts = Py.getThreadState(); // XXX - change interpret to pass through from PyFrame + // need to support something like this, but perhaps we can get this from the frame itself? +// if (throwflag) { /* support for generator.throw() */ +// why = WHY_EXCEPTION; +// goto on_error; +// } + while (count < maxCount) { // XXX - replace with while(true) next_instr += 1; + // this may work: detach setting anything in the frame to improve performance, instead do this + // in a shadow version of the frame that we copy back to 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) { @@ -237,7 +289,7 @@ stack.dup(); break; - case Opcode.DUP_TOPX: + case Opcode.DUP_TOPX: { if (oparg == 2 || oparg == 3) { stack.dupN(oparg); } else { @@ -245,6 +297,7 @@ " (bytecode corruption?)"); } break; + } case Opcode.UNARY_POSITIVE: stack.push(stack.pop().__pos__()); @@ -578,25 +631,25 @@ switch (oparg) { case 3: { - PyObject tb = stack.pop(); + PyTraceback tb = (PyTraceback) (stack.pop()); PyObject value = stack.pop(); PyObject type = stack.pop(); - why = do_raise(type, value, tb); + why = do_raise(ts, type, value, tb); break; } case 2: { PyObject value = stack.pop(); PyObject type = stack.pop(); - why = do_raise(type, value); + why = do_raise(ts, type, value, null); break; } case 1: { PyObject type = stack.pop(); - why = do_raise(type); + why = do_raise(ts, type, null, null); break; } case 0: - why = do_raise(); + why = do_raise(ts, null, null, null); break; default: throw Py.SystemError("bad RAISE_VARARGS oparg"); @@ -644,39 +697,31 @@ break; } - case Opcode.POP_BLOCK: - { - PyTryBlock b = (PyTryBlock) (f.f_exits[--f.f_blockstate[0]]); - while (stack.size() > b.b_level) { - stack.pop(); + case Opcode.POP_BLOCK: { + PyTryBlock b = popBlock(f); + while (stack.size() > b.b_level) { + stack.pop(); + } + break; + } + + case Opcode.END_FINALLY: { + PyObject v = stack.pop(); + if (v instanceof PyStackWhy) { + why = ((PyStackWhy) v).why; + assert (why != Why.YIELD); + if (why == Why.RETURN || why == Why.CONTINUE) { + retval = stack.pop(); } + } else if ((v instanceof PyStackException) || (v instanceof PyString)) { + ts.exception = ((PyStackException) v).exception; + why = Why.RERAISE; + } else if (v != Py.None) { + throw Py.SystemError("'finally' pops bad exception"); } break; -// -// 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(); @@ -804,7 +849,12 @@ stack.push(a._isnot(b)); break; case Opcode.PyCmp_EXC_MATCH: - stack.push(Py.newBoolean(Py.matchException(new PyException(a), b))); + if (a instanceof PyStackException) { + PyException pye = ((PyStackException) a).exception; + stack.push(Py.newBoolean(Py.matchException(pye, b))); + } else { + stack.push(Py.newBoolean(Py.matchException(new PyException(a), b))); + } break; } @@ -907,14 +957,9 @@ case Opcode.SETUP_LOOP: case Opcode.SETUP_EXCEPT: - case Opcode.SETUP_FINALLY: { - if (f.f_exits == null) { // allocate in the frame where they can fit! consider supporting directly in the frame - f.f_exits = new PyObject[CO_MAXBLOCKS]; // f_blockstack in CPython - a simple ArrayList might be best - f.f_blockstate = new int[]{0}; // f_iblock in CPython - } - f.f_exits[f.f_blockstate[0]++] = new PyTryBlock(opcode, next_instr + oparg, stack.size()); + case Opcode.SETUP_FINALLY: + pushBlock(f, new PyTryBlock(opcode, next_instr + oparg, stack.size())); break; - } // // case WITH_CLEANUP: // { @@ -1078,22 +1123,67 @@ } // 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; + why = Why.EXCEPTION; + ts.exception = pye; } + // do some trace handling here + if (why == Why.RERAISE) { + why = Why.EXCEPTION; + } - // process why, blocks - switch (why) { - case RETURN: - return retval; - default: + while (why != Why.NOT && blocksLeft(f)) { + PyTryBlock b = popBlock(f); + assert (why != Why.YIELD); + if (b.b_type == Opcode.SETUP_LOOP && why == Why.CONTINUE) { + pushBlock(f, b); + why = Why.NOT; + next_instr = retval.asInt(); break; + } + while (stack.size() > b.b_level) { + stack.pop(); + } + if (b.b_type == Opcode.SETUP_LOOP && why == Why.BREAK) { + why = Why.NOT; + next_instr = b.b_handler; + break; + } + if (b.b_type == Opcode.SETUP_FINALLY || (b.b_type == Opcode.SETUP_EXCEPT && why == Why.EXCEPTION)) { + if (why == Why.EXCEPTION) { + PyException exc = ts.exception; + if (b.b_type == Opcode.SETUP_EXCEPT) { + exc.normalize(); + } + stack.push(Py.None); // XXX - x3 to conform with CPython which + stack.push(Py.None); // stores the type, val, tb separately on the stack + stack.push(new PyStackException(exc)); + } else { + if (why == Why.RETURN || why == Why.CONTINUE) { + stack.push(retval); + } + stack.push(Py.newString(why.name())); // XXX - hack! + } + why = Why.NOT; + next_instr = b.b_handler; + break; + } + } // unwindstack + + if (why != Why.NOT) { + break; } - } // end while - return Py.None; // should never get here, just for debugging + } + assert (why != Why.YIELD); + while (stack.size() > 0) { + stack.pop(); + } + if (why != Why.RETURN) { + retval = Py.None; + } + + return retval; } // XXX - perhaps add support for max stack size (presumably from co_stacksize) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-23 15:30:34
|
Revision: 5964 http://jython.svn.sourceforge.net/jython/?rev=5964&view=rev Author: zyasoft Date: 2009-01-23 15:30:09 +0000 (Fri, 23 Jan 2009) Log Message: ----------- Basic generators are almost supported. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-23 15:22:27 UTC (rev 5963) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-23 15:30:09 UTC (rev 5964) @@ -8,16 +8,22 @@ 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; + private int count = 0; // total number of opcodes run + private int maxCount = 900; // less than my buffer on iterm + private static PyObject opname; - static synchronized PyObject getOpname() { + private static synchronized PyObject getOpname() { if (opname == null) { opname = __builtin__.__import__("dis").__getattr__("opname"); } return opname; } + + public PyObject _debug(int maxCount) { + this.maxCount = maxCount; + return Py.None; + } + // end debugging public final static int CO_MAXBLOCKS = 20; // same as in CPython public final char[] co_code; // to avoid sign issues @@ -193,7 +199,7 @@ return buf.toString(); } - private static void print_debug(int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { + private static void print_debug(int count, int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { System.err.println(count + "," + f.f_lasti + "> opcode: " + getOpname().__getitem__(Py.newInteger(opcode)) + (opcode > Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + @@ -229,28 +235,41 @@ int oparg = 0; /* Current opcode argument, if any */ Why why = Why.NOT; PyObject retval = null; - ThreadState ts = Py.getThreadState(); // XXX - change interpret to pass through from PyFrame + ThreadState ts = Py.getThreadState(); // XXX - change interpret to pass through from PyFrame since our ts will never change - // need to support something like this, but perhaps we can get this from the frame itself? + // this may work: detach setting/getting anything in the frame to improve performance, instead do this + // in a shadow version of the frame that we copy back to + + next_instr = f.f_lasti; + // check if we have been thrown an exception in the generatorinput, this + // is roughly the same as // if (throwflag) { /* support for generator.throw() */ // why = WHY_EXCEPTION; // goto on_error; // } + if (f.f_savedlocals != null) { + for (int i = 0; i < f.f_savedlocals.length; i++) { + PyObject v = (PyObject)(f.f_savedlocals[i]); + stack.push(v); + } + stack.push(Py.None); // put the generator input in here + f.f_savedlocals = null; + } + while (count < maxCount) { // XXX - replace with while(true) - next_instr += 1; - // this may work: detach setting anything in the frame to improve performance, instead do this - // in a shadow version of the frame that we copy back to - 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]; } - print_debug(next_instr, opcode, oparg, stack, f); + print_debug(count, next_instr, opcode, oparg, stack, f); - count += 1; + count += 1; + next_instr += 1; + f.f_lasti = next_instr; // should have no worries about needing co_lnotab, just keep this current try { switch (opcode) { @@ -1128,7 +1147,11 @@ ts.exception = pye; } - // do some trace handling here + if (why == Why.YIELD) { + break; + } + + // do some trace handling here, but for now just convert to EXCEPTION if (why == Why.RERAISE) { why = Why.EXCEPTION; } @@ -1156,7 +1179,7 @@ if (b.b_type == Opcode.SETUP_EXCEPT) { exc.normalize(); } - stack.push(Py.None); // XXX - x3 to conform with CPython which + stack.push(Py.None); // XXX - x3 to conform with CPython's calling convention, which stack.push(Py.None); // stores the type, val, tb separately on the stack stack.push(new PyStackException(exc)); } else { @@ -1174,15 +1197,26 @@ if (why != Why.NOT) { break; } + + } // end-while of the instruction loop + + if (why != Why.YIELD) { + while (stack.size() > 0) { + stack.pop(); + } + if (why != Why.RETURN) { + retval = Py.None; + } + } else { + // store the stack in the frame for reentry from the yield; + f.f_savedlocals = stack.popN(stack.size()); + // also need to add support for checking the generatorinput etc } - assert (why != Why.YIELD); - while (stack.size() > 0) { - stack.pop(); - } - if (why != Why.RETURN) { - retval = Py.None; - } + f.f_lasti = next_instr; // need to update on function entry, etc + System.err.println(count + "," + f.f_lasti + "> Returning from " + why + ": " + retval + + ", stack: " + stack.toString() + + ", blocks: " + stringify_blocks(f)); return retval; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-24 02:49:56
|
Revision: 5967 http://jython.svn.sourceforge.net/jython/?rev=5967&view=rev Author: zyasoft Date: 2009-01-24 02:49:52 +0000 (Sat, 24 Jan 2009) Log Message: ----------- Now supports generators, via the standard PyGenerator protocol. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 00:17:40 UTC (rev 5966) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 02:49:52 UTC (rev 5967) @@ -240,7 +240,15 @@ // this may work: detach setting/getting anything in the frame to improve performance, instead do this // in a shadow version of the frame that we copy back to + System.err.println("Entry with " + f.f_lasti + " into " + co_code.length); + if (f.f_lasti >= co_code.length) { +// f.f_lasti = -1; +// return Py.None; + throw Py.StopIteration(""); + } + next_instr = f.f_lasti; + // check if we have been thrown an exception in the generatorinput, this // is roughly the same as // if (throwflag) { /* support for generator.throw() */ @@ -250,7 +258,7 @@ if (f.f_savedlocals != null) { for (int i = 0; i < f.f_savedlocals.length; i++) { - PyObject v = (PyObject)(f.f_savedlocals[i]); + PyObject v = (PyObject) (f.f_savedlocals[i]); stack.push(v); } stack.push(Py.None); // put the generator input in here @@ -267,7 +275,7 @@ } print_debug(count, next_instr, opcode, oparg, stack, f); - count += 1; + count += 1; next_instr += 1; f.f_lasti = next_instr; // should have no worries about needing co_lnotab, just keep this current @@ -544,73 +552,40 @@ 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.SLICE + 0: + case Opcode.SLICE + 1: + case Opcode.SLICE + 2: + case Opcode.SLICE + 3: { + PyObject stop = (((opcode - Opcode.SLICE) & 2) != 0) ? stack.pop() : null; + PyObject start = (((opcode - Opcode.SLICE) & 1) != 0) ? stack.pop() : null; + PyObject obj = stack.pop(); + stack.push(obj.__getslice__(start, stop)); + break; + } + + case Opcode.STORE_SLICE + 0: + case Opcode.STORE_SLICE + 1: + case Opcode.STORE_SLICE + 2: + case Opcode.STORE_SLICE + 3: { + PyObject stop = (((opcode - Opcode.SLICE) & 2) != 0) ? stack.pop() : null; + PyObject start = (((opcode - Opcode.SLICE) & 1) != 0) ? stack.pop() : null; + PyObject obj = stack.pop(); + PyObject value = stack.pop(); + obj.__setslice__(start, stop, value); + break; + } + + case Opcode.DELETE_SLICE + 0: + case Opcode.DELETE_SLICE + 1: + case Opcode.DELETE_SLICE + 2: + case Opcode.DELETE_SLICE + 3: { + PyObject stop = (((opcode - Opcode.SLICE) & 2) != 0) ? stack.pop() : null; + PyObject start = (((opcode - Opcode.SLICE) & 1) != 0) ? stack.pop() : null; + PyObject obj = stack.pop(); + obj.__delslice__(start, stop); + break; + } + case Opcode.STORE_SUBSCR: { PyObject key = stack.pop(); PyObject obj = stack.pop(); @@ -979,61 +954,46 @@ case Opcode.SETUP_FINALLY: pushBlock(f, new PyTryBlock(opcode, next_instr + oparg, stack.size())); break; -// -// 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.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.) + */ + PyObject exit = stack.top(); + PyObject u = stack.top(2); + PyObject v; + PyObject w; + if (u == Py.None || u instanceof PyStackWhy) { + u = v = w = Py.None; + } else { + v = stack.top(3); + w = stack.top(4); + } + PyObject x = exit.__call__(u, v, w); + if (u != Py.None && x.__nonzero__()) { + stack.popN(4); + stack.push(Py.None); + } else { + stack.pop(); + } + break; + } + case Opcode.CALL_FUNCTION: { int na = oparg & 0xff; int nk = (oparg >> 8) & 0xff; @@ -1110,21 +1070,14 @@ 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.BUILD_SLICE: { + PyObject step = oparg == 3 ? stack.pop() : null; + PyObject stop = stack.pop(); + PyObject start = stack.pop(); + stack.push(new PySlice(start, stop, step)); + break; + } + case Opcode.EXTENDED_ARG: opcode = co_code[next_instr++]; next_instr += 2; @@ -1197,7 +1150,7 @@ if (why != Why.NOT) { break; } - + } // end-while of the instruction loop if (why != Why.YIELD) { @@ -1210,13 +1163,19 @@ } else { // store the stack in the frame for reentry from the yield; f.f_savedlocals = stack.popN(stack.size()); - // also need to add support for checking the generatorinput etc + // also need to add support for checking the generatorinput etc } f.f_lasti = next_instr; // need to update on function entry, etc + System.err.println(count + "," + f.f_lasti + "> Returning from " + why + ": " + retval + ", stack: " + stack.toString() + ", blocks: " + stringify_blocks(f)); + + if ((co_flags & CO_GENERATOR) != 0 && why == Why.RETURN && retval == Py.None) { + f.f_lasti = -1; + } + return retval; } @@ -1234,6 +1193,10 @@ return stack.get(stack.size() - 1); } + PyObject top(int n) { + return stack.get(stack.size() - n); + } + PyObject pop() { return stack.remove(stack.size() - 1); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-24 04:36:09
|
Revision: 5968 http://jython.svn.sourceforge.net/jython/?rev=5968&view=rev Author: zyasoft Date: 2009-01-24 04:36:06 +0000 (Sat, 24 Jan 2009) Log Message: ----------- Added support for keyword args, *arg, and **kwarg calling conventions. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 02:49:52 UTC (rev 5967) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 04:36:06 UTC (rev 5968) @@ -1,7 +1,6 @@ package org.python.core; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -31,6 +30,8 @@ public final String[] co_names; public final int co_stacksize; // ignored, probably shouldn't be public final PyObject[] co_lnotab; // ignored + private final static int CALL_FLAG_VAR = 1; + private final static int CALL_FLAG_KW = 2; // follows new.code's interface public PyBytecode(int argcount, int nlocals, int stacksize, int flags, @@ -997,62 +998,28 @@ 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)); + if (nk == 0) { + call_function(na, stack); + } else { + call_function(na, nk, stack); + } 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.CALL_FUNCTION_VAR: + case Opcode.CALL_FUNCTION_KW: + case Opcode.CALL_FUNCTION_VAR_KW: { + int na = oparg & 0xff; + int nk = (oparg >> 8) & 0xff; + int flags = (opcode - Opcode.CALL_FUNCTION) & 3; + call_function(na, nk, + (flags & CALL_FLAG_VAR) != 0, + (flags & CALL_FLAG_KW) != 0, + stack); + break; + } + case Opcode.MAKE_FUNCTION: { PyCode code = (PyCode) stack.pop(); PyObject[] defaults = stack.popN(oparg); @@ -1179,6 +1146,90 @@ return retval; } + private static void call_function(int na, PyStack stack) { + switch (na) { + case 0: { + PyObject callable = stack.pop(); + stack.push(callable.__call__()); + break; + } + case 1: { + PyObject arg = stack.pop(); + PyObject callable = stack.pop(); + stack.push(callable.__call__(arg)); + break; + } + case 2: { + PyObject arg1 = stack.pop(); + PyObject arg0 = stack.pop(); + PyObject callable = stack.pop(); + stack.push(callable.__call__(arg0, arg1)); + break; + } + case 3: { + PyObject arg2 = stack.pop(); + PyObject arg1 = stack.pop(); + PyObject arg0 = stack.pop(); + PyObject callable = stack.pop(); + stack.push(callable.__call__(arg0, arg1, arg2)); + break; + } + case 4: { + PyObject arg3 = stack.pop(); + PyObject arg2 = stack.pop(); + PyObject arg1 = stack.pop(); + PyObject arg0 = stack.pop(); + PyObject callable = stack.pop(); + stack.push(callable.__call__(arg0, arg1, arg2, arg3)); + break; + } + default: { + PyObject args[] = stack.popN(na); + PyObject callable = stack.pop(); + stack.push(callable.__call__(args)); + } + } + } + + private static void call_function(int na, int nk, PyStack stack) { + int n = na + nk * 2; + PyObject params[] = stack.popN(n); + PyObject callable = stack.pop(); + + PyObject args[] = new PyObject[na + nk]; + String keywords[] = new String[nk]; + int i; + for (i = 0; i < na; i++) { + args[i] = params[i]; + } + for (int j = 0; i < n; i += 2, j++) { + keywords[j] = params[i].toString(); + args[na + j] = params[i + 1]; + } + stack.push(callable.__call__(args, keywords)); + } + + private static void call_function(int na, int nk, boolean var, boolean kw, PyStack stack) { + int n = na + nk * 2; + PyObject kwargs = kw ? stack.pop() : null; + PyObject starargs = var ? stack.pop() : null; + PyObject params[] = stack.popN(n); + PyObject callable = stack.pop(); + + PyObject args[] = new PyObject[na + nk]; + String keywords[] = new String[nk]; + int i; + for (i = 0; i < na; i++) { + args[i] = params[i]; + } + for (int j = 0; i < n; i += 2, j++) { + keywords[j] = params[i].toString(); + args[na + j] = params[i + 1]; + + } + stack.push(callable._callextra(args, keywords, starargs, kwargs)); + } + // XXX - perhaps add support for max stack size (presumably from co_stacksize) // and capacity hints private class PyStack { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-24 16:48:04
|
Revision: 5969 http://jython.svn.sourceforge.net/jython/?rev=5969&view=rev Author: zyasoft Date: 2009-01-24 16:47:59 +0000 (Sat, 24 Jan 2009) Log Message: ----------- Added support for basic coroutines (no support for throw) and generator expressions. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 04:36:06 UTC (rev 5968) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 16:47:59 UTC (rev 5969) @@ -200,8 +200,9 @@ return buf.toString(); } - private static void print_debug(int count, int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { - System.err.println(count + "," + f.f_lasti + "> opcode: " + + private void print_debug(int count, int next_instr, int opcode, int oparg, PyStack stack, PyFrame f) { + System.err.println(co_name + ":" + + count + "," + f.f_lasti + "> opcode: " + getOpname().__getitem__(Py.newInteger(opcode)) + (opcode > Opcode.HAVE_ARGUMENT ? ", oparg: " + oparg : "") + ", stack: " + stack.toString() + @@ -257,18 +258,22 @@ // goto on_error; // } + // the restore stack aspets should occur ONLY after a yield if (f.f_savedlocals != null) { for (int i = 0; i < f.f_savedlocals.length; i++) { PyObject v = (PyObject) (f.f_savedlocals[i]); stack.push(v); } - stack.push(Py.None); // put the generator input in here + Object generatorInput = f.getGeneratorInput(); + if (generatorInput instanceof PyException) { + throw (PyException)generatorInput; + } + stack.push((PyObject)generatorInput); // put the generator input in here f.f_savedlocals = null; } while (count < maxCount) { // XXX - replace with while(true) - opcode = co_code[next_instr]; if (opcode > Opcode.HAVE_ARGUMENT) { next_instr += 2; @@ -662,16 +667,6 @@ case Opcode.YIELD_VALUE: retval = stack.pop(); - // need to implement something like this when we reenter after a yield -// code.invokevirtual("org/python/core/PyFrame", "getGeneratorInput", "()" + $obj); -// code.dup(); -// code.instanceof_("org/python/core/PyException"); -// Label done2 = new Label(); -// code.ifeq(done2); -// code.checkcast("java/lang/Throwable"); -// code.athrow(); -// code.label(done2); -// code.checkcast("org/python/core/PyObject"); why = Why.YIELD; break; @@ -910,7 +905,7 @@ break; case Opcode.JUMP_ABSOLUTE: - next_instr = oparg - 1; // XXX - continue to a label is probably much better + next_instr = oparg; // XXX - continue to a label is probably much better break; case Opcode.GET_ITER: { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-24 18:02:40
|
Revision: 5970 http://jython.svn.sourceforge.net/jython/?rev=5970&view=rev Author: zyasoft Date: 2009-01-24 18:02:37 +0000 (Sat, 24 Jan 2009) Log Message: ----------- Supports throwing exceptions into generators. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 16:47:59 UTC (rev 5969) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-24 18:02:37 UTC (rev 5970) @@ -193,10 +193,15 @@ if (f.f_exits == null || f.f_blockstate[0] == 0) { return "[]"; } - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < f.f_blockstate[0]; i++) { + StringBuilder buf = new StringBuilder("["); + int len = f.f_blockstate[0]; + for (int i = 0; i < len; i++) { buf.append(f.f_exits[i].toString()); + if (i < len - 1) { + buf.append(", "); + } } + buf.append("]"); return buf.toString(); } @@ -239,53 +244,53 @@ PyObject retval = null; ThreadState ts = Py.getThreadState(); // XXX - change interpret to pass through from PyFrame since our ts will never change - // this may work: detach setting/getting anything in the frame to improve performance, instead do this - // in a shadow version of the frame that we copy back to + // XXX - optimization opportunities + // 1. consider detaching the setting/getting of frame fields to improve performance, instead do this + // in a shadow version of the frame that we copy back to on entry/exit and downcalls System.err.println("Entry with " + f.f_lasti + " into " + co_code.length); if (f.f_lasti >= co_code.length) { -// f.f_lasti = -1; -// return Py.None; - throw Py.StopIteration(""); + throw Py.SystemError(""); } next_instr = f.f_lasti; - // check if we have been thrown an exception in the generatorinput, this - // is roughly the same as -// if (throwflag) { /* support for generator.throw() */ -// why = WHY_EXCEPTION; -// goto on_error; -// } - - // the restore stack aspets should occur ONLY after a yield + // the restore stack aspects should occur ONLY after a yield + boolean checkGeneratorInput = false; if (f.f_savedlocals != null) { for (int i = 0; i < f.f_savedlocals.length; i++) { PyObject v = (PyObject) (f.f_savedlocals[i]); stack.push(v); } - Object generatorInput = f.getGeneratorInput(); - if (generatorInput instanceof PyException) { - throw (PyException)generatorInput; - } - stack.push((PyObject)generatorInput); // put the generator input in here + checkGeneratorInput = true; f.f_savedlocals = null; } while (count < maxCount) { // XXX - replace with while(true) - opcode = co_code[next_instr]; - if (opcode > Opcode.HAVE_ARGUMENT) { - next_instr += 2; - oparg = (co_code[next_instr] << 8) + co_code[next_instr - 1]; - } - print_debug(count, next_instr, opcode, oparg, stack, f); + try { - count += 1; - next_instr += 1; - f.f_lasti = next_instr; // should have no worries about needing co_lnotab, just keep this current + if (checkGeneratorInput) { + checkGeneratorInput = false; + Object generatorInput = f.getGeneratorInput(); + if (generatorInput instanceof PyException) { + throw (PyException) generatorInput; + } + stack.push((PyObject) generatorInput); + } - try { + opcode = co_code[next_instr]; + if (opcode > Opcode.HAVE_ARGUMENT) { + next_instr += 2; + oparg = (co_code[next_instr] << 8) + co_code[next_instr - 1]; + } + print_debug(count, next_instr, opcode, oparg, stack, f); + + count += 1; + next_instr += 1; + f.f_lasti = next_instr; // should have no worries about needing co_lnotab, just keep this current + + switch (opcode) { case Opcode.NOP: break; @@ -307,15 +312,15 @@ break; case Opcode.ROT_TWO: - stack.rotN(2); + stack.rot(2); break; case Opcode.ROT_THREE: - stack.rotN(3); + stack.rot(3); break; case Opcode.ROT_FOUR: - stack.rotN(4); + stack.rot(4); break; case Opcode.DUP_TOP: @@ -324,7 +329,7 @@ case Opcode.DUP_TOPX: { if (oparg == 2 || oparg == 3) { - stack.dupN(oparg); + stack.dup(oparg); } else { throw Py.RuntimeError("invalid argument to DUP_TOPX" + " (bytecode corruption?)"); @@ -1094,9 +1099,8 @@ if (b.b_type == Opcode.SETUP_EXCEPT) { exc.normalize(); } - stack.push(Py.None); // XXX - x3 to conform with CPython's calling convention, which - stack.push(Py.None); // stores the type, val, tb separately on the stack - stack.push(new PyStackException(exc)); + stack.push(new PyStackException(exc)); // x3 to conform with CPython's calling convention, which + stack.dup(2); // stores the type, val, tb separately on the stack } else { if (why == Why.RETURN || why == Why.CONTINUE) { stack.push(retval); @@ -1125,7 +1129,6 @@ } else { // store the stack in the frame for reentry from the yield; f.f_savedlocals = stack.popN(stack.size()); - // also need to add support for checking the generatorinput etc } f.f_lasti = next_instr; // need to update on function entry, etc @@ -1134,6 +1137,10 @@ ", stack: " + stack.toString() + ", blocks: " + stringify_blocks(f)); + if (why == why.EXCEPTION) { + throw ts.exception; + } + if ((co_flags & CO_GENERATOR) != 0 && why == Why.RETURN && retval == Py.None) { f.f_lasti = -1; } @@ -1259,7 +1266,7 @@ stack.add(top()); } - void dupN(int n) { + void dup(int n) { PyObject v = top(); for (int i = 0; i < n; i++) { stack.add(v); @@ -1275,7 +1282,7 @@ return ret; } - void rotN(int n) { + void rot(int n) { int end = stack.size(); List<PyObject> lastN = stack.subList(end - n, end); Collections.rotate(lastN, n); @@ -1308,8 +1315,8 @@ @Override public String toString() { - return "[" + getOpname().__getitem__(Py.newInteger(b_type)) + "," + - b_handler + "," + b_level + "]"; + return "<" + getOpname().__getitem__(Py.newInteger(b_type)) + "," + + b_handler + "," + b_level + ">"; } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-01-27 02:44:12
|
Revision: 5989 http://jython.svn.sourceforge.net/jython/?rev=5989&view=rev Author: zyasoft Date: 2009-01-27 02:26:20 +0000 (Tue, 27 Jan 2009) Log Message: ----------- Fixed RAISE_VARARGS opcode to raise exceptions properly. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-27 02:16:49 UTC (rev 5988) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-01-27 02:26:20 UTC (rev 5989) @@ -625,27 +625,22 @@ PyTraceback tb = (PyTraceback) (stack.pop()); PyObject value = stack.pop(); PyObject type = stack.pop(); - PyException.doRaise(type, value, tb); - break; + throw PyException.doRaise(type, value, tb); } case 2: { PyObject value = stack.pop(); PyObject type = stack.pop(); - PyException.doRaise(type, value, null); - break; + throw PyException.doRaise(type, value, null); } case 1: { PyObject type = stack.pop(); - PyException.doRaise(type, null, null); - break; + throw PyException.doRaise(type, null, null); } case 0: - PyException.doRaise(null, null, null); - break; + throw PyException.doRaise(null, null, null); default: throw Py.SystemError("bad RAISE_VARARGS oparg"); } - break; case Opcode.LOAD_LOCALS: stack.push(f.f_locals); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-06 07:42:18
|
Revision: 6017 http://jython.svn.sourceforge.net/jython/?rev=6017&view=rev Author: zyasoft Date: 2009-02-06 07:42:15 +0000 (Fri, 06 Feb 2009) Log Message: ----------- Fixed slice, exec support. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-06 07:07:45 UTC (rev 6016) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-06 07:42:15 UTC (rev 6017) @@ -566,8 +566,8 @@ case Opcode.STORE_SLICE + 1: case Opcode.STORE_SLICE + 2: case Opcode.STORE_SLICE + 3: { - PyObject stop = (((opcode - Opcode.SLICE) & 2) != 0) ? stack.pop() : null; - PyObject start = (((opcode - Opcode.SLICE) & 1) != 0) ? stack.pop() : null; + PyObject stop = (((opcode - Opcode.STORE_SLICE) & 2) != 0) ? stack.pop() : null; + PyObject start = (((opcode - Opcode.STORE_SLICE) & 1) != 0) ? stack.pop() : null; PyObject obj = stack.pop(); PyObject value = stack.pop(); obj.__setslice__(start, stop, value); @@ -578,8 +578,8 @@ case Opcode.DELETE_SLICE + 1: case Opcode.DELETE_SLICE + 2: case Opcode.DELETE_SLICE + 3: { - PyObject stop = (((opcode - Opcode.SLICE) & 2) != 0) ? stack.pop() : null; - PyObject start = (((opcode - Opcode.SLICE) & 1) != 0) ? stack.pop() : null; + PyObject stop = (((opcode - Opcode.DELETE_SLICE) & 2) != 0) ? stack.pop() : null; + PyObject start = (((opcode - Opcode.DELETE_SLICE) & 1) != 0) ? stack.pop() : null; PyObject obj = stack.pop(); obj.__delslice__(start, stop); break; @@ -662,16 +662,7 @@ 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; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-07 04:04:56
|
Revision: 6018 http://jython.svn.sourceforge.net/jython/?rev=6018&view=rev Author: zyasoft Date: 2009-02-07 04:04:54 +0000 (Sat, 07 Feb 2009) Log Message: ----------- Fixed stack ops (DUP_TOPX, ROT_THREE, ROT_FOUR), INPLACE_POWER. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-06 07:42:15 UTC (rev 6017) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 04:04:54 UTC (rev 6018) @@ -9,8 +9,9 @@ // for debugging private int count = 0; // total number of opcodes run - private int maxCount = 900; // less than my buffer on iterm + private int maxCount = 10000; // less than my buffer on iterm private static PyObject opname; + public static boolean defaultDebug = false; private static synchronized PyObject getOpname() { if (opname == null) { @@ -18,8 +19,12 @@ } return opname; } - private boolean debug = false; + private boolean debug; + public static void _allDebug(boolean setting) { + defaultDebug = setting; + } + public PyObject _debug(int maxCount) { debug = maxCount > 0; this.maxCount = maxCount; @@ -49,6 +54,9 @@ String codestring, PyObject[] constants, String[] names, String varnames[], String filename, String name, int firstlineno, String lnotab, String[] cellvars, String[] freevars) { + + debug = defaultDebug; + co_argcount = nargs = argcount; co_varnames = varnames; co_nlocals = nlocals; // maybe assert = varnames.length; @@ -300,15 +308,15 @@ break; case Opcode.ROT_TWO: - stack.rot(2); + stack.rot2(); break; case Opcode.ROT_THREE: - stack.rot(3); + stack.rot3(); break; case Opcode.ROT_FOUR: - stack.rot(4); + stack.rot4(); break; case Opcode.DUP_TOP: @@ -459,7 +467,7 @@ case Opcode.INPLACE_POWER: { PyObject b = stack.pop(); PyObject a = stack.pop(); - stack.push(a.__ipow__(b)); + stack.push(a._ipow(b)); break; } @@ -693,7 +701,7 @@ case Opcode.BUILD_CLASS: { PyObject methods = stack.pop(); - PyObject bases[] = ((PySequenceList)(stack.pop())).getArray(); + PyObject bases[] = ((PySequenceList) (stack.pop())).getArray(); String name = stack.pop().toString(); stack.push(Py.makeClass(name, bases, methods)); break; @@ -758,7 +766,7 @@ if (debug) { System.err.println("LOAD_CLOSURE: " + Arrays.toString(f.f_env)); } - PyCell cell = (PyCell)(f.getclosure(oparg)); + PyCell cell = (PyCell) (f.getclosure(oparg)); if (cell.ob_ref == null) { cell.ob_ref = f.getlocal(oparg); } @@ -1018,7 +1026,7 @@ case Opcode.MAKE_CLOSURE: { PyCode code = (PyCode) stack.pop(); - PyObject[] closure_cells = ((PySequenceList)(stack.pop())).getArray(); + PyObject[] closure_cells = ((PySequenceList) (stack.pop())).getArray(); // PyObject[] closure_cells = new PyCell[src_closure_cells.length]; // for (int i = 0; i < src_closure_cells.length; i++) { // PyCell cell = new PyCell(); @@ -1061,6 +1069,9 @@ PyException pye = Py.JavaError(t); why = Why.EXCEPTION; ts.exception = pye; + if (debug) { + System.err.println("Caught exception:" + pye); + } } if (why == Why.YIELD) { @@ -1074,7 +1085,9 @@ while (why != Why.NOT && blocksLeft(f)) { PyTryBlock b = popBlock(f); -// System.err.println("Processing block: " + b); + if (debug) { + System.err.println("Processing block: " + b); + } assert (why != Why.YIELD); if (b.b_type == Opcode.SETUP_LOOP && why == Why.CONTINUE) { pushBlock(f, b); @@ -1096,8 +1109,9 @@ if (b.b_type == Opcode.SETUP_EXCEPT) { exc.normalize(); } - stack.push(new PyStackException(exc)); // x3 to conform with CPython's calling convention, which - stack.dup(2); // stores the type, val, tb separately on the stack + stack.push(new PyStackException(exc)); + stack.dup(); // x3 to conform with CPython's calling convention, which + stack.dup(); // stores the type, val, tb separately on the stack } else { if (why == Why.RETURN || why == Why.CONTINUE) { stack.push(retval); @@ -1266,9 +1280,9 @@ } void dup(int n) { - PyObject v = top(); - for (int i = 0; i < n; i++) { - stack.add(v); + int length = stack.size(); + for (int i = n; i > 0; i--) { + stack.add(stack.get(length - i)); } } @@ -1281,14 +1295,36 @@ return ret; } - void rot(int n) { - int end = stack.size(); - List<PyObject> lastN = stack.subList(end - n, end); -// System.err.print("rot(" + n + "): " + lastN.toString() + " -> "); - Collections.rotate(lastN, n - 1); -// System.err.println("rot(" + n + "): " + lastN.toString()); + void rot2() { + int length = stack.size(); + PyObject v = stack.get(length - 1); + PyObject w = stack.get(length - 2); + stack.set(length - 1, w); + stack.set(length - 2, v); } + void rot3() { + int length = stack.size(); + PyObject v = stack.get(length - 1); + PyObject w = stack.get(length - 2); + PyObject x = stack.get(length - 3); + stack.set(length - 1, w); + stack.set(length - 2, x); + stack.set(length - 3, v); + } + + void rot4() { + int length = stack.size(); + PyObject u = stack.get(length - 1); + PyObject v = stack.get(length - 2); + PyObject w = stack.get(length - 3); + PyObject x = stack.get(length - 4); + stack.set(length - 1, v); + stack.set(length - 2, w); + stack.set(length - 3, x); + stack.set(length - 4, u); + } + int size() { return stack.size(); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-07 18:14:35
|
Revision: 6021 http://jython.svn.sourceforge.net/jython/?rev=6021&view=rev Author: zyasoft Date: 2009-02-07 18:14:33 +0000 (Sat, 07 Feb 2009) Log Message: ----------- Further refinement of nested scopes. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 17:47:19 UTC (rev 6020) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 18:14:33 UTC (rev 6021) @@ -779,29 +779,14 @@ break; case Opcode.LOAD_CLOSURE: { -//// if (debug) { -//// System.err.println("LOAD_CLOSURE: " + Arrays.toString(f.f_env)); -//// } -// PyCell cell = (PyCell) (f.getclosure(oparg)); -// if (cell.ob_ref == null) { -// cell.ob_ref = f.getlocal(oparg); -// } -////// cell.ob_ref = f.getname(co_freevars[oparg]); -// stack.push(cell); -// stack.push(f.getclosure(oparg)); - - PyCell cell = (PyCell) (f.getclosure(oparg)); if (cell.ob_ref == null) { -// if (oparg < co_nlocals) { -// cell.ob_ref = f.getlocal(oparg); -// } else { -// String name = co_cellvars[oparg]; - -// cell.ob_ref = f.getname(name); -// } - - String name = co_cellvars[oparg]; + String name; + if (oparg >= co_cellvars.length) { + name = co_freevars[oparg - co_cellvars.length]; + } else { + name = co_cellvars[oparg]; + } // System.err.println("Loading closure: " + name); // XXX - consider some efficient lookup mechanism, like a hash if (f.f_fastlocals != null) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-07 21:26:34
|
Revision: 6022 http://jython.svn.sourceforge.net/jython/?rev=6022&view=rev Author: zyasoft Date: 2009-02-07 21:26:31 +0000 (Sat, 07 Feb 2009) Log Message: ----------- Fixed control flow by pushing the wrapped Why onto the stack (instead of its string representation from the earliest version of this code). Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 18:14:33 UTC (rev 6021) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-07 21:26:31 UTC (rev 6022) @@ -706,9 +706,16 @@ if (why == Why.RETURN || why == Why.CONTINUE) { retval = stack.pop(); } - } else if ((v instanceof PyStackException) || (v instanceof PyString)) { + } else if (v instanceof PyStackException) { ts.exception = ((PyStackException) v).exception; why = Why.RERAISE; + + } else if (v instanceof PyString) { + if (debug) { + System.err.println("ts.exception=" + ts.exception + ", v=" + v); +// ts.exception = new PyException(v); // XXX - what do I do about string exceptions??!!! + } + why = Why.RERAISE; } else if (v != Py.None) { throw Py.SystemError("'finally' pops bad exception"); } @@ -1059,15 +1066,6 @@ case Opcode.MAKE_CLOSURE: { PyCode code = (PyCode) stack.pop(); PyObject[] closure_cells = ((PySequenceList) (stack.pop())).getArray(); -// PyObject[] closure_cells = new PyCell[src_closure_cells.length]; -// for (int i = 0; i < src_closure_cells.length; i++) { -// PyCell cell = new PyCell(); -// cell.ob_ref = src_closure_cells[i]; -// closure_cells[i] = cell; -// } -//// for (int i = 0; i < src_closure_cells.length; i++) { -//// closure_cells[i] = f.getclosure(i); -//// } PyObject[] defaults = stack.popN(oparg); PyFunction func = new PyFunction(f.f_globals, defaults, code, closure_cells); stack.push(func); @@ -1144,13 +1142,12 @@ stack.push(exc.traceback); stack.push(exc.value); stack.push(new PyStackException(exc)); // instead of stack.push(exc.type);, like CPython -// stack.dup(); // x3 to conform with CPython's calling convention, which -// stack.dup(); // stores the type, val, tb separately on the stack } else { if (why == Why.RETURN || why == Why.CONTINUE) { stack.push(retval); } - stack.push(Py.newString(why.name())); // XXX - hack! + // FIGURE OUT THE FLOW HERE, in test_optparse2 + stack.push(new PyStackWhy(why)); } why = Why.NOT; next_instr = b.b_handler; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-14 10:44:19
|
Revision: 6027 http://jython.svn.sourceforge.net/jython/?rev=6027&view=rev Author: zyasoft Date: 2009-02-14 10:44:17 +0000 (Sat, 14 Feb 2009) Log Message: ----------- Set the traceback when intercepting an exception. Set __doc__ strings for functions from the constant pool (if available). Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 09:23:58 UTC (rev 6026) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 10:44:17 UTC (rev 6027) @@ -835,9 +835,11 @@ stack.push(new PyDictionary()); break; - case Opcode.LOAD_ATTR: - stack.push(stack.pop().__getattr__(co_names[oparg])); + case Opcode.LOAD_ATTR: { + String name = co_names[oparg]; + stack.push(stack.pop().__getattr__(name)); break; + } case Opcode.COMPARE_OP: { PyObject b = stack.pop(); @@ -1055,7 +1057,11 @@ case Opcode.MAKE_FUNCTION: { PyCode code = (PyCode) stack.pop(); PyObject[] defaults = stack.popN(oparg); - PyFunction func = new PyFunction(f.f_globals, defaults, code); + PyObject doc = null; + if (code instanceof PyBytecode && ((PyBytecode)code).co_consts.length > 0) { + doc = ((PyBytecode)code).co_consts[0]; + } + PyFunction func = new PyFunction(f.f_globals, defaults, code, doc); stack.push(func); break; } @@ -1093,7 +1099,7 @@ } // end switch } // end try catch (Throwable t) { - PyException pye = Py.JavaError(t); + PyException pye = Py.setException(t, f); why = Why.EXCEPTION; ts.exception = pye; if (debug) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-14 11:17:22
|
Revision: 6028 http://jython.svn.sourceforge.net/jython/?rev=6028&view=rev Author: zyasoft Date: 2009-02-14 11:17:17 +0000 (Sat, 14 Feb 2009) Log Message: ----------- LOAD_DEREF needs to do the same lookup as LOAD_CLOSURE. Populate doc strings for MAKE_CLOSURE. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 10:44:17 UTC (rev 6027) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 11:17:17 UTC (rev 6028) @@ -815,7 +815,36 @@ } case Opcode.LOAD_DEREF: { - stack.push(f.getderef(oparg)); + // common code from LOAD_CLOSURE + PyCell cell = (PyCell) (f.getclosure(oparg)); + if (cell.ob_ref == null) { + String name; + if (oparg >= co_cellvars.length) { + name = co_freevars[oparg - co_cellvars.length]; + } else { + name = co_cellvars[oparg]; + } + // XXX - consider some efficient lookup mechanism, like a hash :), + // at least if co_varnames is much greater than say a certain + // size (but i would think, it's not going to happen in real code. profile?) + if (f.f_fastlocals != null) { + int i = 0; + boolean matched = false; + for (String match : co_varnames) { + if (match.equals(name)) { + matched = true; + break; + } + i++; + } + if (matched) { + cell.ob_ref = f.f_fastlocals[i]; + } + } else { + cell.ob_ref = f.f_locals.__finditem__(name); + } + } + stack.push(cell.ob_ref); break; } @@ -1070,7 +1099,11 @@ PyCode code = (PyCode) stack.pop(); PyObject[] closure_cells = ((PySequenceList) (stack.pop())).getArray(); PyObject[] defaults = stack.popN(oparg); - PyFunction func = new PyFunction(f.f_globals, defaults, code, closure_cells); + PyObject doc = null; + if (code instanceof PyBytecode && ((PyBytecode)code).co_consts.length > 0) { + doc = ((PyBytecode)code).co_consts[0]; + } + PyFunction func = new PyFunction(f.f_globals, defaults, code, doc, closure_cells); stack.push(func); break; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-14 13:22:20
|
Revision: 6029 http://jython.svn.sourceforge.net/jython/?rev=6029&view=rev Author: zyasoft Date: 2009-02-14 11:58:48 +0000 (Sat, 14 Feb 2009) Log Message: ----------- Fixed WITH_CLEANUP so that it properly calls __exit__ with the exception components off the stack. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 11:17:17 UTC (rev 6028) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 11:58:48 UTC (rev 6029) @@ -686,7 +686,7 @@ PyObject locals = stack.pop(); PyObject globals = stack.pop(); PyObject code = stack.pop(); - Py.exec(code, globals==Py.None ? null : globals, locals==Py.None ? null : locals); + Py.exec(code, globals == Py.None ? null : globals, locals == Py.None ? null : locals); break; } @@ -1048,12 +1048,19 @@ v = stack.top(3); w = stack.top(4); } - PyObject x = exit.__call__(u, v, w); - if (u != Py.None && x.__nonzero__()) { - stack.popN(4); + PyObject x = null; + if (u instanceof PyStackException) { + PyException exc = ((PyStackException) u).exception; + x = exit.__call__(exc.type, exc.value, exc.traceback); + } else { + x = exit.__call__(u, v, w); + } + + if (u != Py.None && x != null && x.__nonzero__()) { + stack.popN(4); // XXX - consider stack.stackadj op stack.push(Py.None); } else { - stack.pop(); + stack.pop(); // this should be popping off a block } break; } @@ -1087,8 +1094,8 @@ PyCode code = (PyCode) stack.pop(); PyObject[] defaults = stack.popN(oparg); PyObject doc = null; - if (code instanceof PyBytecode && ((PyBytecode)code).co_consts.length > 0) { - doc = ((PyBytecode)code).co_consts[0]; + if (code instanceof PyBytecode && ((PyBytecode) code).co_consts.length > 0) { + doc = ((PyBytecode) code).co_consts[0]; } PyFunction func = new PyFunction(f.f_globals, defaults, code, doc); stack.push(func); @@ -1100,8 +1107,8 @@ PyObject[] closure_cells = ((PySequenceList) (stack.pop())).getArray(); PyObject[] defaults = stack.popN(oparg); PyObject doc = null; - if (code instanceof PyBytecode && ((PyBytecode)code).co_consts.length > 0) { - doc = ((PyBytecode)code).co_consts[0]; + if (code instanceof PyBytecode && ((PyBytecode) code).co_consts.length > 0) { + doc = ((PyBytecode) code).co_consts[0]; } PyFunction func = new PyFunction(f.f_globals, defaults, code, doc, closure_cells); stack.push(func); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2009-02-14 19:17:07
|
Revision: 6030 http://jython.svn.sourceforge.net/jython/?rev=6030&view=rev Author: zyasoft Date: 2009-02-14 19:17:04 +0000 (Sat, 14 Feb 2009) Log Message: ----------- Fixed UNPACK_SEQUENCE so that ValueError is raised if too few/too many values to unpack. Modified Paths: -------------- branches/pbcvm/src/org/python/core/PyBytecode.java Modified: branches/pbcvm/src/org/python/core/PyBytecode.java =================================================================== --- branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 11:58:48 UTC (rev 6029) +++ branches/pbcvm/src/org/python/core/PyBytecode.java 2009-02-14 19:17:04 UTC (rev 6030) @@ -734,22 +734,10 @@ f.dellocal(co_names[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]); - } + case Opcode.UNPACK_SEQUENCE: + unpack_iterable(oparg, stack); break; - } - + case Opcode.STORE_ATTR: { PyObject obj = stack.pop(); PyObject v = stack.pop(); @@ -1319,6 +1307,26 @@ stack.push(callable._callextra(args, keywords, starargs, kwargs)); } + private static void unpack_iterable(int oparg, PyStack stack) { + PyObject v = stack.pop(); + int i = oparg; + PyObject items[] = new PyObject[oparg]; + for (PyObject item : v.asIterable()) { + if (i <= 0) { + throw Py.ValueError("too many values to unpack"); + } + i--; + items[i] = item; + } + if (i > 0) { + throw Py.ValueError(String.format("need more than %d value%s to unpack", + i, i == 1 ? "" : "s")); + } + for (i = 0; i < oparg; i++) { + stack.push(items[i]); + } + } + // XXX - perhaps add support for max stack size (presumably from co_stacksize) // and capacity hints private class PyStack { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |