[pypy-svn] r60619 - in pypy/branch/avm/pypy/translator/avm: . test

magcius at codespeak.net magcius at codespeak.net
Fri Dec 19 20:01:17 CET 2008


Author: magcius
Date: Fri Dec 19 20:01:17 2008
New Revision: 60619

Added:
   pypy/branch/avm/pypy/translator/avm/
   pypy/branch/avm/pypy/translator/avm/__init__.py
   pypy/branch/avm/pypy/translator/avm/avm.py
   pypy/branch/avm/pypy/translator/avm/avm1.py
   pypy/branch/avm/pypy/translator/avm/avm1gen.py
   pypy/branch/avm/pypy/translator/avm/avm1types.py
   pypy/branch/avm/pypy/translator/avm/bootstrap.py
   pypy/branch/avm/pypy/translator/avm/database.py
   pypy/branch/avm/pypy/translator/avm/function.py
   pypy/branch/avm/pypy/translator/avm/log.py
   pypy/branch/avm/pypy/translator/avm/metavm.py
   pypy/branch/avm/pypy/translator/avm/records.py
   pypy/branch/avm/pypy/translator/avm/support.py
   pypy/branch/avm/pypy/translator/avm/swf.py
   pypy/branch/avm/pypy/translator/avm/tags.py
   pypy/branch/avm/pypy/translator/avm/test/
   pypy/branch/avm/pypy/translator/avm/test/browsertest.py
   pypy/branch/avm/pypy/translator/avm/test/runtest.py
   pypy/branch/avm/pypy/translator/avm/util.py
Log:
Aaaand the experimental non-functioning (yet) AVM1 backend.

Added: pypy/branch/avm/pypy/translator/avm/__init__.py
==============================================================================

Added: pypy/branch/avm/pypy/translator/avm/avm.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/avm.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,66 @@
+
+import py, os
+
+from pypy.rpython.rmodel import inputconst
+from pypy.rpython.typesystem import getfunctionptr
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.ootypesystem import ootype
+from pypy.tool.udir import udir
+from pypy.translator.avm.log import log
+from pypy.translator.avm.asmgen import AsmGen
+from pypy.translator.avm.avm1types import AVM1TypeSystem
+#from pypy.translator.js.opcodes import opcodes
+from pypy.translator.avm.function import Function
+from pypy.translator.avm.database import LowLevelDatabase
+from pypy.translator.avm import bootstrap
+
+from pypy.translator.oosupport.genoo import GenOO
+from heapq import heappush, heappop
+
+
+class AVM1(GenOO):
+    TypeSystem = AVMTypeSystem
+    Function = Function
+    Database = LowLevelDatabase
+
+    def __init__(self, translator, function=[], stackless=False, compress=False, \
+                 logging=False, use_debug=False):
+        if not isinstance(function, list):
+            functions = [functions]
+        GenOO.__init__(self, udir, translator, None)
+
+        pending_graphs = [ translator.annotator.bookeeeper.getdesc(f).cachedgraph(None) for f in functions ]
+        for graph in pending_graphs:
+            self.db.pending_function(graph)
+
+        self.db.translator = translator
+        self.use_debug = use_debug
+        self.assembly_name = self.translator.graphs[0].name
+        self.tmpfile = udir.join(self.assembly_name + '.swf')
+
+    def stack_optimization(self):
+        pass
+
+    def gen_pendings(self):
+        while self.db._pending_nodes:
+            node = self.db.pending_nodes.pop()
+            to_render = []
+            nparent = node
+            while nparent-order != 0:
+                nparent = nparent.parent
+                to_render.append(nparent)
+            to_render.reverse()
+            for i in to_render:
+                i.render(self.ilasm)
+
+    def create_assembler(self):
+        return bootstrap.create_assembler(self.assembly_name)
+
+    def generate_swf(self):
+        self.ilasm = self.create_assembler()
+        self.fix_names()
+        self.gen_entrypoint()
+        while self.db._pending_nodes:
+            self.gen_pendings()
+            self.db.gen_constants(self.ilasm, self.db._pending_nodes)
+        # self.ilasm.close()

