From: <th...@us...> - 2008-06-19 09:17:40
|
Revision: 4674 http://jython.svn.sourceforge.net/jython/?rev=4674&view=rev Author: thobes Date: 2008-06-19 02:17:37 -0700 (Thu, 19 Jun 2008) Log Message: ----------- Merged in the stuff from sandbox/pyasm in the advanced compiler branch. Added the work-in-progress code to version control. Modified Paths: -------------- branches/advanced/.classpath branches/advanced/compiler/org/python/newcompiler/AbstractEnvironment.java branches/advanced/compiler/org/python/newcompiler/ClassEnvironment.java branches/advanced/compiler/org/python/newcompiler/CodeInfo.java branches/advanced/compiler/org/python/newcompiler/CompilerFlag.java branches/advanced/compiler/org/python/newcompiler/Environment.java branches/advanced/compiler/org/python/newcompiler/EnvironmentError.java branches/advanced/compiler/org/python/newcompiler/FunctionEnvironment.java branches/advanced/compiler/org/python/newcompiler/GlobalEnvironment.java branches/advanced/compiler/org/python/newcompiler/ast/AstToBytecode.java branches/advanced/compiler/org/python/newcompiler/ast/ContextBuilder.java Added Paths: ----------- branches/advanced/agent/ branches/advanced/compiler/ branches/advanced/compiler/org/python/compiler/ branches/advanced/compiler/org/python/compiler/iface/ branches/advanced/compiler/org/python/compiler/iface/ClassCompiler.java branches/advanced/compiler/org/python/compiler/iface/CodeCompiler.java branches/advanced/compiler/org/python/compiler/iface/CompilationMode.java branches/advanced/compiler/org/python/compiler/iface/Compiler.java branches/advanced/compiler/org/python/compiler/iface/CompilerFlag.java branches/advanced/compiler/org/python/compiler/iface/Parser.java branches/advanced/compiler/org/python/newcompiler/CompilerPolicy.java branches/advanced/compiler/org/python/newcompiler/ScopeInfo.java branches/advanced/continuations/ branches/advanced/continuations/org/ branches/advanced/continuations/org/python/ branches/advanced/continuations/org/python/continuations/ branches/advanced/continuations/org/python/continuations/Continuation.java branches/advanced/interpreter/ branches/advanced/interpreter/org/ branches/advanced/interpreter/org/python/ branches/advanced/interpreter/org/python/interpreter/ branches/advanced/interpreter/org/python/interpreter/BytecodeInterpreter.java Removed Paths: ------------- branches/advanced/compiler/org/python/bytecode/BytecodeInfo.java Modified: branches/advanced/.classpath =================================================================== --- branches/advanced/.classpath 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/.classpath 2008-06-19 09:17:37 UTC (rev 4674) @@ -5,6 +5,10 @@ <classpathentry kind="src" output="build/classes" path="build/gensrc"/> <classpathentry kind="src" output="build/classes" path="tests/java"/> <classpathentry kind="src" path="bugtests/classes"/> + <classpathentry kind="src" path="agent"/> + <classpathentry kind="src" path="compiler"/> + <classpathentry kind="src" path="continuations"/> + <classpathentry kind="src" path="interpreter"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/> <classpathentry kind="lib" path="extlibs/jline-0.9.94.jar"/> @@ -14,7 +18,7 @@ <classpathentry kind="lib" path="extlibs/postgresql-8.3-603.jdbc4.jar"/> <classpathentry kind="lib" path="extlibs/servlet-api-2.5.jar"/> <classpathentry kind="lib" path="build/jarjar"/> - <classpathentry kind="lib" path="extlibs/antlr-3.0.1.jar"/> - <classpathentry kind="var" path="ANT_HOME/lib/ant.jar"/> + <classpathentry kind="var" path="Ant"/> + <classpathentry kind="lib" path="extlibs/antlr-3.1b1.jar"/> <classpathentry kind="output" path="bugtests/classes"/> </classpath> Copied: branches/advanced/agent (from rev 4673, trunk/sandbox/pyasm/agent) Copied: branches/advanced/compiler (from rev 4673, trunk/sandbox/pyasm/compiler) Deleted: branches/advanced/compiler/org/python/bytecode/BytecodeInfo.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/bytecode/BytecodeInfo.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/bytecode/BytecodeInfo.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -1,59 +0,0 @@ -package org.python.bytecode; - -import java.util.Set; - -import org.python.newcompiler.CodeInfo; -import org.python.newcompiler.CompilerFlag; - -public class BytecodeInfo implements CodeInfo { - - private final String name; - - private final String filename; - - private final int argcount; - - private final int nlocals; - - private final int stacksize; - - private final Set<CompilerFlag> flags; - - public BytecodeInfo(String name, - String filename, - int argcount, - int nlocals, - int stacksize, - int flags) { - this.name = name; - this.filename = filename; - this.argcount = argcount; - this.nlocals = nlocals; - this.stacksize = stacksize; - this.flags = CompilerFlag.parseFlags(flags); - } - - public int getArgumentCount() { - return argcount; - } - - public String getFilename() { - return filename; - } - - public int getLocalsCount() { - return nlocals; - } - - public int getMaxStackSize() { - return stacksize; - } - - public String getName() { - return name; - } - - public Set<CompilerFlag> getCompilerFlags() { - return flags; - } -} Added: branches/advanced/compiler/org/python/compiler/iface/ClassCompiler.java =================================================================== --- branches/advanced/compiler/org/python/compiler/iface/ClassCompiler.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/iface/ClassCompiler.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,4 @@ +package org.python.compiler.iface; + + +public interface ClassCompiler {} Added: branches/advanced/compiler/org/python/compiler/iface/CodeCompiler.java =================================================================== --- branches/advanced/compiler/org/python/compiler/iface/CodeCompiler.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/iface/CodeCompiler.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,4 @@ +package org.python.compiler.iface; + + +public interface CodeCompiler {} Added: branches/advanced/compiler/org/python/compiler/iface/CompilationMode.java =================================================================== --- branches/advanced/compiler/org/python/compiler/iface/CompilationMode.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/iface/CompilationMode.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,6 @@ +package org.python.compiler.iface; + + +public enum CompilationMode { + exec, single, eval +} Added: branches/advanced/compiler/org/python/compiler/iface/Compiler.java =================================================================== --- branches/advanced/compiler/org/python/compiler/iface/Compiler.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/iface/Compiler.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,255 @@ +package org.python.compiler.iface; + +import java.io.File; +import java.io.IOException; +import java.util.Set; + +import org.python.antlr.PythonTree; +import org.python.core.PyClass; +import org.python.core.PyCode; + +/** + * 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. + * + * An instance of this class gets passed to the various components of the compiler subsystem and act + * as a Mediator object in between the components of the compiler subsystem. + * + * + * Currently a lot of code that should reside here resides in {@link org.python.core.Py}: + * + * All code should not be table code, this should be determined by the current compiler strategy: + * {@link org.python.core.Py#newCode(int, String[], String, String, boolean, boolean, + * org.python.core.PyFunctionTable, int, String[], String[], int, int)} + * {@link org.python.core.Py#newCode(int, String[], String, String, int, boolean, boolean, + * org.python.core.PyFunctionTable, int, String[], String[], int, int)} + * {@link org.python.core.Py#newCode(int, String[], String, String, boolean, boolean, + * org.python.core.PyFunctionTable, int)} + * {@link org.python.core.Py#newCode(int, String[], String, String, int, boolean, boolean, + * org.python.core.PyFunctionTable, int)} + * + * If we want to introduce classworking this is where to do it: + * {@link org.python.core.Py#newJavaCode(Class, String)} + * {@link org.python.core.Py#newJavaFunc(Class, String)} + * + * For classes that inherit from java-classes: + * {@link org.python.core.Py#initProxy(org.python.core.PyProxy, String, String, Object[])} + * + * For creating classes: + * {@link org.python.core.Py#makeClass(String, org.python.core.PyObject[], PyCode, org.python.core.PyObject)} + * {@link org.python.core.Py#makeClass(String, org.python.core.PyObject[], PyCode, org.python.core.PyObject, Class)} + * {@link org.python.core.Py#makeClass(String, org.python.core.PyObject[], PyCode, org.python.core.PyObject, org.python.core.PyObject[])} + * {@link org.python.core.Py#makeClass(String, org.python.core.PyObject[], PyCode, org.python.core.PyObject, Class, org.python.core.PyObject[])} + * + * {@link org.python.core.Py#getName()} + * {@link org.python.core.Py#getCompilerFlags()} + * {@link org.python.core.Py#getCompilerFlags(int, boolean)} + * + * Compiling code: + * {@link org.python.core.Py#compile(org.python.parser.ast.modType, String)} + * {@link org.python.core.Py#compile(java.io.InputStream, String, String)} + * {@link org.python.core.Py#compile(org.python.parser.ast.modType, String, String)} + * {@link org.python.core.Py#compile(org.python.parser.ast.modType, String, String, boolean, boolean)} + * + * {@link org.python.core.Py#compile_flags(java.io.InputStream, String, String, org.python.core.CompilerFlags)} + * {@link org.python.core.Py#compile_flags(String, String, String, org.python.core.CompilerFlags)} + * {@link org.python.core.Py#compile_flags(org.python.parser.ast.modType, String, String, boolean, boolean, org.python.core.CompilerFlags)} + * + * {@link org.python.core.Py#compile_command_flags(String, String, String, org.python.core.CompilerFlags, boolean)} + * + * Other things should be removed from {@link org.python.core.Py} as well, such as exception + * handling. But those things should not move here. + * + * @author Tobias Ivarsson + */ +public abstract class Compiler { + + private static Parser defaultParser; + + private static CodeCompiler defaultCodeCompiler; + + private static ClassCompiler defaultClassCompiler; + + public static void setDefaultParser(Parser parser) { + if (parser == null) { + throw new IllegalArgumentException("The default parser cannot be null."); + } + defaultParser = parser; + } + + public static void setDefaultCodeCompiler(CodeCompiler codeCompiler) { + if (codeCompiler == null) { + throw new IllegalArgumentException("The default code compiler cannot be null."); + } + defaultCodeCompiler = codeCompiler; + } + + public static void setDefaultClassCompiler(ClassCompiler classCompiler) { + if (classCompiler == null) { + throw new IllegalArgumentException("The default code compiler cannot be null."); + } + defaultClassCompiler = classCompiler; + } + + public static PyCode compileFromSource(String source, + String filename, + CompilationMode mode, + Set<CompilerFlag> flags) { + return defaultCompiler.compile(source, filename, mode, flags); + } + + public static PythonTree parseFromSource(String source, + CompilationMode mode, + Set<CompilerFlag> flags) { + return defaultCompiler.parse(source, mode, flags); + } + + public static PyCode compileFromSyntaxTree(PythonTree ast, + String filename, + Set<CompilerFlag> flags) { + return defaultCompiler.compile(ast, filename, flags); + } + + public static PyCode compileFromFile(File file, Set<CompilerFlag> flags) throws IOException { + return defaultCompiler.compile(file, flags); + } + + public static PythonTree parseFromFile(File file, Set<CompilerFlag> flags) throws IOException { + return defaultCompiler.parse(file, flags); + } + + public static PyClass makeClass(/* TODO: Decide signature for this method. */) { + return defaultCompiler.buildClass(); + } + + private Compiler currentCapture; + + abstract Parser getParser(); + + abstract CodeCompiler getCodeCompiler(); + + abstract ClassCompiler getClassCompiler(); + + public static Compiler captureCompiler() { + return defaultCompiler.capture(); + } + + public static Compiler captureCompiler(Parser parser) { + return defaultCompiler.capture(parser); + } + + public static Compiler captureCompiler(CodeCompiler codeCompiler) { + return defaultCompiler.capture(codeCompiler); + } + + public static Compiler captureCompiler(ClassCompiler classCompiler) { + return defaultCompiler.capture(classCompiler); + } + + public static Compiler captureCompiler(Parser parser, + CodeCompiler codeCompiler, + ClassCompiler classCompiler) { + return defaultCompiler.capture(parser, codeCompiler, classCompiler); + } + + public Compiler capture() { + return capture(null, null, null); + } + + public Compiler capture(Parser parser) { + return capture(parser, null, null); + } + + public Compiler capture(CodeCompiler codeCompiler) { + return capture(null, codeCompiler, null); + } + + public Compiler capture(ClassCompiler classCompiler) { + return capture(null, null, classCompiler); + } + + public Compiler capture(final Parser newParser, + final CodeCompiler newCodeCompiler, + final ClassCompiler newClassCompiler) { + final Compiler old = this; + return new Compiler() { + + private final Parser parser = (newParser != null) ? newParser : old.getParser(); + + private final CodeCompiler codeCompiler = (newCodeCompiler != null) ? newCodeCompiler + : old.getCodeCompiler(); + + private final ClassCompiler classCompiler = (newClassCompiler != null) ? newClassCompiler + : old.getClassCompiler(); + + @Override + ClassCompiler getClassCompiler() { + return classCompiler; + } + + @Override + CodeCompiler getCodeCompiler() { + return codeCompiler; + } + + @Override + Parser getParser() { + return parser; + } + }; + } + + private static final Compiler defaultCompiler = new Compiler() { + + @Override + ClassCompiler getClassCompiler() { + return defaultClassCompiler; + } + + @Override + CodeCompiler getCodeCompiler() { + return defaultCodeCompiler; + } + + @Override + Parser getParser() { + return defaultParser; + } + }; + + private Compiler() {} + + public PyCode compile(String source, + String filename, + CompilationMode mode, + Set<CompilerFlag> flags) { + // TODO Auto-generated method stub + return null; + } + + public PythonTree parse(String source, CompilationMode mode, Set<CompilerFlag> flags) { + // TODO Auto-generated method stub + return null; + } + + public PyCode compile(PythonTree ast, String filename, Set<CompilerFlag> flags) { + // TODO Auto-generated method stub + return null; + } + + public PyCode compile(File file, Set<CompilerFlag> flags) throws IOException { + // TODO Auto-generated method stub + return null; + } + + public PythonTree parse(File file, Set<CompilerFlag> flags) throws IOException { + // TODO Auto-generated method stub + return null; + } + + public PyClass buildClass() { + // TODO Auto-generated method stub + return null; + } +} Added: branches/advanced/compiler/org/python/compiler/iface/CompilerFlag.java =================================================================== --- branches/advanced/compiler/org/python/compiler/iface/CompilerFlag.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/iface/CompilerFlag.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,5 @@ +package org.python.compiler.iface; + + +public enum CompilerFlag { +} Added: branches/advanced/compiler/org/python/compiler/iface/Parser.java =================================================================== --- branches/advanced/compiler/org/python/compiler/iface/Parser.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/iface/Parser.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,4 @@ +package org.python.compiler.iface; + + +public interface Parser {} Modified: branches/advanced/compiler/org/python/newcompiler/AbstractEnvironment.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/AbstractEnvironment.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/AbstractEnvironment.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -11,7 +11,7 @@ import org.python.bytecode.VariableContext; import org.python.newcompiler.EnvironmentError.EnvironmentProblem; -abstract class AbstractEnvironment implements Environment, EnvironmentInfo, CodeInfo { +abstract class AbstractEnvironment implements Environment, EnvironmentInfo, CodeInfo, ScopeInfo { final Environment parent; @@ -45,8 +45,14 @@ private List<EnvironmentProblem> trouble = new LinkedList<EnvironmentProblem>(); - AbstractEnvironment(Environment parent) { + /** + * The policy that decides how + */ + protected CompilerPolicy policy; + + AbstractEnvironment(Environment parent, CompilerPolicy policy) { this.parent = parent; + this.policy = policy; if (parent != null) { flags = parent.getCompilerFlags(); } @@ -55,6 +61,10 @@ public void markHasExec() { flags.add(CompilerFlag.HAVE_EXEC); } + + public void markForStarImport() { + flags.add(CompilerFlag.IMPORT_STAR); + } public GlobalEnvironment getGlobalEnvironment() { return parent.getGlobalEnvironment(); @@ -108,6 +118,10 @@ public void addFuture(String feature) throws Exception { error(EnvironmentError.FUTURE_OUT_OF_CONTEXT); } + + public void done() { + // TODO: implement this + } /** * Mark that there is an error in the @@ -133,8 +147,8 @@ return Collections.unmodifiableSet(flags); } + // CodeInfo public int getArgumentCount() { - // TODO: implement this return 0; } @@ -157,4 +171,29 @@ // TODO: implement this return null; } + + public Iterable<String> getArgumentNames() { + // TODO: implement this + return null; + } + + public ScopeInfo getScopeInfo() { + return this; + } + + // ScopeInfo + public Iterable<String> getVariableNames() { + // TODO: implement this + return null; + } + + public Iterable<String> getFreeVariableNames() { + // TODO: implement this + return null; + } + + public Iterable<String> getCellVariableNames() { + // TODO: implement this + return null; + } } Modified: branches/advanced/compiler/org/python/newcompiler/ClassEnvironment.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/ClassEnvironment.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/ClassEnvironment.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -2,8 +2,8 @@ public class ClassEnvironment extends AbstractEnvironment { - public ClassEnvironment(Environment parent) { - super(parent); + public ClassEnvironment(Environment parent, CompilerPolicy policy) { + super(parent, policy); } public void addParameter(String name) { Modified: branches/advanced/compiler/org/python/newcompiler/CodeInfo.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/CodeInfo.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/CodeInfo.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -3,6 +3,8 @@ public interface CodeInfo { int getArgumentCount(); + + Iterable<String> getArgumentNames(); int getLocalsCount(); @@ -11,4 +13,6 @@ String getFilename(); String getName(); + + ScopeInfo getScopeInfo(); } Modified: branches/advanced/compiler/org/python/newcompiler/CompilerFlag.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/CompilerFlag.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/CompilerFlag.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -61,7 +61,13 @@ /** * The code block uses names without qualified environment. */ - NAME_BASED_LOOKUP; + NAME_BASED_LOOKUP, + /** + * The code block has an occurrence of + * + * from [module] import * + */ + IMPORT_STAR; private Integer bitFlag; Added: branches/advanced/compiler/org/python/newcompiler/CompilerPolicy.java =================================================================== --- branches/advanced/compiler/org/python/newcompiler/CompilerPolicy.java (rev 0) +++ branches/advanced/compiler/org/python/newcompiler/CompilerPolicy.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,19 @@ +package org.python.newcompiler; + +import java.util.Set; + +public enum CompilerPolicy { + DEFAULT { + + @Override + public EnvironmentError verifyFlag(CompilerFlag flag) { + return null; + } + }; + + public Set<CompilerFlag> inheritFlags(Set<CompilerFlag> flags) { + return null; + } + + public abstract EnvironmentError verifyFlag(CompilerFlag flag); +} Modified: branches/advanced/compiler/org/python/newcompiler/Environment.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/Environment.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/Environment.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -21,8 +21,12 @@ void addParameter(String name); void addFuture(String feature) throws Exception; + + void done(); GlobalEnvironment getGlobalEnvironment(); Set<CompilerFlag> getCompilerFlags(); + + void markForStarImport(); } Modified: branches/advanced/compiler/org/python/newcompiler/EnvironmentError.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/EnvironmentError.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/EnvironmentError.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -1,5 +1,10 @@ package org.python.newcompiler; +/** + * TODO: Add code for failing and producing error messages, warnings and so on. + * + * @author Tobias Ivarsson + */ public enum EnvironmentError { PARAMETER_AS_GLOBAL, BOTH_NONLOCAL_AND_GLOBAL, PARAMETER_AS_NONLOCAL, ILLEGAL_GENERATOR, CANNOT_HAVE_PARAMETERS, DUPLICATE_PARAMETER_NAMES, FUTURE_OUT_OF_CONTEXT; @@ -9,8 +14,13 @@ public static class EnvironmentProblem { - public EnvironmentProblem(EnvironmentError environmentError, int lineNumber) { - // TODO Auto-generated constructor stub + private EnvironmentError error; + + private int lineNumber; + + public EnvironmentProblem(EnvironmentError error, int lineNumber) { + this.error = error; + this.lineNumber = lineNumber; } } } Modified: branches/advanced/compiler/org/python/newcompiler/FunctionEnvironment.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/FunctionEnvironment.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/FunctionEnvironment.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -21,8 +21,8 @@ private List<Label> resumeTable = new LinkedList<Label>(); - public FunctionEnvironment(Environment parent) { - super(parent); + public FunctionEnvironment(Environment parent, CompilerPolicy policy) { + super(parent, policy); } public void setVarArg(String name) { @@ -84,4 +84,9 @@ super.markAsNonlocal(name); } } + + @Override + public int getArgumentCount() { + return parameterCount; + } } Modified: branches/advanced/compiler/org/python/newcompiler/GlobalEnvironment.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/GlobalEnvironment.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/GlobalEnvironment.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -4,8 +4,8 @@ private boolean futureAllowed = true; - public GlobalEnvironment() { - super(null); + public GlobalEnvironment(CompilerPolicy policy) { + super(null, policy); } @Override Added: branches/advanced/compiler/org/python/newcompiler/ScopeInfo.java =================================================================== --- branches/advanced/compiler/org/python/newcompiler/ScopeInfo.java (rev 0) +++ branches/advanced/compiler/org/python/newcompiler/ScopeInfo.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,10 @@ +package org.python.newcompiler; + +public interface ScopeInfo { + + Iterable<String> getVariableNames(); + + Iterable<String> getFreeVariableNames(); + + Iterable<String> getCellVariableNames(); +} Modified: branches/advanced/compiler/org/python/newcompiler/ast/AstToBytecode.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/ast/AstToBytecode.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/ast/AstToBytecode.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -72,12 +72,6 @@ import org.python.bytecode.SliceMode; import org.python.bytecode.UnaryOperator; import org.python.bytecode.VariableContext; -import org.python.core.Py; -import org.python.core.PyInteger; -import org.python.core.PyLong; -import org.python.core.PyObject; -import org.python.core.PyString; -import org.python.core.PyUnicode; import org.python.newcompiler.BytecodeBundle; import org.python.newcompiler.CodeInfo; import org.python.newcompiler.CompilerFlag; @@ -87,6 +81,13 @@ import org.python.newcompiler.YieldPoint; import org.python.newcompiler.bytecode.BytecodeCompiler; import org.python.newcompiler.bytecode.PythonBytecodeCompilingBundle; +import org.python.core.Py; +import org.python.core.PyInteger; +import org.python.core.PyLong; +import org.python.core.PyObject; +import org.python.core.PyString; +import org.python.core.PyUnicode; +import org.python.newcompiler.CompilerPolicy; /** * An AST visitor that feeds a Bytecode visitor. @@ -202,9 +203,12 @@ private final String name; - public AstToBytecode(PythonBytecodeCompilingBundle bundle, String name) { + private final CompilerPolicy policy; + + public AstToBytecode(PythonBytecodeCompilingBundle bundle, CompilerPolicy policy, String name) { this.bundle = bundle; this.name = name; + this.policy = policy; } private String signature() { @@ -226,7 +230,7 @@ private int lastLineNumber = -1; private void buildContext(modType node) throws Exception { - context = node.accept(new ContextBuilder()); + context = node.accept(new ContextBuilder(policy)); } private void sendResumeTable() { Modified: branches/advanced/compiler/org/python/newcompiler/ast/ContextBuilder.java =================================================================== --- trunk/sandbox/pyasm/compiler/org/python/newcompiler/ast/ContextBuilder.java 2008-06-19 08:32:01 UTC (rev 4673) +++ branches/advanced/compiler/org/python/newcompiler/ast/ContextBuilder.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -33,20 +33,29 @@ import org.python.newcompiler.Future; import org.python.newcompiler.GlobalEnvironment; import org.python.newcompiler.YieldPoint; +import org.python.newcompiler.CompilerPolicy; import org.python.parser.ParseException; public class ContextBuilder extends VisitorBase<EnvironmentHolder> implements EnvironmentHolder { - private final Environment globalEnvironment = new GlobalEnvironment(); + private final Environment globalEnvironment; - private Environment currentEnvironment = globalEnvironment; + private final CompilerPolicy policy; + private Environment currentEnvironment; + private Map<PythonTree, EnvironmentInfo> environmentMap = new HashMap<PythonTree, EnvironmentInfo>(); private LinkedHashMap<exprType, YieldPoint> resumeTable = new LinkedHashMap<exprType, YieldPoint>(); private int resumePoint = 0; + public ContextBuilder(CompilerPolicy policy) { + this.policy = policy; + globalEnvironment = new GlobalEnvironment(policy); + currentEnvironment = globalEnvironment; + } + public EnvironmentInfo getEnvironment(PythonTree tree) { return environmentMap.get(tree); } @@ -72,7 +81,7 @@ } // Class body - in new environment Environment last = currentEnvironment; - ClassEnvironment classEnvironment = new ClassEnvironment(currentEnvironment); + ClassEnvironment classEnvironment = new ClassEnvironment(currentEnvironment, policy); environmentMap.put(node, classEnvironment); currentEnvironment = classEnvironment; try { @@ -80,6 +89,7 @@ stmt.accept(this); } } finally { + currentEnvironment.done(); currentEnvironment = last; } return unhandled_node(node); @@ -102,7 +112,8 @@ } // In Function scope Environment last = currentEnvironment; - FunctionEnvironment functionEnvironment = new FunctionEnvironment(currentEnvironment); + FunctionEnvironment functionEnvironment = new FunctionEnvironment(currentEnvironment, + policy); environmentMap.put(node, functionEnvironment); currentEnvironment = functionEnvironment; try { @@ -125,6 +136,7 @@ stmt.accept(this); } } finally { + currentEnvironment.done(); currentEnvironment = last; } return unhandled_node(node); @@ -139,7 +151,8 @@ } // In Lambda scope Environment last = currentEnvironment; - FunctionEnvironment functionEnvironment = new FunctionEnvironment(currentEnvironment); + FunctionEnvironment functionEnvironment = new FunctionEnvironment(currentEnvironment, + policy); environmentMap.put(node, functionEnvironment); currentEnvironment = functionEnvironment; try { @@ -160,6 +173,7 @@ // Lambda body node.body.accept(this); } finally { + currentEnvironment.done(); currentEnvironment = last; } return unhandled_node(node); @@ -170,7 +184,8 @@ comp.iter.accept(this); } Environment last = currentEnvironment; - FunctionEnvironment functionEnvironment = new FunctionEnvironment(currentEnvironment); + FunctionEnvironment functionEnvironment = new FunctionEnvironment(currentEnvironment, + policy); environmentMap.put(node, functionEnvironment); currentEnvironment = functionEnvironment; addYieldPoint(node); @@ -186,6 +201,7 @@ } node.elt.accept(this); } finally { + currentEnvironment.done(); currentEnvironment = last; } return unhandled_node(node); @@ -255,7 +271,7 @@ currentEnvironment.addAssignment(name); } } else { - // Import star :( + currentEnvironment.markForStarImport(); } return unhandled_node(node); } Added: branches/advanced/continuations/org/python/continuations/Continuation.java =================================================================== --- branches/advanced/continuations/org/python/continuations/Continuation.java (rev 0) +++ branches/advanced/continuations/org/python/continuations/Continuation.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,39 @@ +package org.python.continuations; + +public abstract class Continuation { + + private Continuation() { + } + + private static class Break extends Throwable { + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + } + + private static final Break stop = new Break(); + + public static Object dispatch(Continuation current) { + while (true) { + try { + current = current.succeed(); + } catch (Break stop) { + return current.value; + } catch (Throwable tr) { + current = current.fail(tr); + } + } + } + + private Object value; + + private Continuation fail(Throwable tr) { + return null; + } + + private Continuation succeed() throws Throwable { + return null; + } +} Added: branches/advanced/interpreter/org/python/interpreter/BytecodeInterpreter.java =================================================================== --- branches/advanced/interpreter/org/python/interpreter/BytecodeInterpreter.java (rev 0) +++ branches/advanced/interpreter/org/python/interpreter/BytecodeInterpreter.java 2008-06-19 09:17:37 UTC (rev 4674) @@ -0,0 +1,104 @@ +package org.python.interpreter; + +import org.python.bytecode.BytecodeVersion; +import org.python.bytecode.Instruction; +import org.python.bytecode.RawBytecodeVisitor; +import org.python.bytecode.VariableContext; + + +public class BytecodeInterpreter implements RawBytecodeVisitor { + + private final BytecodeVersion version; + + public BytecodeInterpreter(BytecodeVersion version) { + this.version = version; + } + + public void visitAbsouteJump(int addr) { + // TODO Auto-generated method stub + } + + public void visitContinue(int addr) { + // TODO Auto-generated method stub + } + + public void visitDelete(VariableContext context, int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitDeleteAttribute(int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitForIteration(int delta) { + // TODO Auto-generated method stub + } + + public void visitImportFrom(int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitImportName(int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitInstruction(Instruction instruction) { + // TODO Auto-generated method stub + } + + public void visitJumpIfFalse(int delta) { + // TODO Auto-generated method stub + } + + public void visitJumpIfTrue(int delta) { + // TODO Auto-generated method stub + } + + public void visitLoad(VariableContext context, int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitLoadAttribute(int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitLoadClosure(int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitLoadConstant(int constIndex) { + // TODO Auto-generated method stub + } + + public void visitRelativeJump(int delta) { + // TODO Auto-generated method stub + } + + public void visitSetupExcept(int delta) { + // TODO Auto-generated method stub + } + + public void visitSetupFinally(int delta) { + // TODO Auto-generated method stub + } + + public void visitSetupLoop(int delta) { + // TODO Auto-generated method stub + } + + public void visitStop(Instruction stop) { + // TODO Auto-generated method stub + } + + public void visitStore(VariableContext context, int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitStoreAttribute(int nameIndex) { + // TODO Auto-generated method stub + } + + public void visitYield() { + // TODO Auto-generated method stub + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <th...@us...> - 2008-07-14 11:27:26
|
Revision: 4920 http://jython.svn.sourceforge.net/jython/?rev=4920&view=rev Author: thobes Date: 2008-07-14 04:27:24 -0700 (Mon, 14 Jul 2008) Log Message: ----------- Intermediate commit of the advanced compiler, contains a bunch of stuff: * Restructured the imported stuff from the newcompiler and pyasm work. * Changed CompilerFlags and Future imports to use enums. * Started work with pluggable compiler subsystems by moving functionlity from org.python.core.Py to facade classes with smaller areas of responsibility. This has been done for methods for creating code objects and for compiling, this should also be done for the createion of classes and adaptors. * Moved the responsibility for checking for the PyCF_ONLY_AST to the compile builtin function, this enables more static typing in the internals and moves the resposibilities to where it should be. * Removed all dependancies upon a specific implementation of PyCode (PyTableCode), if we want to be able to do interesting compilation optimizations we have to allow for different code implementations. * Changed the contract for how code objects are loaded to a more indirect aproach where the implementation is in charge of loading itself, this is also for better supporting different implementations of code. * Started an outline of code for iterating over a PyObject in java. {@see org.python.core.Py#iter(PyObject)}, this is just something I thought could be nice for projects integrating Jython, it's probalby broken at the moment... Modified Paths: -------------- branches/advanced/.classpath branches/advanced/compiler/org/python/bytecode/ReferenceResolver.java branches/advanced/compiler/org/python/compiler/advanced/ast/AstToBytecode.java branches/advanced/compiler/org/python/javaagent/InstrumentationProxy.java branches/advanced/src/org/python/Version.java branches/advanced/src/org/python/compiler/ClassConstants.java branches/advanced/src/org/python/compiler/CodeCompiler.java branches/advanced/src/org/python/compiler/Future.java branches/advanced/src/org/python/compiler/Module.java branches/advanced/src/org/python/core/BytecodeLoader.java branches/advanced/src/org/python/core/Py.java branches/advanced/src/org/python/core/PyCode.java branches/advanced/src/org/python/core/PyFrame.java branches/advanced/src/org/python/core/PyFunction.java branches/advanced/src/org/python/core/PyRunnable.java branches/advanced/src/org/python/core/PyTableCode.java branches/advanced/src/org/python/core/__builtin__.java branches/advanced/src/org/python/core/imp.java branches/advanced/src/org/python/util/InteractiveInterpreter.java branches/advanced/src/org/python/util/PythonInterpreter.java branches/advanced/src/org/python/util/jython.java Added Paths: ----------- branches/advanced/compiler/org/python/code/ branches/advanced/compiler/org/python/code/CodeTable.java branches/advanced/compiler/org/python/code/SpecializedCode.java branches/advanced/compiler/org/python/compiler/bytecode/ branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java branches/advanced/compiler/org/python/hash/ branches/advanced/compiler/org/python/hash/CzechHavasMajewski.java branches/advanced/compiler/org/python/hash/PerfectHash.java branches/advanced/compiler/org/python/hash/Simple.java branches/advanced/compiler/org/python/hash/Single.java branches/advanced/src/org/python/core/ClassFacade.java branches/advanced/src/org/python/core/CodeBootstrap.java branches/advanced/src/org/python/core/CodeFacade.java branches/advanced/src/org/python/core/CodeLoader.java branches/advanced/src/org/python/core/CompilerFacade.java branches/advanced/src/org/python/core/CompilerFlags.java branches/advanced/src/org/python/core/FutureFeature.java branches/advanced/src/org/python/core/ProxyFacade.java branches/advanced/src/org/python/core/PyRunnableBootstrap.java branches/advanced/src/org/python/core/PythonCompiler.java Removed Paths: ------------- branches/advanced/compiler/org/python/compiler/advanced/bytecode/ branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java branches/advanced/src/org/python/core/CompilerFlags.java Modified: branches/advanced/.classpath =================================================================== --- branches/advanced/.classpath 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/.classpath 2008-07-14 11:27:24 UTC (rev 4920) @@ -9,7 +9,7 @@ <classpathentry kind="src" path="compiler"/> <classpathentry kind="src" path="continuations"/> <classpathentry kind="src" path="interpreter"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.launching.macosx.MacOSXType/JVM 1.5"/> <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/> <classpathentry kind="lib" path="extlibs/jline-0.9.94.jar"/> <classpathentry kind="lib" path="extlibs/junit-3.8.2.jar"/> Modified: branches/advanced/compiler/org/python/bytecode/ReferenceResolver.java =================================================================== --- branches/advanced/compiler/org/python/bytecode/ReferenceResolver.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/compiler/org/python/bytecode/ReferenceResolver.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -10,7 +10,7 @@ import org.python.core.PyObject; import org.python.compiler.advanced.YieldPoint; -import org.python.compiler.advanced.bytecode.BytecodeCompiler; +import org.python.compiler.bytecode.BytecodeCompiler; /** * Added: branches/advanced/compiler/org/python/code/CodeTable.java =================================================================== --- branches/advanced/compiler/org/python/code/CodeTable.java (rev 0) +++ branches/advanced/compiler/org/python/code/CodeTable.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,62 @@ +package org.python.code; + +import org.python.core.PyCode; +import org.python.core.PyFrame; +import org.python.core.PyObject; + +public abstract class CodeTable extends PyCode { + + private final int index; + + protected CodeTable(int tableIndex) { + this.index = tableIndex; + } + + @Override + public PyObject call(PyFrame frame, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject[] args, String[] keywords, PyObject globals, + PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject self, PyObject[] args, String[] keywords, + PyObject globals, PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject globals, PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject arg1, PyObject globals, PyObject[] defaults, + PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject arg1, PyObject arg2, PyObject globals, + PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject arg1, PyObject arg2, PyObject arg3, + PyObject globals, PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + +} Added: branches/advanced/compiler/org/python/code/SpecializedCode.java =================================================================== --- branches/advanced/compiler/org/python/code/SpecializedCode.java (rev 0) +++ branches/advanced/compiler/org/python/code/SpecializedCode.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,56 @@ +package org.python.code; + +import org.python.core.PyCode; +import org.python.core.PyFrame; +import org.python.core.PyObject; + +public abstract class SpecializedCode extends PyCode { + + @Override + public PyObject call(PyFrame frame, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject[] args, String[] keywords, PyObject globals, + PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject self, PyObject[] args, String[] keywords, + PyObject globals, PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject globals, PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject arg1, PyObject globals, PyObject[] defaults, + PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject arg1, PyObject arg2, PyObject globals, + PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + + @Override + public PyObject call(PyObject arg1, PyObject arg2, PyObject arg3, + PyObject globals, PyObject[] defaults, PyObject closure) { + // TODO Auto-generated method stub + return null; + } + +} Modified: branches/advanced/compiler/org/python/compiler/advanced/ast/AstToBytecode.java =================================================================== --- branches/advanced/compiler/org/python/compiler/advanced/ast/AstToBytecode.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/compiler/org/python/compiler/advanced/ast/AstToBytecode.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -79,8 +79,6 @@ import org.python.compiler.advanced.EnvironmentHolder; import org.python.compiler.advanced.EnvironmentInfo; import org.python.compiler.advanced.YieldPoint; -import org.python.compiler.advanced.bytecode.BytecodeCompiler; -import org.python.compiler.advanced.bytecode.PythonBytecodeCompilingBundle; import org.python.core.Py; import org.python.core.PyInteger; import org.python.core.PyLong; @@ -88,6 +86,8 @@ import org.python.core.PyString; import org.python.core.PyUnicode; import org.python.compiler.advanced.CompilerPolicy; +import org.python.compiler.bytecode.BytecodeCompiler; +import org.python.compiler.bytecode.PythonBytecodeCompilingBundle; /** * An AST visitor that feeds a Bytecode visitor. Copied: branches/advanced/compiler/org/python/compiler/bytecode (from rev 4887, branches/advanced/compiler/org/python/compiler/advanced/bytecode) Deleted: branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java =================================================================== --- branches/advanced/compiler/org/python/compiler/advanced/bytecode/BytecodeCompiler.java 2008-07-11 11:52:55 UTC (rev 4887) +++ branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -1,32 +0,0 @@ -package org.python.compiler.advanced.bytecode; - -import java.util.Set; - -import org.python.bytecode.BytecodeVisitor; -import org.python.bytecode.Label; -import org.python.compiler.advanced.CompilerFlag; -import org.python.compiler.advanced.CompilerVariable; - -public interface BytecodeCompiler extends BytecodeVisitor { - - void visitResumeTable(Label start, Iterable<Label> entryPoints); - - BytecodeCompiler constructFunction(Iterable<String> closureNames, - int numDefault, - Set<CompilerFlag> flags); - - BytecodeCompiler constructFunction(Iterable<String> closureNames, - int numDefault, - Set<CompilerFlag> flags, - String name); - - BytecodeCompiler constructClass(String name, - Iterable<String> closureNames, - Set<CompilerFlag> flags); - - CompilerVariable storeContextManagerExit(); - - CompilerVariable enterContextManager(); - - void loadVariable(CompilerVariable contextVariable); -} Copied: branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java (from rev 4916, branches/advanced/compiler/org/python/compiler/advanced/bytecode/BytecodeCompiler.java) =================================================================== --- branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/bytecode/BytecodeCompiler.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,32 @@ +package org.python.compiler.bytecode; + +import java.util.Set; + +import org.python.bytecode.BytecodeVisitor; +import org.python.bytecode.Label; +import org.python.compiler.advanced.CompilerFlag; +import org.python.compiler.advanced.CompilerVariable; + +public interface BytecodeCompiler extends BytecodeVisitor { + + void visitResumeTable(Label start, Iterable<Label> entryPoints); + + BytecodeCompiler constructFunction(Iterable<String> closureNames, + int numDefault, + Set<CompilerFlag> flags); + + BytecodeCompiler constructFunction(Iterable<String> closureNames, + int numDefault, + Set<CompilerFlag> flags, + String name); + + BytecodeCompiler constructClass(String name, + Iterable<String> closureNames, + Set<CompilerFlag> flags); + + CompilerVariable storeContextManagerExit(); + + CompilerVariable enterContextManager(); + + void loadVariable(CompilerVariable contextVariable); +} Deleted: branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java =================================================================== --- branches/advanced/compiler/org/python/compiler/advanced/bytecode/PythonBytecodeCompilingBundle.java 2008-07-11 11:52:55 UTC (rev 4887) +++ branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -1,15 +0,0 @@ -package org.python.compiler.advanced.bytecode; - -import java.util.Set; - -import org.python.compiler.advanced.BytecodeBundle; -import org.python.compiler.advanced.CodeInfo; -import org.python.compiler.advanced.CompilerFlag; - -public interface PythonBytecodeCompilingBundle extends BytecodeBundle { - - BytecodeCompiler compile(String signature, - CodeInfo info, - Set<CompilerFlag> flags, - boolean storeable); -} Copied: branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java (from rev 4916, branches/advanced/compiler/org/python/compiler/advanced/bytecode/PythonBytecodeCompilingBundle.java) =================================================================== --- branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java (rev 0) +++ branches/advanced/compiler/org/python/compiler/bytecode/PythonBytecodeCompilingBundle.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,15 @@ +package org.python.compiler.bytecode; + +import java.util.Set; + +import org.python.compiler.advanced.BytecodeBundle; +import org.python.compiler.advanced.CodeInfo; +import org.python.compiler.advanced.CompilerFlag; + +public interface PythonBytecodeCompilingBundle extends BytecodeBundle { + + BytecodeCompiler compile(String signature, + CodeInfo info, + Set<CompilerFlag> flags, + boolean storeable); +} Added: branches/advanced/compiler/org/python/hash/CzechHavasMajewski.java =================================================================== --- branches/advanced/compiler/org/python/hash/CzechHavasMajewski.java (rev 0) +++ branches/advanced/compiler/org/python/hash/CzechHavasMajewski.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,94 @@ +package org.python.hash; + +import java.util.Arrays; +import java.util.Random; + +/** + * An implementation of the minimal perfect hash generation algorithm described + * in "An optimal algorithm for generating minimal perfect hash functions", + * Zbigniew J. Czech, George Havas, Bohdan S. Majewski, Information Processing + * Letters, 43(5):257\xD0264, October 1992. + * + * @author Tobias Ivarsson + */ +public class CzechHavasMajewski extends PerfectHash { + private final int[] table; + private final String prefix1; + private final String prefix2; + + /** + * Instantiate a new CzechHavasMajewski minimal perfect hash. Verifies the + * hash to assert the it really is perfect. + * + * @param keys the set of keys used in this hash. + * @param table the lookup table for making the hash perfect. + * @param prefix1 the prefix for the first hash sub function. + * @param prefix2 the prefix for the second hash sub function. + */ + public CzechHavasMajewski(String[] keys, int[] table, String prefix1, + String prefix2) { + super(keys); + if (table == null) { + throw new IllegalArgumentException(""); + } + this.table = table; + this.prefix1 = prefix1; + this.prefix2 = prefix2; + verify(); + } + + @Override + int compute(String key) { + return (table[compute(prefix1, key, table.length)] + table[compute( + prefix2, key, table.length)]) + % table.length; + } + + private static int compute(String prefix, String key, int N) { + return mod((prefix + key).hashCode(), N); + } + + @Override + public String getFunctionRepresentation() { + String tableDef = "table=" + Arrays.toString(table); + String function = "(table[hash(\"" + prefix1 + + "\" + key)] + table[hash(\"" + prefix2 + "\" + key)]) % " + + table.length; + return tableDef + "; " + function; + } + + static class RandomHash { + private static final Random random = new Random(); + private static final char[] chars = ("ABCDEFGHIJKLMNOPQRSTWXYZ" + + "abcdefghijklmnopqrstuvwxyz" + "1234567890").toCharArray(); + private final int N; + private final String prefix1; + private final String prefix2; + + RandomHash(int N) { + this.N = N; + this.prefix1 = randomString(10); + this.prefix2 = randomString(10); + } + + boolean computeConnection(String key, Graph graph, int value) { + int hash1 = CzechHavasMajewski.compute(prefix1, key, N); + int hash2 = CzechHavasMajewski.compute(prefix2, key, N); + return graph.connect(hash1, hash2, value); + } + + PerfectHash makePerfectHash(String[] keys, Graph graph) { + return new CzechHavasMajewski(keys, graph.values(), prefix1, + prefix2); + } + + private static String randomString(int size) { + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < size; i++) { + builder.append(chars[random.nextInt(chars.length)]); + } + return builder.toString(); + } + } + +} Added: branches/advanced/compiler/org/python/hash/PerfectHash.java =================================================================== --- branches/advanced/compiler/org/python/hash/PerfectHash.java (rev 0) +++ branches/advanced/compiler/org/python/hash/PerfectHash.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,303 @@ +package org.python.hash; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import org.python.hash.CzechHavasMajewski.RandomHash; + +/** + * Base class for the perfect hash function implementations in this package. + * + * Also contains a factory method for computing the the most appropriate + * implementation of the hash functions in this package. + * + * @author Tobias Ivarsson + */ +public abstract class PerfectHash { + + /** + * Compute the hash code for a given key from the key set. + * + * @param key the key to generate the hash code for. + * @return the hash code for the given key in this perfect hash. + * @throws IllegalArgumentException if the given key is not in the key set + * for the perfect hash. + */ + public int hashCode(String key) { + int hashCode = compute(key); + if (keys[hashCode].equals(key)) { + return hashCode; + } else { + throw new IllegalArgumentException("No such key!"); + } + } + + /** + * Compute the hash code for a given key. If the key is not in the key set, + * return a fallback value + * + * @param key the key to compute the hash code for. + * @param fallback the fallback value. + * @return the hash code for the given key in this perfect hash, or the + * fallback value if the given key is not in the key set of this + * perfect hash. + */ + public int hashCodeWithFallback(String key, int fallback) { + int hashCode = compute(key); + if (keys[hashCode].equals(key)) { + return hashCode; + } else { + return fallback; + } + } + + /** + * Generate a perfect hash function for a given set of keys. + * + * @param keys the keys to generate the perfect hash function for. + * @return the perfect hash function for the given key set. + */ + public static PerfectHash generatePerfectHash(String... keys) { + if (keys == null || keys.length == 0) { + throw new IllegalArgumentException(""); + } + PerfectHash hash; + if (keys.length == 1) { + return new Single(keys[0]); + } + hash = generateSimple(keys); + if (hash != null) { + return hash; + } + hash = generateCzechHavasMajewski(keys); + if (hash != null) { + return hash; + } + throw new IllegalArgumentException( + "failed to compute a perfect hash for the given keys."); + } + + PerfectHash(String[] keys) { + if (keys == null || keys.length == 0) { + throw new IllegalArgumentException( + "No keys specified for the hash function."); + } + this.keys = keys; + } + + private final String[] keys; + + abstract int compute(String key); + + void verify() { + for (String key : keys) { + if (hashCodeWithFallback(key, -1) == -1) { + throw new IllegalArgumentException( + "The specified arguments does not define a perfect hash."); + } + } + } + + private static PerfectHash generateSimple(String[] keys) { + int[] table = new int[keys.length]; + Arrays.fill(table, -1); + for (int i = 0; i < keys.length; i++) { + String key = keys[i]; + int hash = mod(key.hashCode(), table.length); + if (table[hash] != -1) { + return null; + } + table[hash] = i; + } + return new Simple(keys, table); + } + + private static PerfectHash generateCzechHavasMajewski(String[] keys) { + double c = 1.1; + int times = 0; + while (true) { + int N = (int) (keys.length * c); + times += 1; + if ((times % 5) == 0) { + c += 0.1; + } + if (times == 10000) { + return null; + } + RandomHash hash = new RandomHash(N); + Graph G = new Graph(N); + boolean ok = true; + for (int i = 0; ok && (i < keys.length); i++) { + ok &= hash.computeConnection(keys[i], G, i); + } + if (ok & G.isAcyclic()) { + return hash.makePerfectHash(keys, G); + } + } + } + + private static class Edge { + final int start; + final int end; + private final int hash; + + Edge(int start, int end, int N) { + if (end < start) { + int temp = start; + start = end; + end = temp; + } + this.start = start; + this.end = end; + hash = end * N + start; + } + + Edge(int start, int end) { + this.start = start; + this.end = end; + this.hash = 0; + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object other) { + if (other instanceof Edge) { + Edge edge = (Edge) other; + return edge.start == start && edge.end == end; + } else { + return false; + } + } + } + + static class Graph { + private enum VertexState { + UNVISITED, VISITED + } + + private final Map<Edge, Integer> edgeValues = new HashMap<Edge, Integer>(); + private final Map<Integer, Set<Integer>> reachable = new HashMap<Integer, Set<Integer>>(); + private final int num_vertices; + + private Graph(int N) { + this.num_vertices = N; + } + + private Set<Integer> getReachable(int vertex) { + Set<Integer> result = reachable.get(vertex); + if (result == null) { + reachable.put(vertex, result = new HashSet<Integer>()); + } + return result; + } + + boolean connect(int first, int second, int value) { + edgeValues.put(new Edge(first, second, num_vertices), value); + return getReachable(first).add(second) + && getReachable(second).add(first); + } + + int[] values() { + return dfs(new ValueBuilder(num_vertices)).values; + } + + private boolean isAcyclic() { + return dfs(new CycleTest()).acyclic; + } + + private <T extends Searcher> T dfs(T action) { + VertexState[] state = new VertexState[num_vertices]; + Arrays.fill(state, VertexState.UNVISITED); + for (int i = 0; i < num_vertices; i++) { + if (state[i] == VertexState.UNVISITED) { + Stack<Edge> visitStack = new Stack<Edge>(); + visitStack.push(new Edge(-1, i)); + while (!visitStack.isEmpty()) { + Edge edge = visitStack.pop(); + state[edge.end] = VertexState.VISITED; // OR rather + // "VISITING" + for (int neighbour : getReachable(edge.end)) { + if (neighbour != edge.start) { + if (state[neighbour] == VertexState.UNVISITED) { + visitStack.push(new Edge(edge.end, + neighbour)); + action.apply(edge.end, neighbour, + edgeValues); + } else { + action.fail(); + return action; + } + } + } + state[edge.end] = VertexState.VISITED; + } + } + } + return action; + } + } + + private static abstract class Searcher { + abstract void fail(); + + void apply(int vertex, int neighbour, Map<Edge, Integer> edgeValues) { + } + } + + private static class CycleTest extends Searcher { + boolean acyclic = true; + + @Override + void fail() { + acyclic = false; + } + } + + private static class ValueBuilder extends Searcher { + int[] values; + + ValueBuilder(int N) { + values = new int[N]; + Arrays.fill(values, 0); + } + + @Override + void fail() { + values = null; + } + + @Override + void apply(int vertex, int neighbour, Map<Edge, Integer> edgeValues) { + int newValue = edgeValues.get(new Edge(vertex, neighbour, + values.length)) + - values[vertex]; + values[neighbour] = mod(newValue, values.length); + } + } + + @Override + public final String toString() { + return "PerfectHash{type=" + getClass().getSimpleName() + "; " + + getFunctionRepresentation() + "}"; + } + + abstract String getFunctionRepresentation(); + + static int mod(int value, int n) { + value %= n; + if (value < 0) { + return n + value; + } else { + return value; + } + } + +} Added: branches/advanced/compiler/org/python/hash/Simple.java =================================================================== --- branches/advanced/compiler/org/python/hash/Simple.java (rev 0) +++ branches/advanced/compiler/org/python/hash/Simple.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,42 @@ +package org.python.hash; + +import java.util.Arrays; + +/** + * A simple implementation of a minimal perfect hash, usable in the cases where + * the standard {@link String#hashCode()} yields a perfect hash for the set of + * keys. + * + * @author Tobias Ivarsson + */ +public class Simple extends PerfectHash { + + private final int[] table; + + /** + * Instantiate a new minimal perfect hash that uses + * {@link String#hashCode()}. Verifies the hash to assert the it really is + * perfect. + * + * @param keys the set of keys used in this hash. + * @param table the reordering table for the hash. + */ + public Simple(String[] keys, int[] table) { + super(keys); + this.table = table; + verify(); + } + + @Override + int compute(String key) { + return table[mod(key.hashCode(), table.length)]; + } + + @Override + String getFunctionRepresentation() { + String tableDef = "table=" + Arrays.toString(table); + String body = "table[hash(key) % table.length]"; + return tableDef + "; " + body; + } + +} Added: branches/advanced/compiler/org/python/hash/Single.java =================================================================== --- branches/advanced/compiler/org/python/hash/Single.java (rev 0) +++ branches/advanced/compiler/org/python/hash/Single.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,31 @@ +package org.python.hash; + +/** + * A simple implementation of a minimal perfect hash for the cases where the key + * set is minimal. + * + * @author Tobias Ivarsson + */ +public class Single extends PerfectHash { + + /** + * Instantiate a new single value minimal perfect hash. Verifies the hash to + * assert the it really is perfect. + * + * @param key the key used in this hash. + */ + public Single(String key) { + super(new String[] { key }); + } + + @Override + int compute(String key) { + return 0; + } + + @Override + String getFunctionRepresentation() { + return "0"; + } + +} \ No newline at end of file Modified: branches/advanced/compiler/org/python/javaagent/InstrumentationProxy.java =================================================================== --- branches/advanced/compiler/org/python/javaagent/InstrumentationProxy.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/compiler/org/python/javaagent/InstrumentationProxy.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -13,7 +13,6 @@ private static volatile InstrumentationProxy proxy; private final Instrumentation instrumentation; private static final Runnable attacher = new Runnable() { - @Override public void run() { // TODO: add means to attach an agent to this, already running, JVM } Modified: branches/advanced/src/org/python/Version.java =================================================================== --- branches/advanced/src/org/python/Version.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/Version.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -3,8 +3,14 @@ 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$"; @@ -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); + } } Modified: branches/advanced/src/org/python/compiler/ClassConstants.java =================================================================== --- branches/advanced/src/org/python/compiler/ClassConstants.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/compiler/ClassConstants.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -1,21 +1,34 @@ package org.python.compiler; +import org.python.core.PyCode; +import org.python.core.PyComplex; +import org.python.core.PyException; +import org.python.core.PyFloat; +import org.python.core.PyFrame; +import org.python.core.PyFunctionTable; +import org.python.core.PyInteger; +import org.python.core.PyLong; +import org.python.core.PyObject; +import org.python.core.PyProxy; +import org.python.core.PyString; +import org.python.core.PyUnicode; +import org.python.objectweb.asm.Type; + public interface ClassConstants { - final static String $pyObj = "Lorg/python/core/PyObject;"; - final static String $pyObjArr = "[Lorg/python/core/PyObject;"; - final static String $pyStr = "Lorg/python/core/PyString;"; - final static String $pyUnicode = "Lorg/python/core/PyUnicode;"; - final static String $pyExc = "Lorg/python/core/PyException;"; - final static String $pyFrame = "Lorg/python/core/PyFrame;"; - final static String $pyCode = "Lorg/python/core/PyCode;"; - final static String $pyInteger = "Lorg/python/core/PyInteger;"; - final static String $pyLong = "Lorg/python/core/PyLong;"; - final static String $pyFloat = "Lorg/python/core/PyFloat;"; - final static String $pyComplex = "Lorg/python/core/PyComplex;"; - final static String $pyRunnable = "Lorg/python/core/PyRunnable;"; - final static String $pyFuncTbl = "Lorg/python/core/PyFunctionTable;"; - final static String $pyProxy = "Lorg/python/core/PyProxy;"; + final static String $pyObj = Type.getDescriptor(PyObject.class); + final static String $pyObjArr = "[" + $pyObj; + final static String $pyStr = Type.getDescriptor(PyString.class); + final static String $pyUnicode = Type.getDescriptor(PyUnicode.class); + final static String $pyExc = Type.getDescriptor(PyException.class); + final static String $pyFrame = Type.getDescriptor(PyFrame.class); + final static String $pyCode = Type.getDescriptor(PyCode.class); + final static String $pyInteger = Type.getDescriptor(PyInteger.class); + final static String $pyLong = Type.getDescriptor(PyLong.class); + final static String $pyFloat = Type.getDescriptor(PyFloat.class); + final static String $pyComplex = Type.getDescriptor(PyComplex.class); + final static String $pyFuncTbl = Type.getDescriptor(PyFunctionTable.class); + final static String $pyProxy = Type.getDescriptor(PyProxy.class); final static String $obj = "Ljava/lang/Object;"; final static String $objArr = "[Ljava/lang/Object;"; Modified: branches/advanced/src/org/python/compiler/CodeCompiler.java =================================================================== --- branches/advanced/src/org/python/compiler/CodeCompiler.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/compiler/CodeCompiler.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -1308,7 +1308,7 @@ case FloorDiv: name = "_floordiv"; break; } - if (node.op == operatorType.Div && module.getFutures().areDivisionOn()) { + if (node.op == operatorType.Div && module.getFutures().isDivisionOn()) { name = "_truediv"; } code.invokevirtual("org/python/core/PyObject", name, "(" + $pyObj + ")" + $pyObj); @@ -1353,7 +1353,7 @@ case BitAnd: name = "_iand"; break; case FloorDiv: name = "_ifloordiv"; break; } - if (node.op == operatorType.Div && module.getFutures().areDivisionOn()) { + if (node.op == operatorType.Div && module.getFutures().isDivisionOn()) { name = "_itruediv"; } code.invokevirtual("org/python/core/PyObject", name, "(" + $pyObj + ")" + $pyObj); Modified: branches/advanced/src/org/python/compiler/Future.java =================================================================== --- branches/advanced/src/org/python/compiler/Future.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/compiler/Future.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -2,55 +2,28 @@ package org.python.compiler; +import java.util.EnumSet; +import java.util.Set; + import org.python.antlr.*; import org.python.antlr.ast.*; import org.python.antlr.ast.Module; +import org.python.core.CodeFlag; +import org.python.core.FutureFeature; public class Future { + + private final Set<FutureFeature> features = EnumSet.noneOf(FutureFeature.class); - private boolean division = false; - private boolean with_statement = false; - private boolean absolute_import = false; - - private static final String FUTURE = "__future__"; - private boolean check(ImportFrom cand) throws Exception { - if (!cand.module.equals(FUTURE)) + if (!cand.module.equals(FutureFeature.MODULE_NAME)) return false; - int n = cand.names.length; - if (n == 0) { + if (cand.names.length == 0) { throw new ParseException( "future statement does not support import *",cand); } - for (int i = 0; i < n; i++) { - String feature = cand.names[i].name; - // *known* features - if (feature.equals("nested_scopes")) { - continue; - } - 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"); - } - if (feature.equals("GIL") || feature.equals("global_interpreter_lock")) { - throw new ParseException("Never going to happen!"); - } - throw new ParseException("future feature "+feature+ - " is not defined",cand); + for (aliasType feature : cand.names) { + FutureFeature.addFeature(feature.name, features); } return true; } @@ -59,8 +32,8 @@ org.python.core.CompilerFlags cflags) throws Exception { - if (cflags != null) { - division = cflags.division; + if (cflags != null && cflags.isFlagSet(CodeFlag.CO_FUTURE_DIVISION)) { + FutureFeature.division.addTo(features); } int beg = 0; stmtType[] suite = null; @@ -86,33 +59,33 @@ } if (cflags != null) { - cflags.division = cflags.division || division; + for (FutureFeature feature : features) { + feature.setFlag(cflags); + } } - if (cflags != null) { - cflags.with_statement = cflags.with_statement || with_statement; - } - if (cflags != null) { - cflags.absolute_import = cflags.absolute_import || absolute_import; - } } public static void checkFromFuture(ImportFrom node) throws Exception { if (node.from_future_checked) return; - if (node.module.equals(FUTURE)) { + if (node.module.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; + public boolean isDivisionOn() { + return features.contains(FutureFeature.division); } public boolean withStatementSupported() { - return with_statement; + return features.contains(FutureFeature.with_statement); } + + public boolean useAbsoluteImport() { + return features.contains(FutureFeature.absolute_import); + } } Modified: branches/advanced/src/org/python/compiler/Module.java =================================================================== --- branches/advanced/src/org/python/compiler/Module.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/compiler/Module.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -10,9 +10,14 @@ import org.python.objectweb.asm.Label; import org.python.objectweb.asm.Opcodes; +import org.python.objectweb.asm.Type; +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.python.antlr.ParseException; import org.python.antlr.PythonTree; import org.python.antlr.ast.Suite; @@ -261,7 +266,7 @@ c.iconst(moreflags); - c.invokestatic("org/python/core/Py", "newCode", "(I" + $strArr + $str + $str + "IZZ" + $pyFuncTbl + "I" + $strArr + $strArr + "II)" + $pyCode); + c.invokestatic("org/python/core/CodeFacade", "newCode", "(I" + $strArr + $str + $str + "IZZ" + $pyFuncTbl + "I" + $strArr + $strArr + "II)" + $pyCode); c.putstatic(module.classfile.name, name, $pyCode); } } @@ -469,17 +474,17 @@ code.jy_npurecell = scope.jy_npurecell; if (compiler.optimizeGlobals) { - code.moreflags |= org.python.core.PyTableCode.CO_OPTIMIZED; + code.moreflags |= CodeFlag.CO_OPTIMIZED.flag; } if (compiler.my_scope.generator) { - code.moreflags |= org.python.core.PyTableCode.CO_GENERATOR; + code.moreflags |= 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 |= 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 |= CodeFlag.CO_FUTURE_DIVISION.flag; } } @@ -509,10 +514,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+";", @@ -567,6 +588,7 @@ addInit(); addRunnable(); addMain(); + addBootstrap(); addFunctions(); Modified: branches/advanced/src/org/python/core/BytecodeLoader.java =================================================================== --- branches/advanced/src/org/python/core/BytecodeLoader.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/core/BytecodeLoader.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -63,9 +63,12 @@ public static PyCode makeCode(String name, byte[] data, String filename) { try { Class<?> c = makeClass(name, data); + return CodeLoader.loadCode(c, name, filename); + /* Object o = c.getConstructor(new Class[] {String.class}) .newInstance(new Object[] {filename}); return ((PyRunnable)o).getMain(); + */ } catch (Exception e) { throw Py.JavaError(e); } Added: branches/advanced/src/org/python/core/ClassFacade.java =================================================================== --- branches/advanced/src/org/python/core/ClassFacade.java (rev 0) +++ branches/advanced/src/org/python/core/ClassFacade.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,12 @@ +package org.python.core; + +/** + * For classes that inherit from java-classes: + * {@link org.python.core.Py#initProxy(org.python.core.PyProxy, String, String, Object[])} + * + * For creating classes: {@link org.python.core.Py#makeClass} + * Linked to from: {@link org.python.compiler.CodeCompiler} + */ +public class ClassFacade { + +} Added: branches/advanced/src/org/python/core/CodeBootstrap.java =================================================================== --- branches/advanced/src/org/python/core/CodeBootstrap.java (rev 0) +++ branches/advanced/src/org/python/core/CodeBootstrap.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,7 @@ +package org.python.core; + +public interface CodeBootstrap { + + PyCode loadCode(CodeLoader loader); + +} Added: branches/advanced/src/org/python/core/CodeFacade.java =================================================================== --- branches/advanced/src/org/python/core/CodeFacade.java (rev 0) +++ branches/advanced/src/org/python/core/CodeFacade.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,50 @@ +package org.python.core; + + +public class CodeFacade { + public static PyCode newCode(int argcount, String varnames[], + String filename, String name, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id, + String[] cellvars, String[] freevars, + int npurecell, int moreflags) { + return new PyTableCode(argcount, varnames, + filename, name, 0, args, keywords, funcs, + func_id, cellvars, freevars, npurecell, + moreflags); + } + + public static PyCode newCode(int argcount, String varnames[], + String filename, String name, + int firstlineno, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id, + String[] cellvars, String[] freevars, + int npurecell, int moreflags) { + return new PyTableCode(argcount, varnames, + filename, name, firstlineno, args, keywords, + funcs, func_id, cellvars, freevars, npurecell, + moreflags); + } + + // -- + public static PyCode newCode(int argcount, String varnames[], + String filename, String name, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id) { + return new PyTableCode(argcount, varnames, + filename, name, 0, args, keywords, funcs, + func_id); + } + + public static PyCode newCode(int argcount, String varnames[], + String filename, String name, + int firstlineno, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id) { + return new PyTableCode(argcount, varnames, + filename, name, firstlineno, args, keywords, + funcs, func_id); + } + +} Added: branches/advanced/src/org/python/core/CodeLoader.java =================================================================== --- branches/advanced/src/org/python/core/CodeLoader.java (rev 0) +++ branches/advanced/src/org/python/core/CodeLoader.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,63 @@ +package org.python.core; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import org.python.compiler.ClassConstants; +import org.python.objectweb.asm.Type; + +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; + } + }; + } +} Added: branches/advanced/src/org/python/core/CompilerFacade.java =================================================================== --- branches/advanced/src/org/python/core/CompilerFacade.java (rev 0) +++ branches/advanced/src/org/python/core/CompilerFacade.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,91 @@ +package org.python.core; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.python.compiler.Module; +import org.python.core.util.StringUtil; +import org.python.antlr.ast.modType; + +/** + * 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 int nameindex = 0; + + static synchronized String newClassName() { + String name = "org.python.pycode._pyx" + nameindex; + nameindex += 1; + return name; + } + + private static PythonCompiler compiler; + + // w/o compiler-flags + + public static PyCode compile(InputStream istream, String filename, + String type) { + return compile_flags(istream, filename, type, null); + } + + // with compiler-flags + + static PyCode compile_flags(modType node, String name, + String filename, boolean linenumbers, boolean printResults, + CompilerFlags cflags) { + try { + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + Module.compile(node, ostream, name, filename, linenumbers, + printResults, false, cflags); + + Py.saveClassFile(name, ostream); + + return BytecodeLoader.makeCode(name, ostream.toByteArray(), + filename); + } catch (Throwable t) { + throw ParserFacade.fixParseError(null, t, filename); + } + } + + public static PyCode compile_flags(InputStream istream, String filename, + String type, CompilerFlags cflags) { + modType node = ParserFacade.parse(istream, type, filename, cflags); + boolean printResults = false; + if (type.equals("single")) printResults = true; + return compile_flags(node, newClassName(), filename, true, printResults, + cflags); + } + + public static PyCode compile_flags(String data, String filename, + String type, CompilerFlags cflags) { + return compile_flags(new ByteArrayInputStream(StringUtil.toBytes(data + + "\n\n")), filename, type, cflags); + } + + public static PyObject compile_command_flags(String string, + String filename, String kind, CompilerFlags cflags, + boolean stdprompt) { + modType node = ParserFacade.partialParse(string + "\n", kind, filename, + cflags, stdprompt); + + if (node == null) return Py.None; + return compile_flags(node, newClassName(), filename, true, true, cflags); + } + + public static void compile(modType node, OutputStream ostream, String name, + String filename, boolean linenumbers, boolean printResults, + boolean setFile, CompilerFlags cflags) throws Exception { + org.python.compiler.Module.compile(node, ostream, name, filename, + linenumbers, printResults, setFile, cflags); + } +} Deleted: branches/advanced/src/org/python/core/CompilerFlags.java =================================================================== --- branches/advanced/src/org/python/core/CompilerFlags.java 2008-07-14 11:03:54 UTC (rev 4919) +++ branches/advanced/src/org/python/core/CompilerFlags.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -1,44 +0,0 @@ - -package org.python.core; - -public class CompilerFlags { - - public boolean nested_scopes = true; - public boolean division; - public boolean generator_allowed = true; - public boolean only_ast = false; - public boolean with_statement = false; - public boolean absolute_import = false; - - public String encoding; - - public CompilerFlags(){} - - public CompilerFlags(int co_flags) { - if ((co_flags & org.python.core.PyTableCode.CO_NESTED) != 0) { - this.nested_scopes = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_FUTUREDIVISION) != 0) { - this.division = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_GENERATOR_ALLOWED) != 0) { - this.generator_allowed = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_FUTURE_ABSOLUTE_IMPORT) != 0) { - this.absolute_import = true; - } - if ((co_flags & org.python.core.PyTableCode.CO_WITH_STATEMENT) != 0) { - this.with_statement = true; - } - if ((co_flags & org.python.core.PyTableCode.PyCF_ONLY_AST) != 0) { - this.only_ast = true; - } - } - - public String toString() { - return String.format("CompilerFlags[division=%s nested_scopes=%s generators=%s " - + "with_statement=%s absolute_import=%s]", division, nested_scopes, generator_allowed, - with_statement, absolute_import); - } - -} Added: branches/advanced/src/org/python/core/CompilerFlags.java =================================================================== --- branches/advanced/src/org/python/core/CompilerFlags.java (rev 0) +++ branches/advanced/src/org/python/core/CompilerFlags.java 2008-07-14 11:27:24 UTC (rev 4920) @@ -0,0 +1,65 @@ +package org.python.core; + +import java.util.Set; + +import org.python.Version; + +public class CompilerFlags { + // XXX: I'm not positive that this is the right place for this constant. + public static final int PyCF_ONLY_AST = 0x0400; + @Deprecated + public boolean only_ast = false; + + public String encoding; + private final Set<CodeFlag> flags = Version.getDefaultCodeFlags(); + + public CompilerFlags() { + } + + public CompilerFlags(int co_flags) { + for (CodeFlag flag : CodeFlag.parse(co_flags)) { + setFlag(flag); + } + // This is deprecated + if ((co_flags & PyCF_ONLY_AST) != 0) { + this.only_ast = true; + } + } + + 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]", + isFlagSet(CodeFlag.CO_FUTURE_DIVISION), + isFlagSet(CodeFlag.CO_NESTED), + isFlagSet(CodeFlag.CO_GENERATOR_ALLOWED), + ... [truncated message content] |
From: <th...@us...> - 2008-07-14 13:03:23
|
Revision: 4926 http://jython.svn.sourceforge.net/jython/?rev=4926&view=rev Author: thobes Date: 2008-07-14 06:03:20 -0700 (Mon, 14 Jul 2008) Log Message: ----------- Manually merging changes from the asm-branch onto the advanced compiler branch. The reason for doing it manually is because I am so hard core... No, just kidding, it's because svnmerge.py doesn't work that well when one branch is a branch from another branch. Luckily the changes were not that hard. The advanced branch has the same test status as the asm branch. While comparing the regtest results I found a previously undiscovered bug, In org.python.core.PyFunction#setFuncCode the first check doesn't check to see if the passed in argument is null, it checks to see if the code object already in there is null, which is silly. The reason this worked before is that the instanceof test that was removed in the advanced branch guarantees that the object is not null. Modified Paths: -------------- branches/advanced/CPythonLib.includes branches/advanced/Lib/datetime.py branches/advanced/Lib/gzip.py branches/advanced/Lib/popen2.py branches/advanced/Lib/test/regrtest.py branches/advanced/Lib/test/string_tests.py branches/advanced/Lib/test/test_cpickle.py branches/advanced/Lib/test/test_enumerate.py branches/advanced/Lib/test/test_float_jy.py branches/advanced/Lib/test/test_format_jy.py branches/advanced/Lib/test/test_iter.py branches/advanced/Lib/test/test_jy_compile.py branches/advanced/Lib/test/test_largefile.py branches/advanced/Lib/test/test_mhlib.py branches/advanced/Lib/test/test_repr.py branches/advanced/Lib/test/test_richcmp.py branches/advanced/Lib/test/test_scope.py branches/advanced/Lib/test/test_time.py branches/advanced/Lib/test/test_types.py branches/advanced/Lib/test/test_zlib.py branches/advanced/Lib/threading.py branches/advanced/Lib/zlib.py branches/advanced/build.xml branches/advanced/grammar/Python.g branches/advanced/grammar/PythonPartial.g branches/advanced/src/com/ziclix/python/sql/zxJDBC.java branches/advanced/src/org/python/antlr/PythonPartialTokenSource.java branches/advanced/src/org/python/antlr/PythonTokenSource.java branches/advanced/src/org/python/compiler/CodeCompiler.java branches/advanced/src/org/python/core/Options.java branches/advanced/src/org/python/core/Py.java branches/advanced/src/org/python/core/PyCallIter.java branches/advanced/src/org/python/core/PyEnumerate.java branches/advanced/src/org/python/core/PyException.java branches/advanced/src/org/python/core/PyFile.java branches/advanced/src/org/python/core/PyFunction.java branches/advanced/src/org/python/core/PyIterator.java branches/advanced/src/org/python/core/PySequenceIter.java branches/advanced/src/org/python/core/PyString.java branches/advanced/src/org/python/core/PyUnicode.java branches/advanced/src/org/python/core/ThreadStateMapping.java branches/advanced/src/org/python/core/__builtin__.java branches/advanced/src/org/python/core/codecs.java branches/advanced/src/org/python/core/imp.java branches/advanced/src/org/python/modules/imp.java branches/advanced/src/org/python/modules/time/PyTimeTuple.java branches/advanced/src/org/python/modules/time/Time.java branches/advanced/src/templates/mappings branches/advanced/tests/shell/test-jython.sh Added Paths: ----------- branches/advanced/Lib/_rawffi.py branches/advanced/Lib/platform.py branches/advanced/Lib/test/junit_xml.py branches/advanced/Lib/test/test__rawffi.py branches/advanced/Lib/test/test_cmath_jy.py branches/advanced/Lib/test/test_complex_jy.py branches/advanced/Lib/test/test_str.py branches/advanced/Lib/test/test_support.py branches/advanced/Lib/uu.py branches/advanced/extlibs/svnant-jars/ branches/advanced/extlibs/svnant-jars/svnClientAdapter.jar branches/advanced/extlibs/svnant-jars/svnant.jar branches/advanced/extlibs/svnant-jars/svnjavahl.jar branches/advanced/src/org/python/core/PyEnumerateDerived.java branches/advanced/src/templates/enumerate.derived branches/advanced/tests/c/ branches/advanced/tests/c/ctypes_test.c Removed Paths: ------------- branches/advanced/Lib/test/output/test_operations branches/advanced/Lib/test/output/test_types branches/advanced/Lib/test/test_complex.py branches/advanced/Lib/test/test_datetime.py branches/advanced/Lib/test/test_long.py branches/advanced/Lib/test/test_operations.py branches/advanced/extlibs/svnant-jars/svnClientAdapter.jar branches/advanced/extlibs/svnant-jars/svnant.jar branches/advanced/extlibs/svnant-jars/svnjavahl.jar branches/advanced/tests/c/ctypes_test.c Property Changed: ---------------- branches/advanced/ Property changes on: branches/advanced ___________________________________________________________________ Name: svnmerge-integrated - /branches/asm:1-4922 /trunk/jython:1-4738 Modified: branches/advanced/CPythonLib.includes =================================================================== --- branches/advanced/CPythonLib.includes 2008-07-14 12:19:10 UTC (rev 4925) +++ branches/advanced/CPythonLib.includes 2008-07-14 13:03:20 UTC (rev 4926) @@ -13,6 +13,8 @@ __future__.py _LWPCookieJar.py _MozillaCookieJar.py +_strptime.py +_threading_local.py aifc.py anydbm.py atexit.py Copied: branches/advanced/Lib/_rawffi.py (from rev 4923, branches/asm/Lib/_rawffi.py) =================================================================== --- branches/advanced/Lib/_rawffi.py (rev 0) +++ branches/advanced/Lib/_rawffi.py 2008-07-14 13:03:20 UTC (rev 4926) @@ -0,0 +1,57 @@ +import com.sun.jna as jna + +def get_libc(): + return CDLL("c") + +typecode_map = {'h': 2, 'H': 2} + +class Array(object): + def __init__(self, typecode): + self.typecode = typecode + self.itemsize = typecode_map[typecode] + + def __call__(self, size, autofree=False): + if not autofree: + raise Exception + return ArrayInstance(self, size) + +class ArrayInstance(object): + def __init__(self, shape, size): + self.shape = shape + self.alloc = jna.Memory(shape.itemsize * size) + + def __setitem__(self, index, value): + self.alloc.setShort(index, value) + + def __getitem__(self, index): + return self.alloc.getShort(index) + +class FuncPtr(object): + def __init__(self, fn, name, argtypes, restype): + self.fn = fn + self.name = name + self.argtypes = argtypes + self.restype = restype + + def __call__(self, *args): + container = Array('H')(1, autofree=True) + container[0] = self.fn.invokeInt([i[0] for i in args]) + return container + +class CDLL(object): + def __init__(self, libname): + self.lib = jna.NativeLibrary.getInstance(libname) + self.cache = dict() + + def ptr(self, name, argtypes, restype): + key = (name, tuple(argtypes), restype) + try: + return self.cache[key] + except KeyError: + fn = self.lib.getFunction(name) + fnp = FuncPtr(fn, name, argtypes, restype) + self.cache[key] = fnp + return fnp + + + Modified: branches/advanced/Lib/datetime.py =================================================================== --- branches/advanced/Lib/datetime.py 2008-07-14 12:19:10 UTC (rev 4925) +++ branches/advanced/Lib/datetime.py 2008-07-14 13:03:20 UTC (rev 4926) @@ -12,6 +12,8 @@ Sources for time zone and DST data: http://www.twinsun.com/tz/tz-link.htm +This was originally copied from the sandbox of the CPython CVS repository. +Thanks to Tim Peters for suggesting using it. """ import time as _time @@ -575,9 +577,11 @@ def __add__(self, other): if isinstance(other, timedelta): - return self.__class__(self.__days + other.__days, - self.__seconds + other.__seconds, - self.__microseconds + other.__microseconds) + # for CPython compatibility, we cannot use + # our __class__ here, but need a real timedelta + return timedelta(self.__days + other.__days, + self.__seconds + other.__seconds, + self.__microseconds + other.__microseconds) return NotImplemented __radd__ = __add__ @@ -593,9 +597,11 @@ return NotImplemented def __neg__(self): - return self.__class__(-self.__days, - -self.__seconds, - -self.__microseconds) + # for CPython compatibility, we cannot use + # our __class__ here, but need a real timedelta + return timedelta(-self.__days, + -self.__seconds, + -self.__microseconds) def __pos__(self): return self @@ -608,9 +614,11 @@ def __mul__(self, other): if isinstance(other, (int, long)): - return self.__class__(self.__days * other, - self.__seconds * other, - self.__microseconds * other) + # for CPython compatibility, we cannot use + # our __class__ here, but need a real timedelta + return timedelta(self.__days * other, + self.__seconds * other, + self.__microseconds * other) return NotImplemented __rmul__ = __mul__ @@ -619,7 +627,7 @@ if isinstance(other, (int, long)): usec = ((self.__days * (24*3600L) + self.__seconds) * 1000000 + self.__microseconds) - return self.__class__(0, 0, usec // other) + return timedelta(0, 0, usec // other) return NotImplemented __floordiv__ = __div__ @@ -728,7 +736,7 @@ if isinstance(year, str): # Pickle support self = object.__new__(cls) - self.__setstate((year,)) + self.__setstate(year) return self _check_date_fields(year, month, day) self = object.__new__(cls) @@ -901,9 +909,10 @@ self.__month, self.__day + other.days) self._checkOverflow(t.year) - result = self.__class__(t.year, t.month, t.day) + result = date(t.year, t.month, t.day) return result - return NotImplemented + raise TypeError + # XXX Should be 'return NotImplemented', but there's a bug in 2.2... __radd__ = __add__ @@ -963,10 +972,9 @@ yhi, ylo = divmod(self.__year, 256) return ("%c%c%c%c" % (yhi, ylo, self.__month, self.__day), ) - def __setstate(self, t): - assert isinstance(t, tuple) and len(t) == 1, `t` - string = t[0] - assert len(string) == 4 + def __setstate(self, string): + if len(string) != 4 or not (1 <= ord(string[2]) <= 12): + raise TypeError("not enough arguments") yhi, ylo, self.__month, self.__day = map(ord, string) self.__year = yhi * 256 + ylo @@ -1089,7 +1097,7 @@ self = object.__new__(cls) if isinstance(hour, str): # Pickle support - self.__setstate((hour, minute or None)) + self.__setstate(hour, minute or None) return self _check_tzinfo_arg(tzinfo) _check_time_fields(hour, minute, second, microsecond) @@ -1327,21 +1335,16 @@ else: return (basestate, self._tzinfo) - def __setstate(self, state): - assert isinstance(state, tuple) - assert 1 <= len(state) <= 2 - string = state[0] - assert len(string) == 6 + def __setstate(self, string, tzinfo): + if len(string) != 6 or ord(string[0]) >= 24: + raise TypeError("an integer is required") self.__hour, self.__minute, self.__second, us1, us2, us3 = \ map(ord, string) self.__microsecond = (((us1 << 8) | us2) << 8) | us3 - if len(state) == 1: - self._tzinfo = None - else: - self._tzinfo = state[1] + self._tzinfo = tzinfo def __reduce__(self): - return (self.__class__, self.__getstate()) + return (time, self.__getstate()) _time_class = time # so functions w/ args named "time" can get at the class @@ -1359,7 +1362,7 @@ if isinstance(year, str): # Pickle support self = date.__new__(cls, year[:4]) - self.__setstate((year, month)) + self.__setstate(year, month) return self _check_tzinfo_arg(tzinfo) _check_time_fields(hour, minute, second, microsecond) @@ -1396,8 +1399,17 @@ converter = _time.gmtime y, m, d, hh, mm, ss, weekday, jday, dst = converter(t) us = int((t % 1.0) * 1000000) + + if us == 1000001 or us == 999999: + us = 0 + rounded = True + else: + rounded = False + ss = min(ss, 59) # clamp out leap seconds if the platform has them result = cls(y, m, d, hh, mm, ss, us, tz) + if rounded: + result += timedelta(seconds=1) if tz is not None: result = tz.fromutc(result) return result @@ -1439,6 +1451,15 @@ time.tzinfo) combine = classmethod(combine) + def strptime(cls, date_string, format): + """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]) + + The year, month and day arguments are required. tzinfo may be None, or an + instance of a tzinfo subclass. The remaining arguments may be ints or longs.""" + return cls(*(_time.strptime(date_string, format))[0:6]) + + strptime = classmethod(strptime) + def timetuple(self): "Return local time tuple compatible with time.localtime()." dst = self._dst() @@ -1561,7 +1582,7 @@ if L[-1] == 0: del L[-1] if L[-1] == 0: - del L[-1] + del L[-1] s = ", ".join(map(str, L)) s = "%s(%s)" % ('datetime.' + self.__class__.__name__, s) if self._tzinfo is not None: @@ -1625,7 +1646,7 @@ def __eq__(self, other): if isinstance(other, datetime): return self.__cmp(other) == 0 - elif hasattr(other, "timetuple"): + elif hasattr(other, "timetuple") and not isinstance(other, date): return NotImplemented else: return False @@ -1633,7 +1654,7 @@ def __ne__(self, other): if isinstance(other, datetime): return self.__cmp(other) != 0 - elif hasattr(other, "timetuple"): + elif hasattr(other, "timetuple") and not isinstance(other, date): return NotImplemented else: return True @@ -1641,7 +1662,7 @@ def __le__(self, other): if isinstance(other, datetime): return self.__cmp(other) <= 0 - elif hasattr(other, "timetuple"): + elif hasattr(other, "timetuple") and not isinstance(other, date): return NotImplemented else: _cmperror(self, other) @@ -1649,7 +1670,7 @@ def __lt__(self, other): if isinstance(other, datetime): return self.__cmp(other) < 0 - elif hasattr(other, "timetuple"): + elif hasattr(other, "timetuple") and not isinstance(other, date): return NotImplemented else: _cmperror(self, other) @@ -1657,7 +1678,7 @@ def __ge__(self, other): if isinstance(other, datetime): return self.__cmp(other) >= 0 - elif hasattr(other, "timetuple"): + elif hasattr(other, "timetuple") and not isinstance(other, date): return NotImplemented else: _cmperror(self, other) @@ -1665,7 +1686,7 @@ def __gt__(self, other): if isinstance(other, datetime): return self.__cmp(other) > 0 - elif hasattr(other, "timetuple"): + elif hasattr(other, "timetuple") and not isinstance(other, date): return NotImplemented else: _cmperror(self, other) @@ -1713,7 +1734,7 @@ self.__second + other.seconds, self.__microsecond + other.microseconds) self._checkOverflow(t.year) - result = self.__class__(t.year, t.month, t.day, + result = datetime(t.year, t.month, t.day, t.hour, t.minute, t.second, t.microsecond, tzinfo=self._tzinfo) return result @@ -1768,19 +1789,12 @@ else: return (basestate, self._tzinfo) - def __setstate(self, state): - assert isinstance(state, tuple) - assert 1 <= len(state) <= 2 - string = state[0] - assert len(string) == 10 + def __setstate(self, string, tzinfo): (yhi, ylo, self.__month, self.__day, self.__hour, self.__minute, self.__second, us1, us2, us3) = map(ord, string) self.__year = yhi * 256 + ylo self.__microsecond = (((us1 << 8) | us2) << 8) | us3 - if len(state) == 1: - self._tzinfo = None - else: - self._tzinfo = state[1] + self._tzinfo = tzinfo def __reduce__(self): return (self.__class__, self.__getstate()) @@ -2000,9 +2014,3 @@ pretty bizarre, and a tzinfo subclass can override fromutc() if it is. """ -def _test(): - import test_datetime - test_datetime.test_main() - -if __name__ == "__main__": - _test() Modified: branches/advanced/Lib/gzip.py =================================================================== --- branches/advanced/Lib/gzip.py 2008-07-14 12:19:10 UTC (rev 4925) +++ branches/advanced/Lib/gzip.py 2008-07-14 13:03:20 UTC (rev 4926) @@ -55,7 +55,11 @@ """ myfileobj = None - max_read_chunk = 10 * 1024 * 1024 # 10Mb + # XXX: repeated 10mb chunk reads hurt test_gzip.test_many_append's + # performance on Jython (maybe CPython's allocator recycles the same + # 10mb buffer whereas Java's doesn't) + #max_read_chunk = 10 * 1024 * 1024 # 10Mb + max_read_chunk = 256 * 1024 # 256kb def __init__(self, filename=None, mode=None, compresslevel=9, fileobj=None): Copied: branches/advanced/Lib/platform.py (from rev 4923, branches/asm/Lib/platform.py) =================================================================== --- branches/advanced/Lib/platform.py (rev 0) +++ branches/advanced/Lib/platform.py 2008-07-14 13:03:20 UTC (rev 4926) @@ -0,0 +1,1270 @@ +#!/usr/bin/env python + +""" This module tries to retrieve as much platform-identifying data as + possible. It makes this information available via function APIs. + + If called from the command line, it prints the platform + information concatenated as single string to stdout. The output + format is useable as part of a filename. + +""" +# This module is maintained by Marc-Andre Lemburg <ma...@eg...>. +# If you find problems, please submit bug reports/patches via the +# Python SourceForge Project Page and assign them to "lemburg". +# +# Note: Please keep this module compatible to Python 1.5.2. +# +# Still needed: +# * more support for WinCE +# * support for MS-DOS (PythonDX ?) +# * support for Amiga and other still unsupported platforms running Python +# * support for additional Linux distributions +# +# Many thanks to all those who helped adding platform-specific +# checks (in no particular order): +# +# Charles G Waldman, David Arnold, Gordon McMillan, Ben Darnell, +# Jeff Bauer, Cliff Crawford, Ivan Van Laningham, Josef +# Betancourt, Randall Hopper, Karl Putland, John Farrell, Greg +# Andruk, Just van Rossum, Thomas Heller, Mark R. Levinson, Mark +# Hammond, Bill Tutt, Hans Nowak, Uwe Zessin (OpenVMS support), +# Colin Kong, Trent Mick, Guido van Rossum +# +# History: +# +# <see CVS and SVN checkin messages for history> +# +# 1.0.3 - added normalization of Windows system name +# 1.0.2 - added more Windows support +# 1.0.1 - reformatted to make doc.py happy +# 1.0.0 - reformatted a bit and checked into Python CVS +# 0.8.0 - added sys.version parser and various new access +# APIs (python_version(), python_compiler(), etc.) +# 0.7.2 - fixed architecture() to use sizeof(pointer) where available +# 0.7.1 - added support for Caldera OpenLinux +# 0.7.0 - some fixes for WinCE; untabified the source file +# 0.6.2 - support for OpenVMS - requires version 1.5.2-V006 or higher and +# vms_lib.getsyi() configured +# 0.6.1 - added code to prevent 'uname -p' on platforms which are +# known not to support it +# 0.6.0 - fixed win32_ver() to hopefully work on Win95,98,NT and Win2k; +# did some cleanup of the interfaces - some APIs have changed +# 0.5.5 - fixed another type in the MacOS code... should have +# used more coffee today ;-) +# 0.5.4 - fixed a few typos in the MacOS code +# 0.5.3 - added experimental MacOS support; added better popen() +# workarounds in _syscmd_ver() -- still not 100% elegant +# though +# 0.5.2 - fixed uname() to return '' instead of 'unknown' in all +# return values (the system uname command tends to return +# 'unknown' instead of just leaving the field emtpy) +# 0.5.1 - included code for slackware dist; added exception handlers +# to cover up situations where platforms don't have os.popen +# (e.g. Mac) or fail on socket.gethostname(); fixed libc +# detection RE +# 0.5.0 - changed the API names referring to system commands to *syscmd*; +# added java_ver(); made syscmd_ver() a private +# API (was system_ver() in previous versions) -- use uname() +# instead; extended the win32_ver() to also return processor +# type information +# 0.4.0 - added win32_ver() and modified the platform() output for WinXX +# 0.3.4 - fixed a bug in _follow_symlinks() +# 0.3.3 - fixed popen() and "file" command invokation bugs +# 0.3.2 - added architecture() API and support for it in platform() +# 0.3.1 - fixed syscmd_ver() RE to support Windows NT +# 0.3.0 - added system alias support +# 0.2.3 - removed 'wince' again... oh well. +# 0.2.2 - added 'wince' to syscmd_ver() supported platforms +# 0.2.1 - added cache logic and changed the platform string format +# 0.2.0 - changed the API to use functions instead of module globals +# since some action take too long to be run on module import +# 0.1.0 - first release +# +# You can always get the latest version of this module at: +# +# http://www.egenix.com/files/python/platform.py +# +# If that URL should fail, try contacting the author. + +__copyright__ = """ + Copyright (c) 1999-2000, Marc-Andre Lemburg; mailto:ma...@le... + Copyright (c) 2000-2003, eGenix.com Software GmbH; mailto:in...@eg... + + Permission to use, copy, modify, and distribute this software and its + documentation for any purpose and without fee or royalty is hereby granted, + provided that the above copyright notice appear in all copies and that + both that copyright notice and this permission notice appear in + supporting documentation or portions thereof, including modifications, + that you make. + + EGENIX.COM SOFTWARE GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO + THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, + INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOFTWARE ! + +""" + +__version__ = '1.0.4' + +import sys,string,os,re + +### Platform specific APIs + +_libc_search = re.compile(r'(__libc_init)' + '|' + '(GLIBC_([0-9.]+))' + '|' + '(libc(_\w+)?\.so(?:\.(\d[0-9.]*))?)') + +def libc_ver(executable=sys.executable,lib='',version='', + + chunksize=2048): + + """ Tries to determine the libc version that the file executable + (which defaults to the Python interpreter) is linked against. + + Returns a tuple of strings (lib,version) which default to the + given parameters in case the lookup fails. + + Note that the function has intimate knowledge of how different + libc versions add symbols to the executable and thus is probably + only useable for executables compiled using gcc. + + The file is read and scanned in chunks of chunksize bytes. + + """ + f = open(executable,'rb') + binary = f.read(chunksize) + pos = 0 + while 1: + m = _libc_search.search(binary,pos) + if not m: + binary = f.read(chunksize) + if not binary: + break + pos = 0 + continue + libcinit,glibc,glibcversion,so,threads,soversion = m.groups() + if libcinit and not lib: + lib = 'libc' + elif glibc: + if lib != 'glibc': + lib = 'glibc' + version = glibcversion + elif glibcversion > version: + version = glibcversion + elif so: + if lib != 'glibc': + lib = 'libc' + if soversion > version: + version = soversion + if threads and version[-len(threads):] != threads: + version = version + threads + pos = m.end() + f.close() + return lib,version + +def _dist_try_harder(distname,version,id): + + """ Tries some special tricks to get the distribution + information in case the default method fails. + + Currently supports older SuSE Linux, Caldera OpenLinux and + Slackware Linux distributions. + + """ + if os.path.exists('/var/adm/inst-log/info'): + # SuSE Linux stores distribution information in that file + info = open('/var/adm/inst-log/info').readlines() + distname = 'SuSE' + for line in info: + tv = string.split(line) + if len(tv) == 2: + tag,value = tv + else: + continue + if tag == 'MIN_DIST_VERSION': + version = string.strip(value) + elif tag == 'DIST_IDENT': + values = string.split(value,'-') + id = values[2] + return distname,version,id + + if os.path.exists('/etc/.installed'): + # Caldera OpenLinux has some infos in that file (thanks to Colin Kong) + info = open('/etc/.installed').readlines() + for line in info: + pkg = string.split(line,'-') + if len(pkg) >= 2 and pkg[0] == 'OpenLinux': + # XXX does Caldera support non Intel platforms ? If yes, + # where can we find the needed id ? + return 'OpenLinux',pkg[1],id + + if os.path.isdir('/usr/lib/setup'): + # Check for slackware verson tag file (thanks to Greg Andruk) + verfiles = os.listdir('/usr/lib/setup') + for n in range(len(verfiles)-1, -1, -1): + if verfiles[n][:14] != 'slack-version-': + del verfiles[n] + if verfiles: + verfiles.sort() + distname = 'slackware' + version = verfiles[-1][14:] + return distname,version,id + + return distname,version,id + +_release_filename = re.compile(r'(\w+)[-_](release|version)') +_release_version = re.compile(r'([\d.]+)[^(]*(?:\((.+)\))?') + +# Note:In supported_dists below we need 'fedora' before 'redhat' as in +# Fedora redhat-release is a link to fedora-release. + +def dist(distname='',version='',id='', + + supported_dists=('SuSE', 'debian', 'fedora', 'redhat', 'mandrake')): + + """ Tries to determine the name of the Linux OS distribution name. + + The function first looks for a distribution release file in + /etc and then reverts to _dist_try_harder() in case no + suitable files are found. + + Returns a tuple (distname,version,id) which default to the + args given as parameters. + + """ + try: + etc = os.listdir('/etc') + except os.error: + # Probably not a Unix system + return distname,version,id + for file in etc: + m = _release_filename.match(file) + if m: + _distname,dummy = m.groups() + if _distname in supported_dists: + distname = _distname + break + else: + return _dist_try_harder(distname,version,id) + f = open('/etc/'+file,'r') + firstline = f.readline() + f.close() + m = _release_version.search(firstline) + if m: + _version,_id = m.groups() + if _version: + version = _version + if _id: + id = _id + else: + # Unkown format... take the first two words + l = string.split(string.strip(firstline)) + if l: + version = l[0] + if len(l) > 1: + id = l[1] + return distname,version,id + +class _popen: + + """ Fairly portable (alternative) popen implementation. + + This is mostly needed in case os.popen() is not available, or + doesn't work as advertised, e.g. in Win9X GUI programs like + PythonWin or IDLE. + + Writing to the pipe is currently not supported. + + """ + tmpfile = '' + pipe = None + bufsize = None + mode = 'r' + + def __init__(self,cmd,mode='r',bufsize=None): + + if mode != 'r': + raise ValueError,'popen()-emulation only supports read mode' + import tempfile + self.tmpfile = tmpfile = tempfile.mktemp() + os.system(cmd + ' > %s' % tmpfile) + self.pipe = open(tmpfile,'rb') + self.bufsize = bufsize + self.mode = mode + + def read(self): + + return self.pipe.read() + + def readlines(self): + + if self.bufsize is not None: + return self.pipe.readlines() + + def close(self, + + remove=os.unlink,error=os.error): + + if self.pipe: + rc = self.pipe.close() + else: + rc = 255 + if self.tmpfile: + try: + remove(self.tmpfile) + except error: + pass + return rc + + # Alias + __del__ = close + +def popen(cmd, mode='r', bufsize=None): + + """ Portable popen() interface. + """ + # Find a working popen implementation preferring win32pipe.popen + # over os.popen over _popen + popen = None + if os.environ.get('OS','') == 'Windows_NT': + # On NT win32pipe should work; on Win9x it hangs due to bugs + # in the MS C lib (see MS KnowledgeBase article Q150956) + try: + import win32pipe + except ImportError: + pass + else: + popen = win32pipe.popen + if popen is None: + if hasattr(os,'popen'): + popen = os.popen + # Check whether it works... it doesn't in GUI programs + # on Windows platforms + if sys.platform == 'win32': # XXX Others too ? + try: + popen('') + except os.error: + popen = _popen + else: + popen = _popen + if bufsize is None: + return popen(cmd,mode) + else: + return popen(cmd,mode,bufsize) + +def _norm_version(version,build=''): + + """ Normalize the version and build strings and return a single + version string using the format major.minor.build (or patchlevel). + """ + l = string.split(version,'.') + if build: + l.append(build) + try: + ints = map(int,l) + except ValueError: + strings = l + else: + strings = map(str,ints) + version = string.join(strings[:3],'.') + return version + +_ver_output = re.compile(r'(?:([\w ]+) ([\w.]+) ' + '.*' + 'Version ([\d.]+))') + +def _syscmd_ver(system='',release='',version='', + + supported_platforms=('win32','win16','dos','os2')): + + """ Tries to figure out the OS version used and returns + a tuple (system,release,version). + + It uses the "ver" shell command for this which is known + to exists on Windows, DOS and OS/2. XXX Others too ? + + In case this fails, the given parameters are used as + defaults. + + """ + if sys.platform not in supported_platforms: + return system,release,version + + # Try some common cmd strings + for cmd in ('ver','command /c ver','cmd /c ver'): + try: + pipe = popen(cmd) + info = pipe.read() + if pipe.close(): + raise os.error,'command failed' + # XXX How can I supress shell errors from being written + # to stderr ? + except os.error,why: + #print 'Command %s failed: %s' % (cmd,why) + continue + except IOError,why: + #print 'Command %s failed: %s' % (cmd,why) + continue + else: + break + else: + return system,release,version + + # Parse the output + info = string.strip(info) + m = _ver_output.match(info) + if m: + system,release,version = m.groups() + # Strip trailing dots from version and release + if release[-1] == '.': + release = release[:-1] + if version[-1] == '.': + version = version[:-1] + # Normalize the version and build strings (eliminating additional + # zeros) + version = _norm_version(version) + return system,release,version + +def _win32_getvalue(key,name,default=''): + + """ Read a value for name from the registry key. + + In case this fails, default is returned. + + """ + from win32api import RegQueryValueEx + try: + return RegQueryValueEx(key,name) + except: + return default + +def win32_ver(release='',version='',csd='',ptype=''): + + """ Get additional version information from the Windows Registry + and return a tuple (version,csd,ptype) referring to version + number, CSD level and OS type (multi/single + processor). + + As a hint: ptype returns 'Uniprocessor Free' on single + processor NT machines and 'Multiprocessor Free' on multi + processor machines. The 'Free' refers to the OS version being + free of debugging code. It could also state 'Checked' which + means the OS version uses debugging code, i.e. code that + checks arguments, ranges, etc. (Thomas Heller). + + Note: this function only works if Mark Hammond's win32 + package is installed and obviously only runs on Win32 + compatible platforms. + + """ + # XXX Is there any way to find out the processor type on WinXX ? + # XXX Is win32 available on Windows CE ? + # + # Adapted from code posted by Karl Putland to comp.lang.python. + # + # The mappings between reg. values and release names can be found + # here: http://msdn.microsoft.com/library/en-us/sysinfo/base/osversioninfo_str.asp + + # Import the needed APIs + try: + import win32api + except ImportError: + return release,version,csd,ptype + from win32api import RegQueryValueEx,RegOpenKeyEx,RegCloseKey,GetVersionEx + from win32con import HKEY_LOCAL_MACHINE,VER_PLATFORM_WIN32_NT,\ + VER_PLATFORM_WIN32_WINDOWS + + # Find out the registry key and some general version infos + maj,min,buildno,plat,csd = GetVersionEx() + version = '%i.%i.%i' % (maj,min,buildno & 0xFFFF) + if csd[:13] == 'Service Pack ': + csd = 'SP' + csd[13:] + if plat == VER_PLATFORM_WIN32_WINDOWS: + regkey = 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion' + # Try to guess the release name + if maj == 4: + if min == 0: + release = '95' + elif min == 10: + release = '98' + elif min == 90: + release = 'Me' + else: + release = 'postMe' + elif maj == 5: + release = '2000' + elif plat == VER_PLATFORM_WIN32_NT: + regkey = 'SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion' + if maj <= 4: + release = 'NT' + elif maj == 5: + if min == 0: + release = '2000' + elif min == 1: + release = 'XP' + elif min == 2: + release = '2003Server' + else: + release = 'post2003' + else: + if not release: + # E.g. Win3.1 with win32s + release = '%i.%i' % (maj,min) + return release,version,csd,ptype + + # Open the registry key + try: + keyCurVer = RegOpenKeyEx(HKEY_LOCAL_MACHINE,regkey) + # Get a value to make sure the key exists... + RegQueryValueEx(keyCurVer,'SystemRoot') + except: + return release,version,csd,ptype + + # Parse values + #subversion = _win32_getvalue(keyCurVer, + # 'SubVersionNumber', + # ('',1))[0] + #if subversion: + # release = release + subversion # 95a, 95b, etc. + build = _win32_getvalue(keyCurVer, + 'CurrentBuildNumber', + ('',1))[0] + ptype = _win32_getvalue(keyCurVer, + 'CurrentType', + (ptype,1))[0] + + # Normalize version + version = _norm_version(version,build) + + # Close key + RegCloseKey(keyCurVer) + return release,version,csd,ptype + +def _mac_ver_lookup(selectors,default=None): + + from gestalt import gestalt + import MacOS + l = [] + append = l.append + for selector in selectors: + try: + append(gestalt(selector)) + except (RuntimeError, MacOS.Error): + append(default) + return l + +def _bcd2str(bcd): + + return hex(bcd)[2:] + +def mac_ver(release='',versioninfo=('','',''),machine=''): + + """ Get MacOS version information and return it as tuple (release, + versioninfo, machine) with versioninfo being a tuple (version, + dev_stage, non_release_version). + + Entries which cannot be determined are set to the paramter values + which default to ''. All tuple entries are strings. + + Thanks to Mark R. Levinson for mailing documentation links and + code examples for this function. Documentation for the + gestalt() API is available online at: + + http://www.rgaros.nl/gestalt/ + + """ + # Check whether the version info module is available + try: + import gestalt + import MacOS + except ImportError: + return release,versioninfo,machine + # Get the infos + sysv,sysu,sysa = _mac_ver_lookup(('sysv','sysu','sysa')) + # Decode the infos + if sysv: + major = (sysv & 0xFF00) >> 8 + minor = (sysv & 0x00F0) >> 4 + patch = (sysv & 0x000F) + + if (major, minor) >= (10, 4): + # the 'sysv' gestald cannot return patchlevels + # higher than 9. Apple introduced 3 new + # gestalt codes in 10.4 to deal with this + # issue (needed because patch levels can + # run higher than 9, such as 10.4.11) + major,minor,patch = _mac_ver_lookup(('sys1','sys2','sys3')) + release = '%i.%i.%i' %(major, minor, patch) + else: + release = '%s.%i.%i' % (_bcd2str(major),minor,patch) + if sysu: + major = int((sysu & 0xFF000000L) >> 24) + minor = (sysu & 0x00F00000) >> 20 + bugfix = (sysu & 0x000F0000) >> 16 + stage = (sysu & 0x0000FF00) >> 8 + nonrel = (sysu & 0x000000FF) + version = '%s.%i.%i' % (_bcd2str(major),minor,bugfix) + nonrel = _bcd2str(nonrel) + stage = {0x20:'development', + 0x40:'alpha', + 0x60:'beta', + 0x80:'final'}.get(stage,'') + versioninfo = (version,stage,nonrel) + if sysa: + machine = {0x1: '68k', + 0x2: 'PowerPC', + 0xa: 'i386'}.get(sysa,'') + return release,versioninfo,machine + +def _java_getprop(name,default): + + from java.lang import System + try: + return System.getProperty(name) + except: + return default + +def java_ver(release='',vendor='',vminfo=('','',''),osinfo=('','','')): + + """ Version interface for Jython. + + Returns a tuple (release,vendor,vminfo,osinfo) with vminfo being + a tuple (vm_name,vm_release,vm_vendor) and osinfo being a + tuple (os_name,os_version,os_arch). + + Values which cannot be determined are set to the defaults + given as parameters (which all default to ''). + + """ + # Import the needed APIs + try: + import java.lang + except ImportError: + return release,vendor,vminfo,osinfo + + vendor = _java_getprop('java.vendor',vendor) + release = _java_getprop('java.version',release) + vm_name,vm_release,vm_vendor = vminfo + vm_name = _java_getprop('java.vm.name',vm_name) + vm_vendor = _java_getprop('java.vm.vendor',vm_vendor) + vm_release = _java_getprop('java.vm.version',vm_release) + vminfo = vm_name,vm_release,vm_vendor + os_name,os_version,os_arch = osinfo + os_arch = _java_getprop('os.arch',os_arch) + os_name = _java_getprop('os.name',os_name) + os_version = _java_getprop('os.version',os_version) + osinfo = os_name,os_version,os_arch + + return release,vendor,vminfo,osinfo + +### System name aliasing + +def system_alias(system,release,version): + + """ Returns (system,release,version) aliased to common + marketing names used for some systems. + + It also does some reordering of the information in some cases + where it would otherwise cause confusion. + + """ + if system == 'Rhapsody': + # Apple's BSD derivative + # XXX How can we determine the marketing release number ? + return 'MacOS X Server',system+release,version + + elif system == 'SunOS': + # Sun's OS + if release < '5': + # These releases use the old name SunOS + return system,release,version + # Modify release (marketing release = SunOS release - 3) + l = string.split(release,'.') + if l: + try: + major = int(l[0]) + except ValueError: + pass + else: + major = major - 3 + l[0] = str(major) + release = string.join(l,'.') + if release < '6': + system = 'Solaris' + else: + # XXX Whatever the new SunOS marketing name is... + system = 'Solaris' + + elif system == 'IRIX64': + # IRIX reports IRIX64 on platforms with 64-bit support; yet it + # is really a version and not a different platform, since 32-bit + # apps are also supported.. + system = 'IRIX' + if version: + version = version + ' (64bit)' + else: + version = '64bit' + + elif system in ('win32','win16'): + # In case one of the other tricks + system = 'Windows' + + return system,release,version + +### Various internal helpers + +def _platform(*args): + + """ Helper to format the platform string in a filename + compatible format e.g. "system-version-machine". + """ + # Format the platform string + platform = string.join( + map(string.strip, + filter(len,args)), + '-') + + # Cleanup some possible filename obstacles... + replace = string.replace + platform = replace(platform,' ','_') + platform = replace(platform,'/','-') + platform = replace(platform,'\\','-') + platform = replace(platform,':','-') + platform = replace(platform,';','-') + platform = replace(platform,'"','-') + platform = replace(platform,'(','-') + platform = replace(platform,')','-') + + # No need to report 'unknown' information... + platform = replace(platform,'unknown','') + + # Fold '--'s and remove trailing '-' + while 1: + cleaned = replace(platform,'--','-') + if cleaned == platform: + break + platform = cleaned + while platform[-1] == '-': + platform = platform[:-1] + + return platform + +def _node(default=''): + + """ Helper to determine the node name of this machine. + """ + try: + import socket + except ImportError: + # No sockets... + return default + try: + return socket.gethostname() + except socket.error: + # Still not working... + return default + +# os.path.abspath is new in Python 1.5.2: +if not hasattr(os.path,'abspath'): + + def _abspath(path, + + isabs=os.path.isabs,join=os.path.join,getcwd=os.getcwd, + normpath=os.path.normpath): + + if not isabs(path): + path = join(getcwd(), path) + return normpath(path) + +else: + + _abspath = os.path.abspath + +def _follow_symlinks(filepath): + + """ In case filepath is a symlink, follow it until a + real file is reached. + """ + filepath = _abspath(filepath) + while os.path.islink(filepath): + filepath = os.path.normpath( + os.path.join(filepath,os.readlink(filepath))) + return filepath + +def _syscmd_uname(option,default=''): + + """ Interface to the system's uname command. + """ + if sys.platform in ('dos','win32','win16','os2'): + # XXX Others too ? + return default + try: + f = os.popen('uname %s 2> /dev/null' % option) + except (AttributeError,os.error): + return default + output = string.strip(f.read()) + rc = f.close() + if not output or rc: + return default + else: + return output + +def _syscmd_file(target,default=''): + + """ Interface to the system's file command. + + The function uses the -b option of the file command to have it + ommit the filename in its output and if possible the -L option + to have the command follow symlinks. It returns default in + case the command should fail. + + """ + target = _follow_symlinks(target) + try: + f = os.popen('file %s 2> /dev/null' % target) + except (AttributeError,os.error): + return default + output = string.strip(f.read()) + rc = f.close() + if not output or rc: + return default + else: + return output + +### Information about the used architecture + +# Default values for architecture; non-empty strings override the +# defaults given as parameters +_default_architecture = { + 'win32': ('','WindowsPE'), + 'win16': ('','Windows'), + 'dos': ('','MSDOS'), +} + +_architecture_split = re.compile(r'[\s,]').split + +def architecture(executable=sys.executable,bits='',linkage=''): + + """ Queries the given executable (defaults to the Python interpreter + binary) for various architecture information. + + Returns a tuple (bits,linkage) which contains information about + the bit architecture and the linkage format used for the + executable. Both values are returned as strings. + + Values that cannot be determined are returned as given by the + parameter presets. If bits is given as '', the sizeof(pointer) + (or sizeof(long) on Python version < 1.5.2) is used as + indicator for the supported pointer size. + + The function relies on the system's "file" command to do the + actual work. This is available on most if not all Unix + platforms. On some non-Unix platforms where the "file" command + does not exist and the executable is set to the Python interpreter + binary defaults from _default_architecture are used. + + """ + # Use the sizeof(pointer) as default number of bits if nothing + # else is given as default. + if not bits: + import struct + try: + size = struct.calcsize('P') + except struct.error: + # Older installations can only query longs + size = struct.calcsize('l') + bits = str(size*8) + 'bit' + + # Get data from the 'file' system command + output = _syscmd_file(executable,'') + + if not output and \ + executable == sys.executable: + # "file" command did not return anything; we'll try to provide + # some sensible defaults then... + if _default_architecture.has_key(sys.platform): + b,l = _default_architecture[sys.platform] + if b: + bits = b + if l: + linkage = l + return bits,linkage + + # Split the output into a list of strings omitting the filename + fileout = _architecture_split(output)[1:] + + if 'executable' not in fileout: + # Format not supported + return bits,linkage + + # Bits + if '32-bit' in fileout: + bits = '32bit' + elif 'N32' in fileout: + # On Irix only + bits = 'n32bit' + elif '64-bit' in fileout: + bits = '64bit' + + # Linkage + if 'ELF' in fileout: + linkage = 'ELF' + elif 'PE' in fileout: + # E.g. Windows uses this format + if 'Windows' in fileout: + linkage = 'WindowsPE' + else: + linkage = 'PE' + elif 'COFF' in fileout: + linkage = 'COFF' + elif 'MS-DOS' in fileout: + linkage = 'MSDOS' + else: + # XXX the A.OUT format also falls under this class... + pass + + return bits,linkage + +### Portable uname() interface + +_uname_cache = None + +def uname(): + + """ Fairly portable uname interface. Returns a tuple + of strings (system,node,release,version,machine,processor) + identifying the underlying platform. + + Note that unlike the os.uname function this also returns + possible processor information as an additional tuple entry. + + Entries which cannot be determined are set to ''. + + """ + global _uname_cache + + if _uname_cache is not None: + return _uname_cache + + # Get some infos from the builtin os.uname API... + try: + system,node,release,version,machine = os.uname() + + except AttributeError: + # Hmm, no uname... we'll have to poke around the system then. + system = sys.platform + release = '' + version = '' + node = _node() + machine = '' + processor = '' + use_syscmd_ver = 1 + + # Try win32_ver() on win32 platforms + if system == 'win32': + release,version,csd,ptype = win32_ver() + if release and version: + use_syscmd_ver = 0 + + # Try the 'ver' system command available on some + # platforms + if use_syscmd_ver: + system,release,version = _syscmd_ver(system) + # Normalize system to what win32_ver() normally returns + # (_syscmd_ver() tends to return the vendor name as well) + if system == 'Microsoft Windows': + system = 'Windows' + + # In case we still don't know anything useful, we'll try to + # help ourselves + if system in ('win32','win16'): + if not version: + if system == 'win32': + version = '32bit' + else: + version = '16bit' + system = 'Windows' + + elif system[:4] == 'java': + release,vendor,vminfo,osinfo = java_ver() + system = 'Java' + version = string.join(vminfo,', ') + if not version: + version = vendor + + elif os.name == 'mac': + release,(version,stage,nonrel),machine = mac_ver() + system = 'MacOS' + + else: + # System specific extensions + if system == 'OpenVMS': + # OpenVMS seems to have release and version mixed up + if not release or release == '0': + release = version + version = '' + # Get processor information + try: + import vms_lib + except ImportError: + pass + else: + csid, cpu_number = vms_lib.getsyi('SYI$_CPU',0) + if (cpu_number >= 128): + processor = 'Alpha' + else: + processor = 'VAX' + else: + # Get processor information from the uname system command + processor = _syscmd_uname('-p','') + + # 'unknown' is not really any useful as information; we'll convert + # it to '' which is more portable + if system == 'unknown': + system = '' + if node == 'unknown': + node = '' + if release == 'unknown': + release = '' + if version == 'unknown': + version = '' + if machine == 'unknown': + machine = '' + if processor == 'unknown': + processor = '' + + # normalize name + if system == 'Microsoft' and release == 'Windows': + system = 'Windows' + release = 'Vista' + + _uname_cache = system,node,release,version,machine,processor + return _uname_cache + +### Direct interfaces to some of the uname() return values + +def system(): + + """ Returns the system/OS name, e.g. 'Linux', 'Windows' or 'Java'. + + An empty string is returned if the value cannot be determined. + + """ + return uname()[0] + +def node(): + + """ Returns the computer's network name (which may not be fully + qualified) + + An empty string is returned if the value cannot be determined. + + """ + return uname()[1] + +def release(): + + """ Returns the system's release, e.g. '2.2.0' or 'NT' + + An empty string is returned if the value cannot be determined. + + """ + return uname()[2] + +def version(): + + """ Returns the system's release version, e.g. '#3 on degas' + + An empty string is returned if the value cannot be determined. + + """ + return uname()[3] + +def machine(): + + """ Returns the machine type, e.g. 'i386' + + An empty string is returned if the value cannot be determined. + + """ + return uname()[4] + +def processor(): + + """ Returns the (true) processor name, e.g. 'amdk6' + + An empty string is returned if the value cannot be + determined. Note that many platforms do not provide this + information or simply return the same value as for machine(), + e.g. NetBSD does this. + + """ + return uname()[5] + +### Various APIs for extracting information from sys.version + +_sys_version_parser = re.compile(r'([\w.+]+)\s*' + '\(#?([^,]+),\s*([\w ]+),\s*([\w :]+)\)\s*' + '\[([^\]]+)\]?') +_sys_version_cache = None + +def _sys_version(): + + """ Returns a parsed version of Python's sys.version as tuple + (version, buildno, builddate, compiler) referring to the Python + version, build number, build date/time as string and the compiler + identification string. + + Note that unlike the Python sys.version, the returned value + for the Python version will always include the patchlevel (it + defaults to '.0'). + + """ + global _sys_version_cache + + if _sys_version_cache is not None: + return _sys_version_cache + version, buildno, builddate, buildtime, compiler = \ + _sys_version_parser.match(sys.version).groups() + builddate = builddate + ' ' + buildtime + l = string.split(version, '.') + if len(l) == 2: + l.append('0') + version = string.join(l, '.') + _sys_version_cache = (version, buildno, builddate, compiler) + return _sys_version_cache + +def python_version(): + + """ Returns the Python version as string 'major.minor.patchlevel' + + Note that unlike the Python sys.version, the returned value + will always include the patchlevel (it defaults to 0). + + """ + return _sys_version()[0] + +def python_version_tuple(): + + """ Returns the Python version as tuple (major, minor, patchlevel) + of strings. + + Note that unlike the Python sys.version, the returned value + will always include the patchlevel (it defaults to 0). + + """ + return string.split(_sys_version()[0], '.') + +def python_build(): + + """ Returns a tuple (buildno, builddate) stating the Python + build number and date as strings. + + """ + return _sys_version()[1:3] + +def python_compiler(): + + """ Returns a string identifying the compiler used for compiling + Python. + + """ + return _sys_version()[3] + +### The Opus Magnum of platform strings :-) + +_platform_cache = {} + +def platform(aliased=0, terse=0): + + """ Returns a single string identifying the underlying platform + with as much useful information as possible (but no more :). + + The output is intended to be human readable rather than + machine parseable. It may look different on different + platforms and this is intended. + + If "aliased" is true, the function will use aliases for + various platforms that report system names which differ from + their common names, e.g. SunOS will be reported as + Solaris. The system_alias() function is used to implement + this. + + Setting terse to true causes the function to return only the + absolute minimum information needed to identify the platform. + + """ + result = _platform_cache.get((aliased, terse), None) + if result is not None: + return result + + # Get uname information and then apply platform specific cosmetics + # to it... + system,node,release,version,machine,processor = uname() + if machine == processor: + processor = '' + if aliased: + system,release,version = system_alias(system,release,version) + + if system == 'Windows': + # MS platforms + rel,vers,csd,ptype = win32_ver(version) + if terse: + platform = _platform(system,release) + else: + platform = _platform(system,release,version,csd) + + elif system in ('Linux',): + # Linux based systems + distname,distversion,distid = dist('') + if distname and not terse: + platform = _platform(system,release,machine,processor, + 'with', + distname,distversion,distid) + else: + # If the distribution name is unknown check for libc vs. glibc + libcname,libcversion = libc_ver(sys.executable) + platform = _platform(system,release,machine,processor, + 'with', + libcname+libcversion) + elif system == 'Java': + # Java platforms + r,v,vminfo,(os_name,os_version,os_arch) = java_ver() + if terse: + platform = _platform(system,release,version) + else: + platform = _platform(system,release,version, + 'on', + os_name,os_version,os_arch) + + elif system == 'MacOS': + # MacOS platforms + if terse: + platform = _platform(system,release) + else: + platform = _platform(system,release,machine) + + else: + # Generic handler + if terse: + platform = _platform(system,release) + else: + bits,linkage = architecture(sys.executable) + platform = _platform(system,release,machi... [truncated message content] |
From: <th...@us...> - 2008-07-14 17:41:42
|
Revision: 4929 http://jython.svn.sourceforge.net/jython/?rev=4929&view=rev Author: thobes Date: 2008-07-14 10:41:33 -0700 (Mon, 14 Jul 2008) Log Message: ----------- Verifying that svnmerge works on the advanced branch now. Merged revisions 4928 via svnmerge from https://jython.svn.sourceforge.net/svnroot/jython/branches/asm ........ r4928 | zyasoft | 2008-07-14 17:19:01 +0200 (Mon, 14 Jul 2008) | 3 lines ReferenceQueue objs, by their nature, only make sense if transient. So make them so, this enables interoperation with Terracotta. ........ Modified Paths: -------------- branches/advanced/src/org/python/core/AutoInternalTables.java branches/advanced/src/org/python/core/IdImpl.java Property Changed: ---------------- branches/advanced/ Property changes on: branches/advanced ___________________________________________________________________ Name: svnmerge-integrated - /branches/asm:1-4926 + /branches/asm:1-4928 Modified: branches/advanced/src/org/python/core/AutoInternalTables.java =================================================================== --- branches/advanced/src/org/python/core/AutoInternalTables.java 2008-07-14 15:19:01 UTC (rev 4928) +++ branches/advanced/src/org/python/core/AutoInternalTables.java 2008-07-14 17:41:33 UTC (rev 4929) @@ -8,7 +8,7 @@ public abstract class AutoInternalTables extends InternalTables { - protected ReferenceQueue queue = new ReferenceQueue(); + protected transient ReferenceQueue queue = new ReferenceQueue(); protected abstract Reference newAutoRef(short type, Object key, Object obj); Modified: branches/advanced/src/org/python/core/IdImpl.java =================================================================== --- branches/advanced/src/org/python/core/IdImpl.java 2008-07-14 15:19:01 UTC (rev 4928) +++ branches/advanced/src/org/python/core/IdImpl.java 2008-07-14 17:41:33 UTC (rev 4929) @@ -8,7 +8,7 @@ public static class WeakIdentityMap { - private ReferenceQueue refqueue = new ReferenceQueue(); + private transient ReferenceQueue refqueue = new ReferenceQueue(); private HashMap hashmap = new HashMap(); private void cleanup() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |