[pypy-svn] r66799 - in pypy/branch/avm/pypy/translator/avm1: . test
magcius at codespeak.net
magcius at codespeak.net
Thu Aug 13 00:29:19 CEST 2009
Author: magcius
Date: Thu Aug 13 00:29:18 2009
New Revision: 66799
Added:
pypy/branch/avm/pypy/translator/avm1/__init__.py
pypy/branch/avm/pypy/translator/avm1/conftest.py
pypy/branch/avm/pypy/translator/avm1/metavm.py
pypy/branch/avm/pypy/translator/avm1/node.py
pypy/branch/avm/pypy/translator/avm1/opcodes.py
pypy/branch/avm/pypy/translator/avm1/test/__init__.py
pypy/branch/avm/pypy/translator/avm1/test/test_runtest.py
pypy/branch/avm/pypy/translator/avm1/types.py
pypy/branch/avm/pypy/translator/avm1/util.py
Removed:
pypy/branch/avm/pypy/translator/avm1/avm.py
Modified:
pypy/branch/avm/pypy/translator/avm1/avm1.py
pypy/branch/avm/pypy/translator/avm1/avm1gen.py
pypy/branch/avm/pypy/translator/avm1/constant.py
pypy/branch/avm/pypy/translator/avm1/database.py
pypy/branch/avm/pypy/translator/avm1/genavm.py
pypy/branch/avm/pypy/translator/avm1/tags.py
pypy/branch/avm/pypy/translator/avm1/test/browsertest.py
pypy/branch/avm/pypy/translator/avm1/test/harness.py
pypy/branch/avm/pypy/translator/avm1/test/runtest.py
pypy/branch/avm/pypy/translator/avm1/test/test_int.py
Log:
Merge commit 'avm1/master'
Added: pypy/branch/avm/pypy/translator/avm1/__init__.py
==============================================================================
Modified: pypy/branch/avm/pypy/translator/avm1/avm1.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/avm1.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/avm1.py Thu Aug 13 00:29:18 2009
@@ -19,35 +19,12 @@
CONSTANT8 = DataType(8, "constant 8", "B")
CONSTANT16 = DataType(9, "constant 16", "H")
-class Index(object):
- def __init__(self, index):
- self.index = index
-
-class Value(object):
- def __init__(self, value):
- self.value = value
-
-class Null(object):
- type = NULL
-
-class Undefined(object):
- type = UNDEFINED
-
-class ConstantIndexDescriptor(object):
- def __get__(self, obj, objtype):
- return CONSTANT8 if obj.index < 256 else CONSTANT16
-
-class Constant(Index):
- type = ConstantIndexDescriptor()
-
-class Register(object):
- type = REGISTER
-
-class RegisterByIndex(Register, Index):
- pass
-
-class RegisterByValue(Register, Value):
- pass
+preload = dict(this="preload_this",
+ arguments="preload_args",
+ super="preload_super",
+ _root="preload_root",
+ _parent="preload_parent",
+ _global="preload_global")
class Action(object):
@@ -128,7 +105,7 @@
self.insert_end = insert_end
self.labels = {}
- self.branch_blocks = {}
+ self.branch_blocks = []
self.actions = []
self.current_offset = 0
@@ -174,6 +151,9 @@
def add_action(self, action):
if self._sealed:
raise SealedBlockError("Block is sealed. Cannot add new actions")
+
+ assert isinstance(action, Action)
+
self.code = "" # Dirty the code.
action.offset = self.current_offset
action.get_block_props_early(self)
@@ -187,7 +167,7 @@
return old_action
# Two nots negate. Take them out.
- if action.ACTION_NAME == "ActionNot" and action.ACTION_NAME == "ActionNot":
+ if len(self.actions) > 0 and action.ACTION_NAME == "ActionNot" and self.actions[-1].ACTION_NAME == "ActionNot":
self.actions.pop()
self.current_offset -= 1 # len(ShortAction) is 1
return None
@@ -199,10 +179,16 @@
return action
def serialize(self):
+ if not self._sealed:
+ raise SealedBlockError("Block must be sealed before it can be serialized")
if len(self.code) > 0:
return self.code
bytes = []
+ block_offset = 0
for action in self.actions:
+ if isinstance(action, Block):
+ block_offset += len(action)
+ action.offset += block_offset
action.get_block_props_late(self)
bytes += action.serialize()
if self.insert_end:
@@ -258,46 +244,47 @@
Block.__init__(self, toplevel, False)
self.function_name = name
self.params = parameters
+ self.preload_register_count = 1 # Start at 1.
# Flags
+ self.registers = [None]
self.preload_parent = False
self.preload_root = False
self.suppress_super = True
self.preload_super = False
- self.suppress_args = False
- self.preload_args = True
+ self.suppress_args = True
+ self.preload_args = False
self.suppress_this = True
self.preload_this = False
self.preload_global = False
self.eval_flags()
-
- def eval_flags(self): # WARNING! eval_flags will clear registers!
- # bits = BitStream()
- # bits.write_bit_value(self.flags, 16)
- # bits.rewind()
- # preload_parent = bits.read_bit()
- # preload_root = bits.read_bit()
- # suppress_super = bits.read_bit()
- # preload_super = bits.read_bit()
- # suppress_args = bits.read_bit()
- # preload_args = bits.read_bit()
- # suppress_this = bits.read_bit()
- # preload_this = bits.read_bit()
- # bits.cursor += 7 # skip over 7 Reserved bits
- # preload_global = bits.read_bit()
+
+ for name in parameters:
+ self.registers.append(name)
- self.registers = [None]
+ def eval_flags(self):
# According to the docs, this is the order of register allocation.
- if self.preload_this: self.registers.append("this")
- if self.preload_args: self.registers.append("arguments")
- if self.preload_super: self.registers.append("super")
- if self.preload_root: self.registers.append("_root")
- if self.preload_parent: self.registers.append("_parent")
- if self.preload_global: self.registers.append("_global")
+ if self.preload_this and "this" not in self.registers:
+ self.suppress_this = False
+ self.registers.insert(1, "this")
+
+ if self.preload_args and "arguments" not in self.registers:
+ self.suppress_args = False
+ self.registers.insert(2, "arguments")
+
+ if self.preload_super and "super" not in self.registers:
+ self.suppress_super = False
+ self.registers.insert(3, "super")
+
+ if self.preload_root and "_root" not in self.registers:
+ self.registers.insert(4, "_root")
+
+ if self.preload_parent and "_parent" not in self.registers:
+ self.registers.insert(5, "_parent")
- for name in self.params:
- self.registers.append(name)
+ if self.preload_global and "_global" not in self.registers:
+ self.registers.insert(6, "_global")
def gen_data(self):
@@ -315,7 +302,7 @@
self.block_data = Block.serialize(self)
bytes = [self.function_name, "\0",
- struct.pack("HB", len(self.params), len(self.registers)-1),
+ struct.pack("HB", len(self.params), len(self.registers)),
bits.serialize()]
for name in self.params:
@@ -411,10 +398,11 @@
def get_block_props_late(self, block):
if len(self.branch_label) > 0:
- self.branch_offset = block.labels[self.branch_label] - self.offset
+ print "BRANCH:", self.branch_label, block.labels[self.branch_label], self.offset
+ self.branch_offset = block.labels[self.branch_label] - self.offset - len(self)
def gen_data(self):
- return struct.pack("H", self.branch_offset)
+ return struct.pack("h", self.branch_offset)
class ActionJump(BranchingActionBase):
ACTION_NAME = "ActionJump"
@@ -433,37 +421,20 @@
self.add_element(*args)
def add_element(self, element):
- if hasattr(element, "__iter__") and not isinstance(element, basestring):
- for e in element:
- self.add_element(e)
- if isinstance(element, (Null, Undefined)):
- self.values.append((0, element.type))
- elif isinstance(element, basestring):
- self.values.append((element, STRING))
- elif isinstance(element, bool):
- self.values.append((element, BOOLEAN))
- elif isinstance(element, int):
- self.values.append((element, INTEGER))
- elif isinstance(element, float):
- if element > 0xFFFFFFFF:
- self.values.append((element, DOUBLE))
- else:
- self.values.append((element, FLOAT))
- elif isinstance(element, Index):
- self.values.append((element.index, element.type))
- elif isinstance(element, RegisterByValue):
- self.values.append((element.value, RegisterByValue))
-
+ if hasattr(element, "__iter__") and not isinstance(element, (basestring, tuple)):
+ for t in element:
+ self.add_element(t)
+ else:
+ if element in (NULL, UNDEFINED):
+ element = (None, element)
+ assert isinstance(element, tuple)
+ self.values.append(element)
+
def get_block_props_early(self, block):
for index, (value, type) in enumerate(self.values):
if type == STRING:
constant_index = block.constants.add_constant(value)
self.values[index] = (constant_index, CONSTANT8 if constant_index < 256 else CONSTANT16)
- elif type == RegisterByValue:
- register_index = block.find_register(value)
- if register_index < 0:
- raise ValueError("register value '%s' not found in registers at this point" % value)
- self.values[index] = (register_index, REGISTER)
def gen_data(self):
bytes = []
@@ -511,13 +482,16 @@
has_catch_block = len(self.catch_block.actions) > 0
bits = BitStream()
bits.zero_fill(5)
- bits.write_bit(isinstance(self.catch_object, Register))
+ bits.write_bit(isinstance(self.catch_object, int))
bits.write_bit(len(self.finally_block.actions) > 0)
bits.write_bit(has_catch_block)
bytes = [bits.serialize()]
- bytes += [struct.pack("HHH", len(self.try_block) + 5 if has_catch_block else 0, len(self.catch_block), len(self.finally_block))]
- bytes += self.catch_object.index if isinstance(self.catch_object, Register) else (self.catch_object + "\0")
- return "".join(bytes)
+ bytes += [struct.pack("3H",
+ len(self.try_block) + 5 if has_catch_block else 0,
+ len(self.catch_block),
+ len(self.finally_block))]
+ bytes += [self.catch_object, "" if isinstance(self.catch_object, int) else "\0"]
+ return bytes
def gen_outer_data(self):
bytes = [self.try_block.serialize()]
@@ -556,17 +530,28 @@
def gen_data(self):
return struct.pack("H", len(self.block)) + self.block.serialize()
-
-def make_short_action(value, name):
+
+SHORT_ACTIONS = {}
+
+# turns NextFrame into next_frame
+def make_underlined(name):
+ return ''.join('_' + c.lower() if c.isupper() else c for c in name)[1:]
+
+def make_short_action(value, name, push_count=0):
def __len__(self):
return 1 # 1 (Action ID)
def serialize(self):
return chr(self.ACTION_ID)
+
+ act = type(name, (Action,), dict(ACTION_ID=value, ACTION_NAME=name, push_count=push_count,
+ __len__=__len__, serialize=serialize))
+
+ SHORT_ACTIONS[name[6:].lower()] = act
+ SHORT_ACTIONS[make_underlined(name[6:])] = act
- return type(name, (Action,), dict(ACTION_ID=value, ACTION_NAME=name,
- __len__=__len__, serialize=serialize))
+ return act
ActionNextFrame = make_short_action(0x04, "ActionNextFrame")
ActionPreviousFrame = make_short_action(0x05, "ActionPreviousFrame")
@@ -574,29 +559,29 @@
ActionStop = make_short_action(0x07, "ActionStop")
ActionToggleQuality = make_short_action(0x08, "ActionToggleQuality")
ActionStopSounds = make_short_action(0x09, "ActionStopSounds")
-ActionAdd = make_short_action(0x0a, "ActionAdd")
-ActionSubtract = make_short_action(0x0b, "ActionSubtract")
-ActionMultiply = make_short_action(0x0c, "ActionMultiply")
-ActionDivide = make_short_action(0x0d, "ActionDivide")
-ActionEquals = make_short_action(0x0e, "ActionEquals")
-ActionLess = make_short_action(0x0f, "ActionLess")
-ActionAnd = make_short_action(0x10, "ActionAnd")
-ActionOr = make_short_action(0x11, "ActionOr")
+ActionAdd = make_short_action(0x0a, "ActionAdd", -1)
+ActionSubtract = make_short_action(0x0b, "ActionSubtract", -1)
+ActionMultiply = make_short_action(0x0c, "ActionMultiply", -1)
+ActionDivide = make_short_action(0x0d, "ActionDivide", -1)
+ActionEquals = make_short_action(0x0e, "ActionEquals", -1)
+ActionLess = make_short_action(0x0f, "ActionLess", -1)
+ActionAnd = make_short_action(0x10, "ActionAnd", -1)
+ActionOr = make_short_action(0x11, "ActionOr", -1)
ActionNot = make_short_action(0x12, "ActionNot")
-ActionStringEquals = make_short_action(0x13, "ActionStringEquals")
+ActionStringEquals = make_short_action(0x13, "ActionStringEquals", -1)
ActionStringLength = make_short_action(0x14, "ActionStringLength")
ActionStringExtract = make_short_action(0x15, "ActionStringExtract")
-ActionPop = make_short_action(0x17, "ActionPop")
+ActionPop = make_short_action(0x17, "ActionPop", -1)
ActionToInteger = make_short_action(0x18, "ActionToInteger")
ActionGetVariable = make_short_action(0x1c, "ActionGetVariable")
-ActionSetVariable = make_short_action(0x1d, "ActionSetVariable")
+ActionSetVariable = make_short_action(0x1d, "ActionSetVariable", -2)
ActionSetTarget2 = make_short_action(0x20, "ActionSetTarget2")
-ActionStringAdd = make_short_action(0x21, "ActionStringAdd")
-ActionGetProperty = make_short_action(0x22, "ActionGetProperty")
-ActionSetProperty = make_short_action(0x23, "ActionSetProperty")
+ActionStringAdd = make_short_action(0x21, "ActionStringAdd", -1)
+ActionGetProperty = make_short_action(0x22, "ActionGetProperty", -1)
+ActionSetProperty = make_short_action(0x23, "ActionSetProperty", -3)
ActionCloneSprite = make_short_action(0x24, "ActionCloneSprite")
ActionRemoveSprite = make_short_action(0x25, "ActionRemoveSprite")
-ActionTrace = make_short_action(0x26, "ActionTrace")
+ActionTrace = make_short_action(0x26, "ActionTrace", -1)
ActionStartDrag = make_short_action(0x27, "ActionStartDrag")
ActionEndDrag = make_short_action(0x28, "ActionEndDrag")
ActionStringLess = make_short_action(0x29, "ActionStringLess")
@@ -616,7 +601,7 @@
ActionDefineLocalVal = make_short_action(0x3c, "ActionDefineLocalVal")
ActionCallFunction = make_short_action(0x3d, "ActionCallFunction")
ActionReturn = make_short_action(0x3e, "ActionReturn")
-ActionModulo = make_short_action(0x3f, "ActionModulo")
+ActionModulo = make_short_action(0x3f, "ActionModulo", -1)
ActionNewObject = make_short_action(0x40, "ActionNewObject")
ActionDefineLocal = make_short_action(0x41, "ActionDefineLocal")
ActionInitArray = make_short_action(0x42, "ActionInitArray")
@@ -624,26 +609,26 @@
ActionTypeof = make_short_action(0x44, "ActionTypeof")
ActionGetTargetPath = make_short_action(0x45, "ActionGetTargetPath")
ActionEnumerate = make_short_action(0x46, "ActionEnumerate")
-ActionTypedAdd = make_short_action(0x47, "ActionTypedAdd")
-ActionTypedLessThan = make_short_action(0x48, "ActionTypedLessThan")
-ActionTypedEquals = make_short_action(0x49, "ActionTypedEquals")
+ActionTypedAdd = make_short_action(0x47, "ActionTypedAdd", -1)
+ActionTypedLess = make_short_action(0x48, "ActionTypedLess", -1)
+ActionTypedEquals = make_short_action(0x49, "ActionTypedEquals", -1)
ActionConvertToNumber = make_short_action(0x4a, "ActionConvertToNumber")
ActionConvertToString = make_short_action(0x4b, "ActionConvertToString")
-ActionDuplicate = make_short_action(0x4c, "ActionDuplicate")
+ActionDuplicate = make_short_action(0x4c, "ActionDuplicate", 1)
ActionSwap = make_short_action(0x4d, "ActionSwap")
-ActionGetMember = make_short_action(0x4e, "ActionGetMember")
-ActionSetMember = make_short_action(0x4f, "ActionSetMember")
+ActionGetMember = make_short_action(0x4e, "ActionGetMember", -1)
+ActionSetMember = make_short_action(0x4f, "ActionSetMember", -3)
ActionIncrement = make_short_action(0x50, "ActionIncrement")
ActionDecrement = make_short_action(0x51, "ActionDecrement")
ActionCallMethod = make_short_action(0x52, "ActionCallMethod")
ActionCallNewMethod = make_short_action(0x53, "ActionCallNewMethod")
-ActionBitAnd = make_short_action(0x60, "ActionBitAnd")
-ActionBitOr = make_short_action(0x61, "ActionBitOr")
-ActionBitXor = make_short_action(0x62, "ActionBitXor")
-ActionShiftLeft = make_short_action(0x63, "ActionShiftLeft")
-ActionShiftRight = make_short_action(0x64, "ActionShiftRight")
-ActionShiftUnsigned = make_short_action(0x65, "ActionShiftUnsigned")
-ActionStrictEquals = make_short_action(0x66, "ActionStrictEquals")
-ActionGreater = make_short_action(0x67, "ActionGreater")
-ActionStringGreater = make_short_action(0x68, "ActionStringGreater")
+ActionBitAnd = make_short_action(0x60, "ActionBitAnd", -1)
+ActionBitOr = make_short_action(0x61, "ActionBitOr", -1)
+ActionBitXor = make_short_action(0x62, "ActionBitXor", -1)
+ActionShiftLeft = make_short_action(0x63, "ActionShiftLeft", -1)
+ActionShiftRight = make_short_action(0x64, "ActionShiftRight", -1)
+ActionShiftUnsigned = make_short_action(0x65, "ActionShiftUnsigned", -1)
+ActionStrictEquals = make_short_action(0x66, "ActionStrictEquals", -1)
+ActionGreater = make_short_action(0x67, "ActionGreater", -1)
+ActionStringGreater = make_short_action(0x68, "ActionStringGreater", -1)
ActionExtends = make_short_action(0x69, "ActionExtends")
Modified: pypy/branch/avm/pypy/translator/avm1/avm1gen.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/avm1gen.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/avm1gen.py Thu Aug 13 00:29:18 2009
@@ -2,10 +2,33 @@
""" backend generator routines
"""
-from pypy.translator.avm import avm1
+from pypy.objspace.flow import model as flowmodel
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.avm import avm1, types
+from pypy.translator.oosupport.treebuilder import SubOperation
+from pypy.translator.oosupport.metavm import Generator as OOGenerator, InstructionList
+from pypy.translator.oosupport.constant import push_constant
from collections import namedtuple
-Scope = namedtuple("Scope", "block parent callback stack")
+ClassName = namedtuple("ClassName", "namespace classname")
+Scope = namedtuple("Scope", "block parent callback islabel")
+
+def render_sub_op(sub_op, db, generator):
+ op = sub_op.op
+ instr_list = db.genoo.opcodes.get(op.opname, None)
+ assert instr_list is not None, 'Unknown opcode: %s ' % op
+ assert isinstance(instr_list, InstructionList)
+ # Don't do that, please
+ #assert instr_list[-1] is StoreResult, "Cannot inline an operation that doesn't store the result"
+
+ # record that we know about the type of result and args
+ db.cts.lltype_to_cts(op.result.concretetype)
+ for v in op.args:
+ db.cts.lltype_to_cts(v.concretetype)
+
+ instr_list = InstructionList(instr_list[:-1]) # leave the value on the stack if this is a sub-op
+ instr_list.render(generator, op)
+ # now the value is on the stack
def make_variable(name):
if isinstance(name, Variable):
@@ -24,63 +47,77 @@
def __add__(self, other):
if isinstance(other, StackDummy):
other = other.name
- return Variable("CONCAT %r %r" % (self.name, other))
+ return Variable("ADD %r %r" % (self.name, other))
def __radd__(self, other):
- if isinstance(other, StackDummy):
- other = other.name
- return Variable("CONCAT %r %r" % (other, self.name))
-
+ return other + self
+
+class ScriptObject(StackDummy):
+ pass
class Function(StackDummy):
pass
-class AVM1Gen(object):
+class AVM1Gen(OOGenerator):
""" AVM1 'assembler' generator routines """
-
- def __getattribute__(self, name):
- return object.__getattribute__(self, name)
def __init__(self, block=None):
+ self.stack = []
+ self.namespaces = {}
self.block = block or avm1.Block(None, True)
- self.scope = Scope(self.block, None, None, [])
+ self.scope = Scope(self.block, None, None, False)
self.action(self.block.constants)
-
+ self.ilasm = self
+
def new_label(self):
- return self.scope.block.new_label()
+ return self.fn_block.new_label()
def push_stack(self, *values):
print "PUSHSTACK:", values
for element in values:
- if isinstance(element, avm1.RegisterByIndex):
- element = Variable(self.scope.block.registers[element.index])
- elif isinstance(element, avm1.RegisterByValue):
- element = Variable(element.value)
- self.scope.stack.append(element)
+ self.stack.append(element)
+
+ @property
+ def fn_block(self):
+ if self.scope.islabel:
+ return self.scope.parent.block
+ return self.scope.block
def pop_stack(self, n=1):
- v = [self.scope.stack.pop() for i in xrange(n)]
+ v = [self.stack.pop() for i in xrange(n)]
print "POPSTACK:", v
return v
def store_register(self, name, index=-1):
- index = self.scope.block.store_register(name, index)
+ index = self.fn_block.store_register(name, index)
self.action(avm1.ActionStoreRegister(index))
return index
def find_register(self, name):
- return self.scope.block.find_register(name)
+ print "FINDING REGISTER:", name
+ return self.fn_block.find_register(name)
def action(self, action):
return self.scope.block.add_action(action)
- def enter_scope(self, new_code_obj, exit_callback=None):
- self.scope = Scope(new_code_obj, self.scope, exit_callback, [])
-
+ def set_label(self, label):
+ print "SETLABEL:", label
+
+ if self.scope.islabel:
+ self.exit_scope()
+
+ label, block = self._branch_start(label)
+ self.enter_scope(block, islabel=True)
+
+ def enter_scope(self, new_code_obj, exit_callback=None, islabel=False):
+ print "ENTERSCOPE"
+ self.scope = Scope(new_code_obj, self.scope, exit_callback, islabel)
+
def in_function(self):
- return self.scope.block.FUNCTION_TYPE
+ return self.fn_block.FUNCTION_TYPE
def exit_scope(self):
+ print "EXITSCOPE"
block_len = self.finalize_block(self.scope.block)
exit_callback = self.scope.callback
@@ -92,56 +129,87 @@
exit_callback()
def finalize_block(self, block):
- for label, branch_block in block.branch_blocks.iteritems():
- if not branch_block.is_sealed():
- raise Exception, "Branch block hasn't been finalized"
+ for label, branch_block in block.branch_blocks:
+ if not branch_block.sealed:
+ branch_block.seal()
+
# Set the label.
block.labels[label] = block.current_offset
+
+ print label, block.current_offset
+
# Add the actions, which updates current_offset
for act in branch_block.actions:
+
block.add_action(act)
return block.seal()
+
+ # def begin_namespace(self, _namespace):
+ # n = _namespace.split('.')
+ # namespace = self.namespaces
+ # if n[0] not in self.namespaces:
+ # self.namespaces[n[0]] = {}
+ # self.push_const(n[0])
+ # self.init_object()
+ # self.set_variable()
+ # self.push_var(n[0])
+ # for ns in n[1:]:
+ # if not ns in namespace:
+ # namespace[ns] = {}
+ # namespace = namespace[ns]
+ # self.push_const(ns)
+ # self.init_object()
+ # self.set_member()
def begin_function(self, name, arglist):
self.enter_scope(self.action(avm1.ActionDefineFunction2(self.block, name, arglist)))
-
- def begin_prototype_method(self, function_name, _class, arglist):
+
+ def begin_static_method(self, function_name, _class, arglist):
def exit_callback(block):
self.set_member()
- self.push_const(function_name, "prototype", _class)
- self.get_variable()
- self.get_member()
+ self.load(_class)
+ self.push_const(function_name)
self.enter_scope(self.action(avm1.ActionDefineFunction2(self.block, "", arglist, 0)), exit_callback)
self.push_stack(Function(function_name))
+ def begin_method(self, function_name, _class, arglist):
+ def exit_callback(block):
+ self.set_member()
+ self.load(_class)
+ self.push_const("prototype")
+ self.get_member()
+ self.push_const(function_name)
+ self.enter_scope(self.action(avm1.ActionDefineFunction2(self.block, "", arglist, 0)), exit_callback)
+ self.push_stack(Function(function_name))
+
def set_variable(self):
value, name = self.pop_stack(2)
print "SETVARIABLE: %r = %r" % (name, value)
if isinstance(name, Variable):
name = name.name
assert isinstance(name, basestring)
- if self.find_register(name) >= 0:
+ if self.find_register(name) >= 0 and self.in_function() == 2:
self.store_register(name)
self.action(avm1.ActionSetVariable())
def get_variable(self):
name, = self.pop_stack()
- print "GETVARIABLE: %s" % (name,)
+ print "GETVARIABLE:", name
self.action(avm1.ActionGetVariable())
self.push_stack(make_variable(name))
def set_member(self):
self.action(avm1.ActionSetMember())
self.pop_stack(3)
-
+
def get_member(self):
self.action(avm1.ActionGetMember())
- value, name, obj = self.pop_stack(3)
- print "GETMEMBER:", value, name, obj
+ name, obj = self.pop_stack(2)
+ print "GETMEMBER:", name, obj
self.push_stack(Variable("%s.%s") % obj, name)
def push_reg_index(self, index):
- self.push_const(avm1.RegisterByIndex(index))
+ self.action(avm1.ActionPush((index, avm1.REGISTER)))
def push_arg(self, v):
assert self.in_function() > 0, "avm1gen::push_arg called while not in function scope."
@@ -152,12 +220,20 @@
def push_var(self, v):
k = self.find_register(v)
+ print k
if k >= 0:
+ self.push_stack(v)
self.push_reg_index(k)
else:
+ if self.in_function() == 2:
+ if v in avm1.preload:
+ setattr(self.scope.block, avm1.preload[v])
+ self.scope.block.eval_flags()
+ return self.push_var(v)
self.push_const(v)
self.get_variable()
- index = self.store_register(v)
+ if self.in_function() == 2:
+ self.store_register(v)
def push_this(self):
self.push_var("this")
@@ -165,17 +241,12 @@
def push_local(self, v):
self.push_var(v.name)
- def push_const(self, *v):
- self.push_stack(*v)
- return self.action(avm1.ActionPush(v))
-
- def push_undefined(self):
- self.push_const(avm1.Undefined)
-
- def push_null(self):
- self.push_const(avm1.Null)
+ def push_const(self, *args):
+ self.push_stack(*args)
+ self.action(avm1.ActionPush(types.pytype_to_avm1(v) for v in args))
def return_stmt(self):
+ print "RETURNSTMT"
self.pop_stack()
self.action(avm1.ActionReturn())
@@ -195,15 +266,19 @@
self.action(avm1.ActionNot())
self.pop_stack(2)
- def init_object(self, members=None):
- self.push_const(members.iteritems(), len(members))
+ def init_object(self, members={}):
+ self.push_const(*members.items())
+ self.push_const(len(members))
self.action(avm1.ActionInitObject())
- self.pop_stack(2)
+ self.pop_stack(self.pop_stack()[0])
+ self.push_stack(ScriptObject("object"))
- def init_array(self, members=None):
- self.push_const(members, len(members))
- self.pop_stack(2)
+ def init_array(self, members=[]):
+ self.push_const(members)
+ self.push_const(len(members))
self.action(avm1.ActionInitArray())
+ self.pop_stack(self.pop_stack()[0])
+ self.push_stack(ScriptObject("array"))
# Assumes the args and number of args are on the stack.
def call_function(self, func_name):
@@ -220,7 +295,7 @@
self.push_stack(Variable("%s_RETURN" % func_name))
# Assumes the args and number of args and ScriptObject are on the stack.
- def call_method(self, func_name):
+ def call_method_n(self, func_name):
self.push_const(func_name)
self.action(avm1.ActionCallMethod())
name, obj, nargs = self.pop_stack(3)
@@ -230,34 +305,25 @@
# Assumes the args and number of args are on the stack.
def call_method_constvar(self, _class, func_name):
self.push_var(_class)
- self.call_method()
-
- # Boolean value should be on stack when this is called
- def branch_if_true(self, label=""):
- if len(label) == 0:
- label = self.new_label()
- self.scope.block.branch_blocks[label] = avm1.Block(self.block, False)
- self.action(avm1.ActionIf(label))
- self.pop_stack()
- return (label, self.scope.block.branch_blocks[label])
+ self.call_method_n(func_name)
# Assumes the value is on the stack.
- def set_proto_field(self, objname, member_name):
- self.push_const("prototype")
- self.push_var(objname)
- self.get_member()
- self.swap()
- self.push_const(member_name)
- self.swap()
- self.set_member()
+ # def set_proto_field(self, objname, member_name):
+ # self.push_const("prototype")
+ # self.push_var(objname)
+ # self.get_member()
+ # self.swap()
+ # self.push_const(member_name)
+ # self.swap()
+ # self.set_member()
# Assumes the value is on the stack.
- def set_static_field(self, objname, member_name):
- self.push_var(objname)
- self.swap()
- self.push_const(member_name)
- self.swap()
- self.set_member()
+ # def set_static_field(self, objname, member_name):
+ # self.push_var(objname)
+ # self.swap()
+ # self.push_const(member_name)
+ # self.swap()
+ # self.set_member()
# If no args are passed then it is assumed that the args and number of args are on the stack.
def newobject_constthis(self, obj, *args):
@@ -270,8 +336,9 @@
def newobject(self):
self.action(avm1.ActionNewObject())
- _, nargs = self.pop_stack()
- self.pop_stack(nargs)
+ name, nargs = self.pop_stack()
+ args = self.pop_stack(nargs)
+ self.push_stack(ScriptObject(name))
# FIXME: will refactor later
#load_str = load_const
@@ -300,11 +367,135 @@
def throw(self): # Assumes the value to be thrown is on the stack.
self.action(avm1.ActionThrow())
self.pop_stack()
+
+ # oosupport Generator routines
+ def emit(self, op):
+ a = avm1.SHORT_ACTIONS[op]
+ if a.push_count > 0:
+ a.push_stack(StackDummy("Generated by %r" % op))
+ elif a.push_count < 0:
+ self.pop_stack(-a.push_count)
+ self.action(a())
+
+ def pop(self, TYPE):
+ self.action(avm1.ActionPop())
+ self.pop_stack()
- def concat_string(self):
- self.action(avm1.ActionTypedAdd())
- self.push_stack(self.pop_stack()[0] + self.pop_stack()[0])
+ def dup(self, TYPE):
+ self.action(avm1.ActionDuplicate())
+ self.push_stack([self.pop_stack()] * 2)
+
+ def load(self, v):
+ print v, type(v)
+ if hasattr(v, "__iter__") and not isinstance(v, basestring):
+ for i in v:
+ self.load(v)
+ elif isinstance(v, ClassName):
+ if v.namespace:
+ ns = v.namespace.split('.')
+ self.push_var(ns[0])
+ for i in ns[:0:-1]:
+ self.push_const(i)
+ self.get_member()
+ else:
+ self.push_var(v.classname)
+ elif isinstance(v, flowmodel.Variable):
+ if v.concretetype is ootype.Void:
+ return # ignore it
+ elif self.load_variable_hook(v):
+ return
+ else:
+ self.push_local(v)
+ elif isinstance(v, flowmodel.Constant):
+ push_constant(self.db, v.concretetype, v.value, self)
+ elif isinstance(v, SubOperation):
+ render_sub_op(v, self.db, self)
+ else:
+ self.push_const(v)
+ #self.push_var(v)
+
+ def load_variable_hook(self, v):
+ return False
- #def extends(self):
+ #def downcast(self, TYPE):
+ # pass
+
+ #def getclassobject(self, OOINSTANCE):
# pass
+
+ #def instantiate(self):
+ # pass
+
+ #def instanceof(self, TYPE):
+ # pass
+
+ def _make_label(self, label):
+ print "MAKE LABEL:", label
+ if label == "" or label is None:
+ label = self.new_label()
+
+ blocks = dict(self.fn_block.branch_blocks)
+
+ if label in self.fn_block.branch_blocks:
+ block = blocks[label]
+ else:
+ block = avm1.Block(self.block, False)
+ self.fn_block.branch_blocks.append((label, block))
+ return (label, block)
+
+ def _branch_start(self, label):
+ return self._make_label(label)
+
+ # Boolean value should be on stack when this is called
+ def branch_unconditionally(self, label):
+ print "BRANCH TO:", label
+ label, block = self._branch_start(label)
+ self.action(avm1.ActionJump(label))
+ return label, block
+
+ def branch_conditionally(self, iftrue, label):
+ label, block = self._branch_start(label)
+ if not iftrue:
+ self.action(avm1.ActionNot())
+ self.action(avm1.ActionIf(label))
+ self.pop_stack()
+ return label, block
+
+ def branch_if_equal(self, label):
+ label, block = self._branch_start(label)
+ self.action(avm1.ActionEquals())
+ self.action(avm1.ActionIf(label))
+ self.pop_stack(2)
+ return label, block
+
+ def call_graph(self, graph):
+ self.call_function(graph.func_name)
+
+ def call_method(self, OOCLASS, method_name):
+ pass
+
+ def call_oostring(self, OOTYPE):
+ self.action(avm1.ActionConvertToString())
+
+ call_oounicode = call_oostring
+
+ # def new(self, TYPE):
+ # pass
+
+ def oonewarray(self, TYPE, length):
+ self.newobject_constthis("Array", 1)
+
+ def push_null(self, TYPE=None):
+ self.action(avm1.ActionPush(avm1.NULL))
+ self
+
+ def push_undefined(self):
+ self.action(avm1.ActionPush(avm1.UNDEFINED))
+ self.push_stack(avm1.UNDEFINED)
+
+ def push_primitive_constant(self, TYPE, value):
+ if TYPE is ootype.Void:
+ self.push_undefined()
+ else:
+ self.push_const(value)
Added: pypy/branch/avm/pypy/translator/avm1/conftest.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/conftest.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,19 @@
+class ConftestPlugin:
+ def pytest_addoption(self, parser):
+ group = parser.addgroup("pypy-avm options")
+ # group.addoption('--source', action="store_true", dest="source", default=False,
+ # help="only generate IL source, don't compile")
+ # group.addoption('--wd', action="store_true", dest="wd", default=False,
+ # help="store temporary files in the working directory")
+ # group.addoption('--stdout', action="store_true", dest="stdout", default=False,
+ # help="print the generated IL code to stdout, too")
+ # group.addoption('--nostop', action="store_true", dest="nostop", default=False,
+ # help="don't stop on warning. The generated IL code could not compile")
+ # group.addoption('--nowrap', action="store_true", dest="nowrap", default=False,
+ # help="don't wrap exceptions but let them to flow out of the entry point")
+ # group.addoption('--verify', action="store_true", dest="verify", default=False,
+ # help="check that compiled executables are verifiable")
+ # group.addoption('--norun', action='store_true', dest="norun", default=False,
+ # help="don't run the compiled executable")
+ # group.addoption('--trace', action='store_true', dest='trace', default=False,
+ # help='Trace execution of generated code')
Modified: pypy/branch/avm/pypy/translator/avm1/constant.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/constant.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/constant.py Thu Aug 13 00:29:18 2009
@@ -25,11 +25,14 @@
def _begin_gen_constants(self, asmgen, all_constants):
self.asmgen = asmgen
+ self.asmgen.push_const(CONST_OBJNAME)
self.asmgen.init_object()
self.asmgen.store_register(CONST_OBJNAME)
- self.asmgen.push_const(CONST_OBJNAME)
self.asmgen.set_variable()
return asmgen
+
+ def _end_gen_constants(self, a, b):
+ pass
# _________________________________________________________________
# OOSupport interface
Modified: pypy/branch/avm/pypy/translator/avm1/database.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/database.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/database.py Thu Aug 13 00:29:18 2009
@@ -1,9 +1,6 @@
-import string
-from pypy.translator.avm.class_ import Class
-from pypy.translator.avm.delegate import Delegate
-from pypy.translator.avm.cts import types
+#from pypy.translator.avm.class_ import Class
from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.ootypesystem.module import ll_os
+from pypy.translator.cli.support import Counter
from pypy.translator.oosupport.database import Database as OODatabase
try:
@@ -16,7 +13,6 @@
OODatabase.__init__(self, genoo)
self.classes = {} # INSTANCE --> class_name
self.classnames = set() # (namespace, name)
- self.recordnames = {} # RECORD --> name
self.functions = {} # graph --> function_name
self.methods = {} # graph --> method_name
self.consts = {} # value --> AbstractConst
@@ -26,17 +22,6 @@
def next_count(self):
return self.unique()
- def _default_record_name(self, RECORD):
- trans = string.maketrans('[]<>(), :', '_________')
- name = ['Record']
- # XXX: refactor this: we need a proper way to ensure unique names
- for f_name, (FIELD_TYPE, f_default) in RECORD._fields.iteritems():
- type_name = FIELD_TYPE._short_name().translate(trans)
- name.append(f_name)
- name.append(type_name)
-
- return '__'.join(name)
-
def _default_class_name(self, INSTANCE):
parts = INSTANCE._name.rsplit('.', 1)
if len(parts) == 2:
@@ -52,42 +37,26 @@
self.pending_node(function)
return function.get_name()
- def pending_class(self, INSTANCE):
- try:
- return self.classes[INSTANCE]
- except KeyError:
- pass
+ # def pending_class(self, INSTANCE):
+ # try:
+ # return self.classes[INSTANCE]
+ # except KeyError:
+ # pass
- if isinstance(INSTANCE, dotnet.NativeInstance):
- self.classes[INSTANCE] = INSTANCE._name
- return INSTANCE._name
- else:
- namespace, name = self._default_class_name(INSTANCE)
- name = self.get_unique_class_name(namespace, name)
- if namespace is None:
- full_name = name
- else:
- full_name = '%s.%s' % (namespace, name)
- self.classes[INSTANCE] = full_name
- cls = Class(self, INSTANCE, namespace, name)
- self.pending_node(cls)
- return full_name
-
- def pending_record(self, RECORD):
- try:
- return BUILTIN_RECORDS[RECORD]
- except KeyError:
- pass
- try:
- return self.recordnames[RECORD]
- except KeyError:
- pass
- name = self._default_record_name(RECORD)
- name = self.get_unique_class_name(None, name)
- self.recordnames[RECORD] = name
- r = Record(self, RECORD, name)
- self.pending_node(r)
- return name
+ # if isinstance(INSTANCE, dotnet.NativeInstance):
+ # self.classes[INSTANCE] = INSTANCE._name
+ # return INSTANCE._name
+ # else:
+ # namespace, name = self._default_class_name(INSTANCE)
+ # name = self.get_unique_class_name(namespace, name)
+ # if namespace is None:
+ # full_name = name
+ # else:
+ # full_name = '%s.%s' % (namespace, name)
+ # self.classes[INSTANCE] = full_name
+ # cls = Class(self, INSTANCE, namespace, name)
+ # self.pending_node(cls)
+ # return full_name
def record_function(self, graph, name):
self.functions[graph] = name
@@ -113,18 +82,3 @@
return NATIVE_INSTANCE._name
except KeyError:
return self.classes[INSTANCE]
-
- def get_record_name(self, RECORD):
- try:
- return BUILTIN_RECORDS[RECORD]
- except KeyError:
- return self.recordnames[RECORD]
-
- def record_delegate(self, TYPE):
- try:
- return self.delegates[TYPE]
- except KeyError:
- name = 'StaticMethod__%d' % len(self.delegates)
- self.delegates[TYPE] = name
- self.pending_node(Delegate(self, TYPE, name))
- return name
Modified: pypy/branch/avm/pypy/translator/avm1/genavm.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/genavm.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/genavm.py Thu Aug 13 00:29:18 2009
@@ -1,21 +1,38 @@
-import sys
-import shutil
import py
-from py.compat import subprocess
-from pypy.config.config import Config
from pypy.translator.oosupport.genoo import GenOO
-from pypy.translator.cli import conftest
-from pypy.translator.cli.avm1gen import AVM1Gen
+from pypy.translator.avm.avm1gen import AVM1Gen
+from pypy.translator.avm.constant import AVM1ConstGenerator
+from pypy.translator.avm.database import LowLevelDatabase
+from pypy.translator.avm.function import Function
+from pypy.translator.avm.opcodes import opcodes
+from pypy.translator.avm.types import AVM1TypeSystem
class GenAVM1(GenOO):
- ConstantGenerator = constant.AVM1ConstGenerator
+ opcodes = opcodes
+ Function = Function
+ Database = LowLevelDatabase
+ TypeSystem = AVM1TypeSystem
+ ConstantGenerator = AVM1ConstGenerator
+
def __init__(self, tmpdir, translator, entrypoint, config=None, exctrans=False):
GenOO.__init__(self, tmpdir, translator, entrypoint, config, exctrans)
- self.assembly_name = entrypoint.get_name()
self.const_stat = str(tmpdir.join('const_stat'))
+ self.ilasm = None
def create_assembler(self):
return AVM1Gen()
+
+ def generate_source(self):
+ if self.ilasm is None:
+ self.ilasm = self.create_assembler()
+ self.fix_names()
+ self.gen_entrypoint()
+ self.gen_pendings()
+ self.db.gen_constants(self.ilasm)
+
+ # Don't do treebuilding stuff
+ def stack_optimization(self):
+ pass
Added: pypy/branch/avm/pypy/translator/avm1/metavm.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/metavm.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,68 @@
+
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.oosupport.metavm import MicroInstruction
+from pypy.translator.avm.avm1gen import StackDummy
+
+class _SetField(MicroInstruction):
+ def render(self, generator, op):
+ this, field, value = op.args
+
+ if value.concretetype is ootype.Void:
+ return
+
+ generator.load(this)
+ generator.load(field)
+ generator.load(value)
+ generator.set_member()
+
+class _GetField(MicroInstruction):
+ def render(self, generator, op):
+
+ if op.result.concretetype is ootype.Void:
+ return
+
+ this, field = op.args
+ generator.load(this)
+ generator.load(field)
+ generator.get_member()
+
+class _StoreResultStart(MicroInstruction):
+ def render(self, generator, op):
+ print "STORERESULT START:", op.result.name
+ generator.push_const(op.result.name)
+
+class _StoreResultEnd(MicroInstruction):
+ def render(self, generator, op):
+ print "STORERESULT END:", op.result.name
+ generator.set_variable()
+
+
+class _PushArgsForFunctionCall(MicroInstruction):
+ def render(self, generator, op):
+ args = op.args
+ for arg in args:
+ print arg, type(arg)
+ generator.load(arg)
+ generator.push_const(len(args))
+
+class CallConstantMethod(MicroInstruction):
+ def __init__(self, obj, func_name):
+ self.obj = obj
+ self.func_name = func_name
+
+ def render(self, generator, op):
+ generator.push_var(self.obj)
+ generator.call_method_n(self.func_name)
+
+class PushConst(MicroInstruction):
+ def __init__(self, *args):
+ self.args = args
+
+ def render(self, generator, op):
+ generator.push_const(*self.args)
+
+PushArgsForFunctionCall = _PushArgsForFunctionCall()
+StoreResultStart = _StoreResultStart()
+StoreResultEnd = _StoreResultEnd()
+GetField = _GetField()
+SetField = _SetField()
Added: pypy/branch/avm/pypy/translator/avm1/node.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/node.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,9 @@
+class Node(object):
+ def get_name(self):
+ pass
+
+ def dependencies(self):
+ pass
+
+ def render(self, ilasm):
+ pass
Added: pypy/branch/avm/pypy/translator/avm1/opcodes.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/opcodes.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,140 @@
+
+from pypy.translator.oosupport import metavm as om
+from pypy.translator.avm import metavm as am, avm1 as a
+
+DoNothing = [om.PushAllArgs]
+
+misc_ops = {
+ 'new': [om.New],
+ 'runtimenew': [om.RuntimeNew],
+ 'oosetfield': [am.SetField],
+ 'oogetfield': [am.GetField],
+# 'oosend': am.CallMethod
+}
+
+unary_ops = {
+ 'same_as': DoNothing,
+ 'bool_not': 'not',
+ 'int_neg': 'negate',
+ 'int_neg_ovf': 'negate',
+ 'int_abs': [am.PushArgsForFunctionCall, am.CallConstantMethod("Math", "abs")],
+
+ 'cast_int_to_char': [am.PushArgsForFunctionCall, am.CallConstantMethod("String", "fromCharCode")],
+ 'cast_int_to_unichar': [am.PushArgsForFunctionCall, am.CallConstantMethod("String", "fromCharCode")],
+ 'cast_int_to_float': DoNothing,
+ 'cast_int_to_longlong': DoNothing,
+ 'cast_int_to_uint': DoNothing,
+ 'cast_int_to_long': DoNothing,
+ 'cast_uint_to_float': DoNothing,
+ 'cast_uint_to_longlong': DoNothing,
+ 'cast_uint_to_int' : DoNothing,
+ 'cast_uint_to_long': DoNothing,
+
+ 'cast_bool_to_int': 'convert_to_number',
+ 'cast_bool_to_uint': 'convert_to_number',
+ 'cast_bool_to_float': 'convert_to_number',
+
+
+}
+
+binary_ops = {
+ 'int_add': 'typed_add',
+ 'int_sub': 'subtract',
+ 'int_mul': 'multiply',
+ 'int_floordiv': [om.PushAllArgs, 'divide', am.PushConst(1), am.CallConstantMethod("Math", "floor")],
+ 'int_mod': 'modulo',
+ 'int_lt': 'typed_less',
+ 'int_le': [om.PushAllArgs, 'greater', 'not'],
+ 'int_eq': 'typed_equals',
+ 'int_ne': [om.PushAllArgs, 'typed_equals', 'not'],
+ 'int_gt': 'greater',
+ 'int_ge': [om.PushAllArgs, 'typed_less', 'not'],
+
+ 'int_and': 'bit_and',
+ 'int_or': 'bit_or',
+ 'int_lshift': 'shift_left',
+ 'int_rshift': 'shift_right',
+ 'int_xor': 'bit_xor',
+
+ 'uint_add': 'typed_add',
+ 'uint_sub': 'subtract',
+ 'uint_mul': 'multiply',
+ 'uint_floordiv': [om.PushAllArgs, 'divide', am.PushConst(1), am.CallConstantMethod("Math", "floor")],
+ 'uint_mod': 'modulo',
+ 'uint_lt': 'typed_less',
+ 'uint_le': [om.PushAllArgs, 'greater', 'not'],
+ 'uint_eq': 'typed_equals',
+ 'uint_ne': [om.PushAllArgs, 'typed_equals', 'not'],
+ 'uint_gt': 'greater',
+ 'uint_ge': [om.PushAllArgs, 'typed_less', 'not'],
+
+ 'uint_and': 'bit_and',
+ 'uint_or': 'bit_or',
+ 'uint_lshift': 'shift_left',
+ 'uint_rshift': 'shift_right',
+ 'uint_xor': 'bit_xor',
+
+ 'float_add': 'typed_add',
+ 'float_sub': 'subtract',
+ 'float_mul': 'multiply',
+ 'float_floordiv': [om.PushAllArgs, 'divide', am.PushConst(1), am.CallConstantMethod("Math", "floor")],
+ 'float_mod': 'modulo',
+ 'float_lt': 'typed_less',
+ 'float_le': [om.PushAllArgs, 'greater', 'not'],
+ 'float_eq': 'typed_equals',
+ 'float_ne': [om.PushAllArgs, 'typed_equals', 'not'],
+ 'float_gt': 'greater',
+ 'float_ge': [om.PushAllArgs, 'typed_less', 'not'],
+
+ 'float_and': 'bit_and',
+ 'float_or': 'bit_or',
+ 'float_lshift': 'shift_left',
+ 'float_rshift': 'shift_right',
+ 'float_xor': 'bit_xor',
+
+ 'llong_add': 'typed_add',
+ 'llong_sub': 'subtract',
+ 'llong_mul': 'multiply',
+ 'llong_floordiv': [om.PushAllArgs, 'divide', am.PushConst(1), am.CallConstantMethod("Math", "floor")],
+ 'llong_mod': 'modulo',
+ 'llong_lt': 'typed_less',
+ 'llong_le': [om.PushAllArgs, 'greater', 'not'],
+ 'llong_eq': 'typed_equals',
+ 'llong_ne': [om.PushAllArgs, 'typed_equals', 'not'],
+ 'llong_gt': 'greater',
+ 'llong_ge': [om.PushAllArgs, 'typed_less', 'not'],
+
+ 'llong_and': 'bit_and',
+ 'llong_or': 'bit_or',
+ 'llong_lshift': 'shift_left',
+ 'llong_rshift': 'shift_right',
+ 'llong_xor': 'bit_xor',
+
+ 'ullong_add': 'typed_add',
+ 'ullong_sub': 'subtract',
+ 'ullong_mul': 'multiply',
+ 'ullong_floordiv': [om.PushAllArgs, 'divide', am.PushConst(1), am.CallConstantMethod("Math", "floor")],
+ 'ullong_mod': 'modulo',
+ 'ullong_lt': 'typed_less',
+ 'ullong_le': [om.PushAllArgs, 'greater', 'not'],
+ 'ullong_eq': 'typed_equals',
+ 'ullong_ne': [om.PushAllArgs, 'typed_equals', 'not'],
+ 'ullong_gt': 'greater',
+ 'ullong_ge': [om.PushAllArgs, 'typed_less', 'not'],
+ 'ullong_lshift': 'shift_left',
+ 'ullong_rshift': 'shift_right',
+}
+
+opcodes = misc_ops.copy()
+opcodes.update(unary_ops)
+opcodes.update(binary_ops)
+
+for key, value in opcodes.iteritems():
+ if isinstance(value, str):
+ value = [am.StoreResultStart, om.PushAllArgs, value, am.StoreResultEnd]
+ if am.StoreResultStart not in value:
+ value.insert(0, am.StoreResultStart)
+ if am.StoreResultEnd not in value:
+ value.append(am.StoreResultEnd)
+ value = om.InstructionList(value)
+ opcodes[key] = value
Modified: pypy/branch/avm/pypy/translator/avm1/tags.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/tags.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/tags.py Thu Aug 13 00:29:18 2009
@@ -3,6 +3,7 @@
from pypy.translator.avm.records import RecordHeader, ShapeWithStyle, Matrix, CXForm
from pypy.translator.avm.avm1 import Block
+from pypy.translator.avm.util import BitStream
next_character_id = 1
@@ -117,12 +118,42 @@
return (struct.pack("<HH", self.shapeid, self.depth) +
(self.transform.serialize() + self.colortransform.serialize()).serialize())
+class PlaceObject2(PlaceObject):
+
+ TAG_TYPE = 26
+ TAG_MIN_VERSION = 3
+
+ def __init__(self, shapeid, depth, transform=None, colortransform=None):
+ self.shapeid = shapeid
+ self.depth = depth
+ self.transform = transform
+ self.colortransform = colortransform
+
+ def serialize_data(self):
+ flags = BitStream()
+ flags.write_bit(False) # HasClipActions
+ flags.write_bit(False) # HasClipDepth
+ flags.write_bit(False) # HasName
+ flags.write_bit(False) # HasRatio
+ flags.write_bit(self.colortransform is not None)
+ flags.write_bit(self.transform is not None)
+ flags.write_bit(True) # HasCharacter
+ flags.write_bit(False) # FlagMove
+
+ bytes = flags.serialize() + struct.pack("<HH", self.depth, self.shapeid)
+ bits = BitStream()
+ if self.transform is not None:
+ bits += self.transform.serialize()
+ if self.colortransform is not None:
+ bits += self.colortransform.serialize()
+ return bytes + bits.serialize()
+
class DefineEditText(SwfTag):
TAG_TYPE = 37
TAG_MIN_VERSION = 4
- def __init__(self, rect, variable, text="", readonly=False, isHTML=False,
+ def __init__(self, rect, variable, text="", readonly=True, isHTML=False,
wordwrap=False, multiline=True, password=False, autosize=True,
selectable=True, border=False, color=None, maxlength=None,
layout=None, font=None, size=12, fontclass=None, characterid=None):
Added: pypy/branch/avm/pypy/translator/avm1/test/__init__.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/test/__init__.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1 @@
+#
Modified: pypy/branch/avm/pypy/translator/avm1/test/browsertest.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/test/browsertest.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/test/browsertest.py Thu Aug 13 00:29:18 2009
@@ -16,6 +16,7 @@
<body>
<object type="application/x-shockwave-flash" data="test.swf" width="%d" height="%d">
<param name="movie" value="test.swf" />
+<param name="allowScriptAccess" value="always" />
</object>
</body>
</html>"""
@@ -29,18 +30,15 @@
return True
elif string == "false":
return False
- elif string == "null" or string == "undefined":
- return None
- elif string.isdigit():
+ elif all(c in "0123456789-" for c in string):
return int(string)
return string
class TestCase(object):
- def __init__(self, name, swfdata, testcount):
+ def __init__(self, name, swfdata):
self.name = name
self.swfdata = swfdata
- self.results = []
- self.testcount = testcount
+ self.result = None
class TestHandler(BaseHTTPRequestHandler):
"""The HTTP handler class that provides the tests and handles results"""
@@ -59,9 +57,10 @@
self.serve_data(mime, data)
def do_POST(self):
+ print self.path
if self.path == "/test.result":
form = parse_qs(self.rfile.read(int(self.headers['content-length'])))
- self.server.testcase.results.append(parse_result(form['result'][0]))
+ self.server.testcase.result = parse_result(form['result'][0])
def serve_data(self, content_type, data):
self.send_response(200)
@@ -80,14 +79,14 @@
def get_result(self):
testcase = self.httpd.testcase
- while len(testcase.results) < testcase.testcount:
+ while testcase.result is None:
self.httpd.handle_request()
- return self.httpd.testcase.results
+ return testcase.result
-def browsertest(name, swfdata, testcount):
- testcase = TestCase(str(name), swfdata, testcount)
+def browsertest(name, swfdata):
+ testcase = TestCase(str(name), swfdata)
driver = BrowserTest()
driver.start_server(config.http_port, testcase)
webbrowser.open('http://localhost:%d/test.html' % config.http_port)
-
+
return driver.get_result()
Modified: pypy/branch/avm/pypy/translator/avm1/test/harness.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/test/harness.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/test/harness.py Thu Aug 13 00:29:18 2009
@@ -5,23 +5,22 @@
class TestHarness(object):
def __init__(self, name):
self.testname = name
- self.in_test = False
- self.expected = []
self.swf = s.SwfData()
self.swf.add_tag(t.SetBackgroundColor(0x333333))
self.swf.add_tag(t.DefineEditText(r.Rect(0, 0, 0, 0), "txt",
"Testing %s." % (name,), color=r.RGBA(0xFFFFFF)))
- self.swf.add_tag(t.PlaceObject(1, 2))
+ self.swf.add_tag(t.PlaceObject2(1, 2))
self.actions = g.AVM1Gen(t.DoAction())
self.swf.add_tag(self.actions.block)
self.swf.add_tag(t.ShowFrame())
self.swf.add_tag(t.End())
+ self.start_test()
def print_text(self, text):
self.actions.push_const("txt", "\n" + text)
self.actions.push_var("txt")
self.actions.swap()
- self.actions.concat_string()
+ self.actions.emit('typed_add')
self.actions.set_variable()
def print_var(self, prefix, varname):
@@ -29,8 +28,8 @@
self.actions.push_var("txt")
self.actions.push_const("\n" + prefix)
self.actions.push_var(varname)
- self.actions.concat_string()
- self.actions.concat_string()
+ self.actions.emit('typed_add')
+ self.actions.emit('typed_add')
self.actions.set_variable()
def print_stack(self, prefix):
@@ -40,31 +39,29 @@
self.actions.swap()
self.actions.push_const("\n" + prefix)
self.actions.swap()
- self.actions.concat_string()
- self.actions.concat_string()
+ self.actions.emit('typed_add')
+ self.actions.emit('typed_add')
self.actions.set_variable()
- def start_test(self, name):
- assert not self.in_test
- self.in_test = True
- self.print_text("Running test %s." % name)
+ def start_test(self):
+ self.print_text("Running test %s." % self.testname)
self.actions.push_const("result")
- def finish_test(self, expected):
+ def finish_test(self):
# result value is on the stack,
# followed by the string "result"
- assert self.in_test
- self.in_test = False
- self.expected.append(expected)
self.actions.set_variable()
self.print_var("Got: ", "result")
self.actions.push_const("/test.result", "") # URL, target
self.actions.action(a.ActionGetURL2("POST", True, True))
+ self.actions.push_const("javascript:window.close()", "") # Close the window.
+ self.actions.action(a.ActionGetURL2(""))
- def do_test(self):
- assert not self.in_test
- with open("test.swf", "w") as f:
+ def do_test(self, debug=False):
+ self.finish_test()
+ self.actions.scope.block.seal()
+ if debug:
+ f = open("test.swf", "w")
f.write(self.swf.serialize())
- results = b.browsertest(self.testname, self.swf, len(self.expected))
- for e, r in zip(self.expected, results):
- assert e == r
+ f.close()
+ return b.browsertest(self.testname, self.swf)
Modified: pypy/branch/avm/pypy/translator/avm1/test/runtest.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/test/runtest.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/test/runtest.py Thu Aug 13 00:29:18 2009
@@ -10,13 +10,14 @@
from pypy.translator.backendopt.checkvirtual import check_virtual_methods
from pypy.translator.oosupport.support import patch_os, unpatch_os
from pypy.translator.avm.test.harness import TestHarness
+from pypy.translator.avm.genavm import GenAVM1
-def translate_space_op(gen, op):
- if op.opname == "cast_int_to_char":
- gen.push_arg(op.args[0])
- gen.push_const(1)
- gen.push_var("String")
- gen.call_method("fromCharCode")
+# def translate_space_op(gen, op):
+# if op.opname == "cast_int_to_char":
+# gen.push_arg(op.args[0])
+# gen.push_const(1)
+# gen.push_var("String")
+# gen.call_method("fromCharCode")
def compile_function(func, name, annotation=[], graph=None, backendopt=True,
auto_raise_exc=False, exctrans=False,
@@ -24,8 +25,11 @@
olddefs = patch_os()
gen = _build_gen(func, annotation, name, graph, backendopt,
exctrans, annotatorpolicy, nowrap)
+ harness = TestHarness(name)
+ gen.ilasm = harness.actions
+ gen.generate_source()
unpatch_os(olddefs) # restore original values
- return gen
+ return gen, harness
def _build_gen(func, annotation, name, graph=None, backendopt=True, exctrans=False,
annotatorpolicy=None, nowrap=False):
@@ -50,62 +54,29 @@
backend_optimizations(t)
main_graph = t.graphs[0]
-
- harness = TestHarness(name)
- harness.actions.begin_function(main_graph.name, [v.name for v in main_graph.getargs()])
- for op in main_graph.startblock.operations:
- translate_space_op(harness.actions, op)
- harness.actions.return_stmt()
- harness.actions.exit_scope()
+ tmpdir = py.path.local('.')
- return harness
-
-class StructTuple(tuple):
- def __getattr__(self, name):
- if name.startswith('item'):
- i = int(name[len('item'):])
- return self[i]
- else:
- raise AttributeError, name
-
-class OOList(list):
- def ll_length(self):
- return len(self)
-
- def ll_getitem_fast(self, i):
- return self[i]
-
-class InstanceWrapper:
- def __init__(self, class_name):
- self.class_name = class_name
-
-class ExceptionWrapper:
- def __init__(self, class_name):
- self.class_name = class_name
-
- def __repr__(self):
- return 'ExceptionWrapper(%s)' % repr(self.class_name)
+ return GenAVM1(tmpdir, t, None, exctrans)
class AVM1Test(BaseRtypingTest, OORtypeMixin):
def __init__(self):
self._func = None
self._ann = None
+ self._genoo = None
self._harness = None
- self._test_count = 1
def _compile(self, fn, args, ann=None, backendopt=True, auto_raise_exc=False, exctrans=False):
if ann is None:
ann = [lltype_to_annotation(typeOf(x)) for x in args]
- if self._func is fn and self._ann == ann:
- return self._harness
- else:
- self._harness = compile_function(fn, self.__class__.__name__, ann,
- backendopt=backendopt,
- auto_raise_exc=auto_raise_exc,
- exctrans=exctrans)
- self._func = fn
- self._ann = ann
- return self._harness
+ self._genoo, self._harness = compile_function(fn,
+ "%s.%s" % (self.__class__.__name__, fn.func_name),
+ ann,
+ backendopt=backendopt,
+ auto_raise_exc=auto_raise_exc,
+ exctrans=exctrans)
+ self._func = fn
+ self._ann = ann
+ return self._harness
def _skip_win(self, reason):
if platform.system() == 'Windows':
@@ -123,16 +94,12 @@
backendopt = getattr(self, 'backendopt', True) # enable it by default
return backendopt
- def interpret(self, fn, args, expected=None, annotation=None, backendopt=None, exctrans=False):
+ def interpret(self, fn, args, annotation=None, backendopt=None, exctrans=False):
backendopt = self._get_backendopt(backendopt)
harness = self._compile(fn, args, annotation, backendopt=backendopt, exctrans=exctrans)
- harness.start_test("%d" % self._test_count)
- self._test_count += 1
harness.actions.call_function_constargs(fn.func_name, *args)
- harness.finish_test(expected)
-
- def do_test(self):
- self._harness.do_test()
+ result = harness.do_test(True)
+ return result
def interpret_raises(self, exception, fn, args, backendopt=None, exctrans=False):
import exceptions # needed by eval
Modified: pypy/branch/avm/pypy/translator/avm1/test/test_int.py
==============================================================================
--- pypy/branch/avm/pypy/translator/avm1/test/test_int.py (original)
+++ pypy/branch/avm/pypy/translator/avm1/test/test_int.py Thu Aug 13 00:29:18 2009
@@ -2,20 +2,49 @@
import py
from pypy.translator.avm.test.runtest import AVM1Test
from pypy.rpython.test.test_rint import BaseTestRint
+from pypy.rlib.rarithmetic import r_longlong
class TestAVM1Int(AVM1Test, BaseTestRint):
def test_char_constant(self):
def dummyfn(i):
return chr(i)
- self.interpret(dummyfn, [ord(' ')], ' ')
- self.interpret(dummyfn, [ord('a')], 'a')
- self.do_test()
+ _ = self.interpret(dummyfn, [ord(' ')])
+ assert _ == ' '
+ _ = self.interpret(dummyfn, [ord('a')])
+ assert _ == 'a'
def test_rarithmetic(self):
pass # it doesn't make sense here
div_mod_iteration_count = 20
+
+ def test_div_mod(self):
+ import random
+ for inttype in (int, r_longlong):
-if __name__ == "__main__":
- TestAVM1Int().test_char_constant()
+ # def d(x, y):
+ # return x/y
+
+ # for i in range(self.div_mod_iteration_count):
+ # x = inttype(random.randint(-100000, 100000))
+ # y = inttype(random.randint(-100000, 100000))
+ # if not y: continue
+ # res = self.interpret(d, [x, y])
+ # print "x:", x, "y:", y, "result in Flash:", res, "result in Python:", d(x, y)
+ # assert res == d(x, y)
+
+ def m(x, y):
+ return x%y
+
+ for i in range(self.div_mod_iteration_count):
+ x = inttype(random.randint(-100000, 100000))
+ y = inttype(random.randint(-100000, 100000))
+ if not y: continue
+ res = self.interpret(m, [x, y])
+ print "x:", x, "y:", y, "result in Flash:", res, "result in Python:", m(x, y)
+ assert res == m(x, y)
+
+
+if __name__=="__main__":
+ TestAVM1Int().test_div_mod()
Added: pypy/branch/avm/pypy/translator/avm1/test/test_runtest.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/test/test_runtest.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,18 @@
+import autopath
+import py
+from pypy.translator.oosupport.test_template.runtest import BaseTestRunTest
+from pypy.translator.avm.test.runtest import AVM1Test
+
+class TestRunTest(BaseTestRunTest, AVM1Test):
+
+ def test_auto_raise_exc(self):
+ def fn():
+ raise ValueError
+ f = self._compile(fn, [], auto_raise_exc=True)
+ py.test.raises(ValueError, f)
+
+ def test_big_arglist(self):
+ def fn(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9):
+ return a0
+ res = self.interpret(fn, [42]*10)
+ assert res == 42
Added: pypy/branch/avm/pypy/translator/avm1/types.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/types.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,47 @@
+
+from pypy.translator.avm import avm1
+from pypy.objspace.flow import model as flowmodel
+from pypy.rlib.rarithmetic import r_longlong
+from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.lltypesystem import lltype
+
+_pytype_to_avm1 = {
+ str: avm1.STRING,
+ unicode: avm1.STRING,
+ int: avm1.INTEGER,
+ long: avm1.INTEGER,
+ bool: avm1.BOOLEAN,
+ float: avm1.DOUBLE,
+ r_longlong: avm1.INTEGER,
+}
+
+class AVM1Number(object):
+ pass
+
+class AVM1Primitive(object):
+ pass
+
+_lltype_to_avm1 = {
+ lltype.Number: AVM1Number,
+ lltype.Primitive: AVM1Primitive
+}
+
+def pytype_to_avm1(value):
+ return (value, _pytype_to_avm1[type(value)])
+
+def lltype_to_avm1(value):
+ return _lltype_to_avm1[type(value)]
+
+class AVM1TypeSystem(object):
+ def __init__(self, db):
+ self.db = db
+
+ def escape_name(self, name):
+ return name
+
+ def lltype_to_cts(self, TYPE):
+ return lltype_to_avm1(TYPE)
+
+ def llvar_to_cts(self, var):
+ print var.name
+ return self.lltype_to_cts(var.concretetype), var.name
Added: pypy/branch/avm/pypy/translator/avm1/util.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm1/util.py Thu Aug 13 00:29:18 2009
@@ -0,0 +1,256 @@
+
+import struct, os, math
+
+ALIGN_LEFT = "left"
+ALIGN_RIGHT = "right"
+
+class BitStream(object):
+
+ """ BitStream is a class for taking care of data structures that are bit-packed, like SWF."""
+
+ def __init__(self, bits=[]):
+ """
+ Constructor.
+ """
+ self.bits = [bool(b) and b != "0" for b in bits]
+ self.cursor = 0
+ self.chunks = set((0,))
+
+ def read_bit(self):
+ """Reads a bit from the bit stream and returns it as either True or False. IndexError is thrown if reading past the end of the stream."""
+ self.cursor += 1
+ return self.bits[self.cursor-1]
+
+ def read_bits(self, length):
+ """Reads length bits and return them in their own bit stream."""
+ self.cursor += length
+ return BitStream(self.bits[self.cursor-length:self.cursor])
+
+ def write_bit(self, value):
+ """Writes the boolean value to the bit stream."""
+ if self.cursor < len(self.bits):
+ self.bits[self.cursor] = bool(value)
+ else:
+ self.bits.append(bool(value))
+ self.cursor += 1
+
+ def write_bits(self, bits, offset=0, length=0):
+ """Writes length bits from bits to this bit stream, starting reading at offset. If length
+ is 0, the entire stream is used."""
+ if length < 1:
+ length = len(bits)
+
+ if length > self.bits_available():
+ for i in range(length - self.bits_available()):
+ self.bits.append(False)
+
+ self.bits[self.cursor:self.cursor+length] = (bool(x) for x in bits[offset:offset+length])
+ self.cursor += length
+
+ def read_int_value(self, length):
+ """Read length bits and return a number containing those bits with the last bit read being
+ the least significant bit."""
+ n = 0
+ for i in reversed(xrange(length)):
+ n |= self.read_bit() << i
+ return n
+
+ def write_int_value(self, value, length=-1):
+ """Writes an int to the specified number of bits in the stream, the most significant bit
+ first. If length is not specified or negative, the log base 2 of value is taken."""
+
+ if length < 0:
+ try:
+ length = int(math.ceil(math.log(value, 2))) # Get the log base 2, or number of bits value will fit in.
+ except ValueError:
+ length = 1
+ self.chunk()
+ for i in reversed(xrange(length)):
+ self.write_bit(value & (1 << i))
+
+
+ def read_fixed_value(self, eight_bit):
+ """Reads a fixed point number, either 8.8 or 16.16. If eight_bit is True, an
+ 8.8 format is used, otherwise 16.16."""
+ return self.read_int_value(length) / float(0x100 if eight_bit else 0x10000)
+
+ def write_fixed_value(self, value, eight_bit):
+ """Writes a fixed point number of length, decimal part first. If eight_bit is True,
+ an 8.8 format is used instead of a 16.16 format."""
+ self.write_bit_value(value * float(0x100 if eight_bit else 0x10000), 8 if eight_bit else 16)
+
+ # Precalculated, see the Wikipedia links below.
+ _EXPN_BIAS = {16: 16, 32: 127, 64: 1023}
+ _N_EXPN_BITS = {16: 5, 32: 8, 64: 8}
+ _N_FRAC_BITS = {16: 10, 32: 23, 64: 52}
+ _FLOAT_NAME = {16: "float16", 32: "float", 64: "double"}
+
+ def read_float_value(self, length):
+ """Reads a floating point number of length, which must be 16 (float16), 32 (float),
+ or 64 (double). See: http://en.wikipedia.org/wiki/IEEE_floating-point_standard"""
+
+ if length not in BitStream._FLOAT_NAME:
+ raise ValueError, "length is not 16, 32 or 64."
+
+ sign = self.read_bit()
+ expn = self.read_int_value(BitStream._N_EXPN_BITS[length])
+ frac = self.read_int_value(BitStream._N_FRAC_BITS[length])
+
+ frac_total = float(1 << BitStream._N_FRAC_BITS[length])
+
+ if expn == 0:
+ if frac == 0:
+ return 0
+ else:
+ return ~frac + 1 if sign else frac
+ elif expn == frac_total - 1:
+ if frac == 0:
+ return float("-inf") if sign else float("inf")
+ else:
+ return float("nan")
+
+ return (-1 if sign else 1) * 2**(expn - BitStream._EXPN_BIAS[length]) * (1 + frac / frac_total)
+
+ def write_float_value(self, value, length):
+ """Writes a floating point number of length, which must be 16 (float16),
+ 32 (float), or 64 (double). See: http://en.wikipedia.org/wiki/IEEE_floating-point_standard"""
+
+ if length not in BitStream._FLOAT_NAME:
+ raise ValueError, "length is not 16, 32 or 64."
+
+ if value == 0: # value is zero, so we don't care about length
+ self.write_int_value(0, length)
+
+ if math.isnan(value):
+ self.one_fill(length)
+ return
+ elif value == float("-inf"): # negative infinity
+ self.one_fill(BitStream._N_EXPN_BITS[length] + 1) # sign merged
+ self.zero_fill(BitStream._N_FRAC_BITS[length])
+ return
+ elif value == float("inf"): # positive infinity
+ self.write_bit(False)
+ self.one_fill(BitStream._N_EXPN_BITS[length])
+ self.zero_fill(BitStream._N_FRAC_BITS[length])
+ return
+
+ if value < 0:
+ self.write_bit(True)
+ value = ~value + 1
+ else:
+ self.write_bit(False)
+
+ exp = BitStream._EXPN_BIAS[length]
+ if value < 1:
+ while int(value) != 1:
+ value *= 2
+ exp -= 1
+ else:
+ while int(value) != 1:
+ value /= 2
+ exp += 1
+
+ if exp < 0 or exp > ( 1 << BitStream._N_EXPN_BITS[length] ):
+ raise ValueError, "Exponent out of range in %s [%d]." % (BitStream._FLOAT_NAME[length], length)
+
+ frac_total = 1 << BitStream._N_FRAC_BITS[length]
+ self.write_int_value(exp, BitStream._N_EXPN_BITS[length])
+ self.write_int_value(int((value-1)*frac_total) & (frac_total - 1), BitStream._N_FRAC_BITS[length])
+
+
+ def one_fill(self, amount):
+ """Fills amount bits with one. The equivalent of calling
+ self.write_boolean(True) amount times, but more efficient."""
+
+ if amount > self.bits_available():
+ for i in range(amount - self.bits_available()):
+ self.bits.append(True)
+
+ self.bits[self.cursor:self.cursor+amount] = [True] * amount
+ self.cursor += amount
+
+ def zero_fill(self, amount):
+ """Fills amount bits with zero. The equivalent of calling
+ self.write_boolean(False) amount times, but more efficient."""
+
+ if amount > self.bits_available():
+ for i in range(amount - self.bits_available()):
+ self.bits.append(False)
+
+ self.bits[self.cursor:self.cursor+amount] = [False] * amount
+ self.cursor += amount
+
+ def seek(self, offset, whence=os.SEEK_SET):
+ if whence == os.SEEK_SET:
+ self.cursor = offset
+ elif whence == os.SEEK_CUR:
+ self.cursor += offset
+ elif whence == os.SEEK_END:
+ self.cursor = len(self.bits) - abs(offset)
+
+ def rewind(self):
+ self.seek(0, os.SEEK_SET)
+
+ def skip_to_end(self):
+ self.seek(0, os.SEEK_END)
+
+ def bits_available(self):
+ return len(self.bits) - self.cursor
+
+ def flush(self):
+ self.zero_fill(8 - (len(self) % 8))
+
+ def chunk(self):
+ self.chunks.add(int(math.ceil(self.cursor / 8.)))
+
+ def __len__(self):
+ return len(self.bits)
+
+ def __getitem__(self, i):
+ return self.bits.__getitem__(i)
+
+ def __setitem__(self, i, v):
+ return self.bits.__setitem__(i, v)
+
+ def __str__(self):
+ return "".join("1" if b else "0" for b in self.bits)
+
+ def __add__(self, bits):
+ b = BitStream()
+ b.write_bits(self)
+ b.write_bits(bits)
+ return b
+
+ def __iadd__(self, bits):
+ self.write_bits(bits)
+ return self
+
+ def serialize(self, align=ALIGN_LEFT, endianness=None):
+ """Serialize bit array into a byte string, aligning either
+ on the right (ALIGN_RIGHT) or left (ALIGN_LEFT). Endianness
+ can also be "<" for little-endian modes."""
+ lst = self.bits[:]
+ leftover = len(lst) % 8
+ if leftover > 0:
+ if align == ALIGN_RIGHT:
+ lst[:0] = [False] * (8-leftover) # Insert some False values to pad the list so it is aligned to the right.
+ else:
+ lst += [False] * (8-leftover)
+
+ lst = BitStream(lst)
+ tmp = [lst.read_int_value(8) for i in xrange(int(math.ceil(len(lst)/8.0)))]
+
+ bytes = [None] * len(tmp)
+ if endianness == "<":
+ m = sorted(self.chunks) + [len(tmp)]
+ for start, end in zip(m, m[1::]):
+ bytes[start:end] = tmp[end-1:None if start == 0 else start-1:-1]
+ else:
+ bytes = tmp
+ return ''.join(chr(b) for b in bytes)
+
+ def parse(self, string, endianness="<"):
+ """Parse a bit array from a byte string into this BitStream."""
+ for char in string:
+ self.write_int_value(ord(char), 8)
+
More information about the Pypy-commit
mailing list