Added: pypy/branch/avm/pypy/translator/avm/avm1.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/avm1.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,625 @@
+
+# AVM1 = ActionScript Virtual Machine 1
+# Used for ActionScript 1 and 2
+
+from pypy.translator.avm.util import BitStream
+import struct
+
+class DataTypes(object):
+    
+    def __init__(self, id, name, size):
+        self.id = id
+        self.name = name
+        self.size = size
+        
+    def __str__(self):
+        return self.name
+
+    def __call__(self, *a, **b):
+        pass
+    
+    __unicode__ = __str__
+
+DataTypes.STRING      = DataTypes(0, "string", "Z")
+DataTypes.FLOAT       = DataTypes(1, "float", "f")
+DataTypes.NULL        = DataTypes(2, "null", "!")
+DataTypes.UNDEFINED   = DataTypes(3, "undefined", "!")
+DataTypes.REGISTER    = DataTypes(4, "register", "B")
+DataTypes.BOOLEAN     = DataTypes(5, "boolean", "B")
+DataTypes.DOUBLE      = DataTypes(6, "double", "d")
+DataTypes.INTEGER     = DataTypes(7, "integer", "l")
+DataTypes.CONSTANT8   = DataTypes(8, "constant 8", "B")
+DataTypes.CONSTANT16  = DataTypes(9, "constant 16", "H")
+
+class Index(object):
+    def __init__(self, index):
+        self.index = index
+
+class Value(object):
+    def __init__(self, value):
+        self.value = value
+
+Null = object()
+Null.type = DataTypes.Null
+
+Undefined = object()
+Undefined.type = DataTypes.UNDEFINED
+
+class Constant(Index):
+    def __getattr__(self, name):
+        if name == "type":
+            if self.index < 256:
+                return DataTypes.CONSTANT8
+            return DataTypes.CONSTANT16
+        return Index.__getattr__(self, name)
+
+class RegisterByIndex(Index):
+    type = DataTypes.REGISTER
+
+class RegisterByValue(Value):
+    type = DataTypes.REGISTER
+
+class Action(object):
+    
+    ACTION_NAME = "NotImplemented"
+    ACTION_ID = 0x00
+    
+    def __init__(self):    
+        self.offset = 0
+        self.label_name = ""
+    
+    def serialize(self):
+        inner_data = self.gen_data()
+        outer_data = self.gen_outer_data()
+        header = struct.pack("BH", self.ACTION_ID, len(inner_data))
+        return bytes + inner_data + outer_data
+    
+    def __len__(self):
+        return 6 + len(self.gen_data()) + len(self.gen_outer_data())
+    
+    def gen_data(self):
+        raise NotImplementedError, "Action::gen_data is not implemented in the abstract class"
+
+    def gen_outer_data(self):
+        raise NotImplementedError, "Action::gen_outer_data is not implemented in the abstract class"
+    
+    def get_block_props_early(self, block):
+        raise NotImplementedError, "Action::get_block_props_early is not implemented in the abstract class"
+
+    def get_block_props_late(self, block):
+        raise NotImplementedError, "Action::get_block_props_late is not implemented in the abstract class"
+
+class RegisterError(IndexError):
+    pass
+
+global_registers = []
+
+class Block(object):
+
+    AUTO_LABEL_TEMPLATE = "label%d"
+    MAX_REGISTERS = 4
+    FUNCTION_TYPE = 0
+
+    def __init__(self, insert_end=False):
+        self.code = ""
+        self.__sealed = False
+        self.insert_end = insert_end
+        
+        self.labels = {}
+        self.branch_blocks = {}
+        self.constants = ActionConstantPool()
+        self.actions = [self.constants]
+        
+        self.current_offset = 0
+        self.label_count = 0
+        self.registers = global_registers
+
+    def get_free_register(self):
+        if None in self.registers:
+            return self.registers.index(None)
+        elif len(self.registers) < self.MAX_REGISTERS:
+            return len(self.registers)
+        else:
+            raise RegisterError, "maximum number of registers in use"
+
+    def store_register(self, value, index=-1):
+        if value in self.registers:
+            return self.registers.index(value)
+        if index < 1:
+            index = self.get_free_register()
+        self.registers[index] = value
+        return index
+
+    def find_register(self, value):
+        if value in self.registers:
+            return self.registers.index(value)
+        return -1
+    
+    def free_register(self, index):
+        self.registers[index] = None
+    
+    def __len__(self):
+        return self.current_offset + (2 if self.insert_end else 0)
+
+    def seal(self):
+        self.__sealed = True
+        return len(self)
+
+    def is_sealed(self):
+        return self.__sealed
+    
+    def add_action(self, action):
+        if self.__sealed:
+            raise Exception, "Block is sealed. Cannot add new actions"
+        self.code = "" # Dirty the code.
+        action.offset = self.current_offset
+        action.get_block_props_early(self)
+        
+        # Do some early optimizations. Combine two pushes into one.
+        if isinstance(action, ActionPush) and isinstance(self.actions[-1], ActionPush):
+            old_action = self.actions[-1]
+            old_len = len(old_action)
+            self.actions[-1].values.extend(action.values)
+            self.current_offset += len(old_action) - old_len
+            return None
+
+        # Two nots negate. Take them out.
+        if isinstance(action, ActionNot) and isinstance(self.actions[-1], ActionNot):
+            self.actions.pop()
+            self.current_offset -= 1 # len(ShortAction) is 1
+            return None
+            
+        if not isinstance(action, Block): # Don't add block length until we've finalized.
+            self.current_offset += len(action)
+        
+        self.actions.append(action)
+        return action
+    
+    def serialize(self):
+        if len(self.code) > 0:
+            return self.code
+        bytes = []
+        for action in self.actions:
+            action.get_block_props_late(self)
+            bytes += action.serialize()
+        if self.insert_end:
+            bytes += "\0\0"
+        self.code = "".join(bytes)
+        return self.code
+
+    def new_label(self):
+        self.label_count += 1
+        name = Block.AUTO_LABEL_TEMPLATE % self.label_count
+        self.labels[name] = -1
+        return name
+        
+    def set_label_here(self, name):
+        self.labels[name] = self.current_offset
+
+    def new_label_here(self):
+        name = self.new_label()
+        self.labels[name] = self.current_offset
+        return name
+
+class ActionCall(Action):
+    ACTION_NAME = "ActionCall"
+    ACTION_ID = 0x9e
+
+class ActionConstantPool(Action):
+    ACTION_NAME = "ActionConstantPool"
+    ACTION_ID = 0x88
+
+    def __init__(self, *args):
+        self.pool = []
+        for string in args:
+            if not string in self.pool:
+                self.pool.append(args)
+
+    def add_constant(self, string):
+        if not string in self.pool:
+            self.pool.append(string)
+            return len(self.pool)-1
+        return self.pool.index(string)
+    
+    def gen_data(self):
+        return struct.pack("H", len(self.pool)) + "".join([item + "\0" for item in self.pool])
+
+class ActionDefineFunction(Block, Action):
+    ACTION_NAME = "ActionDefineFunction"
+    ACTION_ID = 0x9b
+    FUNCTION_TYPE = 1
+
+    def __init__(self, name, parameters):
+        Block.__init__(self, False)
+        self.function_name = name
+        self.params = params
+
+    def gen_data(self):
+        self.block_data = Block.serialize(self)
+        bytes = [self.function_name, "\0", struct.pack("H", len(self.params))]
+        bytes += [p + "\0" for p in self.params]
+        bytes += struct.pack("H", len(self.block_data))
+        return "".join(bytes)
+
+    def gen_outer_data(self):
+        return self.block_data
+
+class ActionDefineFunction2(Block, Action):
+    ACTION_NAME = "ActionDefineFunction2"
+    ACTION_ID = 0x8e
+    MAX_REGISTERS = 256
+    FUNCTION_TYPE = 2
+
+    def __init__(self, name, parameters, flags=0):
+        Block.__init__(self, False)
+        self.function_name = name
+        self.params = params
+        self.flags = flags & 0xFF01
+        self.eval_flags()
+
+    def find_register(self):
+        if value in self.registers:
+            return self.registers.index(value)+1
+        return -1
+    
+    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()
+
+        # According to the docs, this is the order of register allocation.
+        if preload_this:   self.registers.append("this")
+        if preload_args:   self.registers.append("arguments")
+        if preload_super:  self.registers.append("super")
+        if preload_root:   self.registers.append("_root")
+        if preload_parent: self.registers.append("_parent")
+        if preload_global: self.registers.append("_global")
+        
+        for name in self.params:
+            self.registers.append(name)
+        
+    def gen_data(self):
+        self.block_data = Block.serialize(self)
+        params = [p for p in self.params if isinstance(p, RegisterParam)]
+        bytes = [self.function_name, "\0", struct.pack("HBH", len(params), len(self.registers)-1, self.flags)]
+        for name in self.params:
+            bytes += [chr(self.registers.index(name)+1), name, "\0"]
+        
+        bytes += [struct.pack("H", len(self.block_data))]
+        return "".join(bytes)
+
+    def gen_outer_data(self):
+        return self.block_data
+
+class ActionGetURL(Action):
+    ACTION_NAME = "ActionGetURL"
+    ACTION_ID = 0x83
+
+    def __init__(self, url, target=""):
+        self.url = url
+        self.target = target
+
+    def gen_data(self):
+        return "%s\0%s\0" % (self.url, self.target)
+
+class ActionGetURL2(Action):
+    ACTION_NAME = "ActionGetURL2"
+    ACTION_ID = 0x9a
+
+    METHOD_NONE = 0
+    METHOD_GET  = 1
+    METHOD_POST = 2
+
+    def __init__(self, method, load_target=False, load_variables=False):
+        self.method = max(method, 2)
+        self.load_target = load_target
+        self.load_variables = load_varibles
+
+    def gen_data(self):
+        bits = BitStream()
+        bits.write_bit_value(self.method, 2)
+        bits.zero_fill(4)
+        bits.write_boolean(load_target)
+        bits.write_boolean(load_variables)
+        return bits.serialize()
+
+class ActionGotoFrame(Action):
+    ACTION_NAME = "ActionGotoFrame"
+    ACTION_ID = 0x81
+
+    def __init__(self, index):
+        self.index = index
+
+    def gen_data(self):
+        return struct.pack("H", self.index)
+
+class ActionGotoFrame2(Action):
+    ACTION_NAME = "ActionGotoFrame2"
+    ACTION_ID = 0x9f
+
+    def __init__(self, play=False, scene_bias=0):
+        self.play = play
+        self.scene_bias = scene_bias
+
+    def gen_data(self):
+        bits = BitStream()
+        bits.zero_fill(6)
+        bits.write_boolean(self.scene_bias > 0)
+        bits.write_boolean(self.play)
+
+        if self.scene_bias > 0:
+            return bits.serialize() + struct.pack("H", sceneBias)
+
+        return bits.serialize()
+
+class ActionGotoLabel(Action):
+    ACTION_NAME = "ActionGotoLabel"
+    ACTION_ID = 0x81
+
+    def __init__(self, label_name):
+        self.label_name = label_name
+
+    def serialize(self):
+        return self.label_name + "\0"
+
+class BranchingActionBase(Action):
+
+    def __init__(self, branch):
+        if isinstance(branch, str):
+            self.branch_label = branch
+            self.branch_offset = 0
+        elif isinstance(branch, int):
+            self.branch_label = None
+            self.branch_offset = branch
+
+    def get_block_props_late(self, block):
+        if len(self.branch_label) > 0:
+            self.branch_offset = block.labels[self.branch_label] - self.offset
+
+    def gen_data(self):
+        return struct.pack("H", self.branch_offset)
+
+class ActionJump(BranchingActionBase):
+    ACTION_NAME = "ActionJump"
+    ACTION_ID = 0x99
+
+class ActionIf(BranchingActionBase):
+    ACTION_NAME = "ActionIf"
+    ACTION_ID = 0x9d
+
+class ActionPush(Action):
+    ACTION_NAME = "ActionPush"
+    ACTION_ID = 0x96
+
+    def __init__(self, *args):
+        self.values = []
+        self.add_element(args)
+
+    def add_element(self, element):
+        if isinstance(element, (list, tuple)):
+            for el in element:
+                self.add_element(el)
+        elif hasattr(element, "type"):
+            self.values.append((0, type))
+        elif isinstance(element, str):
+            self.values.append((element, DataTypes.STRING))
+        elif isinstance(element, bool):
+            self.values.append((element, DataTypes.BOOLEAN))
+        elif isinstance(element, int):
+            self.values.append((element, DataTypes.INTEGER))
+        elif isinstance(element, float):
+            if element > 0xFFFFFFFF:
+                self.values.append((element, DataTypes.DOUBLE))
+            else:
+                self.values.append((element, DataTypes.FLOAT))
+        elif isinstance(element, Index):
+            self.values.append((element.index, element.type))
+        elif isinstance(element, RegisterByValue):
+            self.values.append((element.value, RegisterByValue))
+
+    def get_block_props_early(self, block):
+        for index, (value, type) in enumerate(self.values):
+            if type == DataTypes.STRING:
+                constant_index = block.constants.add_constant(value)
+                self.values[index] = (constant_index, DataTypes.CONSTANT8 if constant_index < 256 else DataTypes.CONSTANT16)
+            elif type == RegisterByValue:
+                register_index = block.store_register(value)
+                self.values[index] = (register_index, DataTypes.REGISTER)
+    
+    def gen_data(self):
+        bytes = []
+        for value, type in self.values:
+            bytes += chr(type.id)
+            if type.size == "Z":
+                bytes += [value, "\0"]
+            elif type.size != "!":
+                bytes += struct.pack(type.size, value)[0]
+        return "".join(bytes)
+
+class ActionSetTarget(object):
+    ACTION_NAME = "ActionSetTarget"
+    ACTION_ID = 0x8b
+
+    def __init__(self, target):
+        self.target = target
+
+    def gen_data(self):
+        return self.target + "\0"
+
+class ActionStoreRegister(object):
+    ACTION_NAME = "ActionStoreRegister"
+    ACTION_ID = 0x87
+
+    def __init__(self, index):
+        self.index = index
+
+    def gen_data(self):
+        return chr(index)
+
+class ActionTry(object):
+    ACTION_NAME = "ActionTry"
+    ACTION_ID = 0x8f
+
+    def __init__(self, catch_object, try_block=None, catch_block=None, finally_block=None):
+
+        self.catch_object = catch_object
+        
+        self.try_block = try_block or Block()
+        self.catch_block = catch_block or Block()
+        self.finally_block = finally_block or Block()
+
+    def gen_data(self):
+        has_catch_block = len(self.catch_block.actions) > 0
+        bits = BitStream()
+        bits.zero_fill(5)
+        bits.write_boolean(isinstance(self.catch_object, Register))
+        bits.write_boolean(len(self.finally_block.actions) > 0)
+        bits.write_boolean(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(finallyBlock))]
+        bytes += self.catch_object.index if isinstance(self.catch_object, Register) else (self.catch_object + "\0")
+        return "".join(bytes)
+
+    def gen_outer_data(self):
+        bytes = [self.try_block.serialize()]
+        if len(self.catch_block.actions) > 0:
+            bytes += ActionJump(len(self.catch_block)).serialize()
+            bytes += catchBlock.serialize()
+        bytes += self.finally_block.serialize()
+
+class ActionWaitForFrame(Action):
+    ACTION_NAME = "ActionWaitForFrame"
+    ACTION_ID = 0x8a
+
+    def __init__(self, index, skip_count=0):
+        self.index = index
+        self.skip_count = skip_count
+
+    def gen_data(self):
+        return struct.pack("HB", self.index, self.skip_count)
+    
+class ActionWaitForFrame2(Action):
+    ACTION_NAME = "ActionWaitForFrame2"
+    ACTION_ID = 0x8d
+
+    def __init__(self, skip_count=0):
+        self.skip_count = skip_count
+
+    def gen_data(self):
+        return chr(self.skip_count)
+
+class ActionWith(Action):
+    ACTION_NAME = "ActionWith"
+    ACTION_ID = 0x94
+    
+    def __init__(self, with_block):
+        self.block = with_block or Block()
+
+    def gen_data(self):
+        return struct.pack("H", len(block)) + block.serialize()
+    
+class ShortAction(Action):
+    
+    def __call__(self, *args, **kwargs):
+        return self
+    
+    def __init__(self, id, name):
+        self.ACTION_ID = id
+        self.ACTION_NAME = name
+        Action.__init__(self)
+
+    def __len__(self):
+        return 1 # 1 (Action ID)
+
+    def serialize(self)
+        return chr(self.ACTION_ID)
+
+ActionNextFrame           = ShortAction(0x04, "ActionNextFrame")
+ActionPreviousFrame       = ShortAction(0x05, "ActionPreviousFrame")
+ActionPlay                = ShortAction(0x06, "ActionPlay")
+ActionStop                = ShortAction(0x07, "ActionStop")
+ActionToggleQuality       = ShortAction(0x08, "ActionToggleQuality")
+ActionStopSounds          = ShortAction(0x09, "ActionStopSounds")
+ActionAdd                 = ShortAction(0x0a, "ActionAdd")
+ActionSubtract            = ShortAction(0x0b, "ActionSubtract")
+ActionMultiply            = ShortAction(0x0c, "ActionMultiply")
+ActionDivide              = ShortAction(0x0d, "ActionDivide")
+ActionEquals              = ShortAction(0x0e, "ActionEquals")
+ActionLess                = ShortAction(0x0f, "ActionLess")
+ActionAnd                 = ShortAction(0x10, "ActionAnd")
+ActionOr                  = ShortAction(0x11, "ActionOr")
+ActionNot                 = ShortAction(0x12, "ActionNot")
+ActionStringEquals        = ShortAction(0x13, "ActionStringEquals")
+ActionStringLength        = ShortAction(0x14, "ActionStringLength")
+ActionStringExtract       = ShortAction(0x15, "ActionStringExtract")
+ActionPop                 = ShortAction(0x17, "ActionPop")
+ActionToInteger           = ShortAction(0x18, "ActionToInteger")
+ActionGetVariable         = ShortAction(0x1c, "ActionGetVariable")
+ActionSetVariable         = ShortAction(0x1d, "ActionSetVariable")
+ActionSetTarget2          = ShortAction(0x20, "ActionSetTarget2")
+ActionStringAdd           = ShortAction(0x21, "ActionStringAdd")
+ActionGetProperty         = ShortAction(0x22, "ActionGetProperty")
+ActionSetProperty         = ShortAction(0x23, "ActionSetProperty")
+ActionCloneSprite         = ShortAction(0x24, "ActionCloneSprite")
+ActionRemoveSprite        = ShortAction(0x25, "ActionRemoveSprite")
+ActionTrace               = ShortAction(0x26, "ActionTrace")
+ActionStartDrag           = ShortAction(0x27, "ActionStartDrag")
+ActionEndDrag             = ShortAction(0x28, "ActionEndDrag")
+ActionStringLess          = ShortAction(0x29, "ActionStringLess")
+ActionThrow               = ShortAction(0x2a, "ActionThrow")
+ActionCastOp              = ShortAction(0x2b, "ActionCastOp")
+ActionImplementsOp        = ShortAction(0x2c, "ActionImplementsOp")
+ActionRandomNumber        = ShortAction(0x30, "ActionRandomNumber")
+ActionMBStringLength      = ShortAction(0x31, "ActionMBStringLength")
+ActionCharToAscii         = ShortAction(0x32, "ActionCharToAscii")
+ActionAsciiToChar         = ShortAction(0x33, "ActionAsciiToChar")
+ActionGetTime             = ShortAction(0x34, "ActionGetTime")
+ActionMBStringExtract     = ShortAction(0x35, "ActionMBStringExtract")
+ActionMBCharToAscii       = ShortAction(0x36, "ActionMBCharToAscii")
+ActionMBAsciiToChar       = ShortAction(0x37, "ActionMBAsciiToChar")
+ActionDelVar              = ShortAction(0x3a, "ActionDelVar")
+ActionDelThreadVars       = ShortAction(0x3b, "ActionDelThreadVars")
+ActionDefineLocalVal      = ShortAction(0x3c, "ActionDefineLocalVal")
+ActionCallFunction        = ShortAction(0x3d, "ActionCallFunction")
+ActionReturn              = ShortAction(0x3e, "ActionReturn")
+ActionModulo              = ShortAction(0x3f, "ActionModulo")
+ActionNewObject           = ShortAction(0x40, "ActionNewObject")
+ActionDefineLocal         = ShortAction(0x41, "ActionDefineLocal")
+ActionInitArray           = ShortAction(0x42, "ActionInitArray")
+ActionInitObject          = ShortAction(0x43, "ActionInitObject")
+ActionTypeof              = ShortAction(0x44, "ActionTypeof")
+ActionGetTargetPath       = ShortAction(0x45, "ActionGetTargetPath")
+ActionEnumerate           = ShortAction(0x46, "ActionEnumerate")
+ActionTypedAdd            = ShortAction(0x47, "ActionTypedAdd")
+ActionTypedLessThan       = ShortAction(0x48, "ActionTypedLessThan")
+ActionTypedEquals         = ShortAction(0x49, "ActionTypedEquals")
+ActionConvertToNumber     = ShortAction(0x4a, "ActionConvertToNumber")
+ActionConvertToString     = ShortAction(0x4b, "ActionConvertToString")
+ActionDuplicate           = ShortAction(0x4c, "ActionDuplicate")
+ActionSwap                = ShortAction(0x4d, "ActionSwap")
+ActionGetMember           = ShortAction(0x4e, "ActionGetMember")
+ActionSetMember           = ShortAction(0x4f, "ActionSetMember")
+ActionIncrement           = ShortAction(0x50, "ActionIncrement")
+ActionDecrement           = ShortAction(0x51, "ActionDecrement")
+ActionCallMethod          = ShortAction(0x52, "ActionCallMethod")
+ActionCallNewMethod       = ShortAction(0x53, "ActionCallNewMethod")
+ActionBitAnd              = ShortAction(0x60, "ActionBitAnd")
+ActionBitOr               = ShortAction(0x61, "ActionBitOr")
+ActionBitXor              = ShortAction(0x62, "ActionBitXor")
+ActionShiftLeft           = ShortAction(0x63, "ActionShiftLeft")
+ActionShiftRight          = ShortAction(0x64, "ActionShiftRight")
+ActionShiftUnsigned       = ShortAction(0x65, "ActionShiftUnsigned")
+ActionStrictEquals        = ShortAction(0x66, "ActionStrictEquals")
+ActionGreater             = ShortAction(0x67, "ActionGreater")
+ActionStringGreater       = ShortAction(0x68, "ActionStringGreater")
+ActionExtends             = ShortAction(0x69, "ActionExtends")

