From: <th...@us...> - 2009-03-02 15:59:24
|
Revision: 6055 http://jython.svn.sourceforge.net/jython/?rev=6055&view=rev Author: thobes Date: 2009-03-02 15:59:20 +0000 (Mon, 02 Mar 2009) Log Message: ----------- Moving the advanced branch. All useful things imported. At this point there are two patches to jython for integrating the advanced compiler: * One patch to make the flags that are passed around in compilation type safe. * One patch to decouple the compiler implementation and provide an extension point where a new compiler can be inserted. Modified Paths: -------------- trunk/sandbox/tobias/.hg/patches/series trunk/sandbox/tobias/.hgignore trunk/sandbox/tobias/README.txt trunk/sandbox/tobias/compiler/src/org/python/compiler/AdvancedCompiler.java trunk/sandbox/tobias/compiler/src/org/python/compiler/AdvancedPreferences.java trunk/sandbox/tobias/compiler/src/org/python/compiler/CodeGenerator.java trunk/sandbox/tobias/compiler/src/org/python/compiler/CompilerDirector.java trunk/sandbox/tobias/compiler/src/org/python/compiler/ConstantChecker.java trunk/sandbox/tobias/compiler/src/org/python/compiler/DirectCodeBundle.java trunk/sandbox/tobias/compiler/src/org/python/compiler/DirectGenerator.java trunk/sandbox/tobias/compiler/src/org/python/compiler/FlowGraphBundle.java trunk/sandbox/tobias/compiler/src/org/python/compiler/FlowGraphGenerator.java trunk/sandbox/tobias/compiler/src/org/python/compiler/GeneratedCodeState.java trunk/sandbox/tobias/compiler/src/org/python/compiler/IntermediateCodeGenerator.java trunk/sandbox/tobias/compiler/src/org/python/compiler/IntermediateCodeGeneratorFactory.java trunk/sandbox/tobias/compiler/src/org/python/compiler/PragmaParser.java trunk/sandbox/tobias/compiler/src/org/python/compiler/ScopeInformation.java trunk/sandbox/tobias/compiler/src/org/python/compiler/ScopesBuilder.java trunk/sandbox/tobias/compiler/src/org/python/compiler/advanced/EnvironmentHolder.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/Block.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/CodeGraph.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/Constant.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/ValueOperation.java Added Paths: ----------- trunk/sandbox/tobias/.classpath trunk/sandbox/tobias/.externalToolBuilders/ trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch trunk/sandbox/tobias/.hg/hgrc trunk/sandbox/tobias/.hg/patches/decouple.patch trunk/sandbox/tobias/.hg/patches/types.patch trunk/sandbox/tobias/.project trunk/sandbox/tobias/.settings/ trunk/sandbox/tobias/.settings/org.eclipse.jdt.core.prefs trunk/sandbox/tobias/agent/ trunk/sandbox/tobias/agent/build.xml trunk/sandbox/tobias/agent/src/ trunk/sandbox/tobias/agent/src/org/python/javaagent/InstrumentationProxy.java trunk/sandbox/tobias/build.xml trunk/sandbox/tobias/bytecode/ trunk/sandbox/tobias/bytecode/build.xml trunk/sandbox/tobias/bytecode/src/ trunk/sandbox/tobias/bytecode/src/org/ trunk/sandbox/tobias/bytecode/src/org/python/ trunk/sandbox/tobias/bytecode/src/org/python/bytecode/ trunk/sandbox/tobias/compiler/build.xml trunk/sandbox/tobias/compiler/src/ trunk/sandbox/tobias/compiler/src/org/ trunk/sandbox/tobias/compiler/src/org/python/ trunk/sandbox/tobias/compiler/src/org/python/compiler/ trunk/sandbox/tobias/compiler/src/org/python/compiler/BytecodeBundle.java trunk/sandbox/tobias/compiler/src/org/python/compiler/BytecodeCodeBundle.java trunk/sandbox/tobias/compiler/src/org/python/compiler/CodeGeneratorGraphVisitor.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/BlockBuilder.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/BlockBuilderImpl.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/BlockState.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/BlockTermination.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/CodeGraphFactory.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/CodeGraphVisitor.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/CodeReference.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/ConsumerCallback.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/GraphInfo.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/Instruction.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/ProducerCallback.java trunk/sandbox/tobias/compiler/src/org/python/compiler/flowgraph/SimpleCallback.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/ trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/Construct.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/Define.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/Exception.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/Import.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/Invocation.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/MemoryOperation.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/Operator.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/SystemCalls.java trunk/sandbox/tobias/compiler/src/org/python/compiler/instructions/TypeOperation.java trunk/sandbox/tobias/compiler/src/org/thobe/ trunk/sandbox/tobias/compiler/src/org/thobe/compiler/ trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/ trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/Graph.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/GraphVisitor.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/HandlerBlock.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/IfNode.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/Node.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/OpNode.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/PhiNode.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/SwitchNode.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/Value.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/ValueNode.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/ValueOperation.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/ValueType.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/VariableLocation.java trunk/sandbox/tobias/compiler/src/org/thobe/compiler/sea/VoidOperation.java trunk/sandbox/tobias/util/ trunk/sandbox/tobias/util/build.xml trunk/sandbox/tobias/util/src/ trunk/sandbox/tobias/util/src/org/ trunk/sandbox/tobias/util/src/org/python/ trunk/sandbox/tobias/util/src/org/python/code/ trunk/sandbox/tobias/util/src/org/python/hash/ Property Changed: ---------------- trunk/sandbox/tobias/ trunk/sandbox/tobias/.hg/patches/ trunk/sandbox/tobias/compiler/ Property changes on: trunk/sandbox/tobias ___________________________________________________________________ Modified: svn:externals - jython https://jython.svn.sourceforge.net/svnroot/jython/trunk/jython + jython https://jython.svn.sourceforge.net/svnroot/jython/trunk/jython frame https://projects.thobe.org/svn/public/javaframe Added: svn:ignore + target Added: trunk/sandbox/tobias/.classpath =================================================================== --- trunk/sandbox/tobias/.classpath (rev 0) +++ trunk/sandbox/tobias/.classpath 2009-03-02 15:59:20 UTC (rev 6055) @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry excluding="com/ziclix/python/sql/|com/ziclix/python/sql/connect/|com/ziclix/python/sql/handler/|com/ziclix/python/sql/pipe/|com/ziclix/python/sql/pipe/csv/|com/ziclix/python/sql/pipe/db/|com/ziclix/python/sql/procedure/|com/ziclix/python/sql/resource/|com/ziclix/python/sql/util/" kind="src" path="jython/src"/> + <classpathentry excluding="org/python/compiler/advanced/ast/" kind="src" path="compiler/src"/> + <classpathentry kind="src" path="util/src"/> + <classpathentry kind="src" path="bytecode/src"/> + <classpathentry kind="src" path="agent/src"/> + <classpathentry kind="src" path="frame/src"/> + <classpathentry kind="src" path="frame/test"/> + <classpathentry kind="src" path="jython/build/gensrc"/> + <classpathentry kind="src" path="jython/tests/java"/> + <classpathentry kind="lib" path="jython/Demo/jreload/example.jar"/> + <classpathentry kind="lib" path="jython/extlibs/antlr-2.7.7.jar"/> + <classpathentry kind="lib" path="jython/extlibs/asm-3.1.jar"/> + <classpathentry kind="lib" path="jython/extlibs/asm-commons-3.1.jar"/> + <classpathentry kind="lib" path="jython/extlibs/asm-util-3.1.jar"/> + <classpathentry kind="lib" path="jython/extlibs/constantine-0.4.jar"/> + <classpathentry kind="lib" path="jython/extlibs/cpptasks/cpptasks.jar"/> + <classpathentry kind="lib" path="jython/extlibs/jarjar-0.7.jar"/> + <classpathentry kind="lib" path="jython/extlibs/jline-0.9.94.jar"/> + <classpathentry kind="lib" path="jython/extlibs/jna-posix.jar"/> + <classpathentry kind="lib" path="jython/extlibs/jna.jar"/> + <classpathentry kind="lib" path="jython/extlibs/junit-3.8.2.jar"/> + <classpathentry kind="lib" path="jython/extlibs/libreadline-java-0.8.jar"/> + <classpathentry kind="lib" path="jython/extlibs/mysql-connector-java-5.1.6.jar"/> + <classpathentry kind="lib" path="jython/extlibs/postgresql-8.3-603.jdbc4.jar"/> + <classpathentry kind="lib" path="jython/extlibs/profile.jar"/> + <classpathentry kind="lib" path="jython/extlibs/servlet-api-2.5.jar"/> + <classpathentry kind="lib" path="jython/extlibs/stringtemplate-3.2.jar"/> + <classpathentry kind="lib" path="jython/extlibs/svnant-jars/svnant.jar"/> + <classpathentry kind="lib" path="jython/extlibs/svnant-jars/svnClientAdapter.jar"/> + <classpathentry kind="lib" path="jython/extlibs/svnant-jars/svnjavahl.jar"/> + <classpathentry kind="lib" path="jython/extlibs/xercesImpl-2.9.1.jar"/> + <classpathentry kind="lib" path="jython/Lib/test/blob.jar"/> + <classpathentry kind="lib" path="jython/Lib/test/bug1239.jar"/> + <classpathentry kind="lib" path="jython/Lib/test/classimport_Lib.jar"/> + <classpathentry kind="lib" path="jython/Lib/test/classimport.jar"/> + <classpathentry kind="lib" path="jython/Lib/test/syspath_import.jar"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.5.0 (Mac OS X default)"/> + <classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/> + <classpathentry kind="lib" path="jython/extlibs/antlr-3.1.2.jar"/> + <classpathentry kind="lib" path="jython/extlibs/antlr-runtime-3.1.2.jar"/> + <classpathentry kind="output" path="target/build"/> +</classpath> Added: trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch =================================================================== --- trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch (rev 0) +++ trunk/sandbox/tobias/.externalToolBuilders/Build preparation.launch 2009-03-02 15:59:20 UTC (rev 6055) @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?><launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType"> +<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AFTER_CLEAN_TARGETS" value="antlr_gen,"/> +<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="antlr_gen,"/> +<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/> +<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/advanced-compiler/jython/build.xml"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="1"/> +</listAttribute> +<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/> +<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="advanced-compiler"/> +<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/advanced-compiler/jython/build.xml}"/> +<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,"/> +<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/> +</launchConfiguration> Added: trunk/sandbox/tobias/.hg/hgrc =================================================================== --- trunk/sandbox/tobias/.hg/hgrc (rev 0) +++ trunk/sandbox/tobias/.hg/hgrc 2009-03-02 15:59:20 UTC (rev 6055) @@ -0,0 +1,3 @@ +[diff] +nodates=1 +git=1 Property changes on: trunk/sandbox/tobias/.hg/patches ___________________________________________________________________ Modified: svn:ignore - status + status guards Added: trunk/sandbox/tobias/.hg/patches/decouple.patch =================================================================== --- trunk/sandbox/tobias/.hg/patches/decouple.patch (rev 0) +++ trunk/sandbox/tobias/.hg/patches/decouple.patch 2009-03-02 15:59:20 UTC (rev 6055) @@ -0,0 +1,375 @@ +diff --git a/jython/src/org/python/compiler/LegacyCompiler.java b/jython/src/org/python/compiler/LegacyCompiler.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/compiler/LegacyCompiler.java +@@ -0,0 +1,72 @@ ++package org.python.compiler; ++ ++import java.io.ByteArrayOutputStream; ++import java.io.OutputStream; ++ ++import org.python.antlr.base.mod; ++import org.python.core.BytecodeLoader; ++import org.python.core.CompilerFlags; ++import org.python.core.Py; ++import org.python.core.PyCode; ++import org.python.core.PythonCodeBundle; ++import org.python.core.PythonCompiler; ++ ++public class LegacyCompiler implements PythonCompiler { ++ ++ public PythonCodeBundle compile(mod node, String name, String filename, ++ boolean linenumbers, boolean printResults, CompilerFlags cflags) { ++ return new LazyLegacyBundle(node, name, filename, linenumbers, ++ printResults, cflags); ++ } ++ ++ private static class LazyLegacyBundle implements PythonCodeBundle { ++ ++ private final mod node; ++ private final String name; ++ private final String filename; ++ private final boolean linenumbers; ++ private final boolean printResults; ++ private final CompilerFlags cflags; ++ private ByteArrayOutputStream ostream = null; ++ ++ public LazyLegacyBundle(mod node, String name, String filename, ++ boolean linenumbers, boolean printResults, CompilerFlags cflags) { ++ this.node = node; ++ this.name = name; ++ this.filename = filename; ++ this.linenumbers = linenumbers; ++ this.printResults = printResults; ++ this.cflags = cflags; ++ } ++ ++ public PyCode loadCode() throws Exception { ++ return BytecodeLoader.makeCode(name, ostream().toByteArray(), ++ filename); ++ } ++ ++ public void writeTo(OutputStream stream) throws Exception { ++ if (this.ostream != null) { ++ stream.write(ostream.toByteArray()); ++ } else { ++ Module.compile(node, stream, name, filename, linenumbers, ++ printResults, cflags); ++ } ++ } ++ ++ public void saveCode(String directory) throws Exception { ++ // FIXME: this is slightly broken, it should use the directory ++ Py.saveClassFile(name, ostream()); ++ } ++ ++ private ByteArrayOutputStream ostream() throws Exception { ++ if (ostream == null) { ++ ostream = new ByteArrayOutputStream(); ++ Module.compile(node, ostream, name, filename, linenumbers, ++ printResults, cflags); ++ } ++ return ostream; ++ } ++ ++ } ++ ++} +diff --git a/jython/src/org/python/compiler/Module.java b/jython/src/org/python/compiler/Module.java +--- a/jython/src/org/python/compiler/Module.java ++++ b/jython/src/org/python/compiler/Module.java +@@ -12,10 +12,14 @@ + + import org.objectweb.asm.Label; + import org.objectweb.asm.Opcodes; ++import org.python.core.CodeBootstrap; + import org.python.core.CodeFlag; ++import org.python.core.CodeLoader; + import org.python.core.CompilerFlags; + import org.python.core.Py; + import org.python.core.PyException; ++import org.python.core.PyRunnableBootstrap; ++import org.objectweb.asm.Type; + import org.python.antlr.ParseException; + import org.python.antlr.PythonTree; + import org.python.antlr.ast.Suite; +@@ -541,10 +545,26 @@ + c.dup(); + c.ldc(classfile.name); + c.invokespecial(classfile.name, "<init>", "(" + $str + ")V"); ++ c.invokevirtual(classfile.name, "getMain", "()" + $pyCode); ++ String bootstrap = Type.getDescriptor(CodeBootstrap.class); ++ c.invokestatic(Type.getInternalName(CodeLoader.class), ++ CodeLoader.SIMPLE_FACTORY_METHOD_NAME, ++ "(" + $pyCode + ")" + bootstrap); + c.aload(0); +- c.invokestatic("org/python/core/Py", "runMain", "(" + $pyRunnable + $strArr + ")V"); ++ c.invokestatic("org/python/core/Py", "runMain", "(" + bootstrap + $strArr + ")V"); + c.return_(); + } ++ ++ public void addBootstrap() throws IOException { ++ Code c = classfile.addMethod(CodeLoader.GET_BOOTSTRAP_METHOD_NAME, ++ "()" + Type.getDescriptor(CodeBootstrap.class), ++ ACC_PUBLIC | ACC_STATIC); ++ c.ldc(Type.getType("L" + classfile.name + ";")); ++ c.invokestatic(Type.getInternalName(PyRunnableBootstrap.class), ++ PyRunnableBootstrap.REFLECTION_METHOD_NAME, ++ "(" + $clss + ")" + Type.getDescriptor(CodeBootstrap.class)); ++ c.areturn(); ++ } + + public void addConstants(Code c) throws IOException { + classfile.addField("self", "L"+classfile.name+";", +@@ -599,6 +619,7 @@ + addInit(); + addRunnable(); + addMain(); ++ addBootstrap(); + + addFunctions(); + +diff --git a/jython/src/org/python/core/CodeBootstrap.java b/jython/src/org/python/core/CodeBootstrap.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/CodeBootstrap.java +@@ -0,0 +1,7 @@ ++package org.python.core; ++ ++public interface CodeBootstrap { ++ ++ PyCode loadCode(CodeLoader loader); ++ ++} +diff --git a/jython/src/org/python/core/CodeLoader.java b/jython/src/org/python/core/CodeLoader.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/CodeLoader.java +@@ -0,0 +1,60 @@ ++package org.python.core; ++ ++import java.lang.reflect.InvocationTargetException; ++import java.lang.reflect.Method; ++import java.lang.reflect.Modifier; ++ ++public final class CodeLoader { ++ ++ public static final String GET_BOOTSTRAP_METHOD_NAME = "getCodeBootstrap"; ++ public final String name; ++ public final String filename; ++ ++ private CodeLoader(String name, String filename) { ++ this.name = name; ++ this.filename = filename; ++ } ++ ++ public static boolean canLoad(Class<?> cls) { ++ try { ++ Method getBootstrap = cls.getMethod(GET_BOOTSTRAP_METHOD_NAME); ++ return Modifier.isStatic(getBootstrap.getModifiers()); ++ } catch (Exception e) { ++ return false; ++ } ++ } ++ ++ public static PyCode loadCode(Class<?> cls, String name, String filename) ++ throws SecurityException, NoSuchMethodException, ++ IllegalArgumentException, IllegalAccessException, ++ InvocationTargetException { ++ Method getBootstrap = cls.getMethod(GET_BOOTSTRAP_METHOD_NAME); ++ CodeBootstrap bootstrap = (CodeBootstrap) getBootstrap.invoke(null); ++ return loadCode(bootstrap, name, filename); ++ } ++ ++ public static PyCode loadCode(Class<?> cls) throws SecurityException, ++ IllegalArgumentException, NoSuchMethodException, ++ IllegalAccessException, InvocationTargetException { ++ return loadCode(cls, null, null); ++ } ++ ++ public static PyCode loadCode(CodeBootstrap bootstrap, String name, ++ String filename) { ++ return bootstrap.loadCode(new CodeLoader(name, filename)); ++ } ++ ++ public static PyCode loadCode(CodeBootstrap bootstrap) { ++ return loadCode(bootstrap, null, null); ++ } ++ ++ public static final String SIMPLE_FACTORY_METHOD_NAME = "createSimpleBootstrap"; ++ ++ public static CodeBootstrap createSimpleBootstrap(final PyCode code) { ++ return new CodeBootstrap() { ++ public PyCode loadCode(CodeLoader loader) { ++ return code; ++ } ++ }; ++ } ++} +diff --git a/jython/src/org/python/core/CompilerFacade.java b/jython/src/org/python/core/CompilerFacade.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/CompilerFacade.java +@@ -0,0 +1,39 @@ ++package org.python.core; ++ ++import org.python.antlr.base.mod; ++import org.python.compiler.LegacyCompiler; ++ ++/** ++ * Facade for different compiler implementations. ++ * ++ * The static methods of this class act as a Facade for the compiler subsystem. ++ * This is so that the rest of Jython (even generated code) can statically link ++ * to the static interface of this class, while allowing for different ++ * implementations of the various components of the compiler subsystem. ++ * ++ * @author Tobias Ivarsson ++ */ ++public class CompilerFacade { ++ ++ private static volatile PythonCompiler compiler = loadDefaultCompiler(); ++ ++ public static void setCompiler(PythonCompiler compiler) { ++ CompilerFacade.compiler = compiler; ++ } ++ ++ private static PythonCompiler loadDefaultCompiler() { ++ return new LegacyCompiler(); ++ } ++ ++ public static PyCode compile(mod node, String name, String filename, ++ boolean linenumbers, boolean printResults, CompilerFlags cflags) { ++ try { ++ PythonCodeBundle bundle = compiler.compile(node, name, filename, ++ linenumbers, printResults, cflags); ++ bundle.saveCode(Options.proxyDebugDirectory); ++ return bundle.loadCode(); ++ } catch (Throwable t) { ++ throw ParserFacade.fixParseError(null, t, filename); ++ } ++ } ++} +diff --git a/jython/src/org/python/core/Py.java b/jython/src/org/python/core/Py.java +--- a/jython/src/org/python/core/Py.java ++++ b/jython/src/org/python/core/Py.java +@@ -862,9 +862,19 @@ + * Called by the code generated in {@link Module#addMain()} + */ + public static void runMain(PyRunnable main, String[] args) throws Exception { ++ runMain(new PyRunnableBootstrap(main), args); ++ } ++ ++ /** ++ * Initializes a default PythonInterpreter and runs the code loaded from the ++ * {@link CodeBootstrap} as __main__ Called by the code generated in ++ * {@link Module#addMain()} ++ */ ++ public static void runMain(CodeBootstrap main, String[] args) ++ throws Exception { + PySystemState.initialize(null, null, args, main.getClass().getClassLoader()); + try { +- imp.createFromCode("__main__", main.getMain()); ++ imp.createFromCode("__main__", CodeLoader.loadCode(main)); + } catch (PyException e) { + Py.getSystemState().callExitFunc(); + if (Py.matchException(e, Py.SystemExit)) { +@@ -1632,6 +1642,8 @@ + public static PyCode compile_flags(mod node, String name, String filename, + boolean linenumbers, boolean printResults, + CompilerFlags cflags) { ++ return CompilerFacade.compile(node, name, filename, linenumbers, printResults, cflags); ++ /* + try { + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + Module.compile(node, ostream, name, filename, linenumbers, printResults, cflags); +@@ -1642,6 +1654,7 @@ + } catch (Throwable t) { + throw ParserFacade.fixParseError(null, t, filename); + } ++ */ + } + + public static PyCode compile_flags(mod node, String filename, +diff --git a/jython/src/org/python/core/PyRunnableBootstrap.java b/jython/src/org/python/core/PyRunnableBootstrap.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/PyRunnableBootstrap.java +@@ -0,0 +1,43 @@ ++package org.python.core; ++ ++import java.lang.reflect.Constructor; ++ ++public class PyRunnableBootstrap implements CodeBootstrap { ++ ++ public static final String REFLECTION_METHOD_NAME = "getFilenameConstructorReflectionBootstrap"; ++ private final PyRunnable runnable; ++ ++ PyRunnableBootstrap(PyRunnable runnable) { ++ this.runnable = runnable; ++ } ++ ++ public PyCode loadCode(CodeLoader loader) { ++ return runnable.getMain(); ++ } ++ ++ public static CodeBootstrap getFilenameConstructorReflectionBootstrap( ++ Class<? extends PyRunnable> cls) { ++ final Constructor<? extends PyRunnable> constructor; ++ try { ++ constructor = cls.getConstructor(String.class); ++ } catch (Exception e) { ++ throw new IllegalArgumentException( ++ "PyRunnable class does not specify apropriate constructor.", ++ e); ++ } ++ return new CodeBootstrap() { ++ ++ public PyCode loadCode(CodeLoader loader) { ++ try { ++ return constructor.newInstance(loader.filename).getMain(); ++ } catch (Exception e) { ++ throw new IllegalArgumentException( ++ "PyRunnable class constructor does not support instantiation protocol.", ++ e); ++ } ++ } ++ ++ }; ++ } ++ ++} +diff --git a/jython/src/org/python/core/PythonCodeBundle.java b/jython/src/org/python/core/PythonCodeBundle.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/PythonCodeBundle.java +@@ -0,0 +1,13 @@ ++package org.python.core; ++ ++import java.io.OutputStream; ++ ++public interface PythonCodeBundle { ++ ++ PyCode loadCode() throws Exception; ++ ++ void writeTo(OutputStream stream) throws Exception; ++ ++ void saveCode(String directory) throws Exception; ++ ++} +diff --git a/jython/src/org/python/core/PythonCompiler.java b/jython/src/org/python/core/PythonCompiler.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/PythonCompiler.java +@@ -0,0 +1,11 @@ ++package org.python.core; ++ ++import org.python.antlr.base.mod; ++ ++public interface PythonCompiler { ++ ++ PythonCodeBundle compile(mod node, String name, String filename, ++ boolean linenumbers, boolean printResults, CompilerFlags cflags) ++ throws Exception; ++ ++} Modified: trunk/sandbox/tobias/.hg/patches/series =================================================================== --- trunk/sandbox/tobias/.hg/patches/series 2009-03-02 03:29:30 UTC (rev 6054) +++ trunk/sandbox/tobias/.hg/patches/series 2009-03-02 15:59:20 UTC (rev 6055) @@ -0,0 +1,2 @@ +types.patch #+trunk #-advanced +decouple.patch #+trunk #-advanced Added: trunk/sandbox/tobias/.hg/patches/types.patch =================================================================== --- trunk/sandbox/tobias/.hg/patches/types.patch (rev 0) +++ trunk/sandbox/tobias/.hg/patches/types.patch 2009-03-02 15:59:20 UTC (rev 6055) @@ -0,0 +1,1546 @@ +diff --git a/jython/Lib/codeop.py b/jython/Lib/codeop.py +--- a/jython/Lib/codeop.py ++++ b/jython/Lib/codeop.py +@@ -57,8 +57,8 @@ + """ + + # import internals, not guaranteed interface +-from org.python.core import Py,CompilerFlags +-from org.python.core.PyTableCode import PyCF_DONT_IMPLY_DEDENT ++from org.python.core import Py,CompilerFlags,CompileMode ++from org.python.core.CompilerFlags import PyCF_DONT_IMPLY_DEDENT + + # public interface + +@@ -84,6 +84,7 @@ + """ + if symbol not in ['single','eval']: + raise ValueError,"symbol arg must be either single or eval" ++ symbol = CompileMode.getMode(symbol) + return Py.compile_command_flags(source,filename,symbol,Py.getCompilerFlags(),0) + + class Compile: +@@ -95,6 +96,7 @@ + self._cflags = CompilerFlags() + + def __call__(self, source, filename, symbol): ++ symbol = CompileMode.getMode(symbol) + return Py.compile_flags(source, filename, symbol, self._cflags) + + class CommandCompiler: +@@ -128,5 +130,6 @@ + """ + if symbol not in ['single','eval']: + raise ValueError,"symbol arg must be either single or eval" ++ symbol = CompileMode.getMode(symbol) + return Py.compile_command_flags(source,filename,symbol,self._cflags,0) + +diff --git a/jython/src/org/python/Version.java b/jython/src/org/python/Version.java +--- a/jython/src/org/python/Version.java ++++ b/jython/src/org/python/Version.java +@@ -3,7 +3,13 @@ + + import java.io.InputStream; + import java.io.IOException; ++import java.util.Arrays; ++import java.util.Collection; ++import java.util.EnumSet; + import java.util.Properties; ++import java.util.Set; ++ ++import org.python.core.CodeFlag; + + /** + * Jython version information. +@@ -36,6 +42,10 @@ + /** Short version of branch, e.g. asm. */ + public static String SHORT_BRANCH; + ++ /** The flags that are set by default in a code object. */ ++ private static final Collection<CodeFlag> defaultCodeFlags = Arrays.asList( ++ CodeFlag.CO_NESTED, CodeFlag.CO_GENERATOR_ALLOWED); ++ + private static final String headURL = + "$HeadURL: https://jython.svn.sourceforge.net/svnroot/jython/trunk/jython/src/org/python/Version.java $"; + +@@ -144,4 +154,8 @@ + public static String getVersion() { + return String.format("%.80s (%.80s) %.80s", PY_VERSION, getBuildInfo(), getVM()); + } ++ ++ public static Set<CodeFlag> getDefaultCodeFlags() { ++ return EnumSet.copyOf(defaultCodeFlags); ++ } + } +diff --git a/jython/src/org/python/antlr/BaseParser.java b/jython/src/org/python/antlr/BaseParser.java +--- a/jython/src/org/python/antlr/BaseParser.java ++++ b/jython/src/org/python/antlr/BaseParser.java +@@ -1,15 +1,31 @@ + package org.python.antlr; + + import org.antlr.runtime.CharStream; ++import org.antlr.runtime.CommonTokenStream; ++import org.antlr.runtime.RecognitionException; + import org.antlr.runtime.Token; ++import org.python.antlr.base.mod; + + public class BaseParser { + +- protected CharStream charStream; +- protected boolean partial; +- protected String filename; +- protected String encoding; ++ protected final CharStream charStream; ++ @Deprecated ++ protected final boolean partial; ++ protected final String filename; ++ protected final String encoding; + protected ErrorHandler errorHandler = new FailFastHandler(); ++ ++ public BaseParser(CharStream stream, String filename, String encoding) { ++ this(stream, filename, encoding, false); ++ } ++ ++ @Deprecated ++ public BaseParser(CharStream stream, String filename, String encoding, boolean partial) { ++ this.charStream = stream; ++ this.filename = filename; ++ this.encoding = encoding; ++ this.partial = partial; ++ } + + public void setAntlrErrorHandler(ErrorHandler eh) { + this.errorHandler = eh; +@@ -25,4 +41,60 @@ + return super.nextToken(); + } + } ++ ++ private CharStream charStream(boolean single) { ++ return charStream; ++ } ++ ++ private PythonParser setupParser(boolean single) { ++ PythonLexer lexer = new PyLexer(this.charStream(single)); ++ lexer.setErrorHandler(errorHandler); ++ CommonTokenStream tokens = new CommonTokenStream(lexer); ++ PythonTokenSource indentedSource = new PythonTokenSource(tokens, filename, single); ++ tokens = new CommonTokenStream(indentedSource); ++ PythonParser parser = new PythonParser(tokens, encoding); ++ parser.setErrorHandler(errorHandler); ++ parser.setTreeAdaptor(new PythonTreeAdaptor()); ++ return parser; ++ } ++ ++ public mod parseExpression() { ++ mod tree = null; ++ PythonParser parser = setupParser(false); ++ try { ++ PythonParser.eval_input_return r = parser.eval_input(); ++ tree = (mod)r.tree; ++ } catch (RecognitionException e) { ++ //XXX: this can't happen. Need to strip the throws from antlr ++ // generated code. ++ } ++ return tree; ++ } ++ ++ public mod parseInteractive() { ++ mod tree = null; ++ PythonParser parser = setupParser(true); ++ try { ++ PythonParser.single_input_return r = parser.single_input(); ++ tree = (mod)r.tree; ++ } catch (RecognitionException e) { ++ //I am only throwing ParseExceptions, but "throws RecognitionException" still gets ++ //into the generated code. ++ System.err.println("FIXME: pretty sure this can't happen -- but needs to be checked"); ++ } ++ return tree; ++ } ++ ++ public mod parseModule() { ++ mod tree = null; ++ PythonParser parser = setupParser(false); ++ try { ++ PythonParser.file_input_return r = parser.file_input(); ++ tree = (mod)r.tree; ++ } catch (RecognitionException e) { ++ //XXX: this can't happen. Need to strip the throws from antlr ++ // generated code. ++ } ++ return tree; ++ } + } +diff --git a/jython/src/org/python/antlr/ExpressionParser.java b/jython/src/org/python/antlr/ExpressionParser.java +deleted file mode 100644 +--- a/jython/src/org/python/antlr/ExpressionParser.java ++++ /dev/null +@@ -1,36 +0,0 @@ +-package org.python.antlr; +- +-import org.antlr.runtime.CharStream; +-import org.antlr.runtime.CommonTokenStream; +-import org.antlr.runtime.RecognitionException; +-import org.python.antlr.base.mod; +- +-public class ExpressionParser extends BaseParser { +- +- public ExpressionParser(CharStream cs, String filename, String encoding) { +- this.charStream = cs; +- this.filename = filename; +- this.encoding = encoding; +- } +- +- public mod parse() { +- mod tree = null; +- PythonLexer lexer = new PyLexer(this.charStream); +- lexer.setErrorHandler(errorHandler); +- CommonTokenStream tokens = new CommonTokenStream(lexer); +- PythonTokenSource indentedSource = new PythonTokenSource(tokens, filename); +- tokens = new CommonTokenStream(indentedSource); +- PythonParser parser = new PythonParser(tokens, encoding); +- parser.setErrorHandler(errorHandler); +- parser.setTreeAdaptor(new PythonTreeAdaptor()); +- +- try { +- PythonParser.eval_input_return r = parser.eval_input(); +- tree = (mod)r.tree; +- } catch (RecognitionException e) { +- //XXX: this can't happen. Need to strip the throws from antlr +- // generated code. +- } +- return tree; +- } +-} +diff --git a/jython/src/org/python/antlr/InteractiveParser.java b/jython/src/org/python/antlr/InteractiveParser.java +deleted file mode 100644 +--- a/jython/src/org/python/antlr/InteractiveParser.java ++++ /dev/null +@@ -1,41 +0,0 @@ +-package org.python.antlr; +- +-import java.io.BufferedReader; +-import java.io.IOException; +- +-import org.antlr.runtime.CommonTokenStream; +-import org.antlr.runtime.RecognitionException; +-import org.python.antlr.base.mod; +- +-public class InteractiveParser extends BaseParser { +- +- private BufferedReader bufreader; +- +- public InteractiveParser(BufferedReader br, String filename, String encoding) { +- this.bufreader = br; +- this.filename = filename; +- this.encoding = encoding; +- } +- +- public mod parse() throws IOException { +- mod tree = null; +- PythonLexer lexer = new PyLexer(new NoCloseReaderStream(bufreader)); +- lexer.setErrorHandler(errorHandler); +- CommonTokenStream tokens = new CommonTokenStream(lexer); +- PythonTokenSource indentedSource = new PythonTokenSource(tokens, filename, true); +- tokens = new CommonTokenStream(indentedSource); +- PythonParser parser = new PythonParser(tokens, encoding); +- parser.setErrorHandler(errorHandler); +- parser.setTreeAdaptor(new PythonTreeAdaptor()); +- +- try { +- PythonParser.single_input_return r = parser.single_input(); +- tree = (mod)r.tree; +- } catch (RecognitionException e) { +- //I am only throwing ParseExceptions, but "throws RecognitionException" still gets +- //into the generated code. +- System.err.println("FIXME: pretty sure this can't happen -- but needs to be checked"); +- } +- return tree; +- } +-} +diff --git a/jython/src/org/python/antlr/ModuleParser.java b/jython/src/org/python/antlr/ModuleParser.java +deleted file mode 100644 +--- a/jython/src/org/python/antlr/ModuleParser.java ++++ /dev/null +@@ -1,39 +0,0 @@ +-package org.python.antlr; +- +-import org.antlr.runtime.CharStream; +-import org.antlr.runtime.CommonTokenStream; +-import org.antlr.runtime.RecognitionException; +-import org.python.antlr.base.mod; +- +-public class ModuleParser extends BaseParser { +- public ModuleParser(CharStream cs, String filename, String encoding) { +- this(cs, filename, encoding, false); +- } +- +- public ModuleParser(CharStream cs, String filename, String encoding, boolean partial) { +- this.charStream = cs; +- this.filename = filename; +- this.encoding = encoding; +- this.partial = partial; +- } +- +- public mod file_input() { +- mod tree = null; +- PythonLexer lexer = new PyLexer(this.charStream); +- lexer.setErrorHandler(errorHandler); +- CommonTokenStream tokens = new CommonTokenStream(lexer); +- PythonTokenSource indentedSource = new PythonTokenSource(tokens, filename); +- tokens = new CommonTokenStream(indentedSource); +- PythonParser parser = new PythonParser(tokens, encoding); +- parser.setErrorHandler(errorHandler); +- parser.setTreeAdaptor(new PythonTreeAdaptor()); +- try { +- PythonParser.file_input_return r = parser.file_input(); +- tree = (mod)r.tree; +- } catch (RecognitionException e) { +- //XXX: this can't happen. Need to strip the throws from antlr +- // generated code. +- } +- return tree; +- } +-} +diff --git a/jython/src/org/python/antlr/ast/AstModule.java b/jython/src/org/python/antlr/ast/AstModule.java +--- a/jython/src/org/python/antlr/ast/AstModule.java ++++ b/jython/src/org/python/antlr/ast/AstModule.java +@@ -8,12 +8,12 @@ + import org.python.antlr.op.*; + import org.python.core.AstList; + import org.python.core.ClassDictInit; ++import org.python.core.CompilerFlags; + import org.python.core.imp; + import org.python.core.Py; + import org.python.core.PyInteger; + import org.python.core.PyObject; + import org.python.core.PyString; +-import org.python.core.PyTableCode; + import org.python.core.PyType; + + import org.python.antlr.AST; +@@ -27,7 +27,7 @@ + dict.__setitem__("__doc__", Py.None); + dict.__setitem__("__name__", new PyString("_ast")); + dict.__setitem__("__version__", new PyString("62047")); +- dict.__setitem__("PyCF_ONLY_AST", new PyInteger(PyTableCode.PyCF_ONLY_AST)); ++ dict.__setitem__("PyCF_ONLY_AST", new PyInteger(CompilerFlags.PyCF_ONLY_AST)); + + dict.__setitem__("astlist", AstList.TYPE); + +diff --git a/jython/src/org/python/compiler/Future.java b/jython/src/org/python/compiler/Future.java +--- a/jython/src/org/python/compiler/Future.java ++++ b/jython/src/org/python/compiler/Future.java +@@ -8,73 +8,65 @@ + import org.python.antlr.ast.Interactive; + import org.python.antlr.ast.Module; + import org.python.antlr.ast.Str; ++import org.python.antlr.ast.alias; + import org.python.antlr.base.mod; + import org.python.antlr.base.stmt; ++import org.python.core.CodeFlag; ++import org.python.core.FutureFeature; ++import org.python.core.Pragma; ++import org.python.core.PragmaReceiver; + ++import java.util.EnumSet; + import java.util.List; ++import java.util.Set; + + public class Future { ++ Set<FutureFeature> featureSet = EnumSet.noneOf(FutureFeature.class); ++ private final PragmaReceiver features = new PragmaReceiver() { + +- private boolean division = false; +- private boolean with_statement = false; +- private boolean absolute_import = false; ++ public void add(Pragma pragma) { ++ if (pragma instanceof FutureFeature) { ++ FutureFeature feature = (FutureFeature) pragma; ++ featureSet.add(feature); ++ } ++ } + +- private static final String FUTURE = "__future__"; ++ }; + + private boolean check(ImportFrom cand) throws Exception { +- if (!cand.getInternalModule().equals(FUTURE)) ++ if (!cand.getInternalModule().equals(FutureFeature.MODULE_NAME)) + return false; +- int n = cand.getInternalNames().size(); +- if (n == 0) { +- throw new ParseException("future statement does not support import *", cand); ++ if (cand.getInternalNames().isEmpty()) { ++ throw new ParseException( ++ "future statement does not support import *", cand); + } +- for (int i = 0; i < n; i++) { +- String feature = cand.getInternalNames().get(i).getInternalName(); +- // *known* features +- if (feature.equals("nested_scopes")) { +- continue; ++ try { ++ for (alias feature : cand.getInternalNames()) { ++ // *known* features ++ FutureFeature.addFeature(feature.getInternalName(), features); + } +- if (feature.equals("division")) { +- division = true; +- continue; +- } +- if (feature.equals("generators")) { +- continue; +- } +- if (feature.equals("with_statement")) { +- with_statement = true; +- continue; +- } +- if (feature.equals("absolute_import")) { +- absolute_import = true; +- continue; +- } +- if (feature.equals("braces")) { +- throw new ParseException("not a chance", cand); +- } +- if (feature.equals("GIL") || feature.equals("global_interpreter_lock")) { +- throw new ParseException("Never going to happen!", cand); +- } +- throw new ParseException("future feature " + feature + " is not defined", cand); ++ } catch (ParseException pe) { ++ throw new ParseException(pe.getMessage(), cand); + } + return true; + } + +- public void preprocessFutures(mod node, +- org.python.core.CompilerFlags cflags) +- throws Exception +- { ++ public void preprocessFutures(mod node, org.python.core.CompilerFlags cflags) ++ throws Exception { + if (cflags != null) { +- division = cflags.division; +- with_statement = cflags.with_statement; +- absolute_import = cflags.absolute_import; ++ if (cflags.isFlagSet(CodeFlag.CO_FUTURE_DIVISION)) ++ FutureFeature.division.addTo(features); ++ if (cflags.isFlagSet(CodeFlag.CO_FUTURE_WITH_STATEMENT)) ++ FutureFeature.with_statement.addTo(features); ++ if (cflags.isFlagSet(CodeFlag.CO_FUTURE_ABSOLUTE_IMPORT)) ++ FutureFeature.absolute_import.addTo(features); + } + int beg = 0; + List<stmt> suite = null; + if (node instanceof Module) { + suite = ((Module) node).getInternalBody(); +- if (suite.size() > 0 && suite.get(0) instanceof Expr && +- ((Expr) suite.get(0)).getInternalValue() instanceof Str) { ++ if (suite.size() > 0 && suite.get(0) instanceof Expr ++ && ((Expr) suite.get(0)).getInternalValue() instanceof Str) { + beg++; + } + } else if (node instanceof Interactive) { +@@ -85,45 +77,36 @@ + + for (int i = beg; i < suite.size(); i++) { + stmt s = suite.get(i); +- if (!(s instanceof ImportFrom)) +- break; ++ if (!(s instanceof ImportFrom)) break; + s.from_future_checked = true; +- if (!check((ImportFrom)s)) +- break; ++ if (!check((ImportFrom) s)) break; + } + + if (cflags != null) { +- cflags.division = cflags.division || division; +- } +- if (cflags != null) { +- cflags.with_statement = cflags.with_statement || with_statement; +- } +- if (cflags != null) { +- cflags.absolute_import = cflags.absolute_import || absolute_import; ++ for (FutureFeature feature : featureSet) { ++ feature.setFlag(cflags); ++ } + } + } + +- + public static void checkFromFuture(ImportFrom node) throws Exception { +- if (node.from_future_checked) +- return; +- if (node.getInternalModule().equals(FUTURE)) { +- throw new ParseException("from __future__ imports must occur " + +- "at the beginning of the file",node); ++ if (node.from_future_checked) return; ++ if (node.getInternalModule().equals(FutureFeature.MODULE_NAME)) { ++ throw new ParseException("from __future__ imports must occur " ++ + "at the beginning of the file", node); + } + node.from_future_checked = true; + } + + public boolean areDivisionOn() { +- return division; ++ return featureSet.contains(FutureFeature.division); + } + + public boolean withStatementSupported() { +- return with_statement; ++ return featureSet.contains(FutureFeature.with_statement); + } + + public boolean isAbsoluteImportOn() { +- return absolute_import; ++ return featureSet.contains(FutureFeature.absolute_import); + } +- + } +diff --git a/jython/src/org/python/compiler/Module.java b/jython/src/org/python/compiler/Module.java +--- a/jython/src/org/python/compiler/Module.java ++++ b/jython/src/org/python/compiler/Module.java +@@ -12,6 +12,7 @@ + + import org.objectweb.asm.Label; + import org.objectweb.asm.Opcodes; ++import org.python.core.CodeFlag; + import org.python.core.CompilerFlags; + import org.python.core.Py; + import org.python.core.PyException; +@@ -500,17 +501,17 @@ + code.jy_npurecell = scope.jy_npurecell; + + if (compiler.optimizeGlobals) { +- code.moreflags |= org.python.core.PyTableCode.CO_OPTIMIZED; ++ code.moreflags |= org.python.core.CodeFlag.CO_OPTIMIZED.flag; + } + if (compiler.my_scope.generator) { +- code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR; ++ code.moreflags |= org.python.core.CodeFlag.CO_GENERATOR.flag; + } + if (cflags != null) { +- if (cflags.generator_allowed) { +- code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR_ALLOWED; ++ if (cflags.isFlagSet(CodeFlag.CO_GENERATOR_ALLOWED)) { ++ code.moreflags |= org.python.core.CodeFlag.CO_GENERATOR_ALLOWED.flag; + } +- if (cflags.division) { +- code.moreflags |= org.python.core.PyTableCode.CO_FUTUREDIVISION; ++ if (cflags.isFlagSet(CodeFlag.CO_FUTURE_DIVISION)) { ++ code.moreflags |= org.python.core.CodeFlag.CO_FUTURE_DIVISION.flag; + } + } + +diff --git a/jython/src/org/python/compiler/pbc/Bytecode.java b/jython/src/org/python/compiler/pbc/Bytecode.java +--- a/jython/src/org/python/compiler/pbc/Bytecode.java ++++ b/jython/src/org/python/compiler/pbc/Bytecode.java +@@ -14,6 +14,8 @@ + import java.util.List; + import java.util.Map; + import java.util.Set; ++ ++import org.python.core.CodeFlag; + import org.python.core.Py; + import org.python.core.Opcode; + import org.python.core.PyBaseCode; +@@ -25,7 +27,7 @@ + + private int co_argcount = 0; + private int co_stacksize = 0; +- private int co_flags = PyBaseCode.CO_OPTIMIZED | PyBaseCode.CO_NEWLOCALS; // typical usage ++ private int co_flags = CodeFlag.CO_OPTIMIZED.flag | CodeFlag.CO_NEWLOCALS.flag; // typical usage + // co_filename = '<generated code>' + // co_name = '<lambda>' + // co_firstlineno = 0 +@@ -135,7 +137,7 @@ + + public void YIELD_VALUE() { + stackchange(1, 1); +- co_flags |= PyBaseCode.CO_GENERATOR; ++ co_flags |= CodeFlag.CO_GENERATOR.flag; + emit(Opcode.YIELD_VALUE); + } + +diff --git a/jython/src/org/python/core/CodeFlag.java b/jython/src/org/python/core/CodeFlag.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/CodeFlag.java +@@ -0,0 +1,106 @@ ++package org.python.core; ++ ++import java.util.Arrays; ++import java.util.Collections; ++import java.util.Iterator; ++ ++/** ++ * Represents flags that can be set on code objects. ++ * ++ * @author Tobias Ivarsson ++ */ ++public enum CodeFlag { ++ /** ++ * Denotes that the code block uses fast locals. ++ */ ++ CO_OPTIMIZED(0x0001), ++ /** ++ * Denotes that a new dictionary should be created for the code block. ++ */ ++ CO_NEWLOCALS(0x0002), ++ /** ++ * The compiled code block has a varargs argument. ++ */ ++ CO_VARARGS(0x0004), ++ /** ++ * The compiled code block has a varkeyword argument. ++ */ ++ CO_VARKEYWORDS(0x0008), ++ /** ++ * The compiled code block is a generator code block. ++ */ ++ CO_GENERATOR(0x0020), ++ /** ++ * Denotes that nested scopes are enabled in the code block. ++ */ ++ CO_NESTED(0x0010), ++ /** ++ * Denotes that generators are enabled in the code block. ++ */ ++ CO_GENERATOR_ALLOWED(0x1000), ++ /** ++ * Standard division of integers returns float, truncating division needs to ++ * be enforced. ++ */ ++ CO_FUTURE_DIVISION(0x2000), ++ /** ++ * Absolute import. ++ */ ++ CO_FUTURE_ABSOLUTE_IMPORT(0x4000), ++ /** ++ * With statement. ++ */ ++ CO_FUTURE_WITH_STATEMENT(0x8000); ++ ++ public final int flag; ++ private static Iterable<CodeFlag> allFlags = Collections.unmodifiableList(Arrays.asList(values())); ++ ++ private CodeFlag(int flag) { ++ this.flag = flag; ++ } ++ ++ public boolean isFlagBitSetIn(int flags) { ++ return (flags & flag) != 0; ++ } ++ ++ static Iterable<CodeFlag> parse(final int flags) { ++ return new Iterable<CodeFlag>() { ++ ++ public Iterator<CodeFlag> iterator() { ++ return new Iterator<CodeFlag>() { ++ Iterator<CodeFlag> all = allFlags.iterator(); ++ CodeFlag next = null; ++ ++ public boolean hasNext() { ++ if (next != null) { ++ return true; ++ } ++ while (all.hasNext()) { ++ CodeFlag flag = all.next(); ++ if (flag.isFlagBitSetIn(flags)) { ++ next = flag; ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ public CodeFlag next() { ++ if (hasNext()) try { ++ return next; ++ } finally { ++ next = null; ++ } ++ throw new IllegalStateException(); ++ } ++ ++ public void remove() { ++ throw new UnsupportedOperationException(); ++ } ++ ++ }; ++ } ++ ++ }; ++ } ++} +diff --git a/jython/src/org/python/core/CompileMode.java b/jython/src/org/python/core/CompileMode.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/CompileMode.java +@@ -0,0 +1,33 @@ ++package org.python.core; ++ ++import org.python.antlr.BaseParser; ++import org.python.antlr.base.mod; ++ ++public enum CompileMode { ++ eval { ++ @Override ++ mod dispatch(BaseParser parser) { ++ return parser.parseExpression(); ++ } ++ }, ++ single { ++ @Override ++ mod dispatch(BaseParser parser) { ++ return parser.parseInteractive(); ++ } ++ }, ++ exec { ++ @Override ++ mod dispatch(BaseParser parser) { ++ return parser.parseModule(); ++ } ++ }; ++ abstract mod dispatch(BaseParser parser); ++ ++ public static CompileMode getMode(String mode) { ++ if (!mode.equals("exec") && !mode.equals("eval") && !mode.equals("single")) { ++ throw Py.ValueError("compile() arg 3 must be 'exec' or 'eval' or 'single'"); ++ } ++ return valueOf(mode); ++ } ++} +diff --git a/jython/src/org/python/core/CompilerFlags.java b/jython/src/org/python/core/CompilerFlags.java +--- a/jython/src/org/python/core/CompilerFlags.java ++++ b/jython/src/org/python/core/CompilerFlags.java +@@ -1,46 +1,84 @@ + + package org.python.core; + ++import java.util.Set; ++ ++import org.python.Version; ++ + public class CompilerFlags { +- +- private int co_flags; +- +- public boolean nested_scopes = true; +- public boolean division; +- public boolean generator_allowed = true; +- public boolean with_statement; +- public boolean absolute_import; +- ++ // These flags don't mean anything to the code, only to the compiler ++ public static final int PyCF_SOURCE_IS_UTF8 = 0x0100; ++ public static final int PyCF_DONT_IMPLY_DEDENT = 0x0200; ++ public static final int PyCF_ONLY_AST = 0x0400; + public boolean only_ast; + public boolean dont_imply_dedent; + public boolean source_is_utf8; + + public String encoding; ++ private final Set<CodeFlag> flags = Version.getDefaultCodeFlags(); + + public CompilerFlags() {} + + 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); ++ for (CodeFlag flag : CodeFlag.parse(co_flags)) { ++ setFlag(flag); ++ } ++ only_ast = isEnabled(co_flags, PyCF_ONLY_AST); ++ dont_imply_dedent = isEnabled(co_flags, PyCF_DONT_IMPLY_DEDENT); ++ source_is_utf8 = isEnabled(co_flags, PyCF_SOURCE_IS_UTF8); + } + +- private boolean isEnabled(int codeConstant) { ++ private boolean isEnabled(int co_flags, int codeConstant) { + return (co_flags & codeConstant) != 0; + } + +- public String toString() { +- return String.format("CompilerFlags[division=%s nested_scopes=%s generators=%s " +- + "with_statement=%s absolute_import=%s only_ast=%s " +- + "dont_imply_dedent=%s source_is_utf8=%s]", division, nested_scopes, +- generator_allowed, with_statement, absolute_import, only_ast, +- dont_imply_dedent, source_is_utf8); ++ public void setFlag(CodeFlag flag) { ++ flags.add(flag); + } + ++ public boolean isFlagSet(CodeFlag flag) { ++ return flags.contains(flag); ++ } ++ ++ public String toString() { ++ return String.format( ++ "CompilerFlags[division=%s nested_scopes=%s generators=%s " ++ + "with_statement=%s absolute_import=%s only_ast=%s " ++ + "dont_imply_dedent=%s source_is_utf8=%s]", ++ isFlagSet(CodeFlag.CO_FUTURE_DIVISION), ++ isFlagSet(CodeFlag.CO_NESTED), ++ isFlagSet(CodeFlag.CO_GENERATOR_ALLOWED), ++ isFlagSet(CodeFlag.CO_FUTURE_WITH_STATEMENT), ++ isFlagSet(CodeFlag.CO_FUTURE_ABSOLUTE_IMPORT), ++ only_ast, dont_imply_dedent, source_is_utf8); ++ } ++ ++ public static CompilerFlags getCompilerFlags() { ++ return getCompilerFlags(0, false); ++ } ++ ++ private static final int CO_ALL_FEATURES = CompilerFlags.PyCF_DONT_IMPLY_DEDENT ++ | CompilerFlags.PyCF_ONLY_AST ++ | CompilerFlags.PyCF_SOURCE_IS_UTF8 ++ | CodeFlag.CO_NESTED.flag ++ | CodeFlag.CO_GENERATOR_ALLOWED.flag ++ | CodeFlag.CO_FUTURE_DIVISION.flag ++ | CodeFlag.CO_FUTURE_ABSOLUTE_IMPORT.flag ++ | CodeFlag.CO_FUTURE_WITH_STATEMENT.flag; ++ ++ public static CompilerFlags getCompilerFlags(int flags, boolean dont_inherit) { ++ if ((flags & ~CO_ALL_FEATURES) != 0) { ++ throw Py.ValueError("compile(): unrecognised flags"); ++ } ++ CompilerFlags cflags = null; ++ if (dont_inherit) { ++ cflags = new CompilerFlags(flags); ++ } else { ++ PyFrame frame = Py.getFrame(); ++ if (frame != null && frame.f_code != null) { ++ cflags = new CompilerFlags(frame.f_code.co_flags | flags); ++ } ++ } ++ return cflags; ++ } + } +diff --git a/jython/src/org/python/core/FutureFeature.java b/jython/src/org/python/core/FutureFeature.java +new file mode 100644 +--- /dev/null ++++ b/jython/src/org/python/core/FutureFeature.java +@@ -0,0 +1,101 @@ ++package org.python.core; ++ ++import org.python.antlr.ParseException; ++ ++public enum FutureFeature implements Pragma { ++ /** ++ * Enables nested scopes. ++ */ ++ nested_scopes(CodeFlag.CO_NESTED), ++ /** ++ * Makes integer / integer division return float. ++ */ ++ division(CodeFlag.CO_FUTURE_DIVISION), ++ /** ++ * Enables generators. ++ */ ++ generators(CodeFlag.CO_GENERATOR_ALLOWED), ++ /** ++ * Enables absolute imports. ++ */ ++ absolute_import(CodeFlag.CO_FUTURE_ABSOLUTE_IMPORT), ++ /** ++ * Enables the with statement. ++ */ ++ with_statement(CodeFlag.CO_FUTURE_WITH_STATEMENT), ++ /** ++ * Use braces for block delimiters instead of indentation. ++ */ ++ braces { ++ @Override ++ public void addTo(PragmaReceiver features) { ++ throw new ParseException("not a chance"); ++ } ++ }, ++ /** ++ * Enable the Global Interpreter Lock in Jython. ++ */ ++ GIL { ++ @Override ++ public void addTo(PragmaReceiver features) { ++ throw new ParseException("Never going to happen!"); ++ } ++ }, ++ /** ++ * Enable the Global Interpreter Loc... [truncated message content] |