Revision: 3440
http://jython.svn.sourceforge.net/jython/?rev=3440&view=rev
Author: thobes
Date: 2007-08-20 11:11:16 -0700 (Mon, 20 Aug 2007)
Log Message:
-----------
GSoC is officially over. This is an upload of the PyASM compiler, an ASM powered compiler framework that compiles python bytecode to java bytecode.
The compiler is able to bootstrap itself.
The next step is to document, fix bugs, document, invent test cases and document. I will continue working on this and on the Jython project after the summer of code.
Modified Paths:
--------------
branches/newcompiler/src/org/python/core/NewCompilerResources.java
branches/newcompiler/src/org/python/core/PyFrame.java
branches/newcompiler/src/org/python/core/PyGenerator.java
branches/newcompiler/src/org/python/newcompiler/pyasm/CodeFlags.java
branches/newcompiler/src/org/python/newcompiler/pyasm/CodeReader.java
branches/newcompiler/src/org/python/newcompiler/pyasm/CodeVisitor.java
Added Paths:
-----------
branches/newcompiler/PyASM/
branches/newcompiler/PyASM/marshal.py
branches/newcompiler/PyASM/opcode.py
branches/newcompiler/PyASM/pyasm.py
branches/newcompiler/PyASM/test/
branches/newcompiler/PyASM/test/assign.py
branches/newcompiler/PyASM/test/builtins.py
branches/newcompiler/PyASM/test/call.py
branches/newcompiler/PyASM/test/call_return.py
branches/newcompiler/PyASM/test/class_simple.py
branches/newcompiler/PyASM/test/constants.py
branches/newcompiler/PyASM/test/exception.py
branches/newcompiler/PyASM/test/for.py
branches/newcompiler/PyASM/test/generator.py
branches/newcompiler/PyASM/test/generator_comprehension.py
branches/newcompiler/PyASM/test/generator_finally.py
branches/newcompiler/PyASM/test/generator_state.py
branches/newcompiler/PyASM/test/generator_state2.py
branches/newcompiler/PyASM/test/import.py
branches/newcompiler/PyASM/test/import_from.py
branches/newcompiler/PyASM/test/import_star.py
branches/newcompiler/PyASM/test/list.py
branches/newcompiler/PyASM/test/list_comprehension.py
branches/newcompiler/PyASM/test/print.py
branches/newcompiler/PyASM/test/return.py
branches/newcompiler/PyASM/test/simple_decorator.py
branches/newcompiler/PyASM/test/simple_decorator2.py
branches/newcompiler/PyASM/test/simple_decorator_scopes.py
branches/newcompiler/PyASM/test/simple_decorator_scopes1.py
branches/newcompiler/PyASM/test/simple_decorator_scopes2.py
branches/newcompiler/PyASM/test/simple_func.py
branches/newcompiler/PyASM/test/strings.py
branches/newcompiler/PyASM/test/try.py
branches/newcompiler/PyASM/test/try_except.py
branches/newcompiler/PyASM/test/try_finally.py
branches/newcompiler/PyASM/test/try_finally_function.py
branches/newcompiler/PyASM/test/varargs.py
branches/newcompiler/PyASM/test/while.py
branches/newcompiler/PyASM/test/with.py
branches/newcompiler/PyASM/test.py
branches/newcompiler/src/org/python/newcompiler/asm/
branches/newcompiler/src/org/python/newcompiler/asm/OffsetTracer.java
branches/newcompiler/src/org/python/newcompiler/pyasm/BytecodeError.java
branches/newcompiler/src/org/python/newcompiler/pyasm/BytecodeVisitor.java
branches/newcompiler/src/org/python/newcompiler/pyasm/ConstantStore.java
branches/newcompiler/src/org/python/newcompiler/pyasm/util/
branches/newcompiler/src/org/python/newcompiler/pyasm/util/CodeAdapter.java
branches/newcompiler/src/org/python/newcompiler/pyasm/util/PythonDis.java
branches/newcompiler/src/org/python/newcompiler/pyasm/util/SimpleConstantStore.java
Added: branches/newcompiler/PyASM/marshal.py
===================================================================
--- branches/newcompiler/PyASM/marshal.py (rev 0)
+++ branches/newcompiler/PyASM/marshal.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,469 @@
+"""Marshal module written in Python.
+
+Written by Tobias Ivarsson <tobias@...> for the Jython project.
+
+"""
+
+__all__ = ('dump','dumps','load','loads',)
+
+from StringIO import StringIO
+import string
+import struct
+from types import *#NoneType, EllipsisType, CodeType
+from org.python.newcompiler.pyasm import CodeReader
+from org.python.newcompiler.pyasm.util import PythonDis
+from pyasm import ASMVisitor as CodeVisitor
+from jarray import array
+from java.io import PrintWriter
+from java.lang.System import out
+stdout = PrintWriter(out)
+try:
+ import new
+except ImportError:
+ new = None
+
+def byteArray(string):
+ return array(list(string),'c')
+
+# marshal types
+mappings = dict(
+ TYPE_NULL = ('0', 0),
+ TYPE_NONE = ('N', NoneType),
+ TYPE_FALSE = ('F', 0),
+ TYPE_TRUE = ('T', 0),
+ TYPE_STOPITER = ('S', 0),
+ TYPE_ELLIPSIS = ('.', EllipsisType),
+ TYPE_INT = ('i', int),
+ TYPE_INT64 = ('I', 0),
+ TYPE_FLOAT = ('f', float),
+ TYPE_BINARY_FLOAT = ('g', 0),
+ TYPE_COMPLEX = ('x', complex),
+ TYPE_BINARY_COMPLEX = ('y', 0),
+ TYPE_LONG = ('l', long),
+ TYPE_STRING = ('s', str),
+ TYPE_INTERNED = ('t', 0),
+ TYPE_STRINGREF = ('R', 0),
+ TYPE_TUPLE = ('(', tuple),
+ TYPE_LIST = ('[', list),
+ TYPE_DICT = ('{', dict),
+ TYPE_CODE = ('c', CodeType),
+ TYPE_UNICODE = ('u', unicode),
+ TYPE_UNKNOWN = ('?', 0),
+ TYPE_SET = ('<', set),
+ TYPE_FROZENSET = ('>', frozenset),
+ )
+
+class Marshaller:
+
+ dispatch = {}
+
+ def __init__(self, f):
+ self.f = f
+
+ def dump(self, x):
+ self.dispatch[type(x)](self, x)
+
+ def w_long64(self, x):
+ self.w_long(x)
+ self.w_long(x>>32)
+
+ def w_long(self, x):
+ write = self.f.write
+ write(chr((x) & 0xff))
+ write(chr((x>> 8) & 0xff))
+ write(chr((x>>16) & 0xff))
+ write(chr((x>>24) & 0xff))
+
+ def w_short(self, x):
+ write = self.f.write
+ write(chr((x) & 0xff))
+ write(chr((x>> 8) & 0xff))
+
+ def dump_none(self, x):
+ self.f.write(TYPE_NONE)
+ dispatch[NoneType] = dump_none
+
+ def dump_bool(self, x):
+ if x:
+ self.f.write(TYPE_TRUE)
+ else:
+ self.f.write(TYPE_FALSE)
+ dispatch[BooleanType] = dump_bool
+
+ def dump_ellipsis(self, x):
+ self.f.write(TYPE_ELLIPSIS)
+ try:
+ dispatch[EllipsisType] = dump_ellipsis
+ except NameError:
+ pass
+
+ def dump_int(self, x):
+ y = x>>31
+ if y and y != -1:
+ self.f.write(TYPE_INT64)
+ self.w_long64(x)
+ else:
+ self.f.write(TYPE_INT)
+ self.w_long(x)
+ dispatch[IntType] = dump_int
+
+ def dump_long(self, x):
+ self.f.write(TYPE_LONG)
+ sign = 1
+ if x < 0:
+ sign = -1
+ x = -x
+ digits = []
+ while x:
+ digits.append(x & 0x7FFF)
+ x = x>>15
+ self.w_long(len(digits) * sign)
+ for d in digits:
+ self.w_short(d)
+ dispatch[LongType] = dump_long
+
+ def dump_float(self, x):
+ write = self.f.write
+ write(TYPE_FLOAT)
+ s = `x`
+ write(chr(len(s)))
+ write(s)
+ dispatch[FloatType] = dump_float
+
+ def dump_complex(self, x):
+ write = self.f.write
+ write(TYPE_COMPLEX)
+ s = `x.real`
+ write(chr(len(s)))
+ write(s)
+ s = `x.imag`
+ write(chr(len(s)))
+ write(s)
+ try:
+ dispatch[ComplexType] = dump_complex
+ except NameError:
+ pass
+
+ def dump_string(self, x):
+ self.f.write(TYPE_STRING)
+ self.w_long(len(x))
+ self.f.write(x)
+ dispatch[StringType] = dump_string
+
+ def dump_tuple(self, x):
+ self.f.write(TYPE_TUPLE)
+ self.w_long(len(x))
+ for item in x:
+ self.dump(item)
+ dispatch[TupleType] = dump_tuple
+
+ def dump_list(self, x):
+ self.f.write(TYPE_LIST)
+ self.w_long(len(x))
+ for item in x:
+ self.dump(item)
+ dispatch[ListType] = dump_list
+
+ def dump_dict(self, x):
+ self.f.write(TYPE_DICT)
+ for key, value in x.items():
+ self.dump(key)
+ self.dump(value)
+ self.f.write(TYPE_NULL)
+ dispatch[DictionaryType] = dump_dict
+
+ def dump_code(self, x):
+ self.f.write(TYPE_CODE)
+ self.w_short(x.co_argcount)
+ self.w_short(x.co_nlocals)
+ self.w_short(x.co_stacksize)
+ self.w_short(x.co_flags)
+ self.dump(x.co_code)
+ self.dump(x.co_consts)
+ self.dump(x.co_names)
+ self.dump(x.co_varnames)
+ self.dump(x.co_filename)
+ self.dump(x.co_name)
+ self.w_short(x.co_firstlineno)
+ self.dump(x.co_lnotab)
+ try:
+ dispatch[CodeType] = dump_code
+ except NameError:
+ pass
+
+
+class NULL:
+ pass
+
+class Unmarshaller:
+
+ def __init__(self, f, magic=None):
+ self.magic = magic
+ self.strings = []
+ self.__visitor = None
+ self.f = f
+
+ def load(self):
+ ident = self.f.read(1)
+ if not ident:
+ raise EOFError
+ return self.dispatch[ident](self)
+
+ def read_long(self):
+ a = long( self.read_byte() )
+ b = long( self.read_byte() )
+ c = long( self.read_byte() )
+ d = long( self.read_byte() )
+ res = a | (b<<8) | (c<<16) | (d<<24)
+ if res & 0x80000000 and res > 0:
+ res = res - 0x100000000L
+ return int(res)
+
+ def read_long64(self):
+ a = long( self.read_byte() )
+ b = long( self.read_byte() )
+ c = long( self.read_byte() )
+ d = long( self.read_byte() )
+ e = long( self.read_byte() )
+ f = long( self.read_byte() )
+ g = long( self.read_byte() )
+ h = long( self.read_byte() )
+ res = a | (b<<8) | (c<<16) | (d<<24)
+ res |= (e<<32) | (f<<40) | (g<<48) | (h<<56)
+ if res & (0x8<<60L) and res > 0:
+ res = res - (1<<64L)
+ return res
+
+ def read_short(self):
+ lo = self.read_byte()
+ hi = self.read_byte()
+ res = lo | (hi<<8)
+ if res & 0x8000:
+ res = res - 0x10000
+ return res
+
+ def read_byte(self):
+ res = self.f.read(1)
+ if not res:
+ raise EOFError
+ return ord(res)
+
+ def read_string(self, size):
+ res = self.f.read(size)
+ if len(res) != size:
+ raise EOFError
+ return res
+
+ def load_null(self):
+ return NULL
+
+ def load_none(self):
+ return None
+
+ def load_false(self):
+ return False
+
+ def load_true(self):
+ return True
+
+ def load_stopiter(self):
+ return StopIteration
+
+ def load_ellipsis(self):
+ return Ellipsis
+
+ def load_int(self):
+ return self.read_long()
+
+ def load_int64(self):
+ return self.read_long64()
+
+ def load_float(self):
+ size = self.read_byte()
+ return string.atof( self.read_string(size) )
+
+ def load_binary_float(self):
+ # There is a bug in the Jython struct module, it produces and reads
+ # packed strings reversed. This method compensates for that.
+ def reverse(lizt):
+ while lizt:
+ yield lizt.pop()
+ data = "".join(reverse(list(self.read_string(8))))
+ # had the struct module woked correctly, this would just be a matter of
+ # data = self.read_string(8)
+ return struct.unpack('d', data)[0]
+
+ def load_complex(self):
+ real = self.load_float()
+ imag = self.load_float()
+ return complex(real, imag)
+
+ def load_binary_complex(self):
+ real = self.load_binary_float()
+ imag = self.load_binary_float()
+ return complex(real, imag)
+
+ def load_long(self):
+ size = self.read_long()
+ sign = 1
+ if size < 0:
+ sign = -1
+ size = -size
+ res = 0L
+ for i in xrange(size):
+ x = self.read_short()
+ res = res | (x<<(i*15L))
+ return res * sign
+
+ def load_string(self):
+ size = self.read_long()
+ return self.read_string(size)
+
+ def load_interned(self):
+ string = self.load_string()
+ self.strings.append(string)
+ return string
+
+ def load_stringref(self):
+ return self.strings[self.read_long()]
+
+ def load_tuple(self):
+ return tuple(self.load_list())
+
+ def load_list(self):
+ size = self.read_long()
+ res = []
+ for i in xrange(size):
+ res.append(self.load())
+ return res
+
+ def load_dict(self):
+ res = {}
+ while True:
+ key = self.load()
+ if key is NULL:
+ break
+ value = self.load()
+ res[key] = value
+ return res
+
+
+ def load_code(self):
+ lastVisitor = self.__visitor
+ visitor= _visitor= self.__visitor= CodeVisitor(self.magic, lastVisitor)
+ #visitor = PythonDis(visitor, stdout, False)
+ try:
+ argcount = self.read_long()
+ nlocals = self.read_long()
+ stacksize = self.read_long()
+ flags = self.read_long()
+ code = self.load()
+ constants = self.load()
+ names = self.load()
+ varnames = self.load()
+ freevars = self.load()
+ cellvars = self.load()
+ filename = self.load()
+ name = self.load()
+ firstlineno = self.read_long()
+ lnotab = self.load()
+
+ visitor.visitCode(
+ argcount,
+ nlocals,
+ stacksize,
+ flags,
+ constants,
+ names,
+ varnames,
+ freevars,
+ cellvars,
+ filename,
+ name,
+ firstlineno,)
+ CodeReader(byteArray(code), firstlineno,
+ byteArray(lnotab)).accept(visitor)
+
+ return _visitor.getCode()
+ finally:
+ self.__visitor = lastVisitor
+
+ def load_unicode(self):
+ size = self.read_long()
+ return EncodedFile(StringIO(self.read_string(size)),'utf8').read()
+
+ def load_unknown(self):
+ raise TypeError("Unknown type in unmarshalling")
+
+ def load_set(self):
+ return set(self.load_list())
+
+ def load_frozenset(self):
+ return frozenset(self.load_list())
+
+ dispatch=dict([(i,locals()['load'+n[4:].lower()]) for n,(i,t) in mappings.items()])
+
+
+ def load(self):
+ c = self.f.read(1)
+ if not c:
+ raise EOFError
+ return self.dispatch[c](self)
+
+
+ def r_short(self):
+ read = self.f.read
+ lo = ord(read(1))
+ hi = ord(read(1))
+ x = lo | (hi<<8)
+ if x & 0x8000:
+ x = x - 0x10000
+ return x
+
+ def r_long(self):
+ read = self.f.read
+ a = ord(read(1))
+ b = ord(read(1))
+ c = ord(read(1))
+ d = ord(read(1))
+ x = a | (b<<8) | (c<<16) | (d<<24)
+ if x & 0x80000000 and x > 0:
+ x = string.atoi(x - 0x100000000L)
+ return x
+
+ def r_long64(self):
+ a = self.r_long()
+ b = self.r_long()
+ return a | (b<<32)
+
+
+def dump(x, f):
+ Marshaller(f).dump(x)
+
+def load(f):
+ return Unmarshaller(f).load()
+
+def dumps(x):
+ f = StringIO()
+ dump(x, f)
+ return f.getvalue()
+
+def loads(s):
+ f = StringIO(s)
+ return load(f)
+
+def _makeModule(code):
+ # TODO
+ return code
+
+def _readPyc(filename):
+ f = open(filename, 'rb')
+ def read():
+ return ord(f.read(1))
+ magic = read() | (read()<<8)
+ if not ( f.read(1) == '\r' and f.read(1) == '\n' ):
+ raise TypeError("The file is not a valid pyc file.")
+ mtime = read() | (read()<<8) | (read()<<16) | (read()<<24)
+ # TODO: when this is used for loading, the mtime needs to be considered.
+ return _makeModule( Unmarshaller(f, magic=magic).load() )
+
Added: branches/newcompiler/PyASM/opcode.py
===================================================================
--- branches/newcompiler/PyASM/opcode.py (rev 0)
+++ branches/newcompiler/PyASM/opcode.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,185 @@
+
+"""
+opcode module - potentially shared between dis and other modules which
+operate on bytecodes (e.g. peephole optimizers).
+"""
+
+__all__ = ["cmp_op", "hasconst", "hasname", "hasjrel", "hasjabs",
+ "haslocal", "hascompare", "hasfree", "opname", "opmap",
+ "HAVE_ARGUMENT", "EXTENDED_ARG"]
+
+cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
+ 'is not', 'exception match', 'BAD')
+
+hasconst = []
+hasname = []
+hasjrel = []
+hasjabs = []
+haslocal = []
+hascompare = []
+hasfree = []
+
+opmap = {}
+opname = [''] * 256
+for op in range(256): opname[op] = '<%r>' % (op,)
+del op
+
+def def_op(name, op):
+ opname[op] = name
+ opmap[name] = op
+
+def name_op(name, op):
+ def_op(name, op)
+ hasname.append(op)
+
+def jrel_op(name, op):
+ def_op(name, op)
+ hasjrel.append(op)
+
+def jabs_op(name, op):
+ def_op(name, op)
+ hasjabs.append(op)
+
+# Instruction opcodes for compiled code
+# Blank lines correspond to available opcodes
+
+def_op('STOP_CODE', 0)
+def_op('POP_TOP', 1)
+def_op('ROT_TWO', 2)
+def_op('ROT_THREE', 3)
+def_op('DUP_TOP', 4)
+def_op('ROT_FOUR', 5)
+
+def_op('NOP', 9)
+def_op('UNARY_POSITIVE', 10)
+def_op('UNARY_NEGATIVE', 11)
+def_op('UNARY_NOT', 12)
+def_op('UNARY_CONVERT', 13)
+
+def_op('UNARY_INVERT', 15)
+
+def_op('LIST_APPEND', 18)
+def_op('BINARY_POWER', 19)
+def_op('BINARY_MULTIPLY', 20)
+def_op('BINARY_DIVIDE', 21)
+def_op('BINARY_MODULO', 22)
+def_op('BINARY_ADD', 23)
+def_op('BINARY_SUBTRACT', 24)
+def_op('BINARY_SUBSCR', 25)
+def_op('BINARY_FLOOR_DIVIDE', 26)
+def_op('BINARY_TRUE_DIVIDE', 27)
+def_op('INPLACE_FLOOR_DIVIDE', 28)
+def_op('INPLACE_TRUE_DIVIDE', 29)
+def_op('SLICE+0', 30)
+def_op('SLICE+1', 31)
+def_op('SLICE+2', 32)
+def_op('SLICE+3', 33)
+
+def_op('STORE_SLICE+0', 40)
+def_op('STORE_SLICE+1', 41)
+def_op('STORE_SLICE+2', 42)
+def_op('STORE_SLICE+3', 43)
+
+def_op('DELETE_SLICE+0', 50)
+def_op('DELETE_SLICE+1', 51)
+def_op('DELETE_SLICE+2', 52)
+def_op('DELETE_SLICE+3', 53)
+
+def_op('INPLACE_ADD', 55)
+def_op('INPLACE_SUBTRACT', 56)
+def_op('INPLACE_MULTIPLY', 57)
+def_op('INPLACE_DIVIDE', 58)
+def_op('INPLACE_MODULO', 59)
+def_op('STORE_SUBSCR', 60)
+def_op('DELETE_SUBSCR', 61)
+def_op('BINARY_LSHIFT', 62)
+def_op('BINARY_RSHIFT', 63)
+def_op('BINARY_AND', 64)
+def_op('BINARY_XOR', 65)
+def_op('BINARY_OR', 66)
+def_op('INPLACE_POWER', 67)
+def_op('GET_ITER', 68)
+
+def_op('PRINT_EXPR', 70)
+def_op('PRINT_ITEM', 71)
+def_op('PRINT_NEWLINE', 72)
+def_op('PRINT_ITEM_TO', 73)
+def_op('PRINT_NEWLINE_TO', 74)
+def_op('INPLACE_LSHIFT', 75)
+def_op('INPLACE_RSHIFT', 76)
+def_op('INPLACE_AND', 77)
+def_op('INPLACE_XOR', 78)
+def_op('INPLACE_OR', 79)
+def_op('BREAK_LOOP', 80)
+def_op('WITH_CLEANUP', 81)
+def_op('LOAD_LOCALS', 82)
+def_op('RETURN_VALUE', 83)
+def_op('IMPORT_STAR', 84)
+def_op('EXEC_STMT', 85)
+def_op('YIELD_VALUE', 86)
+def_op('POP_BLOCK', 87)
+def_op('END_FINALLY', 88)
+def_op('BUILD_CLASS', 89)
+
+HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
+
+name_op('STORE_NAME', 90) # Index in name list
+name_op('DELETE_NAME', 91) # ""
+def_op('UNPACK_SEQUENCE', 92) # Number of tuple items
+jrel_op('FOR_ITER', 93)
+
+name_op('STORE_ATTR', 95) # Index in name list
+name_op('DELETE_ATTR', 96) # ""
+name_op('STORE_GLOBAL', 97) # ""
+name_op('DELETE_GLOBAL', 98) # ""
+def_op('DUP_TOPX', 99) # number of items to duplicate
+def_op('LOAD_CONST', 100) # Index in const list
+hasconst.append(100)
+name_op('LOAD_NAME', 101) # Index in name list
+def_op('BUILD_TUPLE', 102) # Number of tuple items
+def_op('BUILD_LIST', 103) # Number of list items
+def_op('BUILD_MAP', 104) # Always zero for now
+name_op('LOAD_ATTR', 105) # Index in name list
+def_op('COMPARE_OP', 106) # Comparison operator
+hascompare.append(106)
+name_op('IMPORT_NAME', 107) # Index in name list
+name_op('IMPORT_FROM', 108) # Index in name list
+
+jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip
+jrel_op('JUMP_IF_FALSE', 111) # ""
+jrel_op('JUMP_IF_TRUE', 112) # ""
+jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code
+
+name_op('LOAD_GLOBAL', 116) # Index in name list
+
+jabs_op('CONTINUE_LOOP', 119) # Target address
+jrel_op('SETUP_LOOP', 120) # Distance to target address
+jrel_op('SETUP_EXCEPT', 121) # ""
+jrel_op('SETUP_FINALLY', 122) # ""
+
+def_op('LOAD_FAST', 124) # Local variable number
+haslocal.append(124)
+def_op('STORE_FAST', 125) # Local variable number
+haslocal.append(125)
+def_op('DELETE_FAST', 126) # Local variable number
+haslocal.append(126)
+
+def_op('RAISE_VARARGS', 130) # Number of raise arguments (1, 2, or 3)
+def_op('CALL_FUNCTION', 131) # #args + (#kwargs << 8)
+def_op('MAKE_FUNCTION', 132) # Number of args with default values
+def_op('BUILD_SLICE', 133) # Number of items
+def_op('MAKE_CLOSURE', 134)
+def_op('LOAD_CLOSURE', 135)
+hasfree.append(135)
+def_op('LOAD_DEREF', 136)
+hasfree.append(136)
+def_op('STORE_DEREF', 137)
+hasfree.append(137)
+
+def_op('CALL_FUNCTION_VAR', 140) # #args + (#kwargs << 8)
+def_op('CALL_FUNCTION_KW', 141) # #args + (#kwargs << 8)
+def_op('CALL_FUNCTION_VAR_KW', 142) # #args + (#kwargs << 8)
+def_op('EXTENDED_ARG', 143)
+EXTENDED_ARG = 143
+
+del def_op, name_op, jrel_op, jabs_op
Added: branches/newcompiler/PyASM/pyasm.py
===================================================================
--- branches/newcompiler/PyASM/pyasm.py (rev 0)
+++ branches/newcompiler/PyASM/pyasm.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,1852 @@
+# Open issues:
+# * Line number reporting on exceptions does not wor, jython uses a separate
+# system for line numbers, and not javas debug-info. It should be possible
+# to replace this though.
+
+import opcode, re
+try:
+ from org.python.newcompiler.pyasm import BytecodeVisitor as Visitor,\
+ Operator, CodeFlags as Flags
+ from org.python.newcompiler.asm import OffsetTracer, InlineingClassVisitor
+ from org.python.core.BytecodeLoader import makeCode
+ from org.objectweb import asm
+ from org.objectweb.asm import Type, Opcodes as Op
+ from org.objectweb.asm.commons import GeneratorAdapter, Method,\
+ TableSwitchGenerator
+ from org.objectweb.asm.tree import analysis
+ from org.python import core
+ from jarray import array
+ import java
+ from java.io import PrintWriter
+ from java.lang.System import out
+ stdout = PrintWriter(out)
+except:
+ # mock code to be able to import the module from CPython, an easy way
+ # to compile it...
+ Visitor = object
+ class ArrantPrac(object):
+ def __getattr__(self,attr):
+ return self
+ Operator = Method = Type = java = core = ArrantPrac()
+ mirror = lambda *x: x
+ Type.getObjectType = mirror
+ Type.getType = mirror
+ Method.getMethod = mirror
+ TableSwitchGenerator = object
+
+ del ArrantPrac
+
+def printFlags(flags):
+ for id in dir(Flags):
+ flag = getattr(Flags,id)
+ if flag & flags == flag:
+ print id, hex(flag)
+ flags ^= flag
+ return flags
+
+def reallyContains(dct, item):
+ if item in dct:
+ keys = list(dct.keys())
+ return item is keys[keys.index(item)]
+ return False
+
+def getType(clazz):
+ if isinstance(clazz,(str,unicode)):
+ return Type.getObjectType(clazz)
+ else:
+ return Type.getType(clazz)
+def getArrayType(typ):
+ if not isinstance(typ,Type):
+ typ = getType(typ)
+ return Type.getType("[%s" % typ.getDescriptor())
+
+def stringArray(*lst):
+ return array(lst,java.lang.String)
+
+pyObjectType = getType(object)
+pyFrameType = getType(core.PyFrame)
+pyCodeType = getType(core.PyCode)
+pyType = getType(core.Py)
+pySysType = getType(core.PySystemState)
+pyExceptionType = getType(core.PyException)
+pyBooleanType = getType(bool)
+pyTupleType = getType(tuple)
+pyListType = getType(list)
+pyDictType = getType(dict)
+pyStringType = getType(str)
+pyBuiltin = getType(core.__builtin__)
+imp = getType(core.imp)
+compilerResources = getType(core.NewCompilerResources)
+objectType = getType(java.lang.Object)
+stringType = getType(java.lang.String)
+throwableType = getType(java.lang.Throwable)
+
+class Switch(TableSwitchGenerator):
+ def __init__(self, generator):
+ self.__generator = generator
+ def generateCase(self, key, end):
+ self.__generator(key, end)
+ def generateDefault(self):
+ self.__generator(None, None)
+
+class CodeReference(object):
+ def __init__(self, name, index):
+ self.__name = name
+ self.index = index
+
+ def getName(self):
+ return self.__name
+
+ def __repr__(self):
+ return "CodeReference(%s, %s)" % (self.__name, self.index)
+
+magicNumbers = {
+ '1.5': 20121,
+ '1.5.1': 20121,
+ '1.5.2': 20121,
+ '1.6': 50428,
+ '2.0': 50823,
+ '2.0.1': 50823,
+ '2.1': 60202,
+ '2.1.1': 60202,
+ '2.1.2': 60202,
+ '2.2': 60717,
+ '2.3a0': 62011,
+ '2.3a0': 62021,
+ '2.3a0': 62011, # OBS!
+ '2.4a0': 62041,
+ '2.4a3': 62051,
+ '2.4b1': 62061,
+ '2.5a0': 62071,
+ '2.5a0': 62081,
+ '2.5a0': 62091,
+ '2.5a0': 62092,
+ '2.5b3': 62101,
+ '2.5b3': 62111,
+ '2.5c1': 62121,
+ '2.5c2': 62131,
+ '2.6a0': 62141,
+ }
+
+class ClassKeeper(object):
+ asType = property(lambda self: Type.getType(
+ "L%s;" % self.__name.replace('.','/')))
+ def __init__(self, name):
+ self.__name = name
+ self.__cw = asm.ClassWriter(asm.ClassWriter.COMPUTE_MAXS
+ #+ asm.ClassWriter.COMPUTE_FRAMES
+ )
+ self.cv = self.__cw
+ #self.cv = InlineingClassVisitor(self.cv)
+ #self.cv = asm.util.TraceClassVisitor(self.cv, stdout)
+ #self.cv = OffsetTracer(self.cv, stdout)
+ self.cv = asm.util.CheckClassAdapter(self.cv)
+ self.cv.visit(Op.V1_4, Op.ACC_PUBLIC, name, None,
+ "org/python/core/PyFunctionTable",
+ stringArray("org/python/core/PyRunnable"))
+ self.__filename = None
+ self.__const = 0
+ self.__constantPool = {}
+ self.__complexConstants = {}
+ self.__constantOrder = []
+ self.__func = 0
+ self.__functionTable = []
+
+ self.clinit = GeneratorAdapter(Op.ACC_STATIC, Method.getMethod(
+ "void <clinit> ()"), None, None, self.cv)
+ self.clinit.visitCode()
+ self.init = GeneratorAdapter(Op.ACC_PUBLIC, Method.getMethod(
+ "void <init> (String)"), None, None, self.cv)
+ self.init.visitCode()
+ self.init.loadThis()
+ self.init.invokeConstructor(Type.getType(core.PyFunctionTable),
+ Method.getMethod("void <init> ()"))
+
+
+ def isCodeConstant(self, name):
+ return name in self.__functionTable
+
+ def func2method(self, name):
+ if name == '?':
+ return 'main$code'
+ return name.replace('<','').replace('>','')
+
+ def codeField(self, id, name):
+ return "%s$%s" % (self.func2method(name), id)
+
+ def newFunction(self, name):
+ name = self.codeField(self.__func, name)
+ self.__functionTable.append(name)
+ self.__lastCode = CodeReference(name, self.__func)
+ self.__func += 1
+ self.cv.visitField(Op.ACC_STATIC + Op.ACC_PRIVATE,
+ name, getType(core.PyCode).getDescriptor(),
+ None, None)
+ ## generate a field for the constants of the code object
+ #self.cv.visitField(Op.ACC_STATIC + Op.ACC_PUBLIC, name + "$co_consts",
+ # getArrayType(core.PyObject).getDescriptor(),
+ # None, None)
+ return GeneratorAdapter(Op.ACC_PRIVATE, Method.getMethod(
+ "org.python.core.PyObject %s (org.python.core.PyFrame)"%name),
+ None, None, self.cv)
+
+ def getCodeReference(self):
+ return self.__lastCode
+
+ def getConstant(self, value):
+ if value in self.__constantPool:
+ return self.__constantPool[value]
+ if isinstance(value,(list,dict,set)):
+ raise TypeError("PyASM cannot handle mutable constants (yet).")
+ if isinstance(value,(tuple,frozenset)):
+ parts = []
+ for part in value:
+ if reallyContains(self.constants,part):
+ parts.append(part)
+ else:
+ parts.append(self.getConstant(part))
+ self.__complexConstants[value] = parts
+ name = "c$$%s" % self.__const
+ self.__const += 1
+ self.cv.visitField(Op.ACC_PRIVATE + Op.ACC_STATIC + Op.ACC_FINAL,
+ name, pyObjectType.getDescriptor(), None, None)
+ self.__constantPool[value] = name
+ self.__constantOrder.append(value)
+ return name
+
+ def getCode(self, mainName):
+ self.generateSupport(mainName)
+ self.cv.visitEnd()
+ byteArray = self.__cw.toByteArray()
+ cn = asm.tree.ClassNode()
+ #asm.ClassReader(byteArray).accept(OffsetTracer(cn, stdout), 0)
+ #asm.ClassReader(byteArray).accept(cn, 0)
+
+ error = False
+
+ #analyzer = analysis.Analyzer(analysis.BasicInterpreter())
+ analyzer = analysis.Analyzer(analysis.BasicVerifier())
+ ###analyzer = analysis.Analyzer(analysis.SimpleVerifier())
+ ###analyzer = analysis.Analyzer(analysis.SourceInterpreter())
+ for m in cn.methods:
+ try:
+ analyzer.analyze(self.__name, m)
+ except analysis.AnalyzerException, ae:
+ print 'Error in "%s %s": %s' % (m.name, m.desc, ae)
+ mp = OffsetTracer.createTMV(len(str(m.instructions.size())))
+ m.accept(mp)
+ getattr(mp,'print')( stdout )
+ stdout.flush()
+ error = True
+ if error:
+ raise RuntimeError, "An error occured, see output"
+
+ return makeCode(self.__name, byteArray, self.__filename)
+
+ def setFilename(self, filename):
+ if self.__filename is not None:
+ assert filename == self.__filename
+ else:
+ self.__filename = filename
+ self.cv.visitSource(filename, None)
+
+ def generateSupport(self, mainName):
+ self.initConstants()
+
+ self.clinit.returnValue()
+ self.clinit.endMethod()
+ self.init.returnValue()
+ self.init.endMethod()
+
+ getMain = GeneratorAdapter(Op.ACC_PUBLIC, Method.getMethod(
+ "org.python.core.PyCode getMain ()"),
+ None, None, self.cv)
+ getMain.visitCode()
+ getMain.getStatic(self.asType, mainName, pyCodeType)
+ getMain.returnValue()
+ getMain.endMethod()
+
+ call_function = GeneratorAdapter( Op.ACC_PUBLIC, Method.getMethod(
+ "org.python.core.PyObject call_function (%s)" % ", ".join(
+ ['int', 'org.python.core.PyFrame'])),
+ None, None, self.cv)
+ call_function.visitCode()
+ call_function.loadThis()
+ call_function.loadArg(1) # the frame
+ call_function.loadArg(0) # the function id
+ def switch(key, end):
+ if key is not None:
+ call_function.invokeVirtual(self.asType, Method.getMethod(
+ "org.python.core.PyObject %s (org.python.core.PyFrame)"
+ % self.__functionTable[key]))
+ call_function.returnValue()
+ else:
+ call_function.visitInsn(Op.ACONST_NULL)
+ call_function.returnValue()
+ call_function.tableSwitch(range(self.__func), Switch(switch))
+ call_function.endMethod()
+
+ constants = {
+ None: ("None", pyObjectType),
+ False: ("False", pyBooleanType),
+ True: ("True", pyBooleanType),
+ StopIteration: ("StopIteration", pyObjectType),
+ Ellipsis: ("Ellipsis", pyObjectType),
+ (): ("EmptyTuple", pyTupleType),
+ "": ("EmptyString", pyStringType),
+ }
+ __compositTypes = {
+ tuple: pyTupleType,
+ list: pyListType,
+ dict: pyDictType,
+ set: pyTupleType,
+ frozenset: pyTupleType,
+ }
+ __compositConstructor = Method.getMethod(
+ "void <init> (org.python.core.PyObject[])")
+ __setConstructor = Method.getMethod(
+ "void <init> (org.python.core.PyObject)")
+ __constantFactory = {
+ int: Method.getMethod(
+ "org.python.core.PyObject newInteger (long)"),
+ float: Method.getMethod(
+ "org.python.core.PyFloat newFloat (double)"),
+ str: Method.getMethod(
+ "org.python.core.PyString newString (String)"),
+ unicode: Method.getMethod(
+ "org.python.core.PyUnicode newUnicode (String)"),
+ }
+ def initConstants(self):
+ # Possible constants that marshal loads:
+ # NULL - raise error, not valid outside of marshal
+ # None - simple singleton => can even be optimized at load time
+ # boolean values: True/False - simple singleton
+ # StopIteration - simple singleton
+ # Ellipsis - simple singleton
+ # int - immutable
+ # float - immutable
+ # complex - immutable
+ # long - immutable
+ # string - immutable
+ # unicode - immutable
+ # code - allready in place...
+ # tuple - build from other constants
+ # list - !MUTABLE! - build from other constants
+ # dict - !MUTABLE! - build from other constants
+ # set - !MUTABLE! - build from other constants
+ # frozenset - build from other constants
+ for value in self.__constantOrder:
+ name = self.__constantPool[value]
+ if reallyContains(self.constants, value):
+ raise ValueError("Constant %s:%s slipped through!" %
+ (name,value))
+ if type(value) in self.__compositTypes:
+ if isinstance(value, (set,frozenset)):
+ self.clinit.newInstance(getType(type(value)))
+ self.clinit.dup()
+ self.clinit.newInstance(self.__compositTypes[type(value)])
+ self.clinit.dup()
+ self.clinit.push(java.lang.Integer(len(value)))
+ self.clinit.newArray(pyObjectType)
+ i = 0
+ for part in self.__complexConstants[value]:
+ self.clinit.dup() # array
+ self.clinit.push(java.lang.Integer(i)) # index
+ if reallyContains(self.constants, part):
+ partName, partType = self.constants[part]
+ self.clinit.getStatic(pyType, partName, partType)
+ else:
+ self.clinit.getStatic(self.asType, part, pyObjectType)
+ self.clinit.arrayStore(pyObjectType) # store
+ i += 1
+ self.clinit.invokeConstructor(
+ self.__compositTypes[type(value)],
+ self.__compositConstructor)
+ if isinstance(value, (set,frozenset)):
+ self.clinit.invokeConstructor(getType(type(value)),
+ self.__setConstructor)
+ elif isinstance(value, complex):
+ self.clinit.newInstance(getType(complex))
+ self.clinit.dup()
+ self.clinit.push(value.real)
+ self.clinit.push(value.imag)
+ self.clinit.invokeConstructor(
+ getType(complex), Method.getMethod(
+ "void <init> (double, double)"))
+ elif isinstance(value, long):
+ self.clinit.push(str(value))
+ self.clinit.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyObject newLong (String)"))
+ elif type(value) in self.__constantFactory:
+ self.clinit.push(value)
+ self.clinit.invokeStatic(
+ pyType, self.__constantFactory[type(value)])
+ else:
+ raise TypeError("Invalid constant type %s (%s)" %
+ (type(value), value))
+ self.clinit.putStatic(self.asType, name, pyObjectType)
+
+
+class Block(object):
+ def __init__(self, asm, stackSize=0, *stateVariables):
+ self.asm = asm
+ self.stackSize = stackSize
+ self.stateVariables = stateVariables
+ nestingStackSize = property(lambda self: self.stackSize)
+ def end(self):
+ """Called when the block scope ends."""
+ for variable in self.stateVariables:
+ variable.end()
+ def exit(self,hasState=None):
+ """Called when a return, yeild, continue or break instruction
+ terminates the block.
+ hasState is True when there is a variable on the stack"""
+ return False
+ def loadState(self):
+ """load the stack state that this block has persisted into variables
+ onto the stack."""
+ pass
+ def storeState(self):
+ """store the stack state that this block persists into variables from
+ the stack into the persistance variables."""
+ pass
+ def exclude(self,start,end):
+ pass
+
+class LoopBlock(Block):
+ def __init__(self, asm, endLabel):
+ # endLabel is an ASM label
+ Block.__init__(self, asm)
+ self.endLabel = endLabel
+ def end(self):
+ #self.asm.visitLabel(self.endLabel)
+ Block.end(self)
+
+class ForBlock(Block):
+ def __init__(self, asm):
+ Block.__init__(self, asm, 1)
+ def exit(self, hasState=None):
+ self.asm.pop() # pop the iterator from the stack.
+ return Block.exit(self, hasState)
+
+class TryBlock(Block):
+ def __init__(self, asm, catch, endLabel, handlerBlock, stackPersistence,
+ stackSize=0, *stateVariables):
+ # endLabel is an ASM label
+ Block.__init__(self, asm, stackSize, *stateVariables)
+ self.__catch = catch
+ self.endLabel = endLabel
+ self.handlerBlock = handlerBlock
+ self.__stackPersistence = stackPersistence
+ surroundingStackSize = property(lambda self: len(self.__stackPersistence))
+ nestingStackSize = property(lambda self: (self.stackSize -
+ self.surroundingStackSize))
+ def end(self):
+ self.asm.visitLabel(self.endLabel)
+ Block.end(self)
+ def endVariables(self):
+ for variable in self.__stackPersistence:
+ variable.end()
+ def loadState(self):
+ for variable in self.__stackPersistence:
+ variable.load()
+ def storeState(self):
+ for i in xrange(len(self.__stackPersistence) -1,-1,-1):
+ variable = self.__stackPersistence[i]
+ variable.store()
+ def exclude(self, start, end):
+ self.__catch.exclude(start, end)
+
+class HandlerBlock(Block):
+ def __init__(self, asm, sourceBlock, stackSize=0, *stateVariables):
+ Block.__init__(self, asm, stackSize, *stateVariables)
+ self.sourceBlock = sourceBlock
+ def end(self):
+ self.sourceBlock.loadState()
+ self.sourceBlock.endVariables()
+
+class TryExceptBlock(TryBlock):
+ def __init__(self, asm, catch, endLabel, stackPersistence):
+ # endLabel is an ASM label
+ TryBlock.__init__(
+ self, asm, catch, endLabel, ExceptBlock(asm, self),
+ stackPersistence)
+ def end(self):
+ TryBlock.end(self)
+ self.loadState()
+
+class ExceptBlock(HandlerBlock):
+ def __init__(self, asm, sourceBlock):
+ HandlerBlock.__init__(self, asm, sourceBlock, 3)
+ def end(self):
+ """stack is: ... exc_traceback exc_value exc_type"""
+ self.asm.dupX2()
+ self.asm.pop()
+ self.asm.swap()
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyException makeException (%s)" % ", ".join([
+ "org.python.core.PyObject"]*3)))
+ self.asm.throwException()
+ HandlerBlock.end(self)
+
+class TryFinallyBlock(TryBlock):
+ def __init__(self, asm, catch, endLabel, handlerLabel, afterLabel,
+ retVariable, stackPersistence):
+ # Labels are ASM labels
+ TryBlock.__init__(
+ self, asm, catch, endLabel,
+ FinallyBlock(asm,self,afterLabel,retVariable),
+ stackPersistence, 0, retVariable)
+ self.handlerLabel = handlerLabel
+ retVariable = property(lambda self: self.handlerBlock.retVariable)
+ resumeLabels = property(lambda self: self.handlerBlock.resumeLabels)
+ def end(self):
+ self.exit(False)
+ TryBlock.end(self)
+ def exit(self,hasState=True):
+ """hasState is True if there is a (return-) variable on the stack."""
+ self.asm.push(java.lang.Integer(len(self.resumeLabels)))
+ self.retVariable.store()
+ if not hasState:
+ self.asm.visitInsn(Op.ACONST_NULL)
+ label = self.asm.newLabel()
+ self.resumeLabels.append(label)
+ self.asm.goTo(self.handlerLabel)
+ self.asm.visitLabel(label)
+ if not hasState:
+ self.asm.pop()
+ return True
+
+class FinallyBlock(HandlerBlock):
+ def __init__(self, asm, sourceBlock, afterLabel, retVariable):
+ HandlerBlock.__init__(self, asm, sourceBlock, 1, retVariable)
+ self.afterLabel = afterLabel
+ self.retVariable = retVariable
+ self.resumeLabels = []
+ nestingStackSize = property(
+ lambda self: self.stackSize - self.sourceBlock.surroundingStackSize)
+ def end(self):
+ throw = self.asm.newLabel()
+ if self.resumeLabels:
+ reRaise = self.asm.newLabel()
+ self.retVariable.load()
+ self.retVariable.end()
+ self.asm.visitTableSwitchInsn(0, len(self.resumeLabels)-1, reRaise,
+ array(self.resumeLabels, asm.Label))
+ self.asm.visitLabel(reRaise)
+ self.asm.dup()
+ self.asm.instanceOf(throwableType)
+ self.asm.visitJumpInsn(Op.IFNE, throw)
+ self.asm.pop()
+ self.asm.goTo(self.afterLabel)
+ self.asm.visitLabel(throw)
+ self.asm.checkCast(throwableType)
+ self.asm.throwException()
+ self.asm.visitLabel(self.afterLabel)
+ HandlerBlock.end(self)
+
+
+class LocalVariable(object):
+ def __init__(self, asm, varType, name):
+ self.asm = asm
+ self.varType = varType
+ self.name = name
+ varno = self.__varno = asm.newLocal(varType)
+ #start = self.__start = asm.newLabel()
+ #end = self.__end = asm.newLabel()
+ #asm.visitLabel(start)
+ def store(self):
+ self.asm.storeLocal(self.__varno, self.varType)
+ def load(self):
+ self.asm.loadLocal(self.__varno, self.varType)
+ def __iadd__(self, value):
+ self.asm.iinc(self.__varno, value)
+ def __int__(self):
+ return self.__varno
+ def end(self):
+ #self.asm.visitLabel(self.__end)
+ #self.asm.visitLocalVariable(self.name, self.varType.getDescriptor(),
+ # None,self.__start,self.__end,self.__varno)
+ pass
+ def ret(self):
+ self.asm.ret(self.__varno)
+ self.end()
+
+class TryCatch(object):
+ def __init__(self, start, end, handle, excType):
+ self.start = start
+ self.end = end
+ self.handle = handle
+ self.excType = excType
+ self.exclusions = []
+ def exclude(self, start, end):
+ self.exclusions.append((start,end))
+ def accept(self, asm):
+ start = self.start
+ for exStart, exEnd in self.exclusions:
+ asm.visitTryCatchBlock(start, exStart, self.handle, self.excType)
+ start = exEnd
+ asm.visitTryCatchBlock(start, self.end, self.handle, self.excType)
+
+class ASMVisitor(Visitor):
+ def __init__(self, magic, parent=None): # FIXME: change contract?
+ if magic is None:
+ magic = magicNumbers['2.5c2']
+ self.__magic = magic
+ self.__blocks = []
+ self.__parent = parent
+ if parent is None:
+ self.__class = ClassKeeper("MODULE")
+ else:
+ self.__class = parent.__class
+ self.__labels = {}
+ self.__codeSchedule = {}
+ self.__tryBlocks = []
+
+ def visitCode(self, argcount, nlocals, stacksize, flags, constants, names,
+ varnames, freevars, cellvars, filename, name, firstlineno):
+ # FIXME: change contract?
+ self.__argcount = argcount # long
+ self.__nlocals = nlocals # long -- ignored ?
+ self.__stacksize = stacksize # long -- ignored ?
+ self.__flags = flags # long
+ self.__constants = constants # (Py)Object[] - PyObject or coderef
+ self.__names = names # String[]
+ self.__varnames = list(varnames) # String[]
+ self.__freevars = list(freevars) # String[]
+ self.__cellvars = list(cellvars) # String[]
+ self.__filename = filename # String
+ self.__name = name # String
+ self.__firstlineno = firstlineno # long
+
+ self.__class.setFilename(filename)
+
+ self.asm = self.__class.newFunction(name)
+ self.asm.visitCode()
+ self.__code = self.__class.getCodeReference()
+
+ def label(self, pyLabel=None):
+ if pyLabel is None:
+ return self.asm.newLabel()
+ elif pyLabel in self.__labels:
+ return self.__labels[pyLabel]
+ else:
+ label = self.asm.newLabel()
+ self.__labels[pyLabel] = label
+ return label
+
+ def newLocal(self, varType, name):
+ return LocalVariable(self.asm, varType, name)
+
+ def scheduleCode(self, label, code=None):
+ """Schedule a code generating function to be executed after visiting
+ a particular label.
+ If code is None, this method returns a decorator..."""
+ def addCode(code):
+ if label.visited:
+ raise RuntimeError("The label '%s' has already been visited."
+ " Cannot schedule code." % label)
+ self.__codeSchedule.setdefault(label, []).append(code)
+ if code is None:
+ return addCode
+ else:
+ addCode(code)
+
+ def push(self, value):
+ if isinstance(value, int):
+ value = java.lang.Integer(value)
+ self.asm.push(value)
+
+ def loadFrame(self):
+ self.asm.loadArg(0)
+
+
+ def getCode(self): # FIXME: change contract?
+ if self.__parent is None:
+ return self.__class.getCode(self.__code.getName())
+ else:
+ return self.__code
+
+ def getName(self, index):
+ return self.__names[index]
+
+ def getVariableName(self, index):
+ return self.__varnames[index]
+
+ def getOuterName(self, index):
+ if index < len(self.__cellvars):
+ return self.__cellvars[index]
+ else:
+ return self.__freevars[index - len(self.__cellvars)]
+
+ def getConstant(self, index):
+ return self.__constants[index]
+
+ binaryOperator = {Operator.ADD: '_add',
+ Operator.SUBTRACT: '_sub',
+ Operator.MULTIPLY: '_mul',
+ Operator.DIVIDE: '_div',
+ Operator.FLOOR_DIVIDE: '_floordiv',
+ Operator.TRUE_DIVIDE: '_truediv',
+ Operator.MODULO: '_mod',
+ Operator.POWER: '_pow',
+ Operator.LSHIFT: '_lshift',
+ Operator.RSHIFT: '_rshift',
+ Operator.AND: '_and',
+ Operator.OR: '_or',
+ Operator.XOR: '_xor',
+ Operator.SUBSCRIPT: '__getitem__',}
+ def visitBinaryOperator(self, operator):
+ """TOS1, TOS -- TOS1 op TOS"""
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject %s (org.python.core.PyObject)" %
+ self.binaryOperator[operator]))
+
+ inplaceOperator = {Operator.ADD: '__iadd__',
+ Operator.SUBTRACT: '__isub__',
+ Operator.MULTIPLY: '__imul__',
+ Operator.DIVIDE: '__idiv__',
+ Operator.FLOOR_DIVIDE: '__ifloordiv__',
+ Operator.TRUE_DIVIDE: '__itruediv__',
+ Operator.MODULO: '__imod__',
+ Operator.POWER: '__ipow__',
+ Operator.LSHIFT: '__ilshift__',
+ Operator.RSHIFT: '__irshift__',
+ Operator.AND: '__iand__',
+ Operator.OR: '__ior__',
+ Operator.XOR: '__ixor__',}
+ def visitInplaceOperator(self, operator):
+ """ -- """
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject %s (org.python.core.PyObject)" %
+ self.inplaceOperator[operator]))
+
+ unaryOperator = {Operator.INVERT: '__invert__',
+ Operator.POSITIVE: '__pos__',
+ Operator.NEGATIVE: '__neg__',
+ Operator.NOT: '__not__',
+ Operator.CONVERT: '__repr__',}
+ def visitUnaryOperator(self, operator):
+ """value -- (op value)"""
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject %s ()" %
+ self.unaryOperator[operator]))
+
+ compareOperator = {Operator.LESS_THAN: '_lt',
+ Operator.LESS_THAN_OR_EQUAL: '_le',
+ Operator.EQUAL: '_eq',
+ Operator.NOT_EQUAL: '_ne',
+ Operator.GREATER_THAN: '_gt',
+ Operator.GREATER_THAN_OR_EQUAL: '_ge',
+ Operator.IN: '_in',
+ Operator.NOT_IN: '_notin',
+ Operator.IS: '_is',
+ Operator.IS_NOT: '_isnot',}
+ def visitCompareOperator(self, operator):
+ """element, element -- bool"""
+ if operator == Operator.EXCEPTION_MATCH:
+ self.asm.swap()
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyException makeException (%s)"%", ".join(
+ ['org.python.core.PyObject'])))
+ self.asm.swap()
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "boolean matchException (%s)" % ", ".join(
+ ['org.python.core.PyException',
+ 'org.python.core.PyObject'])))
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyBoolean newBoolean (boolean)"))
+ else:
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject %s (org.python.core.PyObject)" %
+ self.compareOperator[operator]))
+
+ def visitBuildClass(self):
+ """name, bases, dict -- class"""
+ sequenceType = getType(core.PySequenceList)
+ bases = self.newLocal(getArrayType(pyObjectType), "bases")
+ dict = self.newLocal(pyObjectType, "dict")
+ dict.store()
+ self.asm.checkCast(sequenceType)
+ self.asm.invokeVirtual(sequenceType, Method.getMethod(
+ "org.python.core.PyObject[] getArray ()"))
+ bases.store()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "String toString ()"))
+ bases.load(); bases.end()
+ dict.load(); dict.end()
+ self.asm.invokeStatic(compilerResources, Method.getMethod(
+ "org.python.core.PyObject makeClass (%s)" % ", ".join(
+ ["String", "org.python.core.PyObject[]",
+ "org.python.core.PyObject"])))
+
+ def buildArray(self, size, array):
+ """helper method for buildSequence.
+ Expects `size` elements on the stack, produces an array,
+ returns the local value index for the array (NOT on stack)"""
+ # store the values in the array
+ for i in range(size -1,-1,-1):
+ array.load()
+ self.asm.swap()
+ self.push(i)
+ self.asm.swap()
+ self.asm.arrayStore(pyObjectType)
+
+ def visitUnpackSequence(self, count):
+ """sequence -- (element, )*count"""
+ sequenceType = getType(core.PySequenceList)
+ self.asm.checkCast(sequenceType) # FIXME: could generate better error
+ self.asm.dup()
+ self.asm.invokeVirtual(sequenceType, Method.getMethod(
+ "int size ()"))
+ self.push(count)
+ ok = self.label()
+ self.asm.ifICmp(self.asm.EQ, ok)
+ self.push("Incompatible lengths for unpack")
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyException ValueError (String)"))
+ self.asm.throwException()
+ self.asm.visitLabel(ok)
+ method = Method.getMethod("org.python.core.PyObject pyget (int)")
+ sequence = self.newLocal(sequenceType, "sequence")
+ sequence.store()
+ for i in range(count -1, -1, -1):
+ sequence.load()
+ self.push(i)
+ self.asm.invokeVirtual(sequenceType, method)
+ sequence.end()
+
+ def buildSequence(self, seqType, size):
+ """helper method for BuildTuple and BuildList"""
+ # create an array
+ self.push(size)
+ self.asm.newArray(pyObjectType)
+ # store it for reference
+ array = self.newLocal(getArrayType(pyObjectType),"array")
+ array.store()
+ self.buildArray(size, array)
+ # create a PyList/PyTuple from the array
+ self.asm.newInstance(seqType)
+ self.asm.dup()
+ array.load()
+ array.end()
+ self.asm.invokeConstructor(seqType, Method.getMethod(
+ "void <init> (org.python.core.PyObject[])"))
+
+ def visitBuildTuple(self, size):
+ """(element,) * size -- tuple"""
+ self.buildSequence(getType(core.PyTuple), size)
+
+ def visitBuildList(self, size):
+ """(element,) * size -- list"""
+ self.buildSequence(getType(core.PyList), size)
+
+ def visitBuildMap(self, zero):
+ """ -- dict"""
+ assert zero == 0
+ self.asm.newInstance(pyDictType)
+ self.asm.dup()
+ self.asm.invokeConstructor(Type.getType(core.PyDictionary),
+ Method.getMethod("void <init> ()"))
+
+ def visitBuildSlice(self, numargs):
+ """start, stop[, step] -- slice"""
+ if numargs == 3:
+ pass
+ elif numargs == 2:
+ self.push(None)
+ #elif numargs == 1:
+ # self.push(None)
+ # self.asm.swap()
+ # self.push(None)
+ else:
+ raise TypeError("Can only build slices from 2 or 3 arguments.")
+ #start = self.newLocal(pyObjectType,"start")
+ #stop = self.newLocal(pyObjectType,"stop")
+ #step = self.newLocal(pyObjectType,"step")
+ #step.store()
+ #stop.store()
+ #start.store()
+ step = self.newLocal(pyObjectType,"step")
+ step.store()
+ self.asm.newInstance(Type.getType(core.PySlice))
+ self.asm.dup()
+ self.asm.dup2X2()
+ self.asm.pop()
+ self.asm.pop()
+ #start.load()
+ #stop.load()
+ step.load()
+ #start.end()
+ #stop.end()
+ step.end()
+ self.asm.invokeConstructor(
+ Type.getType(core.PySlice), Method.getMehtod(
+ "void <init> (%s)" % ", ".join(["org.python.core.PyObject"]*3)))
+
+ def setupCallParameters(self, num_pos, num_keyword, arguments, keywords):
+ """helper for the various CallFunction methods."""
+ for i in range(num_keyword -1,-1,-1):
+ arguments.load()
+ self.asm.swap()
+ self.push(num_pos + i)
+ self.asm.swap()
+ self.asm.arrayStore(pyObjectType)
+ keywords.load()
+ self.asm.swap()
+ self.push(i)
+ self.asm.swap()
+ self.asm.arrayStore(getType(java.lang.String))
+ self.buildArray(num_pos, arguments)
+
+ def visitCallFunction(self, num_pos, num_keyword):
+ """(arg,) * num_pos, (name, arg) * num_keyword -- value"""
+ arguments = self.newLocal(getArrayType(pyObjectType),"arguments")
+ keywords = self.newLocal(getArrayType(getType(java.lang.String)),"kw")
+ self.push(num_pos + num_keyword)
+ self.asm.newArray(pyObjectType)
+ arguments.store()
+ self.push(num_keyword)
+ self.asm.newArray(getType(java.lang.String))
+ keywords.store()
+ self.setupCallParameters(num_pos, num_keyword, arguments, keywords)
+ arguments.load()
+ keywords.load()
+ arguments.end()
+ keywords.end()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __call__ (%s)" % ", ".join([
+ "org.python.core.PyObject[]", "String[]"
+ ])))
+
+ def visitCallFunctionKeyword(self, num_pos, num_keyword):
+ """(arg,) * num_pos, (name, arg) * num_keyword, dict -- value"""
+ self.push(None)
+ self.asm.swap()
+ self.visitCallFunctionVarargKeyword(num_pos, num_keyword)
+
+ def visitCallFunctionVararg(self, num_pos, num_keyword):
+ """(arg,) * num_pos, (name, arg) * num_keyword, list -- value"""
+ self.push(None)
+ self.visitCallFunctionVarargKeyword(num_pos, num_keyword)
+
+ def visitCallFunctionVarargKeyword(self, num_pos, num_keyword):
+ """(arg,) * num_pos, (name, arg) * num_keyword, list, dict -- value"""
+ args = self.newLocal(pyObjectType,"args")
+ kwargs = self.newLocal(pyObjectType,"kwargs")
+ kwargs.store()
+ args.store()
+ arguments = self.newLocal(getArrayType(pyObjectType),"arguments")
+ keywords = self.newLocal(getArrayType(getType(java.lang.String)),"kw")
+ self.push(num_pos + num_keyword)
+ self.asm.newArray(pyObjectType)
+ arguments.store()
+ self.push(num_keyword)
+ self.asm.newArray(getType(java.lang.String))
+ keywords.store()
+ self.setupCallParameters(num_pos, num_keyword, arguments, keywords)
+ arguments.load()
+ keywords.load()
+ args.load()
+ kwargs.load()
+ args.end()
+ kwargs.end()
+ arguments.end()
+ keywords.end()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject _callextra (%s)" % ", ".join([
+ "org.python.core.PyObject[]", "String[]",
+ "org.python.core.PyObject", "org.python.core.PyObject",
+ ])))
+
+ def visitBreakLoop(self):
+ """ -- """
+ for i in xrange(len(self.__blocks) -1,-1,-1):
+ block = self.__blocks[i]
+ block.exit(False)
+ if isinstance(block, LoopBlock):
+ self.asm.goTo(block.endLabel)
+ break
+ else: # No surrounding LoopBlock was found
+ raise SyntaxError("break not properly nested in loop.")
+
+ def visitContinueLoop(self, loopStart):
+ """ -- """
+ for i in xrange(len(self.__blocks) -1,-1,-1):
+ block = self.__blocks[i]
+ if isinstance(block, LoopBlock):
+ break
+ else:
+ block.exit(False)
+ self.asm.goTo(self.label(loopStart))
+
+ def visitDeleteAttribute(self, attributeName):
+ """object -- """
+ self.push(attributeName)
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "void __delattr__ (String)"))
+
+ def visitDeleteFast(self, localName):
+ """ -- """
+ self.loadFrame()
+ self.push(self.__varnames.index(localName))
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void dellocal (int)"))
+
+ def visitDeleteGlobal(self, globalName):
+ """ -- """
+ self.loadFrame()
+ self.push(globalName)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void delglobal (String)"))
+
+ def visitDeleteName(self, name):
+ """ -- """
+ self.loadFrame()
+ self.push(name)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void dellocal (String)"))
+
+ def setupSlice(self, plus):
+ """help method for (Load|Store|Delete)Slice"""
+ if plus > 3:
+ raise TypeError("Slices only support pluses in range(4).")
+ if plus == 0: # stack: -
+ self.push(None)
+ self.push(None)
+ self.push(None)
+ elif plus == 1: # stack: start
+ self.push(None)
+ self.push(None)
+ elif plus == 2: # stack: end
+ self.push(None)
+ self.asm.swap()
+ self.push(None)
+ elif plus == 3: # stack: start end
+ self.push(None)
+ ## FUTURE EXTENSION
+ elif plus == 4: # stack: step
+ self.push(None)
+ self.asm.swap()
+ self.push(None)
+ self.asm.swap()
+ elif plus == 5: # stack: start step
+ self.push(None)
+ self.asm.swap()
+ elif plus == 6: # stack: end step
+ self.push(None)
+ self.rot(3)
+ elif plus == 7: # stack: start end step
+ pass
+ else:
+ raise TypeError("Slices only support pluses in range(8).")
+
+ def visitDeleteSlice(self, plus):
+ """object [,object[,object]] -- """
+ self.setupSlice(plus)
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "void __delslice__ (%s)" % ", ".join(
+ ["org.python.core.PyObject"]*3)))
+
+ def visitDeleteSubscript(self):
+ """ object, index -- """
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "void __delitem__ (org.python.core.PyObject)"))
+
+ __dupMax = 5
+ def visitDup(self, numElements=1):
+ """(item, )*numElements -- (item, )*numElements, (item, )*numElements"""
+ if numElements < 1 or numElements > self.__dupMax:
+ raise TypeError("DUP can only be performed on depths in range(1,%s)"
+ % (self.__dupMax + 1))
+ if numElements == 1:
+ self.asm.dup()
+ elif numElements == 2:
+ self.asm.dup2()
+ elif numElements == 3:
+ top = self.newLocal(pyObjectType,"top")
+ top.store()
+ self.asm.dup2()
+ top.load()
+ top.end()
+ self.asm.dupX2()
+ elif numElements == 4:
+ top = self.newLocal(pyObjectType,"top")
+ top2 = self.newLocal(pyObjectType,"top2")
+ top.store()
+ top2.store()
+ self.asm.dup2()
+ top2.load()
+ top.load()
+ top.end()
+ top2.end()
+ self.asm.dup2X2()
+ else: # 5 and more is quite expensive on local variables. O(n)
+ # Store all elements in variables
+ vars = [self.newLocal(pyObjectType,"var%X"%x)
+ for x in range(numElements)]
+ for var in vars:
+ var.store()
+ # reverse the order to assert correct stack order
+ # and load them twice...
+ vars.reverse()
+ for var in vars:
+ var.load()
+ for var in vars:
+ var.load()
+ var.end()
+
+ def visitExecStatement(self):
+ """code, globals, locals -- """
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "void exec (%s)" % ", ".join(["org.python.core.PyObject"]*3)))
+
+ def visitForIteration(self, end):
+ """iter -- iter value | """
+ self.__blocks.append(ForBlock(self.asm))
+ def code():
+ block = self.__blocks.pop()
+ if not isinstance(block, ForBlock):
+ TypeError("Illegal block state, expected ForBlock, not %s"
+ % type(block))
+ block.end()
+ self.scheduleCode(end, code)
+ body = self.label()
+ self.asm.dup()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __iternext__ ()"))
+ self.asm.dup()
+ self.asm.visitJumpInsn(Op.IFNONNULL, body)
+ self.asm.pop2()
+ self.asm.goTo(self.label(end))
+ self.asm.visitLabel(body)
+
+ def visitGetIterator(self):
+ """obj -- iter(obj)"""
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __iter__ ()"))
+
+ def visitImportFrom(self, name):
+ """module -- module module.name"""
+ # not the most beautiful implementation
+ self.asm.dup()
+ self.push(name)
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __getattr__ (String)"))
+
+ def visitImportName(self, name):
+ """[absolutivity] fromlist -- module"""
+ # FIXME: move this to the lib
+ # Jython cannot handle the fromlist being None
+ # here is an ugly hack to avoid that in runtime
+ # something like this should be pushed to the lib
+ ok = self.asm.newLabel()
+ self.asm.dup()
+ self.asm.instanceOf(pyTupleType)
+ self.asm.visitJumpInsn(Op.IFNE, ok)
+ self.asm.pop()
+ self.asm.getStatic(pyType, 'EmptyTuple', pyTupleType)
+ self.asm.visitLabel(ok)
+ if self.__magic >= magicNumbers['2.5a0']: # has absolutivity
+ pass
+ else: # doesn't have absolutivity, add it
+ self.push(-1) # old, standard behaviour
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyInteger newInteger (int)"))
+ self.asm.swap()
+ # FIXME: ignoring absolutivity for now... Absolute import won't work
+ self.asm.swap(); self.asm.pop() # <- ignore absolutivity for now
+ self.push(name)
+ self.asm.swap()
+ self.loadFrame()
+ self.asm.getField(pyFrameType, 'f_globals', pyObjectType)
+ self.asm.swap()
+ self.loadFrame()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getf_locals ()"))
+ self.asm.swap()
+ self.asm.invokeStatic(pyBuiltin, Method.getMethod(
+ "org.python.core.PyObject __import__ (%s)" % ", ".join(
+ ["String", "org.python.core.PyObject",
+ "org.python.core.PyObject", "org.python.core.PyObject"])))
+
+ def visitImportStar(self):
+ """module -- """
+ self.loadFrame()
+ self.asm.invokeStatic(compilerResources, Method.getMethod(
+ "void importAll (%s)" % ", ".join([
+ "org.python.core.PyObject",
+ "org.python.core.PyFrame"])))
+
+ def visitJump(self, destination):
+ """ -- """
+ self.asm.goTo(self.label(destination))
+
+ def visitJumpIfFalse(self, label):
+ """value -- value"""
+ self.asm.dup()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "boolean __nonzero__ ()"))
+ self.asm.visitJumpInsn(Op.IFEQ, self.label(label))
+
+ def visitJumpIfTrue(self, label):
+ """value -- value"""
+ self.asm.dup()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "boolean __nonzero__ ()"))
+ self.asm.visitJumpInsn(Op.IFNE, self.label(label))
+
+ def visitLabel(self, label):
+ """ -- """
+ label.visited = True
+ self.asm.visitLabel(self.label(label))
+ for code in self.__codeSchedule.get(label,()):
+ code()
+
+ def visitLineNumber(self, lineNo):
+ """ -- """
+ # add line number for java debuger
+ label = self.label()
+ self.asm.visitLabel(label)
+ self.asm.visitLineNumber(lineNo, label)
+ # add line number for jython frame
+ self.loadFrame()
+ self.push(lineNo)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void setline (int)"))
+
+ def visitListAppend(self):
+ """list element -- """
+ self.asm.swap()
+ self.asm.checkCast(pyListType)
+ self.asm.swap()
+ self.asm.invokeVirtual(pyListType, Method.getMethod(
+ "void append (org.python.core.PyObject)"))
+
+ def visitLoadAttribute(self, attributeName):
+ """object -- object"""
+ self.push(attributeName)
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __getattr__ (String)"))
+
+ def derefIndex(self, variable):
+ """Helper for LoadClosure, LoadDeref and StoreDeref"""
+ if variable in self.__cellvars:
+ self.push(self.__cellvars.index(variable))
+ else:
+ self.push(len(self.__cellvars) + self.__freevars.index(variable))
+
+ def visitLoadClosure(self, variableName):
+ """ -- cellvar"""
+ if variableName in self.__varnames:
+ self.loadFrame()
+ self.push(self.__varnames.index(variableName))
+ self.derefIndex(variableName)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void to_cell (int, int)"))
+ self.loadFrame()
+ self.derefIndex(variableName)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getclosure (int)"))
+
+ def visitLoadDeref(self, variableName):
+ """ -- object"""
+ self.loadFrame()
+ self.derefIndex(variableName)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getderef (int)"))
+
+ def visitLoadConstant(self, const):
+ """ -- object"""
+ if reallyContains(self.__class.constants,const):
+ constName, constType = self.__class.constants[const]
+ self.asm.getStatic(pyType, constName, constType)
+ elif isinstance(const, CodeReference):
+ self.asm.getStatic(self.__class.asType, const.getName(), pyCodeType)
+ else:
+ self.asm.getStatic(self.__class.asType,
+ self.__class.getConstant(const),
+ pyObjectType)
+
+ def visitLoadFast(self, localName):
+ """ -- object"""
+ self.loadFrame()
+ self.push(self.__varnames.index(localName))
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getlocal (int)"))
+
+ def visitLoadGlobal(self, globalName):
+ """ -- object"""
+ self.loadFrame()
+ self.push(globalName)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getglobal (String)"))
+
+ def visitLoadLocals(self):
+ """ -- locals"""
+ self.loadFrame()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getf_locals ()"))
+
+ def visitLoadName(self, name):
+ """ -- object"""
+ self.loadFrame()
+ self.push(name)
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getname (String)"))
+
+ def visitLoadSlice(self, plus):
+ """object [,object[,object]] -- value"""
+ self.setupSlice(plus)
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __getslice__ (%s)" % ", ".join(
+ ["org.python.core.PyObject"]*3)))
+
+ def visitMakeClosure(self, numDefault):
+ """(value, )*numDefault, tuple, code -- function"""
+ functionType = getType(core.PyFunction)
+ sequenceType = getType(core.PySequenceList)
+ code = self.newLocal(pyCodeType,"code")
+ cell = self.newLocal(sequenceType,"cell")
+ code.store()
+ cell.store()
+ # create an array
+ self.push(numDefault)
+ self.asm.newArray(pyObjectType)
+ # store it for reference
+ default = self.newLocal(getArrayType(pyObjectType),"default")
+ default.store()
+ self.buildArray(numDefault, default)
+ self.asm.newInstance(functionType)
+ self.asm.dup()
+ self.loadFrame()
+ self.asm.getField(pyFrameType, "f_globals", pyObjectType)
+ default.load()
+ code.load()
+ cell.load()
+ code.end()
+ cell.end()
+ default.end()
+ self.asm.invokeVirtual(sequenceType, Method.getMethod(
+ "org.python.core.PyObject[] getArray ()"))
+ self.asm.invokeConstructor(functionType, Method.getMethod(
+ "void <init> (%s)" % ", ".join([
+ "org.python.core.PyObject", # globals
+ "org.python.core.PyObject[]", # defaults
+ "org.python.core.PyCode", # code
+ "org.python.core.PyObject[]", # closure_cells
+ ])))
+
+ def visitMakeFunction(self, numDefault):
+ """(value, )*numDefault, code -- function"""
+ # TODO: the code objects need a "getDoc" method...
+ # since that is where python bytecode stores the docstring
+ functionType = getType(core.PyFunction)
+ sequenceType = getType(core.PySequenceList)
+ code = self.newLocal(pyCodeType,"code")
+ code.store()
+ # create an array
+ self.push(numDefault)
+ self.asm.newArray(pyObjectType)
+ # store it for reference
+ default = self.newLocal(getArrayType(pyObjectType),"default")
+ default.store()
+ self.buildArray(numDefault, default)
+ self.asm.newInstance(functionType)
+ self.asm.dup()
+ self.loadFrame()
+ self.asm.getField(pyFrameType, "f_globals", pyObjectType)
+ default.load()
+ code.load()
+ default.end()
+ code.end()
+ self.asm.invokeConstructor(functionType, Method.getMethod(
+ "void <init> (%s)" % ", ".join([
+ "org.python.core.PyObject", # globals
+ "org.python.core.PyObject[]", # defaults
+ "org.python.core.PyCode", # code
+ ])))
+
+ def visitNOP(self):
+ """ -- """
+ self.asm.visitInsn(Op.NOP) # NOTE: should this be the implementation?
+
+ def visitPop(self):
+ """ -- """
+ self.asm.pop()
+
+ def visitPrintExpression(self):
+ """object -- """
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "void println (org.python.core.PyObject)"))
+
+ def visitPrintItem(self):
+ """object -- """
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "void printComma (org.python.core.PyObject)"))
+
+ def visitPrintItemTo(self):
+ """object, object -- """
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "void printComma (%s)" % ", ".join(
+ ["org.python.core.PyObject)"]*2)))
+
+ def visitPrintNewline(self):
+ """ -- """
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "void println ()"))
+
+ def visitPrintNewlineTo(self):
+ """ -- """
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "void printlnv (org.python.core.PyObject)"))
+
+ def visitRaiseVarargs(self, count):
+ """(object, )*count -- """
+ # if there is content on the stack: reverse it
+ if count == 2:
+ self.asm.swap()
+ elif count == 3:
+ self.asm.swap()
+ self.rot()
+ elif count < 0 or count > 3:
+ raise TypeError("RAISE_VARARGS accepts only arguments in range(4)")
+ self.rot(count)
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyException makeException (%s)" % ", ".join(
+ ["org.python.core.PyObject"]*count)))
+ self.asm.throwException()
+
+ def visitReturnValue(self):
+ """object -- """
+ jumps = False
+ for i in xrange(len(self.__blocks) -1,-1,-1):
+ block = self.__blocks[i]
+ jumps = block.exit() or jumps
+ self.loadFrame()
+ self.push(-1)
+ self.asm.putField(pyFrameType, 'f_lasti', Type.INT_TYPE)
+ if jumps:
+ self.asm.checkCast(pyObjectType)
+ self.asm.returnValue()
+
+ __rotMax = 4
+ def visitRot(self, depth):
+ """(object, )*(depth - 1), element -- element, (object, )*(depth - 1)"""
+ if depth < 2 or depth > self.__rotMax:
+ raise TypeError("ROT can only be performed on depths in range(2,%s)"
+ % (self.__rotMax + 1))
+ if depth == 2: # ROT_2 is swap
+ self.asm.swap()
+ else:
+ top = self.newLocal(pyObjectType,"top")
+ self.asm.swap()
+ top.store()
+ self.visitRot(depth - 1)
+ top.load()
+ top.end()
+
+ def rot(self, depth=3):
+ if depth < 2:
+ raise TypeError("can only rot 2 or larger depths")
+ if depth == 2:
+ self.asm.swap()
+ else:
+ top = self.newLocal(pyObjectType,"top")
+ top.store()
+ self.rot(depth - 1)
+ top.load()
+ top.end()
+ self.asm.swap()
+
+ def tryCatchBlock(self, start, end, handle, excType):
+ # the try/catch-blocks needs to be reversed to assert pythons
+ # behaviour for nested try-blocks, this is done by storing them
+ # when a try/catch-block is encounterd and emmiting them in reversed
+ # order when the end of the code is encounterd.
+ catch = TryCatch(start, end, handle, excType)
+ self.__tryBlocks.append(catch)
+ return catch
+ ## Old behaviour:
+ #self.asm.visitTryCatchBlock(start, end, handle, excType)
+
+ def visitSetupExcept(self, startExcept):
+ """ -- """
+ start = self.label()
+ end = self.label()
+ handle = self.label(startExcept)
+ catch = self.tryCatchBlock(start, end, handle, "java/lang/Throwable")
+ # assert the stack state of surrounding blocks
+ stackDepth = 0
+ for block in self.__blocks:
+ stackDepth += block.nestingStackSize
+ block = TryExceptBlock(self.asm, catch, end,
+ [self.newLocal(pyObjectType,'')
+ for i in xrange(stackDepth)])
+ block.storeState() # store the stack state of surrounding variables
+ self.__blocks.append(block)
+ #@self.scheduleCode(startExcept)
+ def code():
+ """JavaException -- traceback value type
+ Set up the stack when the exception has been rised."""
+ self.__blocks.append(block.handlerBlock)
+ self.loadFrame()
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyException setException (%s)"%", ".join(
+ ["Throwable", "org.python.core.PyFrame"])))
+ exception = self.newLocal(pyExceptionType,"exception")
+ exception.store()
+ block.loadState() # load stack from enclosing blocks
+ exception.load()
+ self.asm.getField(pyExceptionType, "traceback",
+ getType(core.PyTraceback))
+ exception.load()
+ self.asm.getField(pyExceptionType, "value", pyObjectType)
+ exception.load()
+ exception.end()
+ self.asm.getField(pyExceptionType, "type", pyObjectType)
+ self.scheduleCode(startExcept, code)
+ self.asm.visitLabel(start)
+
+ def visitSetupFinally(self, startFinal):
+ """ -- """
+ start = self.label()
+ end = self.label()
+ handle = self.label()
+ internal = self.label()
+ after = self.label()
+ retVariable = self.newLocal(Type.INT_TYPE, "retVariable")
+ self.push(-1)
+ retVariable.store()
+ catch = self.tryCatchBlock(start, end, handle, "java/lang/Throwable")
+ # assert the stack state of surrounding blocks
+ stackDepth = 0
+ for block in self.__blocks:
+ stackDepth += block.nestingStackSize
+ block = TryFinallyBlock(self.asm, catch, end, internal, after,
+ retVariable, [self.newLocal(pyObjectType,'')
+ for i in xrange(stackDepth)])
+ block.storeState() # store the stack state of surrounding variables
+ self.__blocks.append(block)
+ #@self.scheduleCode(startFinal)
+ def code():
+ """JavaException -- PythonException
+ Set up the stack when the exception has been rised."""
+ self.asm.pop()
+ self.asm.goTo(after)
+ self.__blocks.append(block.handlerBlock)
+ self.asm.visitLabel(handle)
+ self.loadFrame()
+ self.asm.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyException setException (%s)"%", ".join(
+ ["Throwable", "org.python.core.PyFrame"])))
+ self.asm.visitLabel(internal)
+ self.scheduleCode(startFinal, code)
+ self.asm.visitLabel(start)
+
+ def visitEndFinally(self):
+ """ -- """
+ block = self.__blocks.pop()
+ if not isinstance(block, (FinallyBlock, ExceptBlock)):
+ raise TypeError("EndFinally popped block of type %s" % type(block))
+ block.end()
+
+ def visitSetupLoop(self, loopEnd):
+ """ -- """
+ block = LoopBlock(self.asm, self.label(loopEnd))
+ self.__blocks.append(block)
+
+ def visitPopBlock(self):
+ """ -- """
+ block = self.__blocks.pop()
+ if not isinstance(block, (LoopBlock, TryFinallyBlock, TryExceptBlock)):
+ raise TypeError("PopBlock popped block of type %s" % type(block))
+ block.end()
+
+ def visitStopCode(self):
+ """ -- """
+ raise TypeError("Encountered STOP_CODE in python bytecode")
+
+ def visitStoreAttribute(self, attributeName):
+ """value, owner -- """
+ self.asm.swap()
+ self.push(attributeName)
+ self.asm.swap()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "void __setattr__ (String, org.python.core.PyObject)"))
+
+ def visitStoreDeref(self, variableName):
+ """object -- """
+ self.loadFrame()
+ self.asm.swap()
+ self.derefIndex(variableName)
+ self.asm.swap()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void setderef (int, org.python.core.PyObject)"))
+
+ def visitStoreFast(self, localName):
+ """object -- """
+ self.loadFrame()
+ self.asm.swap()
+ self.push(self.__varnames.index(localName))
+ self.asm.swap()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void setlocal (int, org.python.core.PyObject)"))
+
+ def visitStoreGlobal(self, globalName):
+ """object -- """
+ self.loadFrame()
+ self.asm.swap()
+ self.push(self.__varnames.index(globalName))
+ self.asm.swap()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void setglobal (int, org.python.core.PyObject)"))
+
+ def visitStoreName(self, name):
+ """object -- """
+ self.loadFrame()
+ self.asm.swap()
+ self.push(name)
+ self.asm.swap()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "void setlocal (String, org.python.core.PyObject)"))
+
+ def visitStoreSlice(self, plus):
+ """value, object [,object[,object]] -- """
+ value = self.newLocal(pyObjectType,"value")
+ # start with digging up the value
+ if plus == 0:
+ self.asm.swap()
+ elif plus == 1 or plus == 2 or plus == 4:
+ self.rot(3)
+ elif plus == 3 or plus == 5 or plus == 6:
+ self.rot(4)
+ elif plus == 7: # quite inefficient
+ top = value # reuse local variable...
+ top.store()
+ self.rot(4)
+ top.load()
+ self.asm.swap()
+ else:
+ raise TypeError("plus for slice may only be in range(8)")
+ value.store()
+
+ self.setupSlice(plus)
+ value.load()
+ value.end()
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __setslice__ (%s)" % ", ".join(
+ ["org.python.core.PyObject"]*4)))
+
+ def visitStoreSubscript(self):
+ """value, object, index -- """
+ self.rot(3)
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "void __setitem__ (%s)" % ", ".join(
+ ["org.python.core.PyObject"]*2)))
+
+ def visitWithCleanup(self):
+ """exitFunction -- """
+ self.asm.invokeStatic(pySysType, Method.getMethod(
+ "org.python.core.PyTuple exc_info ()"))
+ self.asm.invokeVirtual(getType(core.PySequenceList), Method.getMethod(
+ "org.python.core.PyObject[] getArray ()"))
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "org.python.core.PyObject __call__ (%s)" % ", ".join(
+ ["org.python.core.PyObject[]"])))
+ self.asm.invokeVirtual(pyObjectType, Method.getMethod(
+ "boolean __nonzero__ ()"))
+ after = self.label()
+ self.asm.visitJumpInsn(Op.IFEQ, after)
+ self.asm.pop()
+ self.asm.getStatic(pyType, "None", pyObjectType)
+ self.asm.visitLabel(after)
+
+
+ def visitResumeTable(self, start, labels):
+ """ -- """
+ self.loadFrame()
+ self.asm.getField(pyFrameType, 'f_lasti', Type.INT_TYPE)
+ self.asm.visitTableSwitchInsn(1, len(labels), self.label(start),
+ array([self.label(l) for l in labels],
+ asm.Label))
+ #@self.scheduleCode(start)
+ def code():
+ """get input on start as well to assert that exceptions thrown
+ into the generator at the beginning works as expected."""
+ self.loadFrame()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getGeneratorInput ()"))
+ self.asm.pop()
+ self.scheduleCode(start, code)
+
+ def visitYieldValue(self, index, resume):
+ """value -- sendValue"""
+ self.storeStackState()
+ self.loadFrame()
+ self.push(index)
+ self.asm.putField(pyFrameType, 'f_lasti', Type.INT_TYPE)
+ self.asm.returnValue()
+ self.asm.visitLabel(self.label(resume))
+ self.loadStackState()
+ end = self.label()#
+ for block in self.__blocks:#
+ block.exclude(self.label(resume), end)#
+ self.asm.visitLabel(end)#
+ self.loadFrame()
+ self.asm.invokeVirtual(pyFrameType, Method.getMethod(
+ "org.python.core.PyObject getGeneratorInput ()"))
+
+ def storeStackState(self):
+ count = 0
+ stateVariables = []
+ for block in self.__blocks:
+ count += block.stackSize
+ stateVariables.extend(block.stateVariables)
+ if count > 0:
+ ret = self.newLocal(pyObjectType, "temp")
+ ret.store()
+ for i in xrange(len(self.__blocks) -1,-1,-1):
+ block = self.__blocks[i]
+ block.loadState()
+ state = self.newLocal(getArrayType(pyObjectType), "stackstate")
+ self.push(count)
+ self.asm.newArray(pyObjectType)
+ state.store()
+ self.buildArray(count, state)
+ self.loadFrame()
+ state.load()
+ self.asm.putField(pyFrameType, 'f_stackstate',
+ getArrayType(pyObjectType))
+ state.end()
+ ret.load()
+ ret.end()
+ if stateVariables:
+ self.push(len(stateVariables))
+ self.asm.newArray(Type.INT_TYPE)
+ for i in xrange(len(stateVariables)):
+ variable = stateVariables[i]
+ self.asm.dup()
+ self.push(i)
+ variable.load()
+ self.asm.arrayStore(Type.INT_TYPE)
+ self.loadFrame()
+ self.asm.swap()
+ self.asm.putField(pyFrameType, 'f_blockstate',
+ getArrayType(Type.INT_TYPE))
+
+ def loadStackState(self):
+ count = 0
+ stateVariables = []
+ for block in self.__blocks:
+ count += block.stackSize
+ stateVariables.extend(block.stateVariables)
+ if count > 0:
+ state = self.newLocal(getArrayType(pyObjectType), "stackstate")
+ self.loadFrame()
+ self.asm.getField(pyFrameType, 'f_stackstate',
+ getArrayType(pyObjectType))
+ state.store()
+ for i in xrange(count):
+ state.load()
+ self.push(i)
+ self.asm.arrayLoad(pyObjectType)
+ state.end()
+ if stateVariables:
+ self.loadFrame()
+ self.asm.getField(pyFrameType, 'f_blockstate',
+ getArrayType(Type.INT_TYPE))
+ for i in xrange(len(stateVariables)):
+ variable = stateVariables[i]
+ self.asm.dup()
+ self.push(i)
+ self.asm.arrayLoad(Type.INT_TYPE)
+ variable.store()
+ self.asm.pop()
+ for block in self.__blocks:
+ block.storeState()
+
+ def visitEnd(self):
+ """ --DONE"""
+ # emmit stored try/catch-blocks
+ while self.__tryBlocks:
+ self.__tryBlocks.pop().accept( self.asm )
+ init = self.__class.init
+ ## gather the constants for this code object (not used)
+ #init.push(java.lang.Integer(len(self.__constants)))
+ #init.newArray(pyObjectType)
+ #for i in xrange(len(self.__constants)):
+ # name = self.__constants[i]
+ # if self.__class.isCodeConstant(name):
+ # typ = pyCodeType
+ # else:
+ # typ = pyObjectType
+ # init.dup()
+ # init.push(java.lang.Integer(i))
+ # init.getStatic(self.__class.asType, name, typ)
+ # init.arrayStore(pyObjectType)
+ #init.putStatic(self.__class.asType,
+ # self.__code.getName() + "$co_consts",
+ # getArrayType(core.PyObject))
+
+ # emmit code that creates the code object
+ argcount = self.__argcount
+ if self.__flags & Flags.CO_VARARGS:
+ argcount += 1
+ if self.__flags & Flags.CO_VARKEYWORDS:
+ argcount += 1
+ init.push(java.lang.Integer(argcount))
+ # varnames
+ init.push(java.lang.Integer(len(self.__varnames)))
+ init.newArray(stringType)
+ for i in xrange(len(self.__varnames)):
+ init.dup()
+ init.push(java.lang.Integer(i))
+ init.push(self.__varnames[i])
+ init.arrayStore(stringType)
+ init.loadArg(0) # The file name string argument
+ init.push(self.__name) # The name of the function
+ init.push(java.lang.Integer(self.__firstlineno)) # The first line no
+ init.push(java.lang.Integer(bool(self.__flags & Flags.CO_VARARGS)))
+ init.push(java.lang.Integer(bool(self.__flags & Flags.CO_VARKEYWORDS)))
+ init.loadThis() # The function table
+ init.push(java.lang.Integer(self.__code.index)) # the function id
+ # cellvars
+ init.push(java.lang.Integer(len(self.__cellvars)))
+ init.newArray(stringType)
+ for i in xrange(len(self.__cellvars)):
+ init.dup()
+ init.push(java.lang.Integer(i))
+ init.push(self.__cellvars[i])
+ init.arrayStore(stringType)
+ # freevars
+ init.push(java.lang.Integer(len(self.__freevars)))
+ init.newArray(stringType)
+ for i in xrange(len(self.__freevars)):
+ init.dup()
+ init.push(java.lang.Integer(i))
+ init.push(self.__freevars[i])
+ init.arrayStore(stringType)
+ init.push(java.lang.Integer(0)) # purecell (what is this?)
+ init.push(java.lang.Integer(self.__flags)) # compiler flags
+ init.invokeStatic(pyType, Method.getMethod(
+ "org.python.core.PyCode newCode (%s)" % ", ".join(
+ ['int', 'String[]', 'String', 'String', 'int', 'boolean',
+ 'boolean', 'org.python.core.PyFunctionTable', 'int',
+ 'String[]', 'String[]', 'int', 'int'])))
+ init.putStatic(self.__class.asType, self.__code.getName(), pyCodeType)
+ self.asm.endMethod()
+
+if __name__ == '__main__':
+ import os
+ import sys
+ args = list(sys.argv[1:])
+ if os.name == 'java':
+ from marshal import _readPyc as readPyc
+ args.append("pyasm.pyc")
+ print readPyc(args[0])
+ #print readPyc("pyasm.pyc")
+ else:
+ from parser import kompilera
+ args.append("pyasm.py")
+ kompilera(open(args[0]).read())
Added: branches/newcompiler/PyASM/test/assign.py
===================================================================
--- branches/newcompiler/PyASM/test/assign.py (rev 0)
+++ branches/newcompiler/PyASM/test/assign.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,4 @@
+a = 5
+b,c,d = 6,7,8
+f,g,h = a,9,b
+i,(j,k),l = 1,(2,3),4
Added: branches/newcompiler/PyASM/test/builtins.py
===================================================================
--- branches/newcompiler/PyASM/test/builtins.py (rev 0)
+++ branches/newcompiler/PyASM/test/builtins.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,133 @@
+print ArithmeticError
+print AssertionError
+print AttributeError
+#print BaseException
+print DeprecationWarning
+print EOFError
+print Ellipsis
+print EnvironmentError
+print Exception
+print False
+print FloatingPointError
+print FutureWarning
+print GeneratorExit
+print IOError
+print ImportError
+#print ImportWarning
+print IndentationError
+print IndexError
+print KeyError
+print KeyboardInterrupt
+print LookupError
+print MemoryError
+print NameError
+print None
+print NotImplemented
+print NotImplementedError
+print OSError
+print OverflowError
+print PendingDeprecationWarning
+print ReferenceError
+print RuntimeError
+print RuntimeWarning
+print StandardError
+print StopIteration
+print SyntaxError
+print SyntaxWarning
+print SystemError
+print SystemExit
+print TabError
+print True
+print TypeError
+print UnboundLocalError
+print UnicodeDecodeError
+print UnicodeEncodeError
+print UnicodeError
+print UnicodeTranslateError
+#print UnicodeWarning
+print UserWarning
+print ValueError
+print Warning
+print ZeroDivisionError
+print __debug__
+print __doc__
+print __import__
+print __name__
+print abs
+#print all
+#print any
+print apply
+print basestring
+print bool
+#print buffer
+print callable
+print chr
+print classmethod
+print cmp
+print coerce
+print compile
+print complex
+print copyright
+print credits
+print delattr
+print dict
+print dir
+print divmod
+print enumerate
+print eval
+print execfile
+print exit
+print file
+print filter
+print float
+print frozenset
+print getattr
+print globals
+print hasattr
+print hash
+#print help
+print hex
+print id
+print input
+print int
+print intern
+print isinstance
+print issubclass
+print iter
+print len
+print license
+print list
+print locals
+print long
+print map
+print max
+print min
+print object
+print oct
+print open
+print ord
+print pow
+print property
+print quit
+print range
+print raw_input
+print reduce
+print reload
+print repr
+#print reversed
+print round
+print set
+print setattr
+print slice
+#print sorted
+print staticmethod
+print str
+print sum
+print super
+print tuple
+print type
+print unichr
+print unicode
+print vars
+print xrange
+print zip
Added: branches/newcompiler/PyASM/test/call.py
===================================================================
--- branches/newcompiler/PyASM/test/call.py (rev 0)
+++ branches/newcompiler/PyASM/test/call.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,4 @@
+def a(b,c):
+ None
+
+a(1,2)
Added: branches/newcompiler/PyASM/test/call_return.py
===================================================================
--- branches/newcompiler/PyASM/test/call_return.py (rev 0)
+++ branches/newcompiler/PyASM/test/call_return.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,4 @@
+def a(b,c):
+ return c
+
+print a(1,2)
Added: branches/newcompiler/PyASM/test/class_simple.py
===================================================================
--- branches/newcompiler/PyASM/test/class_simple.py (rev 0)
+++ branches/newcompiler/PyASM/test/class_simple.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,8 @@
+class Test(object):
+ def __init__(self, arg):
+ self.arg = arg
+
+ def __str__(self):
+ return "Test(%s)" % repr(self.arg)
+
+print Test('hej')
Added: branches/newcompiler/PyASM/test/constants.py
===================================================================
--- branches/newcompiler/PyASM/test/constants.py (rev 0)
+++ branches/newcompiler/PyASM/test/constants.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,9 @@
+print 1
+print 2
+print True # name lookup...
+print None # name lookup...
+print ""
+print "hej"
+print ()
+print (1,2)
+print 3.14
Added: branches/newcompiler/PyASM/test/exception.py
===================================================================
--- branches/newcompiler/PyASM/test/exception.py (rev 0)
+++ branches/newcompiler/PyASM/test/exception.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,10 @@
+def a1():
+ raise TypeError("probe")
+
+def a2():
+ a1()
+
+def a3():
+ a2()
+
+a3()
Added: branches/newcompiler/PyASM/test/for.py
===================================================================
--- branches/newcompiler/PyASM/test/for.py (rev 0)
+++ branches/newcompiler/PyASM/test/for.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,4 @@
+for x in xrange(10):
+ if x == 4: continue
+ if x == 7: break
+ print x
Added: branches/newcompiler/PyASM/test/generator.py
===================================================================
--- branches/newcompiler/PyASM/test/generator.py (rev 0)
+++ branches/newcompiler/PyASM/test/generator.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,43 @@
+def gen(x):
+ while True:
+ x -= 1
+ if x < 0:
+ break
+ else:
+ print (yield x)
+
+for x in gen(4):
+ print x
+
+it = gen(2)
+print it.next()
+print it.send("hi")
+
+it = gen(3)
+try:
+ it.throw(SystemError, "ok")
+except SystemError, e:
+ print "Caught exception:", e
+try:
+ print it.next()
+except StopIteration:
+ print "ok"
+
+it = gen(3)
+print it.next()
+print it.send('hi')
+try: # this works outside of try-block, why not inside?
+ it.throw(SystemError('ok'))
+except SystemError, e:
+ print "Caught exception:", e
+try:
+ print it.next()
+except StopIteration:
+ print "Caught StopIteration: ok"
+
+it = gen(1)
+it.close()
+
+it = gen(2)
+print it.next()
+it.close()
Added: branches/newcompiler/PyASM/test/generator_comprehension.py
===================================================================
--- branches/newcompiler/PyASM/test/generator_comprehension.py (rev 0)
+++ branches/newcompiler/PyASM/test/generator_comprehension.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,3 @@
+x = (l for l in xrange(10))
+for w in x:
+ print w
Added: branches/newcompiler/PyASM/test/generator_finally.py
===================================================================
--- branches/newcompiler/PyASM/test/generator_finally.py (rev 0)
+++ branches/newcompiler/PyASM/test/generator_finally.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,23 @@
+def gen(n):
+ def make(v):
+ def result():
+ return v
+ return result
+ try:
+ for x in xrange(n):
+ try:
+ data = yield make(x)
+ print data
+ except GeneratorExit:
+ raise
+ except Exception, e:
+ print "EXCEPTION: ", e
+ finally:
+ print "done"
+
+g = gen(10)
+print "g.next():", g.next()()
+print "g.send(14):", g.send(14)()
+print "g.throw(...):", g.throw(RuntimeError("FEL"))()
+print "g.next():", g.next()()
+print "g.close():", g.close()
Added: branches/newcompiler/PyASM/test/generator_state.py
===================================================================
--- branches/newcompiler/PyASM/test/generator_state.py (rev 0)
+++ branches/newcompiler/PyASM/test/generator_state.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,9 @@
+def gen(l):
+ for x in xrange(l):
+ try:
+ yield x
+ finally:
+ print "one"
+
+for x in gen(4):
+ print "res:", x
Added: branches/newcompiler/PyASM/test/generator_state2.py
===================================================================
--- branches/newcompiler/PyASM/test/generator_state2.py (rev 0)
+++ branches/newcompiler/PyASM/test/generator_state2.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,10 @@
+def gen(l):
+ for x in xrange(l):
+ try:
+ yield x
+ except:
+ print "err"
+
+it = gen(4)
+print it.next()
+print it.throw(RuntimeError('probe'))
Added: branches/newcompiler/PyASM/test/import.py
===================================================================
--- branches/newcompiler/PyASM/test/import.py (rev 0)
+++ branches/newcompiler/PyASM/test/import.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,7 @@
+import sys
+import marshal
+import java.lang
+
+print sys
+print marshal
+print java.lang
Added: branches/newcompiler/PyASM/test/import_from.py
===================================================================
--- branches/newcompiler/PyASM/test/import_from.py (rev 0)
+++ branches/newcompiler/PyASM/test/import_from.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,8 @@
+from marshal import loads
+from sys import argv
+from java.lang import Integer, String
+
+print loads
+print argv
+print Integer
+print String
Added: branches/newcompiler/PyASM/test/import_star.py
===================================================================
--- branches/newcompiler/PyASM/test/import_star.py (rev 0)
+++ branches/newcompiler/PyASM/test/import_star.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,3 @@
+from sys import *
+
+print argv
Added: branches/newcompiler/PyASM/test/list.py
===================================================================
--- branches/newcompiler/PyASM/test/list.py (rev 0)
+++ branches/newcompiler/PyASM/test/list.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1 @@
+print [1,2,3,4,5,6,7]
Added: branches/newcompiler/PyASM/test/list_comprehension.py
===================================================================
--- branches/newcompiler/PyASM/test/list_comprehension.py (rev 0)
+++ branches/newcompiler/PyASM/test/list_comprehension.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1 @@
+x = [l for l in xrange(10)]
Added: branches/newcompiler/PyASM/test/print.py
===================================================================
--- branches/newcompiler/PyASM/test/print.py (rev 0)
+++ branches/newcompiler/PyASM/test/print.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1 @@
+print "hello world"
Added: branches/newcompiler/PyASM/test/return.py
===================================================================
--- branches/newcompiler/PyASM/test/return.py (rev 0)
+++ branches/newcompiler/PyASM/test/return.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,2 @@
+def a():
+ return 1
Added: branches/newcompiler/PyASM/test/simple_decorator.py
===================================================================
--- branches/newcompiler/PyASM/test/simple_decorator.py (rev 0)
+++ branches/newcompiler/PyASM/test/simple_decorator.py 2007-08-20 18:11:16 UTC (rev 3440)
@@ -0,0 +1,8 @@
+def dec(x):
+ return x
+
+@dec
+def a(b,c):
+ return c
+
+print a(1,2)
Added: branches/newcompiler/PyASM/test/simple_decorator2.py
===================================================================
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|