Added: pypy/branch/avm/pypy/translator/avm/avm1gen.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/avm1gen.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,216 @@
+
+""" backend generator routines
+"""
+
+from pypy.translator.avm import avm1
+
+
+class AsmGen(object):
+    """ AVM1 'assembler' generator routines """
+    def __init__(self, name, block=None):
+        self.name = name
+        self.block = block or Block(True)
+        self.scope = (self.block, None, None) # (Code object, Parent scope, Exit callback)
+
+    def new_label(self):
+        return self.scope[0].new_label()
+
+    def store_register(self, *args, **kwargs):
+        return self.scope[0].store_register(*args, **kwargs)
+
+    def find_register(self, value):
+        return self.scope[0].find_register(value)
+    
+    def action(self, action):
+        return self.scope[0].add_action(action)
+    
+    def enter_scope(self, new_code_obj, exit_callback):
+        self.scope = (new_code_obj, self.scope, exit_callback)
+
+    def in_function(self):
+        return self.block.FUNCTION_TYPE
+    
+    def exit_scope(self):
+        block_len = self.finalize_block(self, self.scope[0])
+        exit_callback = self.scope[2]
+
+        # Go up to the parent scope.
+        self.scope = self.scope[1]
+        
+        self.scope[0].current_offset += len(block_len)
+        if exit_callback is not None:
+            exit_callback(self)
+
+    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"
+            # Set the label.
+            block.labels[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_function(self, name, arglist):
+        self.enter_scope(self.action(avm1.ActionDefineFunction2(name, arglist)))
+    
+    def begin_prototype_method(self, function_name, _class, arglist):
+        self.action(avm1.ActionPush(function_name, "prototype", _class))
+        self.action(avm1.ActionGetVariable())
+        self.action(avm1.ActionGetMember())
+        self.enter_scope(self.action(avm1.ActionDefineFunction2("", arglist, 0)), lambda s: self.action(avm1.ActionSetMember()))
+    
+    def set_variable(self):
+        self.action(avm1.ActionSetVariable())
+
+    def set_member(self):
+        self.action(avm1.ActionSetMember())
+
+    def get_member(self):
+        self.action(avm1.ActionGetMember())
+
+    def push_arg(self, v):
+        if self.in_function() == 0:
+            raise Exception, "avm1::push_arg called while not in function scope."
+        elif self.in_function() == 1:
+            self.push_local(v.name)
+        else:
+            self.action(avm1.ActionPush(RegisterByValue(v.name)))
+    
+#    def push_value(self, v):
+#        self.action(avm1.ActionPush(v.name))
+
+    def push_this(self, v):
+        k = self.find_register("this")
+        if k > 0:
+            self.action(avm1.ActionPush(RegisterByIndex(k)))
+        else:
+            self.action(avm1.ActionPush("this"))
+            self.action(avm1.ActionGetVariable())
+    
+    def push_local(self, v):
+        k = self.find_register(v.name)
+        if k > 0:
+            self.action(avm1.ActionPush(RegisterByIndex(k)))
+        else:
+            self.action(avm1.ActionPush(v.name))
+            self.action(avm1.ActionGetVariable())
+        
+    def push_const(self, v):
+        self.action(avm1.ActionPush(v))
+
+    def push_undefined(self):
+        self.action(avm1.ActionPush(avm1.Undefined))
+
+    def push_null(self):
+        self.action(avm1.ActionPush(avm1.Null))
+
+    def return_stmt(self):
+        self.action(avm1.ActionReturn())
+
+    def is_equal(self, value=None):
+        if value is not None:
+            self.action(avm1.ActionPush(value))
+        self.action(avm1.ActionEquals())
+
+    def is_not_equal(self, value=None):
+        self.is_equal(value)
+        self.action(avm1.ActionNot())
+    
+    def init_object(self, dict=None):
+        if dict is not None:
+            self.action(avm1.ActionPush([(b,a) for (a,b) in dict.iteritems()], len(dict)))
+        self.action(avm1.ActionInitObject())
+
+    def init_array(self, list=None):
+        if list is not None:
+            self.action(avm1.ActionPush(list, len(list)))
+        self.action(avm1.ActionInitArray())
+    
+    def call_function(self, func_name): # Assumes the args and number of args are on the stack.
+        self.action(avm1.ActionPush(func_name))
+        self.action(avm1.ActionCallFunction())
+    
+    def call_function_constargs(self, func_name, *args):
+        self.action(avm1.ActionPush(args, len(args), func_name))
+        self.action(avm1.ActionCallFunction())
+
+    def call_method(self, func_name): # Assumes the args and number of args and ScriptObject are on the stack, in that order.
+        self.action(avm1.ActionPush(func_name))
+        self.action(avm1.ActionCallMethod())
+        
+    def call_method_constvar(self, _class, func_name): # Assumes vars and number of args are on the stack.
+        self.action(avm1.ActionPush(_class))
+        self.action(avm1.ActionGetVariable())
+        self.action(avm1.ActionPush(func_name))
+        self.action(avm1.ActionCallMethod())
+    
+    def branch_if_true(self, label=""): # Boolean value should be on stack when this is called
+        if len(label) < 0:
+            label = self.new_label()
+        self.scope[0].branch_blocks[label] = Block(False)
+        self.action(avm1.ActionIf(label))
+        return (label, self.scope[0].branch_blocks[label])
+
+    def set_proto_field(self, _class, member_name): # Assumes the value is on the stack.
+        self.action(avm1.ActionPush(member_name, "prototype", _class))
+        self.action(avm1.ActionGetVariable())
+        self.action(avm1.ActionGetMember())
+        self.action(avm1.ActionSwap())
+        self.action(avm1.ActionSetMember())
+    
+    def set_static_field(self, _class, member_name): # Assumes the value is on the stack.
+        self.action(avm1.ActionPush(member_name, _class))
+        self.action(avm1.ActionGetVariable())
+        self.action(avm1.ActionSwap())
+        self.action(avm1.ActionSetMember())
+
+    def newobject_constthis(self, obj, *args): # If no args are passed then it is assumed that the args and number of args are on the stack.
+        if len(args) > 0:
+            self.action(avm1.ActionPush(args, len(args), obj))
+        else:
+            self.action(avm1.ActionPush(obj))
+        self.action(avm1.ActionNewObject())
+    
+    def newobject(self):
+        self.action(avm1.ActionNewObject())
+    
+#     def store_void(self):
+#         if not len(self.right_hand):
+#             return
+#         v = self.right_hand.pop()
+#         if v is not None and v.find('('):
+#             self.codegenerator.writeline(v+";")
+
+    # FIXME: will refactor later
+    #load_str = load_const
+    
+    def begin_switch_varname(self, varname):
+        self.action(avm1.ActionPush(varname))
+        self.action(avm1.ActionGetVariable())
+        self.switch_register = self.store_register(varname)
+        self.action(avm1.ActionStoreRegister(self.switch_register))
+    
+    def write_case(self, testee):
+        self.action(avm1.ActionPush(avm1.RegisterByIndex(self.switch_register), testee))
+        self.action(avm1.ActionStrictEquals())
+        if len(self.case_label) < 1:
+            self.case_label, self.case_block = self.branch_if_true()
+        else:
+            self.branch_if_true(self.case_label)
+
+    def write_break(self):
+        self.exit_scope()
+        self.case_flag = False
+        self.case_block = None
+    
+    def enter_case_branch(self):
+        self.enter_scope(self.case_block)
+    
+#    def inherits(self, subclass_name, parent_name):
+#        self.codegenerator.writeline("inherits(%s,%s);"%(subclass_name, parent_name))
+    
+    def throw(self): # Assumes the value to be thrown is on the stack.
+        self.action(avm1.ActionThrow())

Added: pypy/branch/avm/pypy/translator/avm/avm1types.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/avm1types.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,151 @@
+""" JavaScript type system
+"""
+
+from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.lltypesystem import lltype
+from pypy.translator.cli import oopspec
+
+from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
+from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong, Primitive
+from pypy.rpython.lltypesystem.lltype import Char, UniChar
+from pypy.rpython.ootypesystem.ootype import String, _string, List, StaticMethod
+from pypy.rlib.objectmodel import Symbolic
+
+from pypy.translator.avm.log import log
+
+from types import FunctionType
+from pypy.rpython.extfunc import is_external
+
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+class AVM1TypeSystem(object):
+    """ Class implementing JavaScript type system
+    calls with mapping similiar to cts
+    """
+    def __init__(self, db):
+        self.db = db
+    
+    #def __class(self, name):
+    #    return name.replace(".", "_")
+
+    def escape_name(self, name):
+        return name.replace('.', '_')
+    
+    def llvar_to_cts(self, var):
+        return 'var ', var.name
+    
+    def lltype_to_cts(self, t):
+        if isinstance(t, ootype.Instance):
+            self.db.pending_class(t)
+            return self.escape_name(t._name)
+        elif isinstance(t, ootype.List):
+            return 'Array'
+        elif isinstance(t, ootype.Array):
+            return 'Array'
+        #elif isinstance(t, lltype.Primitive):
+        #    return 'var'
+        elif isinstance(t, ootype.Record):
+            return 'Array'
+        elif isinstance(t, ootype.String.__class__):
+            return 'String'
+        elif isinstance(t, ootype.Dict):
+            return 'Object'
+        elif isinstance(t, ootype.DictItemsIterator):
+            return 'Object'
+        elif t is ootype.StringBuilder:
+            return 'StringBuilder'
+        #return "var"
+        raise NotImplementedError("Type %r" % (t,))
+    
+    def graph_to_signature(self, graph, is_method = False, func_name = None):
+        func_name = func_name or self.db.get_uniquename(graph,graph.name)
+        
+        args = [arg for arg in graph.getargs() if
+                arg.concretetype is not ootype.Void]
+        if is_method:
+            args = args[1:]
+
+        return func_name,args
+    
+    def method_signature(self, obj, name):
+        # TODO: use callvirt only when strictly necessary
+        if isinstance(obj, ootype.Instance):
+            owner, meth = obj._lookup(name)
+            METH = meth._TYPE
+            return obj._name, METH.ARGS
+        elif isinstance(obj, ootype.BuiltinType):
+            meth = oopspec.get_method(obj, name)
+            class_name = self.lltype_to_cts(obj)
+            return class_name,meth.ARGS
+        else:
+            assert False
+    
+    def obj_name(self, obj):
+        return self.lltype_to_cts(obj)
+    
+    def primitive_repr(self, _type, v):
+        if _type is Bool:
+            if v == False:
+                val = 'false'
+            else:
+                val = 'true'
+        elif _type is Void:
+            val = 'undefined'
+        elif isinstance(_type,String.__class__):
+            val = repr(v._str)
+        elif isinstance(_type,List):
+            # FIXME: It's not ok to use always empty list
+            val = repr(v._list)
+        elif isinstance(_type,StaticMethod):
+            if hasattr(v, 'graph') and not is_external(v):
+                self.db.pending_function(v.graph)
+            else:
+                self.db.pending_abstract_function(v)
+            val = v._name
+            val = val.replace('.', '_')
+            if val == '?':
+                val = 'undefined'
+        elif _type is UniChar or _type is Char:
+            #log("Constant %r"%v)
+            s = repr(v)
+            if s.startswith('u'):
+                s = s[1:]
+            if s != "'\''":
+                s.replace("'", '"')
+            val = s
+        elif isinstance(v, Symbolic):
+            val = v.expr
+        elif isinstance(_type, Primitive):
+            #log("Type: %r"%_type)
+            val = str(v)
+        else:
+            assert False, "Unknown constant %r"%_type
+            val = str(v)
+        return val
+    
+    #def lltype_to_cts(self, t, include_class=True):
+    #    return 'var'
+##        if isinstance(t, ootype.Instance):
+##            self.db.pending_class(t)
+##            return self.__class(t._name, include_class)
+##        elif isinstance(t, ootype.Record):
+##            name = self.db.pending_record(t)
+##            return self.__class(name, include_class)
+##        elif isinstance(t, ootype.StaticMethod):
+##            return 'void' # TODO: is it correct to ignore StaticMethod?
+##        elif isinstance(t, ootype.List):
+##            item_type = self.lltype_to_cts(t.ITEM)
+##            return self.__class(PYPY_LIST % item_type, include_class)
+##        elif isinstance(t, ootype.Dict):
+##            key_type = self.lltype_to_cts(t._KEYTYPE)
+##            value_type = self.lltype_to_cts(t._VALUETYPE)
+##            return self.__class(PYPY_DICT % (key_type, value_type), include_class)
+##        elif isinstance(t, ootype.DictItemsIterator):
+##            key_type = self.lltype_to_cts(t._KEYTYPE)
+##            value_type = self.lltype_to_cts(t._VALUETYPE)
+##            return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class)
+##
+##        return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t)

Added: pypy/branch/avm/pypy/translator/avm/bootstrap.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/bootstrap.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,13 @@
+
+
+from pypy.translator.avm.swf import SwfData
+from pypy.translator.avm.tags import DoAction, SetBackgroundColor
+
+def create_assembler(name):
+    return AsmGen(name, DoAction())
+
+def bootstrap_avm1(asmgen):
+    data = SwfData()
+    data.add_tag(SetBackgroundColor(0x333333))
+    data.add_tag(asmgen)
+    return data.serialize()

Added: pypy/branch/avm/pypy/translator/avm/database.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/database.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,472 @@
+
+""" genjs constant database module
+"""
+
+import py
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.avm import avm1
+#from pypy.translator.js.opcodes import opcodes
+from pypy.translator.avm.function import Function
+from pypy.translator.avm.log import log
+#from pypy.translator.js._class import Class
+from pypy.translator.avm.support import AVM1NameManager
+
+from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
+from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong, typeOf
+from pypy.rpython.lltypesystem.lltype import Char, UniChar
+from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.ootypesystem import bltregistry
+
+from pypy.objspace.flow.model import Variable, Constant
+
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+class LowLevelDatabase(object):
+    def __init__(self, genoo):
+        self._pending_nodes = set()
+        self.genoo = genoo
+        self._rendered_nodes = set()
+        self.classes = {} # classdef --> class_name
+        self.functions = {} # graph --> function_name
+        self.function_names = {} # graph --> real_name
+        self.methods = {} # graph --> method_name
+        self.consts = {}  # value --> const_name
+        self.reverse_consts = {}
+        self.const_names = set()
+        self.rendered = set()
+        self.const_var = Variable("__consts")
+        self.name_manager = AVM1NameManager(self)
+        self.pending_consts = []
+        self.cts = self.genoo.TypeSystem(self)
+#        self.proxies = []
+   
+    def is_primitive(self, type_):
+        if type_ in (Void, Bool, Float, Signed, Unsigned, SignedLongLong, UnsignedLongLong, Char, UniChar, ootype.StringBuilder) or \
+            isinstance(type_,ootype.StaticMethod):
+            return True
+        return False
+
+    def pending_function(self, graph):
+        self.pending_node(self.genoo.Function(self, graph))
+
+    def pending_abstract_function(self, name):
+        pass
+        # XXX we want to implement it at some point (maybe...)
+
+    def pending_class(self, classdef):
+        self.pending_node(classdef)
+        return c
+
+    def pending_record(self, record):
+        r = Record(self, record) # I can't find Record anywhere, and it's not in the imports.
+        self.pending_node(r)
+        return r.get_name()
+
+    def pending_node(self, node):
+        if node in self._pending_nodes or node in self._rendered_nodes:
+            return
+        self._pending_nodes.add(node)
+
+    def record_function(self, graph, name):
+        self.functions[graph] = name
+    
+    def get_uniquename(self, graph, name):
+        try:
+            return self.function_names[graph]
+        except KeyError:
+            real_name = self.name_manager.uniquename(name, lenmax=1111111)
+            self.function_names[graph] = real_name
+            return real_name
+
+    def record_class(self, classdef, name):
+        self.classes[classdef] = name
+    
+#    def register_comm_proxy(self, proxy_const, *args):
+#        """ Register external object which should be rendered as
+#        method call
+#        """
+#        self.proxies.append(XmlHttp(proxy_const, *args))
+
+    def graph_name(self, graph):
+        return self.functions.get(graph, None)
+
+    def class_name(self, classdef):
+        return self.classes.get(classdef, None)
+
+    def record_const(self, value, type_ = None, retval='name'):
+        if type_ is None:
+            type_ = typeOf(value)
+        if self.is_primitive(type_):
+            return None
+        const = AbstractConst.make(self, value)
+        if not const:
+            return None
+        try:
+            if retval == 'name':
+                return self.consts[const]
+            else:
+                self.consts[const]
+                return self.reverse_consts[self.consts[const]]
+        except KeyError:
+            if self.genoo.config.translation.verbose:
+                log("New const:%r"%value)
+                if isinstance(value, ootype._string):
+                    log(value._str)
+            else:
+                log.dot()
+            name = const.get_name()
+            if name in self.const_names:
+                name += '__%d' % len(self.consts)
+            self.consts[const] = name
+            self.reverse_consts[name] = const
+            self.const_names.add(name)
+            self.pending_consts.append((const,name))
+        if retval == 'name':
+            return name
+        else:
+            return const
+
+    def gen_constants(self, ilasm, pending):
+        try:
+            while True:
+                const,name = self.pending_consts.pop()
+                const.record_fields()
+        except IndexError:
+            pass
+
+        if pending:
+            return
+
+        #if not self.rendered:
+        #    begin_consts(self.const_var.name)
+        
+        def generate_constants(consts):
+            all_c = [const for const,name in consts.iteritems()]
+            dep_ok = set()
+            while len(all_c) > 0:
+                const = all_c.pop()
+                if const not in self.rendered:
+                    to_render = True
+                    if hasattr(const, 'depends_on') and const.depends_on:
+                        for i in const.depends_on:
+                            if i not in self.rendered and i not in dep_ok:
+                                assert i.depends is None or const in i.depends
+                                to_render = False
+                                continue
+                    
+                    if to_render and (not hasattr(const, 'depends')) or (not const.depends) or const in dep_ok:
+                        yield const,consts[const]
+                        self.rendered.add(const)
+                    else:
+                        all_c.append(const)
+                        for i in const.depends:
+                            all_c.append(i)
+                        dep_ok.add(const)
+
+        # We need to keep track of fields to make sure
+        # our items appear earlier than us
+        for const, name in generate_constants(self.consts):
+            if self.genoo.config.translation.verbose:
+                log("Recording %r %r"%(const,name))
+            else:
+                log.dot()
+                
+            ilasm.push_const(name)
+            const.init(ilasm)
+    
+    def push_const(self, type_, value, ilasm):
+        if self.is_primitive(type_):
+            ilasm.push_const(self.cts.primitive_repr(type_, value))
+        else:
+            try:
+                return self.consts[BuiltinConst(value)]
+            except KeyError:
+                name = self.record_const(value)
+                ilasm.push_local(self.const_var)
+                ilasm.get_field(name)
+            #assert False, 'Unknown constant %s' % const
+
+
+class AbstractConst(object):
+    def __init__(self, db, const):
+        self.db = db
+        self.const = const
+        self.cts = db.genoo.TypeSystem(db)
+        self.depends = set()
+        self.depends_on = set()
+
+    def __hash__(self):
+        return hash(self.get_key())
+
+    def __eq__(self, other):
+        return (other.__class__ is self.__class__ and
+                other.get_key() == self.get_key())
+
+    def __ne__(self, other):
+        return not (self == other)
+    
+    def make(db, const):
+        if isinstance(const, ootype._view):
+            static_type = const._TYPE
+            const = const._inst
+        else:
+            static_type = None
+
+        if isinstance(const, ootype._instance):
+            return InstanceConst(db, const, static_type)
+        elif isinstance(const, ootype._list):
+            return ListConst(db, const)
+        elif isinstance(const, ootype._array):
+            return ListConst(db, const)
+        elif isinstance(const, ootype._record):
+            return RecordConst(db, const)
+        elif isinstance(const, ootype._string):
+            return StringConst(db, const)
+        elif isinstance(const, ootype._dict):
+            return DictConst(db, const)
+        elif isinstance(const, bltregistry._external_inst):
+            return ExtObject(db, const)
+        elif isinstance(const, ootype._class):
+            if const._INSTANCE:
+                return ClassConst(db, const)
+            else:
+                return None
+        else:
+            assert False, 'Unknown constant: %s %r' % (const, typeOf(const))
+    make = staticmethod(make)
+
+    def get_name(self):
+        pass
+
+    def get_type(self):
+        pass
+
+    def init(self, ilasm, name):
+        pass
+    
+    def record_fields(self):
+        pass
+
+class InstanceConst(AbstractConst):
+    def __init__(self, db, obj, static_type):
+        self.depends = set()
+        self.depends_on = set()
+        self.db = db
+        self.cts = db.genoo.TypeSystem(db)
+        self.obj = obj
+        if static_type is None:
+            self.static_type = obj._TYPE
+        else:
+            self.static_type = static_type
+            self.cts.lltype_to_cts(obj._TYPE) # force scheduling of obj's class
+
+    def get_key(self):
+        return self.obj
+
+    def get_name(self):
+        return self.obj._TYPE._name.replace('.', '_')
+
+    def get_type(self):
+        return self.cts.lltype_to_cts(self.static_type)
+
+    def init(self, ilasm):
+        if not self.obj:
+            ilasm.push_null()
+            return
+        
+        classdef = self.obj._TYPE
+        try:
+            classdef._hints['_suggested_external']
+            #ilasm.new(classdef._name.split("."))
+            pass
+        except KeyError:
+            #ilasm.new(classdef._name.replace(".", "_"))
+            pass
+    
+    def record_fields(self):
+        if not self.obj:
+            return
+        INSTANCE = self.obj._TYPE
+        #while INSTANCE:
+        for i, (_type, val) in INSTANCE._allfields().items():
+            if _type is not ootype.Void:
+                name = self.db.record_const(getattr(self.obj, i), _type, 'const')
+                if name is not None:
+                    self.depends.add(name)
+                    name.depends_on.add(self)
+        
+#     def init_fields(self, ilasm, name):
+#         if not self.obj:
+#             return
+        
+#         INSTANCE = self.obj._TYPE
+#         #while INSTANCE:
+#         for i, (_type, el) in INSTANCE._allfields().items():
+#             if _type is not ootype.Void:
+#                 ilasm.push_local(const_var)
+#                 self.db.push_const(_type, getattr(self.obj, i), ilasm)
+#                 ilasm.set_field(None, "%s.%s"%(name, i))
+#                 ilasm.store_void()
+
+class RecordConst(AbstractConst):
+    def get_name(self):
+        return "const_tuple"
+    
+    def init(self, ilasm):
+        if not self.const:
+            ilasm.push_undefined()
+        
+        for i in reversed(self.const._items):
+            el = self.const._items[i]
+            self.db.push_const(typeOf(el), el, ilasm)
+        ilasm.init_array()
+    
+    def record_fields(self):
+        if not self.const:
+            return
+        
+        for i in self.const._items:
+            name = self.db.record_const(self.const._items[i], None, 'const')
+            if name is not None:
+                self.depends.add(name)
+                name.depends_on.add(self)
+    
+    def get_key(self):
+        return self.const
+
+class ListConst(AbstractConst):
+    
+    def _get_list(self):
+        if isinstance(self.const, ootype._list):
+            return self.const._list
+        else:
+            return self.const._array
+
+
+    def get_name(self):
+        return "const_list"
+    
+    def record_fields(self):
+        if not self.const:
+            return
+        
+        for i in self._get_list():
+            name = self.db.record_const(i, None, 'const')
+            if name is not None:
+                self.depends.add(name)
+                name.depends_on.add(self)
+        
+    def get_key(self):
+        return self.const
+
+    def init(self, ilasm):
+        if not self.const:
+            ilasm.push_undefined()
+        
+        lst = self._get_list()
+        for el in lst:
+            self.db.push_const(typeOf(el), el, ilasm)
+        ilasm.push_const(len(lst))
+        ilasm.init_array()
+
+class StringConst(AbstractConst):
+    def get_name(self):
+        return "const_str"
+
+    def get_key(self):
+        return self.const._str
+
+    def init(self, ilasm):
+        if self.const:
+            ilasm.push_const(self.const._str)
+        else:
+            ilasm.push_undefined()
+
+class ClassConst(AbstractConst):
+    def __init__(self, db, const):
+        super(ClassConst, self).__init__(db, const)
+        self.cts.lltype_to_cts(const._INSTANCE) # force scheduling of class
+    
+    def get_key(self):
+        return self.get_name()
+    
+    def get_name(self):
+        return self.const._INSTANCE._name.replace(".", "_")
+    
+    def init(self, ilasm):
+        #ilasm.push_const(self.get_name())
+    
+    #def init_fields(self, ilasm, const_var, name):
+    #    pass
+
+class BuiltinConst(AbstractConst):
+    def __init__(self, name):
+        self.name = name
+    
+    def get_key(self):
+        return self.name
+    
+    def get_name(self):
+        return self.name
+    
+    def init(self, ilasm):
+        ilasm.push_const(self.name)
+
+class DictConst(RecordConst):
+    def record_const(self, co):
+        name = self.db.record_const(co, None, 'const')
+        if name is not None:
+            self.depends.add(name)
+            name.depends_on.add(self)
+    
+    def record_fields(self):
+        if not self.const:
+            return
+        
+        for i in self.const._dict:
+            self.record_const(i)
+            self.record_const(self.const._dict[i])
+
+    def init(self, ilasm):
+        if not self.const:
+            return
+        
+        for i in self.const._dict:
+            el = self.const._dict[i]
+            self.db.push_const(typeOf(el), el, ilasm)
+            self.db.push_const(typeOf(i), i, ilasm)
+        ilasm.push_const(len(_dict))
+        ilasm.init_object()
+
+# class ExtObject(AbstractConst):
+#     def __init__(self, db, const):
+#         self.db = db
+#         self.const = const
+#         self.name = self.get_name()
+#         self.depends = set()
+#         self.depends_on = set()
+    
+#     def get_key(self):
+#         return self.name
+    
+#     def get_name(self):
+#         return self.const._TYPE._name
+    
+#     def init(self, ilasm):
+#         _class = self.const._TYPE._class_
+#         if getattr(_class, '_render_xmlhttp', False):
+#             use_xml = getattr(_class, '_use_xml', False)
+#             base_url = getattr(_class, '_base_url', "") # XXX: should be
+#             method = getattr(_class, '_use_method', 'GET')
+#                 # on per-method basis
+#             self.db.register_comm_proxy(self.const, self.name, use_xml, base_url, method)
+#             ilasm.new(self.get_name())
+#         else:
+#             # Otherwise they just exist, or it's not implemented
+#             if not hasattr(self.const.value, '_render_name'):
+#                 raise ValueError("Prebuilt constant %s has no attribute _render_name,"
+#                                   "don't know how to render" % self.const.value)
+#             ilasm.push_str(self.const.value._render_name)

Added: pypy/branch/avm/pypy/translator/avm/function.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/function.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,236 @@
+
+from pypy.objspace.flow import model as flowmodel
+from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
+from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
+from pypy.rpython.ootypesystem import ootype1
+from pypy.translator.oosupport.metavm import Generator,InstructionList
+from pypy.translator.oosupport import function
+
+from pypy.translator.avm.log import log
+from types import FunctionType
+
+import re
+
+class BaseGenerator(object):
+    def push(self, v):
+        if isinstance(v, flowmodel.Variable):
+            if v.name in self.argset:
+                selftype, selfname = self.args[0]
+                if self.is_method and v.name == selfname:
+                    self.ilasm.push_this()
+                else:
+                    self.ilasm.push_arg(v)
+            else:
+                self.ilasm.push_local(v)
+        elif isinstance(v, flowmodel.Constant):
+            self.db.push_const(v.concretetype, v.value, self.ilasm)
+        elif isinstance(v, str):
+            self.ilasm.push_const(v)
+        else:
+            assert False
+
+    def store(self, v):
+        assert isinstance(v, flowmodel.Variable)
+        if v.concretetype is not Void:
+            self.ilasm.(v)
+        else:
+            self.ilasm.push_null()
+    
+#     def change_name(self, name, to_name):
+#         self.ilasm.change_name(name, to_name)
+
+#     def add_comment(self, text):
+#         pass
+    
+    def function_signature(self, graph):
+        return self.cts.graph_to_signature(graph, False)
+
+    def class_name(self, ooinstance):
+        return ooinstance._name
+
+    def emit(self, instr, *args):
+        self.ilasm.emit(instr, *args)
+
+    def call_graph(self, graph):
+        self.db.pending_function(graph)
+        func_sig = self.function_signature(graph)
+        self.ilasm.call(func_sig)
+    
+    def call_external(self, name, args):
+        self.ilasm.call((name, args))
+
+    #def call_signature(self, signature):
+    #    self.ilasm.call(signature)
+
+    def cast_to(self, lltype):
+        cts_type = self.cts.lltype_to_cts(lltype, False)
+        self.ilasm.castclass(cts_type)
+        
+    def new(self, obj):
+        self.ilasm.new(self.cts.obj_name(obj))
+
+    def oonewarray(self, obj, length):
+        self.ilasm.oonewarray(self.cts.obj_name(obj), length)
+
+    def set_field(self, obj, name):
+        self.ilasm.set_member()
+        #self.ilasm.set_field(self.field_name(obj,name))
+
+    def get_field(self, useless_stuff, name):
+        self.ilasm.get_field(name)
+        
+    def call_method(self, obj, name):
+        func_name, signature = self.cts.method_signature(obj, name)
+        self.ilasm.call_method(obj, name, signature)
+    
+    def call_external_method(self, name, arg_len):
+        self.ilasm.call_method(None, name, [0]*arg_len)
+        
+    def instantiate(self):
+        self.ilasm.runtimenew()
+    
+    def downcast(self, TYPE):
+        pass
+        
+    def load_special(self, v):
+        # special case for loading value
+        # when setting builtin field we need to load function instead of None
+        # FIXME: we cheat here
+        if isinstance(v, flowmodel.Constant) and v.concretetype is ootype.Void and isinstance(v.value, FunctionType):
+            graph = self.db.translator.annotator.bookkeeper.getdesc(v.value).cachedgraph(None)
+            self.db.pending_function(graph)
+            name = graph.name
+            self.ilasm.load_str(name)
+        else:
+            self.load(v)
+            
+    def cast_function(self, name, num):
+        self.ilasm.cast_function(name, num)
+
+    def prefix_op(self, st):
+        self.ilasm.prefix_op(st)
+    
+    def push_const(self, s):
+        self.ilasm.push_const(s)
+        
+    def push_undefined(self):
+        self.ilasm.push_undefined()
+    
+    def push_primitive_constant(self, TYPE, value):
+        self.db.load_const(TYPE, value, self.ilasm)        
+
+    def branch_unconditionally(self, target_label):
+        self.ilasm.jump_block(self.block_map[target_label])
+
+    def branch_conditionally(self, exitcase, target_label):
+        self.ilasm.branch_if(exitcase)
+        self.ilasm.jump_block(self.block_map[target_label])
+        self.ilasm.close_branch()
+
+class Function(function.Function, BaseGenerator):
+    def __init__(self, db, graph, name=None, is_method=False,
+                 is_entrypoint=False, _class=None):
+        self._class = _class
+        super(Function, self).__init__(db, graph, name, is_method, is_entrypoint)
+        self._set_args()
+        self._set_locals()
+        self.order = 0
+        self.name = name or self.db.get_uniquename(self.graph, self.graph.name)
+
+    def _setup_link(self, link, is_exc_link = False):
+        target = link.target
+        for to_load, to_store in zip(link.args, target.inputargs):
+            if to_load.concretetype is not Void:
+                if is_exc_link and isinstance(to_load, flowmodel.Variable) and re.match("last_exc_value", to_load.name):
+                    self.ilasm.load_str("exc")
+                else:
+                    self.load(to_load)
+                self.store(to_store)
+
+    def _create_generator(self, ilasm):
+        return self
+
+    def begin_render(self):
+        block_map = {}
+        for blocknum, block in enumerate(self.graph.iterblocks()):
+            block_map[self._get_block_name(block)] = blocknum
+        self.block_map = block_map
+
+        if self.is_method:
+            args = self.args[1:] # self is implicit
+        else:
+            args = self.args
+        if self.is_method:
+            self.ilasm.begin_method(self.name, self._class, [i[1] for i in args])
+        else:
+            self.ilasm.begin_function(self.name, args)
+        self.ilasm.set_locals(",".join([i[1] for i in self.locals]))
+        self.ilasm.begin_for()
+
+    def render_return_block(self, block):
+        return_var = block.inputargs[0]
+        if return_var.concretetype is not Void:
+            self.load(return_var)
+            self.ilasm.ret()
+        else:
+            self.ilasm.load_void()
+            self.ilasm.ret()
+
+    def end_render(self):
+        self.ilasm.end_for()        
+        self.ilasm.end_function()
+
+    def render_raise_block(self, block):
+        self.ilasm.throw(block.inputargs[1])
+
+    def end_try(self, target_label, cond):
+        self.ilasm.jump_block(self.block_map[target_label])
+        if cond:
+            self.ilasm.catch()
+        #self.ilasm.close_branch()
+
+    # XXX: soon or later we should use the smarter version in oosupport
+    def render_bool_switch(self, block):
+        for link in block.exits:
+            self._setup_link(link)
+            target_label = self._get_block_name(link.target)
+            if link is block.exits[-1]:
+                self.generator.branch_unconditionally(target_label)
+            else:
+                assert type(link.exitcase) is bool
+                assert block.exitswitch is not None
+                self.generator.load(block.exitswitch)
+                self.generator.branch_conditionally(link.exitcase, target_label)
+
+    def record_ll_meta_exc(self, ll_meta_exc):
+        pass
+
+    def begin_catch(self, llexitcase):
+        real_name = self.cts.lltype_to_cts(llexitcase._INSTANCE)
+        s = "isinstanceof(exc, %s)"%real_name
+        self.ilasm.branch_if_string(s)
+    
+    def end_catch(self, target_label):
+        """ Ends the catch block, and branchs to the given target_label as the
+        last item in the catch block """
+        self.ilasm.close_branch()
+
+    def store_exception_and_link(self, link):
+        self._setup_link(link, True)
+        self.ilasm.jump_block(self.block_map[self._get_block_name(link.target)])
+
+    def after_except_block(self):
+        #self.ilasm.close_branch()
+        self.ilasm.throw_real("exc")
+        self.ilasm.close_branch()
+
+    def set_label(self, label):
+        self.ilasm.write_case(self.block_map[label])
+        #self.ilasm.label(label)
+
+    def begin_try(self, cond):
+        if cond:
+            self.ilasm.begin_try()
+
+    def clean_stack(self):
+        self.ilasm.clean_stack()

Added: pypy/branch/avm/pypy/translator/avm/log.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/log.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,4 @@
+import py
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer("avm")
+py.log.setconsumer("avm", ansi_log)

Added: pypy/branch/avm/pypy/translator/avm/metavm.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/metavm.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,301 @@
+""" Opcode meaning objects, descendants of MicroInstruction
+"""
+
+#from pypy.translator.js.jsbuiltin import Builtins
+from pypy.translator.oosupport.metavm import PushArg, PushAllArgs, StoreResult,\
+    InstructionList, New, GetField, MicroInstruction
+
+from pypy.translator.js.log import log
+from pypy.rpython.ootypesystem import ootype
+from types import FunctionType
+from pypy.objspace.flow.model import Constant
+
+class NewBuiltin(MicroInstruction):
+    def __init__(self, arg):
+        self.arg = arg
+    
+    def render(self, generator, op):
+        generator.ilasm.new(self.arg)
+
+class _ListSetitem(MicroInstruction):
+    def render(self, generator, op):
+        # op.args = [function_name, list, value, index]
+        generator.push(op.args[1])
+        generator.push(op.args[3])
+        generator.push(op.args[2])
+        generator.ilasm.set_member()
+ListSetitem = _ListSetitem()
+
+class _ListGetitem(MicroInstruction):
+    def render(self, generator, op):
+        # op.args = [function_name, list, index]
+        generator.push(op.args[1])
+        generator.push(op.args[2])
+        generator.ilasm.get_member()
+ListGetitem = _ListGetitem()
+
+class _ListContains(MicroInstruction):
+    def render(self, generator, op):
+        # op.args = [function_name, list, to_find]
+        generator.push(op.args[1])
+        generator.push(op.args[2])
+        generator.ilasm.is_not_equal_const(avm1.Null())
+ListContains = _ListContains()
+
+class _Call(MicroInstruction):
+    def render(self, generator, op):
+        graph = op.args[0].value.graph
+        self._render_function(generator, graph, op.args)
+
+    def _render_builtin(self, generator, builtin, args):
+        for func_arg in args[1:]: # push parameters
+            generator.load(func_arg)
+        generator.call_external(builtin, args[1:])
+
+    def _render_builtin_prepared_args(self, generator, builtin, args):
+        for func_arg in args:
+            generator.load_str(func_arg)
+        generator.call_external(builtin, args)
+    
+    def _render_builtin_method(self, generator, builtin, args):
+        for func_arg in args:
+            generator.load_special(func_arg)
+        generator.call_external_method(builtin, len(args)-1)
+
+    def _render_function(self, generator, graph, args):
+        for func_arg in args[1:]: # push parameters
+            if func_arg.concretetype is not ootype.Void:
+                generator.load(func_arg)
+        generator.call_graph(graph)
+    
+    def _render_method(self, generator, method_name, args):
+        this = args[0]
+        for arg in args: # push parametes
+            generator.load(arg)
+        generator.call_method(this.concretetype, method_name)
+
+Call = _Call()
+
+class CallBuiltin(_Call):
+    def __init__(self, builtin):
+        self.builtin = builtin
+    
+    def render(self, generator, op):
+        self._render_builtin(generator, self.builtin, op.args)
+
+class CallBuiltinMethod(_Call):
+    def __init__(self, builtin, slice=None, additional_args=[]):
+        self.builtin = builtin
+        self.slice = slice
+        self.additional_args = additional_args
+
+    def render(self, generator, op):
+        if self.slice is not None:
+            args = op.args[self.slice]
+        else:
+            args = op.args
+        args += self.additional_args
+        self._render_builtin_method(generator, self.builtin, args)
+
+class _SameAs(MicroInstruction):
+    def render(self, generator, op):
+        generator.change_name(op.result, op.args[0])
+
+class _CastFun(MicroInstruction):
+    def __init__(self, name, num):
+        self.name = name
+        self.num = num
+
+    def render(self, generator, op):
+        log("Args: %r"%op.args)
+        generator.cast_function(self.name, self.num)
+
+class _Prefix(MicroInstruction):
+    def __init__(self, st):
+        self.st = st
+    
+    def render(self, generator, op):
+        generator.prefix_op(self.st)
+
+class _NotImplemented(MicroInstruction):
+    def __init__(self, reason):
+        self.reason = reason
+    
+    def render(self, generator, op):
+        raise NotImplementedError(self.reason)
+        
+class _CastMethod(MicroInstruction):
+    def __init__(self, method_name, num=0):
+        self.method_name = method_name
+        self.num = num
+
+    def render(self, generator, op):
+        generator.call_external_method(self.method_name, self.num)
+
+class _LoadConst(MicroInstruction):
+    def __init__(self, value):
+        self.value = value
+
+    def render(self, generator, op):
+        generator.load(Constant(self.value, ootype.typeOf(self.value)))
+    
+class _GetBuiltinField(MicroInstruction):
+    def render(self, generator, op):
+        this = op.args[0]
+        field = op.args[1].value[1:]
+        generator.load(this)
+        generator.get_field(None, field)
+
+class _GetPredefinedField(MicroInstruction):
+    def __init__(self, field, num=1):
+        self.field = field
+        self.num = num
+
+    def render(self, generator, op):
+        if op.result.concretetype is ootype.Void:
+            return
+        this = op.args[self.num]
+        generator.load(this)
+        generator.get_field(None, self.field)
+
+GetBuiltinField = _GetBuiltinField()
+
+class _SetBuiltinField(MicroInstruction):
+    def render(self, generator, op):
+        this = op.args[0]
+        field = op.args[1].value
+        if not field.startswith('o'):
+            generator.load_void()
+        else:
+            value = op.args[2]
+            field_name = field[1:]
+            self.run_it(generator, this, field_name, value)
+    
+    def run_it(self, generator, this, field_name, value):
+        generator.load(this)
+        generator.load_special(value)
+        generator.set_field(None, field_name)
+
+class _SetPredefinedField(_SetBuiltinField):
+    def __init__(self, field):
+        self.field = field
+
+    def render(self, generator, op):
+        value = op.args[2]
+        this = op.args[1]
+        self.run_it(generator, this, self.field, value)
+    
+class _SetExternalField(_SetBuiltinField):
+    def render(self, generator, op):
+        self.run_it(generator, op.args[0], op.args[1].value, op.args[2])
+
+SetBuiltinField = _SetBuiltinField()
+SetExternalField = _SetExternalField()
+
+class _CallMethod(_Call):
+    def render(self, generator, op):
+        method = op.args[0]
+        self._render_method(generator, method.value, op.args[1:])
+
+class _CallBuiltinObject(_Call):
+    def render(self, generator, op):
+        this = op.args[1].concretetype
+        method = op.args[0]
+        method_name = this._methods[method.value]._name[1:]
+        generator.load(op.args[1])
+        self._render_builtin_method(generator, method_name, op.args[1:])
+
+class _CallExternalObject(_Call):
+    def render(self, generator, op):
+        this = op.args[1].concretetype
+        method = op.args[0]
+        method_name = method.value
+        #generator.load(op.args[1])
+        self._render_builtin_method(generator, method_name, op.args[1:])
+
+CallBuiltinObject = _CallBuiltinObject()
+CallExternalObject = _CallExternalObject()
+
+class _IsInstance(MicroInstruction):
+    def render(self, generator, op):
+        # FIXME: just temporary hack
+        generator.load(op.args[0])
+        generator.ilasm.load_const(op.args[1].value._name.replace('.', '_'))#[-1])
+        generator.cast_function("isinstanceof", 2)
+
+class _IndirectCall(MicroInstruction):
+    def render(self, generator, op):
+        for func_arg in op.args[1:]: # push parameters
+            generator.load(func_arg)
+        generator.call_external(op.args[0].name, op.args[1:])
+
+class _SetTimeout(MicroInstruction):
+    # FIXME: Dirty hack for javascript callback stuff
+    def render(self, generator, op):
+        val = op.args[1].value
+        assert(isinstance(val, ootype._static_meth))
+        #if isinstance(val, ootype.StaticMethod):
+        real_name = val._name
+        generator.db.pending_function(val.graph)
+            #generator.db.pending_function(val.graph)
+        #else:
+        #    concrete = val.concretize()
+        #    real_name = concrete.value._name
+        #    generator.db.pending_function(concrete.value.graph)
+        generator.load_str("'%s()'" % real_name)
+        generator.load(op.args[2])
+        generator.call_external('setTimeout',[0]*2)
+
+class _DiscardStack(MicroInstruction):
+    def render(self, generator, op):
+        generator.clean_stack()
+
+class SetOnEvent(MicroInstruction):
+    def __init__(self, field):
+        self.field = field
+    
+    # FIXME: Dirty hack for javascript callback stuff
+    def render(self, generator, op):
+        val = op.args[1].value
+        val = val.concretize().value
+        assert(isinstance(val, ootype._static_meth))
+        real_name = val._name
+        generator.db.pending_function(val.graph)
+        generator.load_str("document")
+        generator.load_str(real_name)
+        generator.set_field(None, self.field)
+
+class _CheckLength(MicroInstruction):
+    def render(self, generator, op):
+        assert not generator.ilasm.right_hand
+
+class _ListRemove(MicroInstruction):
+    def render(self, generator, op):
+        generator.list_getitem(op.args[1], op.args[2])
+        generator.call_external('delete', [0])
+
+ListRemove = _ListRemove()
+CheckLength = _CheckLength()
+SetTimeout = _SetTimeout()
+IndirectCall = _IndirectCall()
+IsInstance = _IsInstance()
+CallMethod = _CallMethod()
+CopyName = [PushAllArgs, _SameAs ()]
+CastString = _CastFun("convertToString", 1)
+SameAs = CopyName
+DiscardStack = _DiscardStack()
+
+def fix_opcodes(opcodes):
+    for key, value in opcodes.iteritems():
+        if type(value) is str:
+            value = InstructionList([PushAllArgs, value, StoreResult, CheckLength])
+        elif value == []:
+            value = InstructionList([CheckLength])
+        elif value is not None:
+            if StoreResult not in value:
+                value.append(StoreResult)
+            if CheckLength not in value:
+                value.append(CheckLength)
+            value = InstructionList(value)
+
+        opcodes[key] = value

Added: pypy/branch/avm/pypy/translator/avm/records.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/records.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,238 @@
+
+from pypy.translator.avm.util import BitStream
+
+class RecordHeader(object):
+
+    def __init__(self, type, length):
+        self.type = type
+        self.length = length
+
+    def serialize(self):
+        bits = BitStream()
+        bits.write_bit_value(type, 6)
+        if length < 0x3F:
+            bits.write_bit_value(self.length, 10)
+        else:
+            bits.write_bit_value(0x3F, 10)
+            bits.write_bit_value(self.length, 32)
+        return bits
+
+    def parse(self, bitstream):
+        self.type = bitstream.read_bit_value(6)
+        self.length = bitstream.read_bit_value(10)
+        if self.length >= 0x3F:
+            self.length = bits.read_bit_value(32)
+
+class Rect(object):
+
+    def __init__(self, XMin=0, XMax=0, YMin=0, YMax=0):
+        self.XMin = XMin
+        self.XMax = XMax
+        self.YMin = YMin
+        self.YMax = YMax
+        
+    def union(self, rect):
+        return Rect(min(self.XMin, rect.XMin),
+                    max(self.XMax, rect.XMax),
+                    min(self.YMin, rect.YMin),
+                    max(self.YMax, rect.YMax))
+
+    def serialize(self):
+        if XMin > XMax or YMin > Max:
+            raise ValueError, "Maximum values in a RECT must be larger than the minimum values."
+
+        # Find our values in twips.
+        twpXMin = self.XMin * 20
+        twpXMax = self.XMax * 20
+        twpYMin = self.YMin * 20
+        twpYMax = self.YMax * 20
+        
+        # Find the number of bits required to store the longest
+        # value, then add one to account for the sign bit.
+        longest = max(abs(twpXMin), abs(twpXMax), abs(twpYMin), abs(twpYMax))
+        import math
+        NBits = int(math.ceil(math.log(longest, 2))) + 1
+
+        if NBits > 31:
+            raise ValueError, "Number of bits per value field cannot exceede 31."
+
+        # And write out our bits.
+        bits = BitStream()
+        bits.write_bit_value(NBits, 5)
+        bits.write_bit_value(twpXMin, NBits)
+        bits.write_bit_value(twpXMax, NBits)
+        bits.write_bit_value(twpYMin, NBits)
+        bits.write_bit_value(twpYMax, NBits)
+
+        return bits
+
+    def parse(self, bitstream):
+        
+        NBits = bits.read_bit_value(5)
+        self.XMin = bits.read_bit_value(NBits)
+        self.XMax = bits.read_bit_value(NBits)
+        self.YMin = bits.read_bit_value(NBits)
+        self.YMax = bits.read_bit_value(NBits)
+
+class XY(object):
+
+    def __init__(self, X=0, Y=0):
+        self.X = 0
+        self.Y = 0
+
+    def serialize(self):
+        # Convert to twips plz.
+        twpX = self.X * 20
+        twpY = self.Y * 20
+
+        # Find the number of bits required to store the longest
+        # value, then add one to account for the sign bit.
+        longest = max(abs(twpX), abas(twpY))
+        import math
+        NBits = int(math.ceil(math.log(longest, 2)))+1
+
+        bits = BitStream()
+        bits.write_bit_value(NBits, 5)
+        bits.write_bit_value(twpX, NBits)
+        bits.write_bit_value(twpY, NBits)
+
+        return bits
+
+    def parse(self, bitstream):
+        
+        NBits = bits.read_bit_value(5)
+        self.X = bits.read_bit_value(NBits)
+        self.Y = bits.read_bit_value(NBits)
+
+class RGB(object):
+
+    def __init__(self, color):
+        self.color = color & 0xFFFFFF
+
+    def serialize(self):
+        bits = BitStream()
+        bits.write_bit_value(self.color, 24)
+        return bits
+
+    def parse(self, bitstream):
+        self.color = bitstream.read_bit_value(24)
+
+class RGBA(RGB):
+    
+    def __init__(self, color, alpha=1.0):
+        RGB.__init__(self, color)
+        self.alpha = alpha
+
+    def serialize(self):
+        bits = RGB.serialize(self)
+        bits.write_bit_value(int(self.alpha * 0xFF), 8)
+        return bits
+
+    def parse(self, bitstream):
+        RGB.parse(self, bitstream)
+        self.alpha = bitstream.read_bit_value(8) / 0xFF
+
+class Shape(object):
+
+    def __init__(self):
+        self.shapes = []
+        
+        self.edge_bounds = Rect()
+        self.shape_bounds = Rect()
+        
+        self.has_scaling = False
+        self.has_non_scaling = False
+        
+        self.bounds_calculated = False
+
+    def add_shape_record(self, shape):
+        self.shapes.append(shape)
+        self.bounds_calculated = False
+    
+    def add_shape(self, shape):
+        self.shapes.expand(shape.shapes)
+        self.bounds_calculated = False
+
+    def serialize(self):
+        if EndShapeRecord not in self.shapes:
+            shapes.append(EndShapeRecord())
+
+        bits = BitArray()
+
+        bits.write_bit_value(0, 8) # NumFillBits and NumLineBits
+        for records in self.shapes:
+            bits += record.serialize()
+
+        return bits
+
+    def calculate_bounds(self):
+
+        if self.bounds_calculated:
+            return
+
+        last_x, last_y = 0, 0
+        for record in shapes:
+            last_x, last_y, has_scale, has_non_scale = record.calculate_bounds(last, self.shape_bounds, self.edge_bounds)
+            if has_scale:
+                self.has_scaling = True
+            if has_non_scale:
+                self.has_non_scaling = True
+
+        self.bounds_calculated = True
+
+def ShapeWithStyle(Shape):
+
+    def __init__(self, fills=[], strokes=[]):
+        Shape.__init__(self)
+        self.fills = fills
+        self.strokes = strokes
+
+    def add_fill_style(self, style):
+        self.fills.append(style)
+
+    def add_line_style(self, style):
+        self.strokes.append(style)
+        
+    def add_shape(self, shape):
+        Shape.add_shape(self, shape)
+        try:
+            self.fills += shape.fills
+            self.strokes += shape.strokes
+        except AttributeError:
+            pass
+
+    @static_method
+    def __serialize_style_list(list):
+        bits = BitStream()
+
+        if len(list) <= 0xFF:
+            bits.write_bit_value(len(list), 8)
+        else:
+            bits.write_bit_value(0xFF, 8)
+            bits.write_bit_value(len(list), 16)
+
+        for style in list:
+            bits += style.serialize()
+
+        return bits
+    
+    def serialize(self):
+        bits = BitStream()
+        bits += __serialize_style_list(self.fills)
+        bits += __serialize_style_list(self.strokes)
+        import math
+        bits.write_bit_value(math.ceil(math.log(len(self.fills), 2)), 4)
+        bits.write_bit_value(math.ceil(math.log(len(self.strokes), 2)), 4)
+        return bits
+        
+class LineStyle(object):
+
+    def __init__(self, width=1, color=0, alpha=1.0):
+        self.width = width
+        self.color = RGBA(color, alpha)
+
+    def serialize(self):
+        bits = BitStream()
+        bits.write_bit_value(self.width * 20, 16)
+        bits += color.serialize()
+        return bits

Added: pypy/branch/avm/pypy/translator/avm/support.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/support.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,50 @@
+from pypy.translator.gensupp import NameManager
+#from pypy.translator.js.optimize import is_optimized_function
+
+class AVM1NameManager(NameManager):
+    def __init__(self, db):
+        NameManager.__init__(self)
+        self.db = db
+        self.reserved = {}
+
+
+        # Source:
+        # http://livedocs.adobe.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001236.html
+        reserved_words = '''add and break case catch class continue default
+        delete do dynamic else eq extends finally for function ge get gt if
+        ifFrameLoaded implements import in instanceof interface intrinsic
+        le lt ne new not on onClipEvent or private public return setw
+        static switch tellTarget this throw try typeof var void while with'''
+        
+        for name in reserved_words.split():
+            self.reserved[name] = True
+            
+        predefined_classes_and_objects = '''
+    Accessibility Accordion Alert Array Binding Boolean Button Camera
+    CellRenderer CheckBox Collection Color ComboBox ComponentMixins ContextMenu
+    ContextMenuItem CustomActions CustomFormatterCustomValidator DataGrid
+    DataHolder DataProvider DataSet DataType Date DateChooser DateField Delta
+    DeltaItem DeltaPacket DepthManager EndPoint Error FocusManager Form Function
+    Iterator Key Label List Loader LoadVars LocalConnection Log Math Media Menu
+    MenuBar Microphone Mouse MovieClip MovieClipLoader NetConnection NetStream
+    Number NumericStepper Object PendingCall PopUpManager PrintJob ProgressBar
+    RadioButton RDBMSResolver Screen ScrollPane Selection SharedObject Slide SOAPCall
+    Sound Stage String StyleManager System TextArea TextField TextFormat TextInput
+    TextSnapshot TransferObject Tree TreeDataProvider TypedValue UIComponent
+    UIEventDispatcher UIObject Video WebService WebServiceConnector Window XML
+    XMLConnector XUpdateResolver'''
+        
+        for name in predefined_classes_and_objects.split():
+            self.reserved[name] = True
+        
+        self.make_reserved_names(' '.join(self.reserved))
+        
+        self.predefined = set(predefined_classes_and_objects)
+
+    #def uniquename(self, name, lenmax=0):
+    #    return NameManager.uniquename(self, , lenmax)
+
+    def ensure_non_reserved(self, name):
+        while name in self.reserved:
+            name += '_'
+        return name

Added: pypy/branch/avm/pypy/translator/avm/swf.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/swf.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,59 @@
+
+
+class SwfData(object):
+
+    def __init__(self, width=600, height=400, fps=24, compress=False, version=10):
+        self.width = width
+        self.height = height
+        self.fps = fps
+        self.compress = compress
+        self.version = version
+        self.frame_count = 1
+
+        self.tags = []
+
+    def __getitem__(self, i):
+        return self.tags.__getitem__(i)
+    
+    def __iadd__(self, other):
+        if hasattr(other, "TAG_TYPE"):
+            self.add_tag(other)
+        else:
+            self.add_tags(other)
+    
+    def add_tag(self, tag):
+        if self.version > tag.min_version:
+            self.tags.append(tag)
+
+    def add_tags(self, tag_container):
+        if hasattr(tag_container, "tags"):
+            self.tags += tag_container.tags
+        else:
+            self.tags += tag_container
+    
+    def serialize(self):
+        final_bytes = []
+
+        header = __gen_header()
+        data = __gen_data_stub()
+        data += [tag.serialize() for tag in self.tags]
+        
+        header[3] = len(header) + len("".join(data)) # FileSize
+        if self.compress:
+            import zlib
+            data = zlib.compress(data)
+            
+        return "".join(header + data)
+        
+    def __gen_header(self):
+        import struct
+        return ("CWS" if self.compress else "FWS") + struct.pack("BL", self.version, 0)
+            
+    def __gen_data_stub(self):
+        from util import BitStream
+        from records import Rect
+        data = BitStream()
+        data += Rect(XMax=width, YMax=height).serialize()
+        data.write_bit_value(fps, 16)
+        data.write_bit_value(frame_count, 16)
+        return data.serialize()

Added: pypy/branch/avm/pypy/translator/avm/tags.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/tags.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,46 @@
+
+from pypy.translator.avm.util import BitStream
+from pypy.translator.avm.avm1 import Block
+
+class SwfTag(object):
+
+    TAG_TYPE = -1
+    TAG_MIN_VERSION = -1
+
+    def serialize_data(self):
+        return ""
+    
+    def serialize(self):
+        data = self.serialize_data(self)
+        return RecordHeader(self.TAG_TYPE, len(data)).serialize().serialize() + data
+
+class SetBackgroundColor(SwfTag):
+    
+    TAG_TYPE = 9
+    TAG_MIN_VERSION = 1
+
+    def __init__(self, color):
+        self.color = color
+
+    def serialize_data(self):
+        import struct
+        return struct.pack("LB", color >> 8 & 0xFFFF, color & 0xFF)
+
+class DoAction(SwfTag, Block):
+
+    TAG_TYPE = 12
+    TAG_MIN_VERSION = 3
+
+    def __init__(self):
+        Block.__init__(self, True)
+
+    def serialize_data(self):
+        return Block.serialize(self)
+
+class End(SwfTag):
+
+    TAG_TYPE = 0
+    TAG_MIN_VERSION = 0
+    
+    def serialize(self):
+        return "\0\0"

Added: pypy/branch/avm/pypy/translator/avm/test/browsertest.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/test/browsertest.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,97 @@
+from BaseHTTPServer import HTTPServer as BaseHTTPServer, BaseHTTPRequestHandler
+import py
+from os   import system
+from cgi  import parse_qs
+from sys  import platform
+from time import sleep
+import webbrowser
+from pypy.translator.avm.log import log
+log = log.browsertest
+
+class HTTPServer(BaseHTTPServer):
+    allow_reuse_address = True
+
+class config:
+    http_port = 10001
+
+    html_page = """<html>
+<head>
+<title>PyPy AVM1 Test Case: %s</title>
+</head>
+<body onload="runTest()">
+<object type="application/x-shockwave-flash" data="testcase.swf" width="400" height="300">
+<param name="movie" value="test.swf" />
+</object>
+</body>
+</html>"""
+
+    crossdomain_xml="""<cross-domain-policy>
+<allow-access-from domain="*" secure="false"/>
+</cross-domain-policy>"""
+    
+class TestCase(object):
+    def __init__(self, name, swfdata):
+        self.testcasename = name
+        self.swfdata = swfdata
+        self.result = None
+    
+class TestHandler(BaseHTTPRequestHandler):
+    """The HTTP handler class that provides the tests and handles results"""
+
+    def do_GET(self):
+        global do_status
+        if self.path == "/test.html":
+            data = config.html_page % testcase.xtestcasename
+            mime = 'text/html'
+        elif self.path == "/test.swf":
+            data = testcase.swfdata
+            mime = 'application/x-shockwave-flash'
+        elif self.path == "/crossdomain.xml":
+            data = config.crossdomain_xml
+            mime = 'text/xml'
+        self.serve_data(mime, data)
+        do_status = 'do_GET'
+
+    def do_POST(self):
+        global do_status
+        if self.path == "/test.result":
+            form = parse_qs(self.rfile.read(int(self.headers['content-length'])))
+            testcase.result = form['result'][0]
+        do_status = 'do_POST'
+
+    def serve_data(self, content_type, data):
+        self.send_response(200)
+        self.send_header("Content-type", content_type)
+        self.send_header("Content-length", len(data))
+        self.end_headers()
+        self.wfile.write(data)
+
+
+class BrowserTest(object):
+    """The browser driver"""
+
+    def start_server(self, port, html_page, is_interactive):
+        server_address = ('', port)
+        self.httpd = HTTPServer(server_address, TestHandler)
+        self.httpd.is_interactive = is_interactive
+        self.httpd.html_page = html_page
+
+    def get_result(self):
+        global do_status
+        do_status = None
+        while do_status != 'do_GET':
+            self.httpd.handle_request()
+        while do_status != 'do_POST':
+            self.httpd.handle_request()
+        return jstest.result
+
+
+def browsertest(testcase, swfdata):
+    global driver, testcase
+    testcase = TestCase(str(testcase), str(swfdata))
+    driver = BrowserTest()
+    driver.start_server(config.http_port, html_page, is_interactive)
+        webbrowser.open('http://localhost:%d/test.html' % config.http_port)
+
+    result = driver.get_result()
+    return result

Added: pypy/branch/avm/pypy/translator/avm/test/runtest.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/test/runtest.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,140 @@
+
+import py, os, re, subprocess
+from pypy.translator.translator import TranslationContext
+from pypy.translator.backendopt.all import backend_optimizations
+from pypy.translator.avm.avm import AVM1
+from pypy.translator.avm.test.browsertest import browsertest, TestCase
+# from pypy.translator.avm import conftest
+from pypy.translator.avm.log import log
+from pypy.conftest import option
+from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin
+from pypy.rlib.nonconst import NonConstant
+from pypy.rpython.ootypesystem import ootype
+
+from pypy.rpython.llinterp import LLException
+
+log = log.runtest
+
+class AVM1Exception(object):
+
+class compile_function(object):
+    def __init__(self, function, annotations, stackless=False, view=False, root=None, policy=None):
+        
+        t = TranslationContext()
+        
+        if policy is None:
+            from pypy.annotation.policy import AnnotatorPolicy
+            policy = AnnotatorPolicy()
+            policy.allow_someobjects = False
+
+        self.root = root
+        
+        ann = t.buildannotator(policy=policy)
+        ann.build_types(function, annotations)
+        if view or option.view:
+            t.view()
+
+        t.buildrtyper(type_system="ootype").specialize()
+
+        if view or option.view:
+            t.view()
+
+        self.avm = AVM1(t, function, stackless)
+
+    def _conv(self, v):
+        if isinstance(v, str):
+            return repr(v)
+        return str(v).lower()
+    
+    def call(self, entry_function):
+
+        if entry_function is None:
+            entry_function = self.avm.translator.graphs[0].name
+        else:
+            entry_function = self.avm.translator.annotator.bookeeper.getdesc(entry_function).cached_graph(None)
+
+        output = browsertest("Test Name", self.avm.serialize())
+        return self.reinterpret(output)
+
+    @classmethod
+    def reinterpret(cls, s):
+        if s == 'false':
+            return False
+        elif s == 'true':
+            return True
+        elif s == 'undefined' or s == 'null':
+            return None
+        elif s == 'inf':
+            return 1e400
+        elif s == 'NaN':
+            return 1e400 / 1e400
+        elif s.startswith('[') or s.startswith('('):
+            contents = s[1:-1].split(',')
+            return [self.reintepret(i) for i in contents]
+        else:
+            try:
+                res = float(s)
+                if float(int(res)) == float(res):
+                    return int(res)
+                return res
+            except ValueError:
+                return str(s)
+
+class AVM1Test(BaseRtypingTest, OORtypeMixin):
+    def _compile(self, _fn, args, policy=None):
+        argnames = _fn.func_code.co_varnames[:_fn.func_code.co_argcount]
+        func_name = _fn.func_name
+        if func_name == '<lambda>':
+            func_name = 'func'
+        source = py.code.Source("""
+        def %s():
+            from pypy.rlib.nonconst import NonConstant
+            res = _fn(%s)
+            if isinstance(res, type(None)):
+                return None
+            else:
+                return str(res)"""
+        % (func_name, ",".join(["%s=NonConstant(%r)" % (name, i) for
+                                    name, i in zip(argnames, args)])))
+        exec source.compile() in locals()
+        return compile_function(locals()[func_name], [], policy=policy)
+
+    def interpret(self, fn, args, policy=None):
+        f = self.compile(fn, args, policy)
+        res = f(*args)
+        return res
+
+    def interpret_raises(self, exception, fn, args):
+        try:
+            res = self.interpret(fn, args)
+        except AVM1Exception, e:
+            s = e.args[0]
+            assert s.startswith('uncaught exception')
+            assert re.search(exception.__name__, s)
+        else:
+            raise AssertionError("Did not raise, returned %s" % res)
+
+    def string_to_ll(self, s):
+        return s
+
+    def ll_to_string(self, s):
+        return str(s)
+
+    def ll_to_list(self, l):
+        return l
+
+    def ll_unpack_tuple(self, t, length):
+        assert len(t) == length
+        return tuple(t)
+
+    def class_name(self, value):
+        return value[:-8].split('.')[-1]
+
+    def is_of_instance_type(self, val):
+        m = re.match("^<.* object>$", val)
+        return bool(m)
+
+    def read_attr(self, obj, name):
+        py.test.skip('read_attr not supported on genavm tests')
+
+def check_source_contains(compiled_function, pattern):

Added: pypy/branch/avm/pypy/translator/avm/util.py
==============================================================================
--- (empty file)
+++ pypy/branch/avm/pypy/translator/avm/util.py	Fri Dec 19 20:01:17 2008
@@ -0,0 +1,196 @@
+
+import struct, os
+
+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 = bits
+        self.cursor = 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)
+        self.bits[self.cursor:self.cursor+length] = bits[offset:offset+length]
+        self.cursor += length
+
+    def read_bit_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 xrange(length-1, -1, -1):
+            n |= self.read_bit() << i
+        return n
+    
+    def write_bit_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 int(value) != value:
+            self.write_fixed_value(value, length)
+            return
+        
+        if length < 0:
+            import math
+            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
+
+        for i in xrange(length-1, -1, -1):
+            self.write_bit(value & (1 << i))
+    
+    def read_fixed_value(self, length, eight_bit_mantissa=False):
+        """Reads a fixed point number of length. If eight_bit_mantissa is True, an
+        8.8 format is used instead of a 16.16 format."""
+        min_length = 8 if eight_bit_mantissa else 16
+        if length < min_length:
+            raise ValueError, "Length must be greater than or equal to %(m)s, as %(m)s.%(m)s FB requires at \
+            least %(m)s bits to store." % {"m": min_length}
+        
+        return self.read_bit_value(length) / 0x100 if eight_bit_mantissa else 0x10000
+
+    def write_fixed_value(self, value, length=-1, eight_bit_mantissa=False):
+        """Writes a fixed point number of length, whole part first. If eight_bit_mantissa is True,
+        an 8.8 format is used instead of a 16.16 format. If length is negative, it will be calculated for."""
+        self.writeBitValue( value * ( 0x100 if eight_bit_mantissa else 0x10000 ), length )
+
+    _EXPN_BIAS = {16: 16, 32: 127, 64: 1023}
+    _N_EXPN_BITS = {16: 5, 32: 8, 64: 52}
+    _N_FRAC_BITS = {16: 10, 32: 23, 64: 52}
+    _FLOAT_NAME = {16: "float16", 32: "float", 64: "double"}
+
+    def read_float_value(self, length=16):
+        """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 _FLOAT_NAME:
+            raise ValueError, "Length in read_float_value is not 16, 32 or 64."
+        
+        sign = self.read_bit()
+        expn = self.read_bit_value(_N_EXPN_BITS[length])
+        frac = self.read_bit_value(_N_FRAC_BITS[length])
+        
+        frac_total = 1 << _N_FRAN_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-_EXPN_BIAS[length]) ) * ( 1 + frac / frac_total )
+
+    def write_float_value(self, value, length=16):
+        """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 n == 0: # n is zero, so we don't care about length
+            self.write_bit_value(0, length)
+            
+        import math
+        if math.isnan(value):
+            self.one_fill(length)
+            return
+        elif value == float("-inf"): # negative infinity
+            self.one_fill(_N_EXPN_BITS[length] + 1) # sign merged
+            self.zero_fill(_N_FRAC_BITS[length])
+            return
+        elif value == float("inf"): # positive infinity
+            self.write_bit(False)
+            self.one_fill(_N_EXPN_BITS[length])
+            self.zero_fill(_N_FRAC_BITS[length])
+            return
+
+        if n < 0:
+            self.write_bit(True)
+            n = ~n + 1
+        else:
+            self.write_bit(False)
+        
+        exp = _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 << _N_EXPN_BITS[length] ):
+            raise ValueError, "Exponent out of range in %s [%d]." % (_FLOAT_NAME[length], length)
+
+        frac_total = 1 << _N_FRAC_BITS
+        self.write_bit_value(exp, _N_EXPN_BITS[length])
+        self.write_bit_value(int((value-1)*frac_total) & (frac_total - 1), _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."""
+        self.bits[self.cursor:self.cursor+amount] = [True] * amount
+        
+    def zero_fill(self, amount):
+        """Fills amount bits with zero. The equivalent of calling
+        self.write_boolean(False) amount times, but more efficient."""
+        self.bits[self.cursor:self.cursor+amount] = [False] * 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 serialize(self, align=ALIGN_RIGHT, endianness="<"):
+        """Serialize bit array into a byte string, aligning either on the right
+        (ALIGN_RIGHT) or left (ALIGN_LEFT)"""
+        list = self[:]
+        leftover = len(list) % 8
+        if leftover > 0 and align == BitStream.ALIGN_RIGHT:
+            list[:0] = [False] * (8-leftover) # Insert some False values to pad the list so it is aligned to the right.
+        list = BitStream(list)
+        bytes = [list.read_bit_value(8) for i in range(math.ceil(bits/8.0))]
+        return struct.pack("%s%dB" % (endianness, len(bytes)), *bytes)
+
+    def parse(self, string, endianness="<"):
+        """Parse a bit array from a byte string into this BitStream."""
+        bytes = list(struct.unpack("%s%dB" % (endianness, len(string))))
+        for byte in bytes:
+            self.write_bit_value(byte, 8)



More information about the Pypy-commit mailing list