From: <zy...@us...> - 2009-03-07 04:05:17
|
Revision: 6078 http://jython.svn.sourceforge.net/jython/?rev=6078&view=rev Author: zyasoft Date: 2009-03-07 04:05:04 +0000 (Sat, 07 Mar 2009) Log Message: ----------- Now uses CompilerFlags instead of the co_flags bit vector uniformly in the code. This change enables more programmatic direction of the compiler, including at the very least the desired compiler (once we include more than one!). Removed unnecessary fields in PyFrame that supported the former newcompiler. Made public some additional PyUnicode constructors to support the Java version of unicodedata, whenever that happens. Fixed a memory leak in PyBytecode. Modified Paths: -------------- trunk/jython/src/org/python/core/CompilerFlags.java trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/PyBaseCode.java trunk/jython/src/org/python/core/PyBytecode.java trunk/jython/src/org/python/core/PyFrame.java trunk/jython/src/org/python/core/PyTableCode.java trunk/jython/src/org/python/core/PyUnicode.java trunk/jython/src/org/python/core/__builtin__.java trunk/jython/src/org/python/modules/_marshal.java Modified: trunk/jython/src/org/python/core/CompilerFlags.java =================================================================== --- trunk/jython/src/org/python/core/CompilerFlags.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/CompilerFlags.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -1,3 +1,6 @@ +// At some future point this will also be extended - in conjunction with Py#compileFlags - to add +// support for a compiler factory that user code can choose in place of the normal compiler. +// (Perhaps a better name might have been "CompilerOptions".) package org.python.core; @@ -5,6 +8,12 @@ private int co_flags; + public boolean optimized; + public boolean newlocals; + public boolean varargs; + public boolean varkeywords; + public boolean generator; + public boolean nested_scopes = true; public boolean division; public boolean generator_allowed = true; @@ -21,20 +30,26 @@ public CompilerFlags(int co_flags) { this.co_flags = co_flags; - nested_scopes = isEnabled(PyTableCode.CO_NESTED); - division = isEnabled(PyTableCode.CO_FUTUREDIVISION); - generator_allowed = isEnabled(PyTableCode.CO_GENERATOR_ALLOWED); - absolute_import = isEnabled(PyTableCode.CO_FUTURE_ABSOLUTE_IMPORT); - with_statement = isEnabled(PyTableCode.CO_WITH_STATEMENT); - only_ast = isEnabled(PyTableCode.PyCF_ONLY_AST); - dont_imply_dedent = isEnabled(PyTableCode.PyCF_DONT_IMPLY_DEDENT); - source_is_utf8 = isEnabled(PyTableCode.PyCF_SOURCE_IS_UTF8); + optimized = isEnabled(PyBaseCode.CO_OPTIMIZED); + newlocals = isEnabled(PyBaseCode.CO_NEWLOCALS); + varargs = isEnabled(PyBaseCode.CO_VARARGS); + varkeywords = isEnabled(PyBaseCode.CO_VARKEYWORDS); + generator = isEnabled(PyBaseCode.CO_GENERATOR); + nested_scopes = isEnabled(PyBaseCode.CO_NESTED); + division = isEnabled(PyBaseCode.CO_FUTUREDIVISION); + generator_allowed = isEnabled(PyBaseCode.CO_GENERATOR_ALLOWED); + absolute_import = isEnabled(PyBaseCode.CO_FUTURE_ABSOLUTE_IMPORT); + with_statement = isEnabled(PyBaseCode.CO_WITH_STATEMENT); + only_ast = isEnabled(PyBaseCode.PyCF_ONLY_AST); + dont_imply_dedent = isEnabled(PyBaseCode.PyCF_DONT_IMPLY_DEDENT); + source_is_utf8 = isEnabled(PyBaseCode.PyCF_SOURCE_IS_UTF8); } private boolean isEnabled(int codeConstant) { return (co_flags & codeConstant) != 0; } + @Override public String toString() { return String.format("CompilerFlags[division=%s nested_scopes=%s generators=%s " + "with_statement=%s absolute_import=%s only_ast=%s " @@ -43,4 +58,29 @@ dont_imply_dedent, source_is_utf8); } + public int toBits() { + return (optimized ? PyBaseCode.CO_OPTIMIZED : 0) | + (newlocals ? PyBaseCode.CO_NEWLOCALS : 0) | + (varargs ? PyBaseCode.CO_VARARGS : 0) | + (varkeywords ? PyBaseCode.CO_VARKEYWORDS : 0) | + (generator ? PyBaseCode.CO_GENERATOR : 0) | + (nested_scopes ? PyBaseCode.CO_NESTED : 0) | + (division ? PyBaseCode.CO_FUTUREDIVISION : 0) | + (generator_allowed ? PyBaseCode.CO_GENERATOR_ALLOWED : 0) | + (absolute_import ? PyBaseCode.CO_FUTURE_ABSOLUTE_IMPORT : 0) | + (with_statement ? PyBaseCode.CO_WITH_STATEMENT : 0) | + (only_ast ? PyBaseCode.PyCF_ONLY_AST : 0) | + (dont_imply_dedent ? PyBaseCode.PyCF_DONT_IMPLY_DEDENT : 0) | + (source_is_utf8 ? PyBaseCode.PyCF_SOURCE_IS_UTF8 : 0); + } + + // this will not strictly be an OR once we have other options, like a compiler factory + // in that case, we would assume + public CompilerFlags combine(CompilerFlags flags) { + return new CompilerFlags(this.toBits() | flags.toBits()); + } + + public CompilerFlags combine(int flags) { + return new CompilerFlags(this.toBits() | flags); + } } Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/Py.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -1613,7 +1613,7 @@ } else { PyFrame frame = Py.getFrame(); if (frame != null && frame.f_code != null) { - cflags = new CompilerFlags(frame.f_code.co_flags | flags); + cflags = frame.f_code.co_flags.combine(flags); } else { cflags = new CompilerFlags(flags); } @@ -1621,6 +1621,21 @@ return cflags; } + public static CompilerFlags getCompilerFlags(CompilerFlags flags, boolean dont_inherit) { + CompilerFlags cflags = null; + if (dont_inherit) { + cflags = flags; + } else { + PyFrame frame = Py.getFrame(); + if (frame != null && frame.f_code != null) { + cflags = frame.f_code.co_flags.combine(flags); + } else { + cflags = flags; + } + } + return cflags; + } + // w/o compiler-flags public static PyObject compile(InputStream istream, String filename, String kind) { return compile_flags(istream, filename, kind, new CompilerFlags()); Modified: trunk/jython/src/org/python/core/PyBaseCode.java =================================================================== --- trunk/jython/src/org/python/core/PyBaseCode.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/PyBaseCode.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -13,7 +13,7 @@ public int jy_npurecell; // internal: jython specific public String co_freevars[]; public String co_filename; - public int co_flags; + public CompilerFlags co_flags = new CompilerFlags(); public int co_nlocals; public boolean varargs, varkwargs; @@ -135,7 +135,7 @@ return call(Py.EmptyObjects, Py.NoKeywords, globals, defaults, closure); PyFrame frame = new PyFrame(this, globals); - if ((co_flags & CO_GENERATOR) != 0) { + if (co_flags.generator) { return new PyGenerator(frame, closure); } return call(frame, closure); @@ -149,7 +149,7 @@ Py.NoKeywords, globals, defaults, closure); PyFrame frame = new PyFrame(this, globals); frame.f_fastlocals[0] = arg1; - if ((co_flags & CO_GENERATOR) != 0) { + if (co_flags.generator) { return new PyGenerator(frame, closure); } return call(frame, closure); @@ -164,7 +164,7 @@ PyFrame frame = new PyFrame(this, globals); frame.f_fastlocals[0] = arg1; frame.f_fastlocals[1] = arg2; - if ((co_flags & CO_GENERATOR) != 0) { + if (co_flags.generator) { return new PyGenerator(frame, closure); } return call(frame, closure); @@ -181,7 +181,7 @@ frame.f_fastlocals[0] = arg1; frame.f_fastlocals[1] = arg2; frame.f_fastlocals[2] = arg3; - if ((co_flags & CO_GENERATOR) != 0) { + if (co_flags.generator) { return new PyGenerator(frame, closure); } return call(frame, closure); @@ -297,7 +297,7 @@ co_name, argcount)); } - if ((co_flags & CO_GENERATOR) != 0) { + if (co_flags.generator) { return new PyGenerator(frame, closure); } return call(frame, closure); @@ -313,4 +313,9 @@ protected int getline(PyFrame f) { return f.f_lineno; } + + // returns the augmented version of CompilerFlags (instead of just as a bit vector int) + public CompilerFlags getCompilerFlags() { + return co_flags; + } } Modified: trunk/jython/src/org/python/core/PyBytecode.java =================================================================== --- trunk/jython/src/org/python/core/PyBytecode.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/PyBytecode.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -74,9 +74,9 @@ co_cellvars = cellvars; co_freevars = freevars; co_name = name; - varargs = (flags & CO_VARARGS) != 0; - varkwargs = (flags & CO_VARKEYWORDS) != 0; - co_flags |= flags; + co_flags = new CompilerFlags(flags); + varargs = co_flags.varargs; + varkwargs = co_flags.varkeywords; co_stacksize = stacksize; co_consts = constants; @@ -156,6 +156,9 @@ if (name == "co_consts") { return new PyTuple(co_consts); } + if (name == "co_flags") { + return Py.newInteger(co_flags.toBits()); + } return super.__findattr_ex__(name); } @@ -201,11 +204,11 @@ } private static String stringify_blocks(PyFrame f) { - if (f.f_exits == null || f.f_blockstate[0] == 0) { + if (f.f_exits == null || f.f_lineno == 0) { return "[]"; } StringBuilder buf = new StringBuilder("["); - int len = f.f_blockstate[0]; + int len = f.f_lineno; for (int i = 0; i < len; i++) { buf.append(f.f_exits[i].toString()); if (i < len - 1) { @@ -227,21 +230,26 @@ } } + // the following code exploits the fact that f_exits and f_lineno are only used by code compiled to Java bytecode; + // in their place we implement the block stack for PBC-VM, as mapped below in the comments of pushBlock + private static PyTryBlock popBlock(PyFrame f) { - return (PyTryBlock) (f.f_exits[--f.f_blockstate[0]]); + PyTryBlock block = (PyTryBlock) (f.f_exits[--f.f_lineno]); + f.f_exits[f.f_lineno] = null; // ensure eventual GC of this reference + return block; } 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 + if (f.f_exits == null) { // allocate in the frame where they can fit! TODO 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_lineno = 0; // f_iblock in CPython } - f.f_exits[f.f_blockstate[0]++] = block; + f.f_exits[f.f_lineno++] = block; } private boolean blocksLeft(PyFrame f) { if (f.f_exits != null) { - return f.f_blockstate[0] > 0; + return f.f_lineno > 0; } else { return false; } @@ -414,7 +422,7 @@ PyObject b = stack.pop(); PyObject a = stack.pop(); - if ((co_flags & CO_FUTUREDIVISION) == 0) { + if (!co_flags.division) { stack.push(a._div(b)); } else { stack.push(a._truediv(b)); @@ -524,7 +532,7 @@ case Opcode.INPLACE_DIVIDE: { PyObject b = stack.pop(); PyObject a = stack.pop(); - if ((co_flags & CO_FUTUREDIVISION) == 0) { + if (!co_flags.division) { stack.push(a._idiv(b)); } else { stack.push(a._itruediv(b)); @@ -1242,7 +1250,7 @@ throw ts.exception; } - if ((co_flags & CO_GENERATOR) != 0 && why == Why.RETURN && retval == Py.None) { + if (co_flags.generator && why == Why.RETURN && retval == Py.None) { f.f_lasti = -1; } Modified: trunk/jython/src/org/python/core/PyFrame.java =================================================================== --- trunk/jython/src/org/python/core/PyFrame.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/PyFrame.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -31,12 +31,6 @@ public Object[] f_savedlocals; - /** newcompiler uses this to allow yield in loops. */ - public PyObject[] f_stackstate; - - /** newcompiler uses this to allow yield in finally. */ - public int[] f_blockstate; - private int env_j = 0; private Object generatorInput = Py.None; @@ -68,7 +62,7 @@ // This needs work to be efficient with multiple interpreter states if (locals == null && code != null) { // ! f_fastlocals needed for arg passing too - if ((code.co_flags & PyBaseCode.CO_OPTIMIZED) != 0 || code.nargs > 0) { + if (code.co_flags.optimized || code.nargs > 0) { if (code.co_nlocals > 0) { // internal: may change f_fastlocals = new PyObject[code.co_nlocals - code.jy_npurecell]; @@ -197,7 +191,7 @@ PyObject o = f_fastlocals[i]; if (o != null) f_locals.__setitem__(f_code.co_varnames[i], o); } - if ((f_code.co_flags & PyBaseCode.CO_OPTIMIZED) == 0) { + if (!f_code.co_flags.optimized) { f_fastlocals = null; } } Modified: trunk/jython/src/org/python/core/PyTableCode.java =================================================================== --- trunk/jython/src/org/python/core/PyTableCode.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/PyTableCode.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -45,14 +45,14 @@ co_name = name; if (varargs) { co_argcount -= 1; - co_flags |= CO_VARARGS; + co_flags.varargs = true; } this.varkwargs = varkwargs; if (varkwargs) { co_argcount -= 1; - co_flags |= CO_VARKEYWORDS; + co_flags.varkeywords = true; } - co_flags |= moreflags; + co_flags = new CompilerFlags(co_flags.toBits() | moreflags); this.funcs = funcs; this.func_id = func_id; } @@ -115,6 +115,9 @@ if (name == "co_name") { return new PyString(co_name); } + if (name == "co_flags") { + return Py.newInteger(co_flags.toBits()); + } return super.__findattr_ex__(name); } Modified: trunk/jython/src/org/python/core/PyUnicode.java =================================================================== --- trunk/jython/src/org/python/core/PyUnicode.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/PyUnicode.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -78,11 +78,11 @@ return buffer; } - PyUnicode(Iterator<Integer> iter) { + public PyUnicode(Iterator<Integer> iter) { this(fromCodePoints(iter)); } - PyUnicode(Collection<Integer> ucs4) { + public PyUnicode(Collection<Integer> ucs4) { this(ucs4.iterator()); } Modified: trunk/jython/src/org/python/core/__builtin__.java =================================================================== --- trunk/jython/src/org/python/core/__builtin__.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/core/__builtin__.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -1526,7 +1526,7 @@ public static PyObject compile(PyObject source, String filename, String mode, int flags, boolean dont_inherit) { - if ((flags & ~PyTableCode.CO_ALL_FEATURES) != 0) { + if ((flags & ~PyBaseCode.CO_ALL_FEATURES) != 0) { throw Py.ValueError("compile(): unrecognised flags"); } if (!mode.equals("exec") && !mode.equals("eval") && !mode.equals("single")) { @@ -1542,12 +1542,31 @@ throw Py.TypeError("expected a readable buffer object"); } if (source instanceof PyUnicode) { - flags |= PyTableCode.PyCF_SOURCE_IS_UTF8; + flags |= PyBaseCode.PyCF_SOURCE_IS_UTF8; } return Py.compile_flags(((PyString)source).toString(), filename, mode, Py.getCompilerFlags(flags, dont_inherit)); } + public static PyObject compile(PyObject source, String filename, String mode, CompilerFlags flags, + boolean dont_inherit) { + if (!mode.equals("exec") && !mode.equals("eval") && !mode.equals("single")) { + throw Py.ValueError("compile() arg 3 must be 'exec' or 'eval' or 'single'"); + } + + mod ast = py2node(source); + if (ast != null) { + return Py.compile_flags(ast, filename, mode, Py.getCompilerFlags(flags, dont_inherit)); + } + + if (!(source instanceof PyString)) { + throw Py.TypeError("expected a readable buffer object"); + } + flags.source_is_utf8 = source instanceof PyUnicode; + return Py.compile_flags(((PyString)source).toString(), filename, mode, + Py.getCompilerFlags(flags, dont_inherit)); + } + /** * @returns mod if obj is a wrapper around an AST mod else returns * null Modified: trunk/jython/src/org/python/modules/_marshal.java =================================================================== --- trunk/jython/src/org/python/modules/_marshal.java 2009-03-06 22:18:24 UTC (rev 6077) +++ trunk/jython/src/org/python/modules/_marshal.java 2009-03-07 04:05:04 UTC (rev 6078) @@ -226,7 +226,7 @@ write_int(code.co_argcount); write_int(code.co_nlocals); write_int(code.co_stacksize); - write_int(code.co_flags); + write_int(code.co_flags.toBits()); write_object(Py.newString(new String(code.co_code)), depth + 1); write_object(new PyTuple(code.co_consts), depth + 1); write_strings(code.co_names, depth + 1); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |