[pypy-svn] r34241 - in pypy/dist/pypy/translator: jvm jvm/src jvm/test oosupport

niko at codespeak.net niko at codespeak.net
Sun Nov 5 15:55:08 CET 2006


Author: niko
Date: Sun Nov  5 15:55:06 2006
New Revision: 34241

Added:
   pypy/dist/pypy/translator/jvm/builtin.py
   pypy/dist/pypy/translator/jvm/constant.py
   pypy/dist/pypy/translator/jvm/test/test_class.py
   pypy/dist/pypy/translator/oosupport/constant.py
   pypy/dist/pypy/translator/oosupport/database.py
Modified:
   pypy/dist/pypy/translator/jvm/database.py
   pypy/dist/pypy/translator/jvm/generator.py
   pypy/dist/pypy/translator/jvm/genjvm.py
   pypy/dist/pypy/translator/jvm/node.py
   pypy/dist/pypy/translator/jvm/src/PyPy.java
   pypy/dist/pypy/translator/jvm/typesystem.py
   pypy/dist/pypy/translator/oosupport/metavm.py
Log:
Rather large check-in with JVM restructing.  Warning: new code in oosupport
will likely change to match CLI more closely as I integrate those.  Highlights:

1. Begin the work pulling out constant generation and database code and making
it common between CLI and JVM.  Right now, it's only used by the JVM.  Next
check-in will be to integrate with CLI.

2. Unify database nodes and type system both for instances and built-ins.
This simplifies JVM code considerably.

3. Implement several other random bug fixes.



Added: pypy/dist/pypy/translator/jvm/builtin.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/jvm/builtin.py	Sun Nov  5 15:55:06 2006
@@ -0,0 +1,96 @@
+from pypy.translator.jvm import typesystem as jvmtype
+from pypy.translator.jvm import generator as jvmgen
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.jvm.typesystem import \
+     jInt, jVoid, jStringBuilder, jString, jPyPy, jChar
+
+jStringBuilder = jvmtype.jStringBuilder
+
+# ______________________________________________________________________
+# Mapping of built-in OOTypes to JVM types
+
+class JvmBuiltInType(jvmtype.JvmClassType):
+    
+    """
+    Represents built-in types to JVM.  May optionally be associated
+    with an OOTYPE; if it is, then we will support lookup of the OOTYPE
+    methods and will re-map them as needed to the JVM equivalents.
+    """
+    
+    def __init__(self, db, classty, OOTYPE):
+        jvmtype.JvmClassType.__init__(self, classty.name)
+        self.db = db
+        self.OOTYPE = OOTYPE           # might be None
+    
+        # We need to create a mapping for any generic parameters this
+        # OOTYPE may have. Other than SELFTYPE_T, we map each generic
+        # argument to ootype.ROOT.  We use a hack here where we assume
+        # that the only generic parameters are named SELFTYPE_T,
+        # ITEMTYPE_T, KEYTYPE_T, or VALUETYPE_T.
+        self.generics = {}
+        if hasattr(self.OOTYPE, 'SELFTYPE_T'):
+            self.generics[self.OOTYPE.SELFTYPE_T] = self.OOTYPE
+        for param in ('ITEMTYPE_T', 'KEYTYPE_T', 'VALUETYPE_T'):
+            if hasattr(self.OOTYPE, param):
+                self.generics[getattr(self.OOTYPE, param)] = ootype.ROOT
+
+    def lookup_field(self, fieldnm):
+        """ Given a field name, returns a jvmgen.Field object """
+        _, FIELDTY = self.OOTYPE._lookup_field(fieldnm)
+        jfieldty = self.db.lltype_to_cts(FIELDTY)
+        return jvmgen.Field(
+            self.descriptor.class_name(), fieldnm, jfieldty, False)
+
+    def _map(self, ARG):
+        """ Maps ootype ARG to a java type.  If arg is one of our
+        generic arguments, substitutes the appropriate type before
+        performing the mapping. """
+        return self.db.lltype_to_cts(self.generics.get(ARG,ARG))
+
+    def lookup_method(self, methodnm):
+        """ Given the method name, returns a jvmgen.Method object """
+
+        # Look for a shortcut method
+        try:
+            key = (self.OOTYPE.__class__, methodnm)
+            print "key=%r" % (key,)
+            print "hash=%r" % (built_in_methods,)
+            return built_in_methods[key]
+        except KeyError: pass
+
+        # Lookup the generic method by name.
+        GENMETH = self.OOTYPE._GENERIC_METHODS[methodnm]
+
+        # Create an array with the Java version of each type in the
+        # argument list and return type.
+        jargtypes = [self._map(P) for P in GENMETH.ARGS]
+        jrettype = self._map(GENMETH.RESULT)
+        return jvmgen.Method.v(self, methodnm, jargtypes, jrettype)
+
+# When we lookup a method on a  BuiltInClassNode, we first check
+# the 'built_in_methods' table.  This allows us to redirect to other
+# methods if we like.
+
+def _ll_build_method():
+    # Choose an appropriate ll_build depending on what representation
+    # we are using for ootype.String:
+    if True: # XXX db.using_byte_array...
+        return jvmgen.Method.v(
+            jStringBuilder, "toString", (),jString)
+    return jvmgen.Method.s(
+        jvmgen.PYPYJAVA, "ll_build", (jStringBuilder,), jOOString)
+
+built_in_methods = {
+    (ootype.StringBuilder.__class__, "ll_allocate"):
+    jvmgen.Method.v(jStringBuilder, "ensureCapacity", (jInt,), jVoid),
+    
+    (ootype.StringBuilder.__class__, "ll_append_char"):
+    jvmgen.Method.s(jPyPy, "ll_append_char", (jStringBuilder, jChar), jVoid),
+    
+    (ootype.StringBuilder.__class__, "ll_append"):
+    jvmgen.Method.s(jPyPy, "ll_append", (jStringBuilder, jString), jVoid),
+
+    (ootype.StringBuilder.__class__, "ll_build"):
+    _ll_build_method()
+    
+    }

Added: pypy/dist/pypy/translator/jvm/constant.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/jvm/constant.py	Sun Nov  5 15:55:06 2006
@@ -0,0 +1,81 @@
+from pypy.translator.jvm.generator import \
+     Field, Method, ACONST_NULL, ICONST, LDC, DCONST_0, DCONST_1, LDC2
+from pypy.translator.oosupport.constant import \
+     RecordConst, InstanceConst, ClassConst
+from pypy.translator.jvm.typesystem import jPyPyConst
+
+# ___________________________________________________________________________
+# Simple Constants
+#
+# We create simple dummy constant objects that follow the same
+# inteface as the complex constants from oosupport/constant.py.  None
+# of these requires initialization, so they only support push() and
+# they should never find their way into the database's constant list.
+
+class Const(object):
+    def push(self, gen):
+        """ Emits code required to reference a constant.  Usually invoked
+        by generator.emit() """
+        raise NotImplementedError
+
+class VoidConst(object):
+    def push(self, gen):
+        pass
+
+class NullConst(object):
+    def push(self, gen):
+        gen.emit(ACONST_NULL)
+
+class DoubleConst(Const):
+    def __init__(self, value):
+        self.value = value
+    def push(self, gen):
+        if value == 0.0:
+            gen.emit(DCONST_0)
+        elif value == 1.0:
+            gen.emit(DCONST_1)
+        else:
+            gen.emit(LDC2, self.value)
+
+class UnicodeConst(Const):
+    def __init__(self, value):
+        self.value = value
+    def push(self, gen):
+        assert isinstance(self.value, unicode)
+        gen.emit(LDC, res)
+
+# ___________________________________________________________________________
+# Complex Constants
+
+class JVMFieldStorage(object):
+    """ A mix-in for the oosupport constant classes that stores the
+    pointer for the constant into a field on a class.  It implements
+    the push() and store() methods used by the oosupport classes and
+    elsewhere."""
+    def __init__(self):
+        # Note that self.name and self.value are set by the oosupport
+        # constance class:
+        fieldty = self.db.lltype_to_cts(self.value._TYPE)
+        self.fieldobj = Field(jPyPyConst.name, self.name, fieldty, True)
+        
+    def push(self, gen):
+        self.fieldobj.load(gen)
+
+    def store(self, gen):
+        self.fieldobj.store(gen)
+
+class JVMRecordConst(RecordConst, JVMFieldStorage):
+    def __init__(self, db, record, count):
+        RecordConst.__init__(self, db, record, count)
+        JVMFieldStorage.__init__(self)
+
+class JVMInstanceConst(InstanceConst, JVMFieldStorage):
+    def __init__(self, db, obj, record, count):
+        InstanceConst.__init__(self, db, obj, record, count)
+        JVMFieldStorage.__init__(self)
+
+class JVMClassConst(ClassConst, JVMFieldStorage):
+    def __init__(self, db, class_, count):
+        ClassConst.__init__(self, db, class_, count)
+        JVMFieldStorage.__init__(self)
+

Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py	(original)
+++ pypy/dist/pypy/translator/jvm/database.py	Sun Nov  5 15:55:06 2006
@@ -1,144 +1,69 @@
 """
-The database tracks which graphs have already been generated, and maintains
-a worklist.  It also contains a pointer to the type system.  It is passed
-into every node for generation along with the generator.
+The database centralizes information about the state of our translation,
+and the mapping between the OOTypeSystem and the Java type system.
 """
+
 from cStringIO import StringIO
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
-from pypy.translator.jvm.typesystem import jvm_method_desc, ootype_to_jvm
+from pypy.translator.jvm import typesystem as jvmtype
 from pypy.translator.jvm import node
 from pypy.translator.jvm.option import getoption
 import pypy.translator.jvm.generator as jvmgen
+import pypy.translator.jvm.constant as jvmconst
 from pypy.translator.jvm.typesystem import \
-     jStringBuilder, jInt, jVoid, jString, jOOString, jChar
+     jStringBuilder, jInt, jVoid, jString, jChar, jPyPyConst, jObject
+from pypy.translator.jvm.builtin import JvmBuiltInType
 
-# When we lookup a method on a  BuiltInClassNode, we first check
-# the 'built_in_methods' table.  This allows us to redirect to other
-# methods if we like.
-
-def _ll_build_method():
-    # Choose an appropriate ll_build depending on what representation
-    # we are using for ootype.String:
-    if jOOString == jString:
-        return jvmgen.Method.v(
-            jStringBuilder.class_name(), "toString", (),jString)
-    return jvmgen.Method.s(
-        jvmgen.PYPYJAVA, "ll_build", (jStringBuilder,), jOOString)
-
-built_in_methods = {
-    (ootype.StringBuilder.__class__, "ll_allocate"):
-    jvmgen.Method.v(jStringBuilder.class_name(), "ensureCapacity",
-                    (jInt,), jVoid),
-    
-    (ootype.StringBuilder.__class__, "ll_append_char"):
-    jvmgen.Method.s(jvmgen.PYPYJAVA, "ll_append_char",
-                    (jStringBuilder, jChar), jVoid),
-    
-    (ootype.StringBuilder.__class__, "ll_append"):
-    jvmgen.Method.s(jvmgen.PYPYJAVA, "ll_append",
-                    (jStringBuilder, jOOString), jVoid),
-
-    # XXX will not work with --byte-arrays
-    (ootype.StringBuilder.__class__, "ll_build"):
-    _ll_build_method()
-    
-    }
+from pypy.translator.oosupport.database import Database as OODatabase
 
-class BuiltInClassNode(object):
 
-    """
-    This is a fake node that is returned instead of a node.Class object
-    when pending_class is invoked on a built-in type.  It allows other
-    code to query the fields and methods.
-    """
-    
-    def __init__(self, db, OOTYPE):
-        self.db = db
-        self.OOTYPE = OOTYPE
-        self.jvmtype = db.lltype_to_cts(OOTYPE)
-
-        # Create a generic mapping. Other than SELFTYPE_T, we map each
-        # generic argument to ootype.ROOT.  We use a hack here where
-        # we assume that the only generic parameters are named
-        # SELFTYPE_T, ITEMTYPE_T, KEYTYPE_T, or VALUETYPE_T.
-        
-        self.generics = {}
-
-        if hasattr(self.OOTYPE, 'SELFTYPE_T'):
-            self.generics[self.OOTYPE.SELFTYPE_T] = self.OOTYPE
-
-        for param in ('ITEMTYPE_T', 'KEYTYPE_T', 'VALUETYPE_T'):
-            if hasattr(self.OOTYPE, param):
-                self.generics[getattr(self.OOTYPE, param)] = ootype.ROOT
-
-    def jvm_type(self):
-        return self.jvmtype
-
-    def lookup_field(self, fieldnm):
-        """ Given a field name, returns a jvmgen.Field object """
-        _, FIELDTY = self.OOTYPE._lookup_field(fieldnm)
-        jfieldty = self.db.lltype_to_cts(FIELDTY)
-        return jvmgen.Field(
-            self.jvmtype.class_name(), fieldnm, jfieldty, False)
-
-    def _map(self, ARG):
-        """ Maps ootype ARG to a java type.  If arg is one of our
-        generic arguments, substitutes the appropriate type before
-        performing the mapping. """
-        return self.db.lltype_to_cts(self.generics.get(ARG,ARG))
-
-    def lookup_method(self, methodnm):
-        """ Given the method name, returns a jvmgen.Method object """
-
-        # Look for a shortcut method
-        try:
-            key = (self.OOTYPE.__class__, methodnm)
-            print "key=%r" % (key,)
-            print "hash=%r" % (built_in_methods,)
-            return built_in_methods[key]
-        except KeyError: pass
-
-        # Lookup the generic method by name.
-        GENMETH = self.OOTYPE._GENERIC_METHODS[methodnm]
-
-        # Create an array with the Java version of each type in the
-        # argument list and return type.
-        jargtypes = [self._map(P) for P in GENMETH.ARGS]
-        jrettype = self._map(GENMETH.RESULT)
-        return jvmgen.Method(
-            self.jvmtype.class_name(),
-            methodnm,
-            jvm_method_desc(jargtypes, jrettype),
-            opcode=jvmgen.INVOKEVIRTUAL)
-        
+# ______________________________________________________________________
+# Database object
 
-class Database:
+class Database(OODatabase):
     def __init__(self, genoo):
-        # Public attributes:
-        self.genoo = genoo
+        OODatabase.__init__(self, genoo)
         
         # Private attributes:
         self._classes = {} # Maps ootype class objects to node.Class objects,
                            # and JvmType objects as well
-        self._counter = 0  # Used to create unique names
         self._functions = {}      # graph -> jvmgen.Method
 
         self._function_names = {} # graph --> function_name
 
         self._constants = {}      # flowmodel.Variable --> jvmgen.Const
 
-        self._pending_nodes = set()  # Worklist
-        self._rendered_nodes = set()
+    # _________________________________________________________________
+    # Java String vs Byte Array
+    #
+    # We allow the user to configure whether Python strings are stored
+    # as Java strings, or as byte arrays.  The latter saves space; the
+    # former may be faster.  
 
+    using_byte_array = False
+
+    # XXX have to fill this in
+    
+    # _________________________________________________________________
+    # Miscellaneous
+    
     def _uniq(self, nm):
-        cnt = self._counter
-        self._counter += 1
-        return nm + "_" + str(cnt) + "_"
+        return nm + "_" + str(self.unique())
 
     def _pkg(self, nm):
         return "%s.%s" % (getoption('package'), nm)
 
+    def class_name(self, TYPE):
+        jtype = self.lltype_to_cts(TYPE)
+        assert isinstance(jtype, jvmtype.JvmClassType)
+        return jtype.name
+
+    # _________________________________________________________________
+    # Node Creation
+    #
+    # Creates nodes that represents classes, functions, simple constants.
+    
     def _function_for_graph(self, classobj, funcnm, is_static, graph):
         
         """
@@ -153,46 +78,45 @@
         funcobj = node.Function(
             self, classobj, funcnm, jargtypes, jrettype, graph, is_static)
         return funcobj
-
-    def pending_node(self, node):
-        self._pending_nodes.add(node)
-
-    def pending_class(self, OOCLASS):
-        if not isinstance(OOCLASS, ootype.Instance):
-            return BuiltInClassNode(self, OOCLASS)
+    
+    def _translate_instance(self, OOTYPE):
+        assert isinstance(OOTYPE, ootype.Instance)
+        assert OOTYPE is not ootype.ROOT
 
         # Create class object if it does not already exist:
-        if OOCLASS in self._classes:
-            return self._classes[OOCLASS]
+        if OOTYPE in self._classes:
+            return self._classes[OOTYPE]
         
         # Resolve super class first
-        if OOCLASS._superclass:
-            superclsnm = self.lltype_to_cts(OOCLASS._superclass).class_name()
-        else:
-            superclsobj = "java.lang.Object" #?
+        assert OOTYPE._superclass
+        supercls = self.pending_class(OOTYPE._superclass)
 
         # TODO --- make package of java class reflect the package of the
         # OO class?
         clsnm = self._pkg(
-            self._uniq(OOCLASS._name.replace('.','_')))
-        clsobj = node.Class(clsnm, superclsnm)
+            self._uniq(OOTYPE._name.replace('.','_')))
+        clsobj = node.Class(clsnm, supercls)
+
+        print "Class %s has super %s" % (
+            clsnm, supercls.name)
 
         # Store the class object for future calls
-        self._classes[OOCLASS] = clsobj
-        self._classes[clsobj.jvm_type()] = clsobj
+        self._classes[OOTYPE] = clsobj
 
         # TODO --- mangle field and method names?  Must be
         # deterministic, or use hashtable to avoid conflicts between
         # classes?
         
         # Add fields:
-        for fieldnm, (FIELDOOTY, fielddef) in OOCLASS._fields.iteritems():
+        for fieldnm, (FIELDOOTY, fielddef) in OOTYPE._fields.iteritems():
+            print "Class %s has field %s of type %s" % (
+                clsobj.name, fieldnm, FIELDOOTY)
             if FIELDOOTY is ootype.Void: continue
             fieldty = self.lltype_to_cts(FIELDOOTY)
             clsobj.add_field(jvmgen.Field(clsnm, fieldnm, fieldty, False))
             
         # Add methods:
-        for mname, mimpl in OOCLASS._methods.iteritems():
+        for mname, mimpl in OOTYPE._methods.iteritems():
             if not hasattr(mimpl, 'graph'):
                 # Abstract method
                 TODO
@@ -203,21 +127,21 @@
                 # there would be a type mismatch.
                 args =  mimpl.graph.getargs()
                 SELF = args[0].concretetype
-                if not ootype.isSubclass(OOCLASS, SELF): continue
+                if not ootype.isSubclass(OOTYPE, SELF): continue
                 mobj = self._function_for_graph(
                     clsobj, mname, False, mimpl.graph)
                 clsobj.add_method(mobj)
 
         # currently, we always include a special "dump" method for debugging
         # purposes
-        dump_method = node.TestDumpMethod(self, OOCLASS, clsobj)
+        dump_method = node.TestDumpMethod(self, OOTYPE, clsobj)
         clsobj.add_dump_method(dump_method)
 
         self.pending_node(clsobj)
         return clsobj
 
-    def class_obj_for_jvm_type(self, jvmtype):
-        return self._classes[jvmtype]
+    def pending_class(self, OOTYPE):
+        return self.lltype_to_cts(OOTYPE)
 
     def pending_function(self, graph):
         """
@@ -230,48 +154,66 @@
         if graph in self._functions:
             return self._functions[graph]
         classnm = self._pkg(self._uniq(graph.name))
-        classobj = node.Class(classnm, 'java.lang.Object')
+        classobj = node.Class(classnm, self.pending_class(ootype.ROOT))
         funcobj = self._function_for_graph(classobj, "invoke", True, graph)
         classobj.add_method(funcobj)
         self.pending_node(classobj)
         res = self._functions[graph] = funcobj.method()
         return res
 
-    def len_pending(self):
-        return len(self._pending_nodes)
-
-    def pop(self):
-        return self._pending_nodes.pop()
-
-    def gen_constants(self, gen):
-        pass
+    # _________________________________________________________________
+    # Constant Emitting
+    #
+    # We place all constants in a special "constant" class
+    #
+    # XXX I don't particularly like this code being here.  database
+    # shouldn't be so specific?  Guess it's okay...
+
+    RecordConst = jvmconst.JVMRecordConst
+    InstanceConst = jvmconst.JVMInstanceConst
+    ClassConst = jvmconst.JVMClassConst
+    
+    def _begin_gen_constants(self, gen, all_constants):
+        gen.begin_class(jPyPyConst, jObject)
 
-    def record_const(self, constobj):
-        TYPE = constobj.concretetype
-
-        # Handle the simple cases:
-        if TYPE is ootype.Void:
-            return jvmgen.VoidConst()
-        elif TYPE in (ootype.Bool, ootype.Signed):
-            return jvmgen.SignedIntConst(int(constobj.value))
-        elif TYPE is ootype.Char or TYPE is ootype.UniChar:
-            return jvmgen.SignedIntConst(ord(constobj.value))
-        elif TYPE is ootype.SignedLongLong:
-            return jvmgen.SignedLongConst(int(constobj.value))
-        elif TYPE is ootype.UnsignedLongLong:
-            return jvmgen.UnsignedLongConst(int(constobj.value))
-        elif TYPE is ootype.Float:
-            return jvmgen.DoubleConst(constobj.value)
-
-        # Handle the complex cases:
-        #   In this case, we will need to create a method to
-        #   initialize the value and a field.
-        #   For NOW, we create a new class PER constant.
-        #   Clearly this is probably undesirable in the long
-        #   term.
-        return jvmgen.WarnNullConst() # TODO
+        for c in all_constants:
+            assert isinstance(c, jvmconst.JVMFieldStorage)
+            gen.add_field(c.fieldobj)
+
+        # the constant initialization code is broken up into special
+        # methods that are then invoked from <clinit> --- this is to
+        # prevent the init functions from getting too big
+        self._constant_steps = 1
+        gen.begin_function('constant_init_0', [], [], jVoid, True)
+        return gen
+    
+    def _interrupt_gen_constants(self):
+        gen.return_val(jVoid)
+        gen.end_function()    # end constant_init_N
+        
+        next_nm = "constant_init_%d" % self._constant_steps
+        self._constant_steps += 1
+        gen.begin_function(next_nm, [], [], jVoid, True)
+    
+    def _end_gen_constants(self, gen):
+        gen.return_val(jVoid)
+        gen.end_function()    # end constant_init_N
+
+        # The static init code just needs to call constant_init_1..N
+        gen.begin_function('<clinit>', [], [], jVoid, True)
+        for x in range(self._constant_steps):
+            m = jvmgen.Method.s(jPyPyConst, "constant_init_%d" % x, [], jVoid)
+            gen.emit(m)
+        gen.return_val(jVoid)
+        gen.end_function()
+        
+        gen.end_class()
 
-    # Other
+    # _________________________________________________________________
+    # Type printing functions
+    #
+    # Returns a method that prints details about the value out to
+    # stdout.  Should generalize to make it allow for stderr as well.
     
     _type_printing_methods = {
         ootype.Signed:jvmgen.PYPYDUMPINT,
@@ -282,16 +224,35 @@
         ootype.Class:jvmgen.PYPYDUMPOBJECT,
         ootype.String:jvmgen.PYPYDUMPSTRING,
         ootype.StringBuilder:jvmgen.PYPYDUMPOBJECT,
+        ootype.Void:jvmgen.PYPYDUMPVOID,
         }
 
     def generate_dump_method_for_ootype(self, OOTYPE):
+        """
+        Assuming than an instance of type OOTYPE is pushed on the
+        stack, returns a Method object that you can invoke.  This
+        method will require that you also push an integer (usually 0)
+        that represents the indentation, and then invoke it.  i.e., you
+        can do something like:
+
+        > gen.load(var)
+        > mthd = db.generate_dump_method_for_ootype(var.concretetype)
+        > gen.emit(jvmgen.ICONST, 0)
+        > mthd.invoke(gen)
+
+        to print the value of 'var'.
+        """
         if OOTYPE in self._type_printing_methods:
             return self._type_printing_methods[OOTYPE]
         pclass = self.pending_class(OOTYPE)
         assert hasattr(pclass, 'dump_method'), "No dump_method for %r" % (OOTYPE, )
         return pclass.dump_method.method()
 
+    # _________________________________________________________________
     # Type translation functions
+    #
+    # Functions which translate from OOTypes to JvmType instances.
+    # FIX --- JvmType and their Class nodes should not be different.
 
     def escape_name(self, nm):
         # invoked by oosupport/function.py; our names don't need escaping?
@@ -302,29 +263,56 @@
         and name of the given variable"""
         return self.lltype_to_cts(llv.concretetype), llv.name
 
+    # Dictionary for scalar types; in this case, if we see the key, we
+    # will return the value
+    ootype_to_scalar = {
+        ootype.Void:             jvmtype.jVoid,
+        ootype.Signed:           jvmtype.jInt,
+        ootype.Unsigned:         jvmtype.jInt,
+        ootype.SignedLongLong:   jvmtype.jLong,
+        ootype.UnsignedLongLong: jvmtype.jLong,
+        ootype.Bool:             jvmtype.jBool,
+        ootype.Float:            jvmtype.jDouble,
+        ootype.Char:             jvmtype.jByte,
+        ootype.UniChar:          jvmtype.jChar,
+        ootype.Class:            jvmtype.jClass,
+        ootype.ROOT:             jvmtype.jObject,  # count this as a scalar...
+        }
+
+    # Dictionary for non-scalar types; in this case, if we see the key, we
+    # will return a JvmBuiltInType based on the value
+    ootype_to_builtin = {
+        ootype.String:           jvmtype.jString,
+        ootype.StringBuilder:    jvmtype.jStringBuilder
+        }
+
     def lltype_to_cts(self, OOT):
         """ Returns an instance of JvmType corresponding to
-        the given OOType"""
-
-        # Check the easy cases
-        if OOT in ootype_to_jvm:
-            return ootype_to_jvm[OOT]
+        the given OOType """
 
-        # Now handle the harder ones
+        # Handle built-in types:
+        if OOT in self.ootype_to_scalar:
+            return self.ootype_to_scalar[OOT]
         if isinstance(OOT, lltype.Ptr) and isinstance(t.TO, lltype.OpaqueType):
             return jObject
+        if OOT in self.ootype_to_builtin:
+            return JvmBuiltInType(self, self.ootype_to_builtin[OOT], OOT)
+
+        # Handle non-built-in-types:
         if isinstance(OOT, ootype.Instance):
-            return self.pending_class(OOT).jvm_type()
+            return self._translate_instance(OOT)
         if isinstance(OOT, ootype.Record):
-            return XXX
+            return self._translate_record(OOT)
         if isinstance(OOT, ootype.StaticMethod):
             return XXX
+        
+        assert False, "Untranslatable type %s!" % OOT
 
-        # Uh-oh
-        unhandled_case
-
-    # Invoked by genoo:
-    #   I am not sure that we need them
+    # _________________________________________________________________
+    # Uh....
+    #
+    # These functions are invoked by the code in oosupport, but I
+    # don't think we need them or use them otherwise.
     
     def record_function(self, graph, name):
         self._function_names[graph] = name

Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py	(original)
+++ pypy/dist/pypy/translator/jvm/generator.py	Sun Nov  5 15:55:06 2006
@@ -1,29 +1,49 @@
 import os # 
 from pypy.objspace.flow import model as flowmodel
 from pypy.translator.oosupport.metavm import Generator
-from pypy.translator.jvm.typesystem import \
-     JvmType, jObject, jPrintStream, jvm_for_class, jVoid, jvm_method_desc, \
-     jInt, jByteArray, jOOString, jString, jStringBuilder
 from pypy.rpython.ootypesystem import ootype
+from pypy.translator.oosupport.constant import push_constant
+from pypy.translator.jvm.typesystem import \
+     JvmType, jString, jInt, jLong, jDouble, jBool, jString, \
+     jPyPy, jVoid, jMath, desc_for_method, jPrintStream, jClass, jChar, \
+     jObject, jByteArray
 
 # ___________________________________________________________________________
 # Helper class string constants
 
-PYPYJAVA = "pypy.PyPy"
+PYPYJAVA = jPyPy.name
 
 # ___________________________________________________________________________
-# JVM Opcode Flags:
-#
-#   Indicates certain properties of each opcode.  Used mainly for debugging
-#   assertions
+# Miscellaneous helper functions
+
+def _isnan(v):
+    return v != v*1.0 or (v == 1.0 and v == 2.0)
 
-NOFLAGS   = 0
-BRANCH    = 1          # Opcode is a branching opcode (implies a label argument)
-INVOKE    = 2          # Opcode is a Method object
-CONST5    = 4          # Opcode is specialized for int arguments from -1 to 5
-CONST3    = 8          # Opcode is specialized for int arguments from 0 to 3
-CLASSINM  = 16         # Argument is an internal class name
-FIELD     = 32         # Opcode is a Field object
+def _isinf(v):
+    return v!=0 and (v == v*2)
+
+def _unsigned_to_signed_32(val):
+    """ In the JVM, we store unsigned integers in a signed integer slot
+    (since JVM has no signed integers).  This function converts an
+    unsigned value Python integer (possibly a long) into its corresponding
+    Python signed integer. """
+    if val <= 0x7FFFFFFF:
+        return int(val)
+    return int(_two_comp_32(val))
+
+def _unsigned_to_signed_64(val):
+    """ Same as _unsigned_to_signed_32, but for longs. """
+    if val <= 0x7FFFFFFFFFFFFFFF:
+        return val
+    return _two_comp_64(val)
+
+def _two_comp_32(val):
+    """ Returns the 32 bit two's complement. """
+    return -((val ^ 0xFFFFFFFF)+1)
+
+def _two_comp_64(val):
+    """ Returns the 64 bit two's complement. """
+    return -((val ^ 0xFFFFFFFFFFFFFFFF)+1)
 
 # ___________________________________________________________________________
 # JVM Opcodes:
@@ -31,40 +51,49 @@
 #   Map from symbolic name to an instance of the Opcode class
 
 class Opcode(object):
-    def __init__(self, flags, jvmstr):
+    def __init__(self, jvmstr):
         """
         flags is a set of flags (see above) that describe opcode
         jvmstr is the name for jasmin printouts
         """
-        self.flags = flags
         self.jvmstr = jvmstr
 
     def __repr__(self):
         return "<Opcode %s:%x>" % (self.jvmstr, self.flags)
-        
-    def specialize_opcode(self, args):
+
+    def specialize(self, args):
         """ Process the argument list according to the various flags.
         Returns a tuple (OPCODE, ARGS) where OPCODE is a string representing
-        the new opcode, and ARGS is a list of arguments or empty tuple """
-
-        if self.flags & CONST5: 
-            assert len(args) == 1
-            if args[0] == -1:
-                return self.jvmstr + "_m1", ()
-            elif args[0] >= 0 and args[0] <= 5:
-                return self.jvmstr + "_" + str(args[0]), ()
-            else:
-                return "ldc", args # HACK
-
-        if self.flags & CONST3: 
-            assert len(args) == 1
-            if args[0] >= 0 and args[0] <= 3:
-                return self.jvmstr + "_" + str(args[0]), ()
-
-        if self.flags & CLASSINM:
-            assert len(args) == 1
-            args = [args[0].int_class_name()]
-
+        the new opcode, and ARGS is a list of arguments or empty tuple.
+        Most of these do not do anything. """
+        return (self.jvmstr, args)
+
+class IntConstOpcode(Opcode):
+    """ The ICONST opcode specializes itself for small integer opcodes. """
+    def specialize(self, args):
+        assert len(args) == 1
+        if args[0] == -1:
+            return self.jvmstr + "_m1", ()
+        elif args[0] >= 0 and args[0] <= 5:
+            return self.jvmstr + "_" + str(args[0]), ()
+        # Non obvious: convert ICONST to LDC if the constant is out of
+        # range
+        return "ldc", args
+
+class VarOpcode(Opcode):
+    """ An Opcode which takes a variable index as an argument; specialized
+    to small integer indices. """
+    def specialize(self, args):
+        assert len(args) == 1
+        if args[0] >= 0 and args[0] <= 3:
+            return self.jvmstr + "_" + str(args[0]), ()
+        return Opcode.specialize(self, args)
+
+class IntClassNameOpcode(Opcode):
+    """ An opcode which takes an internal class name as its argument;
+    the actual argument will be a JvmType instance. """
+    def specialize(self, args):
+        args = [args[0].descriptor.int_class_name()]
         return self.jvmstr, args
         
 class OpcodeFamily(object):
@@ -76,12 +105,14 @@
     defines one 'family' of opcodes, such as the LOAD family shown
     above, and produces Opcode objects specific to a particular type.
     """
-    def __init__(self, flags, suffix):
+    def __init__(self, opcclass, suffix):
         """
-        flags is a set of flags (see above) that describe opcode
+        opcclass is the opcode subclass to use (see above) when
+        instantiating a particular opcode
+        
         jvmstr is the name for jasmin printouts
         """
-        self.flags = flags
+        self.opcode_class = opcclass
         self.suffix = suffix
         self.cache = {}
 
@@ -89,27 +120,30 @@
         try:
             return self.cache[prefix]
         except KeyError:
-            self.cache[prefix] = obj = Opcode(self.flags, prefix+self.suffix)
+            self.cache[prefix] = obj = self.opcode_class(
+                prefix+self.suffix)
             return obj
         
     def for_type(self, argtype):
         """ Returns a customized opcode of this family appropriate to
         'argtype', a JvmType object. """
 
+        desc = argtype.descriptor
+
         # These are always true:
-        if argtype[0] == 'L': return self._o("a")   # Objects
-        if argtype[0] == '[': return self._o("a")   # Arrays
-        if argtype == 'I':    return self._o("i")   # Integers
-        if argtype == 'J':    return self._o("l")   # Integers
-        if argtype == 'D':    return self._o("d")   # Doubles
-        if argtype == 'V':    return self._o("")    # Void [used by RETURN]
+        if desc[0] == 'L': return self._o("a")   # Objects
+        if desc[0] == '[': return self._o("a")   # Arrays
+        if desc == 'I':    return self._o("i")   # Integers
+        if desc == 'J':    return self._o("l")   # Integers
+        if desc == 'D':    return self._o("d")   # Doubles
+        if desc == 'V':    return self._o("")    # Void [used by RETURN]
 
         # Chars/Bytes/Booleans are normally represented as ints
         # in the JVM, but some opcodes are different.  They use a
         # different OpcodeFamily (see ArrayOpcodeFamily for ex)
-        if argtype == 'C':    return self._o("i")   # Characters
-        if argtype == 'B':    return self._o("i")   # Bytes
-        if argtype == 'Z':    return self._o("i")   # Boolean
+        if desc == 'C':    return self._o("i")   # Characters
+        if desc == 'B':    return self._o("i")   # Bytes
+        if desc == 'Z':    return self._o("i")   # Boolean
 
         assert False, "Unknown argtype=%s" % repr(argtype)
         raise NotImplementedError
@@ -130,81 +164,83 @@
 for cmpop in ('ne', 'eq', 'lt', 'gt', 'le', 'ge'):
     ifop = "if%s" % cmpop
     if_icmpop = "if_icmp%s" % cmpop
-    globals()[ifop.upper()] = Opcode(BRANCH, ifop)
-    globals()[if_icmpop.upper()] = Opcode(BRANCH, if_icmpop)
+    globals()[ifop.upper()] = Opcode(ifop)
+    globals()[if_icmpop.upper()] = Opcode(if_icmpop)
 
 # Compare references, either against NULL or against each other
-IFNULL =    Opcode(BRANCH, 'ifnull')
-IFNONNULL = Opcode(BRANCH, 'ifnonnull')
-IF_ACMPEQ = Opcode(BRANCH, 'if_acmpeq')
-IF_ACMPNE = Opcode(BRANCH, 'if_acmpne')
+IFNULL =    Opcode('ifnull')
+IFNONNULL = Opcode('ifnonnull')
+IF_ACMPEQ = Opcode('if_acmpeq')
+IF_ACMPNE = Opcode('if_acmpne')
 
 # Method invocation
-INVOKESTATIC = Opcode(INVOKE, 'invokestatic')
-INVOKEVIRTUAL = Opcode(INVOKE, 'invokevirtual')
-INVOKESPECIAL = Opcode(INVOKE, 'invokespecial')
+INVOKESTATIC = Opcode('invokestatic')
+INVOKEVIRTUAL = Opcode('invokevirtual')
+INVOKESPECIAL = Opcode('invokespecial')
 
 # Other opcodes
-LDC =       Opcode(NOFLAGS, 'ldc')       # single-word types
-LDC2 =      Opcode(NOFLAGS, 'ldc2_w')    # double-word types: doubles and longs
-GOTO =      Opcode(BRANCH,  'goto')
-ICONST =    Opcode(CONST5,  'iconst')
-ACONST_NULL=Opcode(NOFLAGS, 'aconst_null')
-DCONST_0 =  Opcode(NOFLAGS, 'dconst_0')
-DCONST_1 =  Opcode(NOFLAGS, 'dconst_0')
-LCONST_0 =  Opcode(NOFLAGS, 'lconst_1')
-LCONST_1 =  Opcode(NOFLAGS, 'lconst_1')
-GETFIELD =  Opcode(FIELD, 'getfield')
-PUTFIELD =  Opcode(FIELD, 'putfield')
-GETSTATIC = Opcode(FIELD, 'getstatic')
-PUTSTATIC = Opcode(FIELD, 'putstatic')
-CHECKCAST = Opcode(CLASSINM, 'checkcast')
-INEG =      Opcode(NOFLAGS, 'ineg')
-IXOR =      Opcode(NOFLAGS, 'ixor')
-IADD =      Opcode(NOFLAGS, 'iadd')
-ISUB =      Opcode(NOFLAGS, 'isub')
-IMUL =      Opcode(NOFLAGS, 'imul')
-IDIV =      Opcode(NOFLAGS, 'idiv')
-IREM =      Opcode(NOFLAGS, 'irem')
-IAND =      Opcode(NOFLAGS, 'iand')
-IOR =       Opcode(NOFLAGS, 'ior')
-ISHL =      Opcode(NOFLAGS, 'ishl')
-ISHR =      Opcode(NOFLAGS, 'ishr')
-IUSHR =     Opcode(NOFLAGS, 'iushr')
-DCMPG =     Opcode(NOFLAGS, 'dcmpg')
-DCMPL =     Opcode(NOFLAGS, 'dcmpl')
-NOP =       Opcode(NOFLAGS, 'nop')
-I2D =       Opcode(NOFLAGS, 'i2d')
-I2L =       Opcode(NOFLAGS, 'i2l')
-D2I=        Opcode(NOFLAGS, 'd2i')
-L2I =       Opcode(NOFLAGS, 'l2i')
-ATHROW =    Opcode(NOFLAGS, 'athrow')
-DNEG =      Opcode(NOFLAGS, 'dneg')
-DADD =      Opcode(NOFLAGS, 'dadd')
-DSUB =      Opcode(NOFLAGS, 'dsub')
-DMUL =      Opcode(NOFLAGS, 'dmul')
-DDIV =      Opcode(NOFLAGS, 'ddiv')
-DREM =      Opcode(NOFLAGS, 'drem')
-LNEG =      Opcode(NOFLAGS, 'lneg')
-LADD =      Opcode(NOFLAGS, 'ladd')
-LSUB =      Opcode(NOFLAGS, 'lsub')
-LMUL =      Opcode(NOFLAGS, 'lmul')
-LDIV =      Opcode(NOFLAGS, 'ldiv')
-LREM =      Opcode(NOFLAGS, 'lrem')
-LAND =      Opcode(NOFLAGS, 'land')
-LOR =       Opcode(NOFLAGS, 'lor')
-LXOR =      Opcode(NOFLAGS, 'lxor')
-LSHL =      Opcode(NOFLAGS, 'lshl')
-LSHR =      Opcode(NOFLAGS, 'lshr')
-LUSHR =     Opcode(NOFLAGS, 'lushr')
-NEW =       Opcode(CLASSINM, 'new')
-DUP =       Opcode(NOFLAGS, 'dup')
-POP =       Opcode(NOFLAGS, 'pop')
-INSTANCEOF= Opcode(CLASSINM, 'instanceof')
+LDC =       Opcode('ldc')       # single-word types
+LDC2 =      Opcode('ldc2_w')    # double-word types: doubles and longs
+GOTO =      Opcode('goto')
+ICONST =    IntConstOpcode('iconst')
+ACONST_NULL=Opcode('aconst_null')
+DCONST_0 =  Opcode('dconst_0')
+DCONST_1 =  Opcode('dconst_0')
+LCONST_0 =  Opcode('lconst_1')
+LCONST_1 =  Opcode('lconst_1')
+GETFIELD =  Opcode('getfield')
+PUTFIELD =  Opcode('putfield')
+GETSTATIC = Opcode('getstatic')
+PUTSTATIC = Opcode('putstatic')
+CHECKCAST = IntClassNameOpcode('checkcast')
+INEG =      Opcode('ineg')
+IXOR =      Opcode('ixor')
+IADD =      Opcode('iadd')
+ISUB =      Opcode('isub')
+IMUL =      Opcode('imul')
+IDIV =      Opcode('idiv')
+IREM =      Opcode('irem')
+IAND =      Opcode('iand')
+IOR =       Opcode('ior')
+ISHL =      Opcode('ishl')
+ISHR =      Opcode('ishr')
+IUSHR =     Opcode('iushr')
+DCMPG =     Opcode('dcmpg')
+DCMPL =     Opcode('dcmpl')
+NOP =       Opcode('nop')
+I2D =       Opcode('i2d')
+I2L =       Opcode('i2l')
+D2I=        Opcode('d2i')
+L2I =       Opcode('l2i')
+ATHROW =    Opcode('athrow')
+DNEG =      Opcode('dneg')
+DADD =      Opcode('dadd')
+DSUB =      Opcode('dsub')
+DMUL =      Opcode('dmul')
+DDIV =      Opcode('ddiv')
+DREM =      Opcode('drem')
+LNEG =      Opcode('lneg')
+LADD =      Opcode('ladd')
+LSUB =      Opcode('lsub')
+LMUL =      Opcode('lmul')
+LDIV =      Opcode('ldiv')
+LREM =      Opcode('lrem')
+LAND =      Opcode('land')
+LOR =       Opcode('lor')
+LXOR =      Opcode('lxor')
+LSHL =      Opcode('lshl')
+LSHR =      Opcode('lshr')
+LUSHR =     Opcode('lushr')
+NEW =       IntClassNameOpcode('new')
+DUP =       Opcode('dup')
+DUP2 =      Opcode('dup2')
+POP =       Opcode('pop')
+POP2 =      Opcode('pop2')
+INSTANCEOF= IntClassNameOpcode('instanceof')
 # Loading/storing local variables
-LOAD =      OpcodeFamily(CONST3, "load")
-STORE =     OpcodeFamily(CONST3, "store")
-RETURN =    OpcodeFamily(NOFLAGS, "return")
+LOAD =      OpcodeFamily(VarOpcode, "load")
+STORE =     OpcodeFamily(VarOpcode, "store")
+RETURN =    OpcodeFamily(Opcode, "return")
 
 # Loading/storing from arrays
 #   *NOTE*: This family is characterized by the type of the ELEMENT,
@@ -213,9 +249,27 @@
 #   Also: here I break from convention by naming the objects ARRLOAD
 #   rather than ALOAD, even though the suffix is 'aload'.  This is to
 #   avoid confusion with the ALOAD opcode.
-ARRLOAD =      ArrayOpcodeFamily(NOFLAGS, "aload")
-ARRSTORE =     ArrayOpcodeFamily(NOFLAGS, "astore")
+ARRLOAD =      ArrayOpcodeFamily(Opcode, "aload")
+ARRSTORE =     ArrayOpcodeFamily(Opcode, "astore")
+
+# ___________________________________________________________________________
+# Labels
+#
+# We use a class here just for sanity checks and debugging print-outs.
+
+class Label(object):
+
+    def __init__(self, number, desc):
+        """ number is a unique integer
+        desc is a short, descriptive string that is a valid java identifier """
+        self.label = "%s_%s" % (desc, number)
 
+    def __repr__(self):
+        return "Label(%s)"%self.label
+
+    def jasmin_syntax(self):
+        return self.label
+    
 # ___________________________________________________________________________
 # Methods
 #
@@ -227,13 +281,37 @@
 
 class Method(object):
     
-    def v(classnm, methnm, argtypes, rettype):
-        return Method(classnm, methnm, jvm_method_desc(argtypes, rettype),
+    def v(classty, methnm, argtypes, rettype):
+        """
+        Shorthand to create a virtual method.
+        'class' - JvmType object for the class
+        'methnm' - name of the method (Python string)
+        'argtypes' - list of JvmType objects, one for each argument but
+        not the this ptr
+        'rettype' - JvmType for return type
+        """
+        assert isinstance(classty, JvmType)
+        classnm = classty.name
+        argtypes = [a.descriptor for a in argtypes]
+        rettype = rettype.descriptor
+        return Method(classnm, methnm, desc_for_method(argtypes, rettype),
                       opcode=INVOKEVIRTUAL)
     v = staticmethod(v)
     
-    def s(classnm, methnm, argtypes, rettype):
-        return Method(classnm, methnm, jvm_method_desc(argtypes, rettype))
+    def s(classty, methnm, argtypes, rettype):
+        """
+        Shorthand to create a static method.
+        'class' - JvmType object for the class
+        'methnm' - name of the method (Python string)
+        'argtypes' - list of JvmType objects, one for each argument but
+        not the this ptr
+        'rettype' - JvmType for return type
+        """
+        assert isinstance(classty, JvmType)
+        classnm = classty.name
+        argtypes = [a.descriptor for a in argtypes]
+        rettype = rettype.descriptor
+        return Method(classnm, methnm, desc_for_method(argtypes, rettype))
     s = staticmethod(s)
     
     def __init__(self, classnm, methnm, desc, opcode=INVOKESTATIC):
@@ -248,48 +326,35 @@
                             self.method_name,
                             self.descriptor)
 
-MATHIABS =              Method('java.lang.Math', 'abs', '(I)I')
-MATHLABS =              Method('java.lang.Math', 'abs', '(L)L')
-MATHDABS =              Method('java.lang.Math', 'abs', '(D)D')
-MATHFLOOR =             Method('java.lang.Math', 'floor', '(D)D')
-PRINTSTREAMPRINTSTR =   Method('java.io.PrintStream', 'print',
-                               '(Ljava/lang/String;)V', opcode=INVOKEVIRTUAL)
-PYPYUINTCMP =           Method(PYPYJAVA, 'uint_cmp', '(II)I')
-PYPYULONGCMP =          Method(PYPYJAVA, 'ulong', '(LL)I')
-PYPYUINTTODOUBLE =      Method(PYPYJAVA, 'uint_to_double', '(I)D')
-PYPYDOUBLETOUINT =      Method(PYPYJAVA, 'double_to_uint', '(D)I')
-PYPYLONGBITWISENEGATE = Method(PYPYJAVA, 'long_bitwise_negate', '(L)L')
-PYPYARRAYTOLIST =       Method(PYPYJAVA, 'array_to_list',
-                               '([Ljava/lang/Object;)Ljava/util/List;')
-PYPYSTRTOINT =          Method(PYPYJAVA, 'str_to_int',
-                               '(Ljava/lang/String;)I')
-PYPYSTRTOUINT =         Method(PYPYJAVA, 'str_to_uint',
-                               '(Ljava/lang/String;)I')
-PYPYSTRTOLONG =         Method(PYPYJAVA, 'str_to_long',
-                               '(Ljava/lang/String;)J')
-PYPYSTRTOULONG =        Method(PYPYJAVA, 'str_to_ulong',
-                               '(Ljava/lang/String;)J')
-PYPYSTRTOBOOL =         Method(PYPYJAVA, 'str_to_bool',
-                               '(Ljava/lang/String;)Z')
-PYPYSTRTODOUBLE =       Method(PYPYJAVA, 'str_to_double',
-                               '(Ljava/lang/String;)D')
-PYPYSTRTOCHAR =         Method(PYPYJAVA, 'str_to_char',
-                               '(Ljava/lang/String;)C')
-PYPYDUMPINDENTED  =     Method(PYPYJAVA, 'dump_indented',
-                                 '(ILjava/lang/String;)V')
-PYPYDUMPINT  =          Method(PYPYJAVA, 'dump_int', '(II)V')
-PYPYDUMPUINT  =         Method(PYPYJAVA, 'dump_uint', '(II)V')
-PYPYDUMPLONG  =         Method(PYPYJAVA, 'dump_long', '(LI)V')
-PYPYDUMPDOUBLE  =       Method(PYPYJAVA, 'dump_double', '(DI)V')
-PYPYDUMPSTRING  =       Method(PYPYJAVA, 'dump_string',
-                               jvm_method_desc((jOOString,jInt),jVoid))
-PYPYDUMPBOOLEAN =       Method(PYPYJAVA, 'dump_boolean', '(ZI)V')
-PYPYDUMPOBJECT =        Method(PYPYJAVA, 'dump_object',
-                               '(Ljava/lang/Object;I)V')
-PYPYRUNTIMENEW =        Method(PYPYJAVA, 'RuntimeNew',
-                               '(Ljava/lang/Class;)Ljava/lang/Object;')
-PYPYSTRING2BYTES =      Method(PYPYJAVA, 'string2bytes',
-                               jvm_method_desc((jString),jByteArray))
+MATHIABS =              Method.s(jMath, 'abs', (jInt,), jInt)
+MATHLABS =              Method.s(jMath, 'abs', (jLong,), jLong)
+MATHDABS =              Method.s(jMath, 'abs', (jDouble,), jDouble)
+MATHFLOOR =             Method.s(jMath, 'floor', (jDouble,), jDouble)
+PRINTSTREAMPRINTSTR =   Method.v(jPrintStream, 'print', (jString,), jVoid)
+CLASSFORNAME =          Method.s(jClass, 'forName', (jString,), jClass)
+PYPYUINTCMP =           Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
+PYPYULONGCMP =          Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
+PYPYUINTTODOUBLE =      Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
+PYPYDOUBLETOUINT =      Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
+PYPYLONGBITWISENEGATE = Method.s(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
+PYPYSTRTOINT =          Method.s(jPyPy, 'str_to_int', (jString,), jInt)
+PYPYSTRTOUINT =         Method.s(jPyPy, 'str_to_uint', (jString,), jInt)
+PYPYSTRTOLONG =         Method.s(jPyPy, 'str_to_long', (jString,), jLong)
+PYPYSTRTOULONG =        Method.s(jPyPy, 'str_to_ulong', (jString,), jLong)
+PYPYSTRTOBOOL =         Method.s(jPyPy, 'str_to_bool', (jString,), jBool)
+PYPYSTRTODOUBLE =       Method.s(jPyPy, 'str_to_double', (jString,), jDouble)
+PYPYSTRTOCHAR =         Method.s(jPyPy, 'str_to_char', (jString,), jChar)
+PYPYDUMPINDENTED  =     Method.s(jPyPy, 'dump_indented', (jInt,jString,), jVoid)
+PYPYDUMPINT  =          Method.s(jPyPy, 'dump_int', (jInt,jInt), jVoid)
+PYPYDUMPUINT  =         Method.s(jPyPy, 'dump_uint', (jInt,jInt), jVoid)
+PYPYDUMPLONG  =         Method.s(jPyPy, 'dump_long', (jLong,jInt), jVoid)
+PYPYDUMPDOUBLE  =       Method.s(jPyPy, 'dump_double', (jDouble,jInt), jVoid)
+PYPYDUMPSTRING  =       Method.s(jPyPy, 'dump_string', (jString,jInt), jVoid)
+PYPYDUMPBOOLEAN =       Method.s(jPyPy, 'dump_boolean', (jBool,jInt), jVoid)
+PYPYDUMPOBJECT =        Method.s(jPyPy, 'dump_object', (jObject,jInt,), jVoid)
+PYPYDUMPVOID =          Method.s(jPyPy, 'dump_void', (jInt,), jVoid)
+PYPYRUNTIMENEW =        Method.s(jPyPy, 'RuntimeNew', (jClass,), jObject)
+PYPYSTRING2BYTES =      Method.s(jPyPy, 'string2bytes', (jString,), jByteArray)
 
 
 # ___________________________________________________________________________
@@ -316,135 +381,15 @@
             gen._instr(PUTFIELD, self)
     def jasmin_syntax(self):
         return "%s/%s %s" % (
-            self.class_name.replace('.','/'), self.field_name, self.jtype)
-
-SYSTEMOUT = Field('java.lang.System', 'out', jPrintStream, True)
-SYSTEMERR = Field('java.lang.System', 'err', jPrintStream, True)
-
-# ___________________________________________________________________________
-# Constants
-#
-# Constant objects record constants of various types, and can be used
-# to emit the required instructions to load their value.
-
-class Const(object):
-    def load(self, gen):
-        """ Emits code required to reference a constant.  Usually invoked
-        by generator.emit() """
-        raise NotImplementedError
-    def initialize(self, gen):
-        """ Emits code required to DEFINE a constant (if any).  Default
-        version does nothing. """
-        pass
-
-class VoidConst(object):
-    def load(self, gen):
-        pass
-
-class NullConst(object):
-    def load(self, gen):
-        gen.emit(ACONST_NULL)
-
-class WarnNullConst(NullConst):
-    def load(self, gen):
-        gen.add_comment("   substituting NULL")
-        NullConst.load(self, gen)
-
-class SignedIntConst(Const):
-    def __init__(self, value):
-        self.value = value
-    def load(self, gen):
-        # In theory, we could get rid of CONST5 flag and do optimization
-        # here, but then all code would have to use SignedIntConst, and
-        # that seems uglier
-        gen.emit(ICONST, self.value)
-
-class UnsignedIntConst(SignedIntConst):
-    def __init__(self, value):
-        assert value >= 0
-        if value <= 0x7FFFFFFF:
-            SignedIntConst.__init__(self, value)
-        else:
-            # Find the negative version of the value that will
-            # represent this constant, and treat it like a signed
-            # integer:
-            value = value ^ 0xFFFFFFFF
-            value += 1
-            value *= -1
-            assert value < 0
-            value = int(value)
-            SignedIntConst.__init__(self, value)
-
-class DoubleConst(Const):
-    def __init__(self, value):
-        self.value = value
-    def load(self, gen):
-        if value == 0.0:
-            gen.emit(DCONST_0)
-        elif value == 1.0:
-            gen.emit(DCONST_1)
-        else:
-            gen.emit(LDC2, self.value)
-
-class SignedLongConst(Const):
-    def __init__(self, value):
-        self.value = value
-    def load(self, gen):
-        if value == 0:
-            gen.emit(LCONST_0)
-        elif value == 1:
-            gen.emit(LCONST_1)
-        else:
-            gen.emit(LDC2, self.value)
-
-class UnsignedLongConst(SignedLongConst):
-    def __init__(self, value):
-        assert value >= 0
-        if value <= 0x7FFFFFFFFFFFFFFFL:
-            SignedIntConst.__init__(self, value)
-        else:
-            # Find the negative version of the value that will
-            # represent this constant, and treat it like a signed
-            # integer:
-            value = value ^ 0xFFFFFFFFFFFFFFFF
-            value += 1
-            value *= -1
-            assert value < 0
-            SignedLongConst.__init__(self, value)
-
-class UnicodeConst(Const):
-    def __init__(self, value):
-        self.value = value
-    def load(self, gen):
-        assert isinstance(self.value, unicode)
-        def escape(char):
-            if char == '"': return r'\"'
-            if char == '\n': return r'\n'
-            return char
-        res = ('"' + 
-               "".join(escape(c) for c in self.value.encode('utf-8')) +
-               '"')
-        gen.emit(LDC, res)
-
-class ComplexConst(Const):
-    def __init__(self, fieldinfo, methodinfo):
-        """
-        Stores information about "complex" constants.  These are constants
-        that we cannot embed in the Java file and which require a method
-        to initialize.  They are stored in static fields, and initialized
-        with static methods that should be embedded in a class's static{}
-        section.
-        
-        fieldinfo --- the static field that will hold the value
-        methodinfo --- a static method that initializes the value.  Should
-        have no arguments.
-        """
-        self.fieldinfo = fieldinfo
-        self.methodinfo = methodinfo
-    def load(self, gen):
-        self.fieldinfo.load(gen)
-    def initialize(self, gen):
-        gen.emit(self.methodinfo)
+            self.class_name.replace('.','/'),
+            self.field_name,
+            self.jtype.descriptor)
+
+SYSTEMOUT =    Field('java.lang.System', 'out', jPrintStream, True)
+SYSTEMERR =    Field('java.lang.System', 'err', jPrintStream, True)
+DOUBLENAN =    Field('java.lang.Double', 'NaN', jDouble, True)
+DOUBLEPOSINF = Field('java.lang.Double', 'POSITIVE_INFINITY', jDouble, True)
+DOUBLENEGINF = Field('java.lang.Double', 'NEGATIVE_INFINITY', jDouble, True)
 
 # ___________________________________________________________________________
 # Generator State
@@ -452,9 +397,9 @@
 class ClassState(object):
     """ When you invoked begin_class(), one of these objects is allocated
     and tracks the state as we go through the definition process. """
-    def __init__(self, classnm, superclassnm):
-        self.class_name = classnm
-        self.superclass_name = superclassnm
+    def __init__(self, classty, superclassty):
+        self.class_type = classty
+        self.superclass_type = superclassty
     def out(self, arg):
         self.file.write(arg)
 
@@ -468,7 +413,7 @@
     def add_var(self, jvar, jtype):
         """ Adds new entry for variable 'jvar', of java type 'jtype' """
         idx = self.next_offset
-        self.next_offset += jtype.type_width()
+        self.next_offset += jtype.descriptor.type_width()
         if jvar:
             assert jvar not in self.local_vars # never been added before
             self.local_vars[jvar] = idx
@@ -504,7 +449,7 @@
     # If the name does not begin with '_', it will be called from
     # outside the generator.
 
-    def begin_class(self, classnm, superclsnm):
+    def begin_class(self, classty, superclsty):
         """
         Begins a class declaration.  Overall flow of class declaration
         looks like:
@@ -517,11 +462,11 @@
 
         Where items in brackets may appear anywhere from 0 to inf times.
         
-        classnm --- full Java name of the class (i.e., "java.lang.String")
-        superclassnm --- full Java name of the super class
+        classty --- JvmType for the class
+        superclassty --- JvmType for the superclass
         """
         assert not self.curclass
-        self.curclass = ClassState(classnm, superclsnm)
+        self.curclass = ClassState(classty, superclsty)
         self._begin_class()
 
     def end_class(self):
@@ -550,10 +495,9 @@
         
         superclsnm --- same Java name of super class as from begin_class
         """
-        jtype = jvm_for_class(self.curclass.class_name)
-        self.begin_function("<init>", [], [jtype], jVoid)
-        self.load_jvm_var(jtype, 0)
-        jmethod = Method(self.curclass.superclass_name, "<init>", "()V",
+        self.begin_function("<init>", [], [self.curclass.class_type], jVoid)
+        self.load_jvm_var(self.curclass.class_type, 0)
+        jmethod = Method(self.curclass.superclass_type.name, "<init>", "()V",
                          opcode=INVOKESPECIAL)
         jmethod.invoke(self)
         self.return_val(jVoid)
@@ -614,8 +558,19 @@
         self._instr(RETURN.for_type(vartype))
 
     def load_string(self, str):
-        uni = str.decode('utf-8')
-        UnicodeConst(uni).load(self)
+        """ Pushes a Java version of a Python string onto the stack.
+        'str' should be a Python string encoded in UTF-8 (I think) """
+        # Create an escaped version of str:
+        def escape(char):
+            if char == '"': return r'\"'
+            if char == '\n': return r'\n'
+            return char
+        res = ('"' + 
+               "".join(escape(c) for c in str) +
+               '"')
+        # Use LDC to load the Java version:
+        #     XXX --- support byte arrays here?  Would be trickier!
+        self._instr(LDC, res)
 
     def load_jvm_var(self, vartype, varidx):
         """ Loads from jvm slot #varidx, which is expected to hold a value of
@@ -657,9 +612,8 @@
         identifier.
 
         'mark' --- if True, then also calls self.mark() with the new lbl """
-        labelnum = self.label_counter
+        res = Label(self.label_counter, desc)
         self.label_counter += 1
-        res = ('Label', labelnum, desc)
         if mark:
             self.mark(res)
         return res
@@ -668,7 +622,7 @@
         """ Convenience method.  Be sure you only call it from a
         virtual method, not static methods. """
         self.load_jvm_var(jObject, 0)
-    
+
     # __________________________________________________________________
     # Exception Handling
 
@@ -749,7 +703,7 @@
             return self.load_jvm_var(jty, idx)
 
         if isinstance(value, flowmodel.Constant):
-            return self.db.record_const(value).load(self)
+            return push_constant(self.db, value.concretetype, value.value, self)
             
         raise Exception('Unexpected type for v in load(): '+
                         repr(value.concretetype) + " v=" + repr(value))
@@ -765,25 +719,14 @@
         raise Exception('Unexpected type for v in store(): '+v)
 
     def set_field(self, CONCRETETYPE, fieldname):
-        if fieldname == "meta":
-            # temporary hack
-            self.add_comment("      WARNING: emulating meta for now")
-            self.emit(POP)
-            self.emit(POP)
-        else:
-            clsobj = self.db.pending_class(CONCRETETYPE)
-            fieldobj = clsobj.lookup_field(fieldname)
-            fieldobj.store(self)
+        clsobj = self.db.pending_class(CONCRETETYPE)
+        fieldobj = clsobj.lookup_field(fieldname)
+        fieldobj.store(self)
 
     def get_field(self, CONCRETETYPE, fieldname):
-        if fieldname == 'meta':
-            self.add_comment("      WARNING: emulating meta for now")
-            self.emit(POP)
-            self.emit(ACONST_NULL)
-        else:
-            clsobj = self.db.pending_class(CONCRETETYPE)
-            fieldobj = clsobj.lookup_field(fieldname)
-            fieldobj.load(self)
+        clsobj = self.db.pending_class(CONCRETETYPE)
+        fieldobj = clsobj.lookup_field(fieldname)
+        fieldobj.load(self)
 
     def downcast(self, TYPE):
         jtype = self.db.lltype_to_cts(TYPE)
@@ -817,17 +760,17 @@
     def call_oostring(self, OOTYPE):
         cts_type = self.db.lltype_to_cts(OOTYPE)
         if cts_type != jByteArray:
-            mthd = Method.s(PYPYJAVA, 'oostring', [cts_type, jInt], jString)
+            mthd = Method.s(jPyPy, 'oostring', [cts_type, jInt], jString)
             self.emit(mthd)
-            if jOOString == jByteArray:
+            if self.db.using_byte_array:
                 self.emit(PYPYSTRING2BYTES)
         else:
-            mthd = Method.s(PYPYJAVA, 'oostring',
+            mthd = Method.s(jPyPy, 'oostring',
                             [jByteArray, jInt], jByteArray)
         
     def new(self, TYPE):
         jtype = self.db.lltype_to_cts(TYPE)
-        ctor = Method(jtype.class_name(), "<init>", "()V", opcode=INVOKESPECIAL)
+        ctor = Method(jtype.name, "<init>", "()V", opcode=INVOKESPECIAL)
         self.emit(NEW, jtype)
         self.emit(DUP)
         self.emit(ctor)
@@ -835,6 +778,69 @@
     def instantiate(self):
         self.emit(PYPYRUNTIMENEW)
 
+    def getclassobject(self, OOINSTANCE):
+        jvmtype = self.db.lltype_to_cts(OOINSTANCE)
+        self.load_string(jvmtype.name)
+        CLASSFORNAME.invoke(self)
+        
+    def dup(self, OOTYPE):
+        jvmtype = self.db.lltype_to_cts(OOTYPE)
+        if jvmtype.descriptor.type_width() == 1:
+            self.emit(DUP)
+        else:
+            self.emit(DUP2)
+            
+    def pop(self, OOTYPE):
+        jvmtype = self.db.lltype_to_cts(OOTYPE)
+        if jvmtype.descriptor.type_width() == 1:
+            self.emit(POP)
+        else:
+            self.emit(POP2)
+
+    def push_null(self, OOTYPE):
+        self.emit(ACONST_NULL)
+
+    def push_primitive_constant(self, TYPE, value):
+        if TYPE is ootype.Void:
+            return
+        elif TYPE in (ootype.Bool, ootype.Signed):
+            self.emit(ICONST, int(value))
+        elif TYPE is ootype.Unsigned:
+            # Converts the unsigned int into its corresponding signed value
+            # and emits it using ICONST.
+            self.emit(ICONST, _unsigned_to_signed_32(value))
+        elif TYPE is ootype.Char or TYPE is ootype.UniChar:
+            self.emit(ICONST, ord(value))
+        elif TYPE is ootype.SignedLongLong:
+            self._push_long_constant(long(value))
+        elif TYPE is ootype.UnsignedLongLong:
+            self._push_long_constant(_unsigned_to_signed_64(value))
+        elif TYPE is ootype.Float:
+            self._push_double_constant(float(value))
+        elif TYPE is ootype.String:
+            self.load_string(str(value))
+
+    def _push_long_constant(self, value):
+        if value == 0:
+            gen.emit(LCONST_0)
+        elif value == 1:
+            gen.emit(LCONST_1)
+        else:
+            gen.emit(LDC2, value)
+
+    def _push_double_constant(self, value):
+        if _isnan(value):
+            DOUBLENAN.load(self)
+        elif _isinf(value):
+            if value > 0: DOUBLEPOSINF.load(self)
+            else: DOUBLENEGINF.load(self)
+        elif value == 0.0:
+            gen.emit(DCONST_0)
+        elif value == 1.0:
+            gen.emit(DCONST_1)
+        else:
+            gen.emit(LDC2, self.value)        
+
     # __________________________________________________________________
     # Methods invoked directly by strings in jvm/opcode.py
 
@@ -945,8 +951,8 @@
         classnm --- full Java name of the class (i.e., "java.lang.String")
         """
 
-        iclassnm = self.curclass.class_name.replace('.', '/')
-        isuper = self.curclass.superclass_name.replace('.', '/')
+        iclassnm = self.curclass.class_type.descriptor.int_class_name()
+        isuper = self.curclass.superclass_type.descriptor.int_class_name()
         
         jfile = "%s/%s.j" % (self.outdir, iclassnm)
 
@@ -970,8 +976,10 @@
         self.curclass.out("  ; %s\n" % comment)
 
     def add_field(self, fobj):
-        self.curclass.out('.field public %s %s\n' % (
-            fobj.field_name, fobj.jtype))
+        kw = ['public']
+        if fobj.is_static: kw.append('static')
+        self.curclass.out('.field %s %s %s\n' % (
+            " ".join(kw), fobj.field_name, fobj.jtype.descriptor))
 
     def _begin_function(self, funcname, argtypes, rettype, static):
 
@@ -981,8 +989,10 @@
         kw = ['public']
         if static: kw.append('static')
         self.curclass.out('.method %s %s(%s)%s\n' % (
-            " ".join(kw), funcname,
-            "".join(argtypes), rettype))
+            " ".join(kw),
+            funcname,
+            "".join([a.descriptor for a in argtypes]),
+            rettype.descriptor))
 
     def _end_function(self):
         self.curclass.out('.limit stack 100\n') # HACK, track max offset
@@ -991,21 +1001,16 @@
 
     def mark(self, lbl):
         """ Marks the point that a label indicates. """
-        _, lblnum, lbldesc = lbl
-        assert _ == "Label"
-        self.curclass.out('  %s_%s:\n' % (lbldesc, lblnum))
+        assert isinstance(lbl, Label)
+        self.curclass.out('  %s:\n' % lbl.jasmin_syntax())
 
     def _instr(self, opcode, *args):
-        jvmstr, args = opcode.specialize_opcode(args)
-        # XXX this whole opcode flag things is stupid, redo to be class based
-        if opcode.flags & BRANCH:
-            assert len(args) == 1
-            _, lblnum, lbldesc = args[0]
-            args = ('%s_%s' % (lbldesc, lblnum),)
-        if opcode.flags & (INVOKE|FIELD):
-            assert len(args) == 1
-            args = (args[0].jasmin_syntax(),)
-        instr_text = '    %s %s' % (jvmstr, " ".join([str(s) for s in args]))
+        jvmstr, args = opcode.specialize(args)
+        def jasmin_syntax(arg):
+            if hasattr(arg, 'jasmin_syntax'): return arg.jasmin_syntax()
+            return str(arg)
+        strargs = [jasmin_syntax(arg) for arg in args]
+        instr_text = '%s %s' % (jvmstr, " ".join(strargs))
         self.curclass.out('    %-60s ; %d\n' % (
             instr_text, self.curfunc.instr_counter))
         self.curfunc.instr_counter+=1

Modified: pypy/dist/pypy/translator/jvm/genjvm.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/genjvm.py	(original)
+++ pypy/dist/pypy/translator/jvm/genjvm.py	Sun Nov  5 15:55:06 2006
@@ -193,6 +193,7 @@
         """ Creates and returns a Generator object according to the
         configuration.  Right now, however, there is only one kind of
         generator: JasminGenerator """
+        print "Uh...?"
         return JasminGenerator(
             self.db, self.jvmsrc.javadir, self.jvmsrc.package)
         

Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py	(original)
+++ pypy/dist/pypy/translator/jvm/node.py	Sun Nov  5 15:55:06 2006
@@ -1,14 +1,24 @@
 """
-Rendering nodes for the JVM.  I suspect that a lot of this could be
-made to be common between CLR and JVM.
+Nodes describe Java structures that we are building.  They know how to
+render themselves so as to build the java structure they describe.
+They are entered onto the database worklist as we go.
+
+Some nodes describe parts of the JVM structure that already exist ---
+for example, there are nodes that are used to describe built-in JVM
+types like String, etc.  In this case, they are never placed on the
+database worklist, and don't know how to render themselves (since they
+don't have to).
+
+Nodes representing classes that we will build also implement the JvmType
+interface defined by database.JvmType.
 """
 
 
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
 from pypy.translator.jvm.typesystem import \
-     jString, jStringArray, jVoid, jThrowable
-from pypy.translator.jvm.typesystem import jvm_for_class, jvm_method_desc, jInt
+     JvmClassType, jString, jStringArray, jVoid, jThrowable, jInt, jPyPyMain, \
+     jObject
 from pypy.translator.jvm.opcodes import opcodes
 from pypy.translator.jvm.option import getoption
 from pypy.translator.oosupport.function import Function as OOFunction
@@ -62,7 +72,7 @@
         }
 
     def render(self, gen):
-        gen.begin_class('pypy.Main', 'java.lang.Object')
+        gen.begin_class(jPyPyMain, jObject)
         gen.begin_function(
             'main', (), [jStringArray], jVoid, static=True)
 
@@ -105,10 +115,10 @@
     
     """ Represents a function to be emitted. """
     
-    def __init__(self, db, classobj, name, jargtypes,
+    def __init__(self, db, classty, name, jargtypes,
                  jrettype, graph, is_static):
         """
-        classobj: the Class object this is a part of (even static
+        classty: the JvmClassType object this is a part of (even static
         functions have a class)
         name: the name of the function
         jargtypes: JvmType of each argument
@@ -117,7 +127,7 @@
         is_static: boolean flag indicate whether func is static (!)
         """
         OOFunction.__init__(self, db, graph, name, not is_static)
-        self.classnm = classobj.name
+        self.classty = classty
         self.jargtypes = jargtypes
         self.jrettype = jrettype
         self._block_labels = {}
@@ -125,13 +135,13 @@
     def method(self):
         """ Returns a jvmgen.Method that can invoke this function """
         if not self.is_method:
-            opcode = jvmgen.INVOKESTATIC
+            ctor = jvmgen.Method.s
             startidx = 0
         else:
-            opcode = jvmgen.INVOKEVIRTUAL
+            ctor = jvmgen.Method.v
             startidx = 1
-        mdesc = jvm_method_desc(self.jargtypes[startidx:], self.jrettype)
-        return jvmgen.Method(self.classnm, self.name, mdesc, opcode=opcode)
+        return ctor(self.classty, self.name,
+                    self.jargtypes[startidx:], self.jrettype)
 
     def begin_render(self):
         # Prepare argument lists for begin_function call
@@ -203,25 +213,22 @@
             
         OOFunction._render_op(self, op)
 
-class Class(Node):
+class Class(Node, JvmClassType):
 
     """ Represents a class to be emitted.  Note that currently, classes
     are emitted all in one shot, not piecemeal. """
 
-    def __init__(self, name, supername):
+    def __init__(self, name, supercls):
         """
-        'name' and 'super_name' should be fully qualified Java class names like
-        "java.lang.String"
+        'name' should be a fully qualified Java class name like
+        "java.lang.String", supercls is a Class object
         """
-        self.name = name             # public attribute
-        self.super_name = supername  # public attribute
+        JvmClassType.__init__(self, name)
+        self.super_class = supercls
         self.fields = {}
         self.rendered = False
         self.methods = {}
 
-    def jvm_type(self):
-        return jvm_for_class(self.name)
-
     def add_field(self, fieldobj):
         """ Creates a new field accessed via the jvmgen.Field
         descriptor 'fieldobj'.  Must be called before render()."""
@@ -230,11 +237,15 @@
 
     def lookup_field(self, fieldnm):
         """ Given a field name, returns a jvmgen.Field object """
-        return self.fields[fieldnm]
+        if fieldnm in self.fields:
+            return self.fields[fieldnm]
+        return self.super_class.lookup_field(fieldnm)
 
     def lookup_method(self, methodnm):
         """ Given the method name, returns a jvmgen.Method object """
-        return self.methods[methodnm].method()
+        if methodnm in self.methods:
+            return self.methods[methodnm].method()
+        return self.super_class.lookup_method(methodnm)
 
     def add_method(self, func):
         """ Creates a new method in this class, represented by the
@@ -249,7 +260,7 @@
         
     def render(self, gen):
         self.rendered = True
-        gen.begin_class(self.name, self.super_name)
+        gen.begin_class(self, self.super_class)
 
         for field in self.fields.values():
             gen.add_field(field)
@@ -268,14 +279,13 @@
         self.OOCLASS = OOCLASS
         self.clsobj = clsobj
         self.name = "_pypy_dump"
-        self.jargtypes = [clsobj.jvm_type(), jInt]
+        self.jargtypes = [clsobj, jInt]
         self.jrettype = jVoid
 
     def method(self):
         """ Returns a jvmgen.Method that can invoke this function """
-        mdesc = jvm_method_desc(self.jargtypes[1:], self.jrettype)
-        return jvmgen.Method(self.clsobj.name, self.name, mdesc,
-                             opcode=jvmgen.INVOKEVIRTUAL)
+        return jvmgen.Method.v(
+            self.clsobj, self.name, self.jargtypes[1:], self.jrettype)
 
     def render(self, gen):
         clsobj = self.clsobj

Modified: pypy/dist/pypy/translator/jvm/src/PyPy.java
==============================================================================
--- pypy/dist/pypy/translator/jvm/src/PyPy.java	(original)
+++ pypy/dist/pypy/translator/jvm/src/PyPy.java	Sun Nov  5 15:55:06 2006
@@ -194,6 +194,9 @@
         System.out.println(text);
     }
 
+    public static void dump_void(int indent) {
+    }
+
     public static void dump_int(int i, int indent) {
         dump_indented(indent, Integer.toString(i));
     }

Added: pypy/dist/pypy/translator/jvm/test/test_class.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/jvm/test/test_class.py	Sun Nov  5 15:55:06 2006
@@ -0,0 +1,10 @@
+import py
+from pypy.translator.jvm.test.runtest import JvmTest
+from pypy.rpython.test.test_rclass import BaseTestRclass
+from pypy.rpython.test.test_rspecialcase import BaseTestRspecialcase
+
+class TestJvmClass(JvmTest, BaseTestRclass):    
+    pass
+
+#class TestCliSpecialCase(CliTest, BaseTestRspecialcase):
+#    pass

Modified: pypy/dist/pypy/translator/jvm/typesystem.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/typesystem.py	(original)
+++ pypy/dist/pypy/translator/jvm/typesystem.py	Sun Nov  5 15:55:06 2006
@@ -34,13 +34,25 @@
 from pypy.translator.jvm.option import getoption
 from pypy.translator.jvm.log import log
 
-class JvmType(str):
+# ___________________________________________________________________________
+# Type Descriptors
+#
+# Internal representations of types for the JVM.  Generally speaking,
+# only the generator code should deal with these and even it tries to
+# avoid them except write before dumping to the output file.
+
+class JvmTypeDescriptor(str):
     """
-    The class we use to represent JVM types; it is just a string with
-    the JVM type descriptor at the moment.  Using JvmType allows us to
-    use isinstance, however. The grammar for type descriptors can be
-    read about here:
+    An internal class representing JVM type descriptors, which are
+    essentially Java's short hand for types.  This is the lowest level
+    of our representation for types and are mainly used when defining
+    the types of fields or arguments to methods.  The grammar for type
+    descriptors can be read about here:
+    
     http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html
+
+    We use this class also to represent method descriptors, which define
+    a set of argument and return types.
     """
     def is_scalar(self):
         return self[0] != 'L' and self[0] != '['
@@ -48,6 +60,8 @@
         return not self.is_scalar()
     def is_array(self):
         return self[0] == '['
+    def is_method(self):
+        return self[0] == '('
     def class_name(self):
         """ Converts a descriptor like Ljava/lang/Object; to
         full class name java.lang.Object """
@@ -68,71 +82,114 @@
 
 # JVM type functions
 
-def jvm_array_of(jtype):
+def desc_for_array_of(jdescr):
     """ Returns a JvmType representing an array of 'jtype', which must be
     another JvmType """
-    assert isinstance(jtype, JvmType)
-    return JvmType('['+str(jtype))
+    assert isinstance(jdescr, JvmTypeDescriptor)
+    return JvmTypeDescriptor('['+jdescr)
 
-def jvm_for_class(classnm):
+def desc_for_class(classnm):
     """ Returns a JvmType representing a particular class 'classnm', which
     should be a fully qualified java class name (i.e., 'java.lang.String') """
-    return JvmType('L%s;' % classnm.replace('.','/'))
-
-# Common JVM types
-jVoid = JvmType('V')
-jInt = JvmType('I')
-jLong = JvmType('J')
-jBool = JvmType('Z')
-jDouble = JvmType('D')
-jByte = JvmType('B')
-jByteArray = jvm_array_of(jByte)
-jChar = JvmType('C')
-jThrowable = jvm_for_class('java.lang.Throwable')
-jObject = jvm_for_class('java.lang.Object')
-jString = jvm_for_class('java.lang.String')
-jStringArray = jvm_array_of(jString)
-jArrayList = jvm_for_class('java.util.ArrayList')
-jHashMap = jvm_for_class('java.util.HashMap')
-jIterator = jvm_for_class('java.util.Iterator')
-jClass = jvm_for_class('java.lang.Class')
-jStringBuilder = jvm_for_class('java.lang.StringBuilder')
-jPrintStream = jvm_for_class('java.io.PrintStream')
-
-# Map from OOType to an internal JVM type descriptor
-#  only handles the simple cases
-ootype_to_jvm = {
-    ootype.Void:             jVoid,
-    ootype.Signed:           jInt,
-    ootype.Unsigned:         jInt,
-    ootype.SignedLongLong:   jLong,
-    ootype.UnsignedLongLong: jLong,
-    ootype.Bool:             jBool,
-    ootype.Float:            jDouble,
-    ootype.Char:             jByte,
-    ootype.UniChar:          jChar,
-    ootype.String:           jString,
-    ootype.ROOT:             jObject,
-
-    # We may want to use PyPy wrappers here later:
-    llmemory.WeakGcAddress:  jObject, # XXX
-    ootype.StringBuilder:    jStringBuilder,
-    ootype.Class:            jClass,
-    ootype.List:             jArrayList,
-    ootype.Dict:             jHashMap,
-    ootype.DictItemsIterator:jIterator
-    }
-
-# Determine which class we will use to represent strings:
-if getoption('byte-arrays'):
-    ootype_to_jvm[ootype.String] = jByteArray
-jOOString = ootype_to_jvm[ootype.String]
+    return JvmTypeDescriptor('L%s;' % classnm.replace('.','/'))
 
-# Method descriptor construction
-def jvm_method_desc(argtypes, rettype):
+def desc_for_method(argtypes, rettype):
     """ A Java method has a descriptor, which is a string specified
     its argument and return types.  This function converts a list of
     argument types (JvmTypes) and the return type (also a JvmType),
     into one of these descriptor strings. """
-    return "(%s)%s" % ("".join(argtypes), rettype)
+    return JvmTypeDescriptor("(%s)%s" % ("".join(argtypes), rettype))
+
+# ______________________________________________________________________
+# Basic JVM Types
+
+class JvmType(object):
+    """
+    The JvmType interface defines the interface for type objects
+    that we return in the database in various places.
+    """
+    def __init__(self, descriptor):
+        """ 'descriptor' should be a jvm.generator.JvmTypeDescriptor object
+        for this type """
+        self.descriptor = descriptor  # public
+        self.name = None              # public, string like "java.lang.Object"
+                                      # (None for scalars and arrays)
+    def lookup_field(self, fieldnm):
+        """ Returns a jvm.generator.Field object representing the field
+        with the given name, or raises KeyError if that field does not
+        exist on this type. """
+        raise NotImplementedException
+    def lookup_method(self, methodnm):
+        """ Returns a jvm.generator.Method object representing the method
+        with the given name, or raises KeyError if that field does not
+        exist on this type. """
+        raise NotImplementedException
+
+    def __repr__(self):
+        return "%s<%s>" % (self.__class__.__name__, self.descriptor)
+
+class JvmScalarType(JvmType):
+    """
+    Subclass used for all scalar type instances.
+    """
+    def __init__(self, descrstr):
+        JvmType.__init__(self, JvmTypeDescriptor(descrstr))
+    def lookup_field(self, fieldnm):
+        raise KeyError(fieldnm)        # Scalar objects have no fields
+    def lookup_method(self, methodnm): 
+        raise KeyError(methodnm)       # Scalar objects have no methods
+
+jVoid = JvmScalarType('V')
+jInt = JvmScalarType('I')
+jLong = JvmScalarType('J')
+jBool = JvmScalarType('Z')
+jDouble = JvmScalarType('D')
+jByte = JvmScalarType('B')
+jChar = JvmScalarType('C')
+class JvmClassType(JvmType):
+    """
+    Base class used for all class instances.  Kind of an abstract class;
+    instances of this class do not support field or method lookup and
+    only work to obtain the descriptor.  We use it on occasion for classes
+    like java.lang.Object etc.
+    """
+    def __init__(self, classnm):
+        JvmType.__init__(self, desc_for_class(classnm))
+        self.name = classnm # public String, like 'java.lang.Object'
+    def lookup_field(self, fieldnm):
+        raise KeyError(fieldnm) # we treat as opaque type
+    def lookup_method(self, methodnm):
+        raise KeyError(fieldnm) # we treat as opaque type
+
+jThrowable = JvmClassType('java.lang.Throwable')
+jObject = JvmClassType('java.lang.Object')
+jString = JvmClassType('java.lang.String')
+jArrayList = JvmClassType('java.util.ArrayList')
+jHashMap = JvmClassType('java.util.HashMap')
+jIterator = JvmClassType('java.util.Iterator')
+jClass = JvmClassType('java.lang.Class')
+jStringBuilder = JvmClassType('java.lang.StringBuilder')
+jPrintStream = JvmClassType('java.io.PrintStream')
+jMath = JvmClassType('java.lang.Math')
+jList = JvmClassType('java.util.List')
+jPyPy = JvmClassType('pypy.PyPy')
+jPyPyConst = JvmClassType('pypy.Constant')
+jPyPyMain = JvmClassType('pypy.Main')
+
+class JvmArrayType(JvmType):
+    """
+    Subclass used for all array instances.
+    """
+    def __init__(self, elemtype):
+        JvmType.__init__(self, desc_for_array_of(elemtype.descriptor))
+        self.element_type = elemtype
+    def lookup_field(self, fieldnm):
+        raise KeyError(fieldnm)  # TODO adjust interface to permit opcode here
+    def lookup_method(self, methodnm): 
+        raise KeyError(methodnm) # Arrays have no methods
+    
+jByteArray = JvmArrayType(jByte)
+jObjectArray = JvmArrayType(jObject)
+jStringArray = JvmArrayType(jString)
+
 

Added: pypy/dist/pypy/translator/oosupport/constant.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/oosupport/constant.py	Sun Nov  5 15:55:06 2006
@@ -0,0 +1,332 @@
+"""
+___________________________________________________________________________
+Constants
+
+Complex code for representing constants.  For each complex constant,
+we create an object and record it in the database.  These objects
+contain the knowledge about how to access the value of the constant,
+as well as the how to initialize it.  The constants are initialized in
+several phases so that interdependencies do not prevent a problem.
+
+The initialization process works like this:
+
+1. create_pointer(): this creates uninitialized pointers, so that
+   circular references can be handled.
+
+2. initialize_opaque(): initializes all objects except for
+   CustomDicts.  This basically allows any operation that treats the
+   object as an opaque pointer.  Most initializations complete here.
+
+3. initialize_full(): initializes custom dicts: objects are inserted
+   into dicts here because their fields have been initialized.  This
+   assumes that no custom dicts are inserted into any other custom dicts.
+
+These three methods will be invoked by the database's gen_constants()
+routine.
+"""
+
+from pypy.rpython.ootypesystem import ootype
+
+PRIMITIVE_TYPES = set([ootype.Void, ootype.Bool, ootype.Char, ootype.UniChar,
+                       ootype.Float, ootype.Signed, ootype.Unsigned,
+                       ootype.String, ootype.SignedLongLong,
+                       ootype.UnsignedLongLong])
+
+def is_primitive(TYPE):
+    return TYPE in PRIMITIVE_TYPES
+
+def push_constant(db, TYPE, value, gen):
+    """ Class method that pushes the value of the specified
+    constant onto the stack.  May or may not create an abstract constant
+    object.
+    
+    db --- a Database
+    TYPE --- the ootype of the constant
+    value --- the ootype instance
+    gen --- a metavm.Generator
+    """
+    if is_primitive(TYPE):
+        return gen.push_primitive_constant(TYPE, value)
+
+    const = db.record_const(value)
+    if const.is_null():
+        gen.push_null(TYPE)
+    else:
+        const.push(gen)
+
+# ______________________________________________________________________
+# Constant generator
+
+class ConstantGenerator(object):
+    pass
+
+# ______________________________________________________________________
+# Constant base class
+
+class AbstractConst(object):
+    PRIORITY = 0
+
+    # ____________________________________________________________
+    # Hashing, equality comparison, and repr()
+    #
+    # Overloaded so that two AbstactConst objects representing
+    # the same OOValue are equal.  Provide a sensible repr()
+    
+    def __hash__(self):
+        return hash(self.value)
+
+    def __eq__(self, other):
+        return self.value == other.value
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __repr__(self):
+        return '<Const %s %s>' % (self.name, self.value)
+
+    # ____________________________________________________________
+    # Simple query routines
+    
+    def get_name(self):
+        pass
+
+    def get_type(self):
+        pass
+
+    def is_null(self):
+        return self.value is ootype.null(self.value._TYPE)
+
+    def is_inline(self):
+        """
+        Inline constants are not stored as static fields in the
+        Constant class, but they are newly created on the stack every
+        time they are used. Classes overriding is_inline should
+        override _load too.
+        """
+        return self.is_null() # by default only null constants are inlined
+
+    # ____________________________________________________________
+    # Loading and storing the constant
+    #
+    # These method are left here as an example.  They are commented
+    # out because they must be implemented by the backend as a mix-in,
+    # and this way there is no conflict between the two base classes.
+
+    #def push(self, gen):
+    #    """
+    #    Pushes the value of this constant onto the stack.
+    #    """
+    #    raise NotImplementedException
+
+    #def store(self, gen):
+    #    """
+    #    The value of the constant will be pushed onto the stack;
+    #    store places it somewhere so it can later be loaded.
+    #    """
+    #    raise NotImplementedException
+
+    # ____________________________________________________________
+    # Initializing the constant
+
+    def record_dependencies(self):
+        """
+        Ensures that all dependent objects are added to the database,
+        and any classes that are used are loaded.  Called when the
+        constant object is created.
+        """
+        raise NotImplementedException
+    
+    def create_pointer(self, gen):
+        """
+        Creates the pointer representing this object, but does not
+        initialize its fields.  First phase of initialization.
+        """
+        raise NotImplementedException
+
+    def initialize_opaque(self, gen):
+        """
+        Initializes any constants that only use other constants in an
+        opaque fashion, without relying on them being fully initialized.
+        The big exception are custom dictionaries.
+        """
+        raise NotImplementedException
+
+    def initialize_full(self, gen):
+        """
+        Initializes all remaining constants, such as custom dicts,
+        that inspect the fields of their arguments.  If it is ever the
+        case that such constants try to access one another, we'll need
+        to add a dependence graph, but currently the execution order
+        of this function between constants is undefined.
+        """
+        raise NotImplementedException
+
+    # ____________________________________________________________
+    # Internal helpers
+    
+    def _record_const_if_complex(self, TYPE, value):
+        if not is_primitive(TYPE):
+            self.db.record_const(value)
+
+
+# ______________________________________________________________________
+# Records
+    
+class RecordConst(AbstractConst):
+    def __init__(self, db, record, count):
+        self.db = db
+        self.cts = db.genoo.TypeSystem(db)
+        self.value = record
+        self.name = 'RECORD__%d' % count
+
+    def record_dependencies(self):
+        if self.value is ootype.null(self.value._TYPE):
+            return
+        for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
+            value = self.value._items[f_name]            
+            self._record_const_if_complex(FIELD_TYPE, value)
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        gen.new(self.value._TYPE)
+        self.store(gen)
+
+    def initialize_opaque(self, gen):
+        assert not self.is_null()
+        self.push(gen)
+        SELFTYPE = self.value._TYPE
+        for f_name, (FIELD_TYPE, f_default) in self.value._TYPE._fields.iteritems():
+            if FIELD_TYPE is not ootype.Void:
+                gen.dup(SELFTYPE)
+                #gen.load(value)
+                load(self.db, FIELD_TYPE, value, gen)
+                gen.set_field(SELFTYPE, f_name)
+        gen.pop(SELFTYPE)
+
+    def initialize_full(self, gen):
+        pass
+
+# ______________________________________________________________________
+# Instances
+    
+class InstanceConst(AbstractConst):
+    def __init__(self, db, obj, static_type, count):
+        self.db = db
+        self.value = obj
+        self.cts = db.genoo.TypeSystem(db)
+        if static_type is None:
+            self.static_type = obj._TYPE
+        else:
+            self.static_type = static_type
+            db.genoo.TypeSystem(db).lltype_to_cts(
+                obj._TYPE) # force scheduling of obj's class
+        class_name = db.class_name(obj._TYPE).replace('.', '_')
+        self.name = '%s__%d' % (class_name, count)
+
+    def record_dependencies(self):
+        if not self.value:
+            return
+
+        INSTANCE = self.value._TYPE
+        while INSTANCE is not None:
+            for name, (TYPE, default) in INSTANCE._fields.iteritems():
+                if TYPE is ootype.Void:
+                    continue
+                type_ = self.cts.lltype_to_cts(TYPE) # record type
+                value = getattr(self.value, name) # record value
+                self._record_const_if_complex(TYPE, value)
+            INSTANCE = INSTANCE._superclass
+
+    def is_null(self):
+        return not self.value
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        gen.new(self.value._TYPE)
+        self.store(gen)
+
+    def _sorted_const_list(self):
+        # XXX, horrible hack: first collect all consts, then render
+        # CustomDicts at last because their ll_set could need other
+        # fields already initialized. We should really think a more
+        # general way to handle such things.
+        const_list = []
+        INSTANCE = self.value._TYPE
+        while INSTANCE is not None:
+            for name, (TYPE, default) in INSTANCE._fields.iteritems():
+                if TYPE is ootype.Void:
+                    continue
+                value = getattr(self.value, name)
+                const_list.append((TYPE, INSTANCE, name, value))
+            INSTANCE = INSTANCE._superclass
+
+        def mycmp(x, y):
+            if isinstance(x[0], ootype.CustomDict) and not isinstance(y[0], ootype.CustomDict):
+                return 1 # a CustomDict is always greater than non-CustomDicts
+            elif isinstance(y[0], ootype.CustomDict) and not isinstance(x[0], ootype.CustomDict):
+                return -1 # a non-CustomDict is always less than CustomDicts
+            else:
+                return cmp(x, y)
+        const_list.sort(mycmp)
+
+        return const_list
+
+    def initialize_opaque(self, gen):
+        assert not self.is_null()
+
+        # Get a list of all the constants we'll need to initialize.
+        # I am not clear on why this needs to be sorted, actually,
+        # but we sort it.
+        const_list = self._sorted_const_list()
+        
+        # Push ourself on the stack, and cast to our actual type if it
+        # is not the same as our static type
+        SELFTYPE = self.value._TYPE
+        self.push(gen)
+        if SELFTYPE is not self.static_type:
+            gen.downcast(SELFTYPE)
+
+        # Store each of our fields in the sorted order
+        for FIELD_TYPE, INSTANCE, name, value in const_list:
+            gen.dup(SELFTYPE)
+            push_constant(self.db, FIELD_TYPE, value, gen)
+            gen.set_field(INSTANCE, name)
+
+        # Pop selves from stack when done.
+        gen.pop(SELFTYPE)
+
+    def initialize_full(self, gen):
+        pass
+
+# ______________________________________________________________________
+# Class constants
+
+class ClassConst(AbstractConst):
+    def __init__(self, db, class_, count):
+        self.db = db
+        self.cts = db.genoo.TypeSystem(db)
+        self.value = class_
+        self.name = 'CLASS__%d' % count
+
+    def record_dependencies(self):
+        INSTANCE = self.value._INSTANCE
+        if INSTANCE is not None:
+            self.cts.lltype_to_cts(INSTANCE) # force scheduling class generation
+
+    def is_null(self):
+        return self.value._INSTANCE is None
+
+    def is_inline(self):
+        return True
+
+    def create_pointer(self, gen):
+        assert not self.is_null()
+        INSTANCE = self.value._INSTANCE
+        gen.getclassobject(INSTANCE)
+        self.store(gen)
+
+    def initialize_opaque(self, gen):
+        pass
+
+    def initialize_full(self, gen):
+        pass

Added: pypy/dist/pypy/translator/oosupport/database.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/oosupport/database.py	Sun Nov  5 15:55:06 2006
@@ -0,0 +1,158 @@
+from pypy.translator.oosupport.constant import is_primitive
+from pypy.rpython.ootypesystem import ootype
+
+class Database(object):
+
+    def __init__(self, genoo):
+        self.genoo = genoo
+        self.cts = genoo.TypeSystem(self)
+        self._pending_nodes = set()
+        self._rendered_nodes = set()
+        self._const_cache = {}
+        self._unique_counter = 0
+
+    # ____________________________________________________________
+    # Miscellaneous
+
+    def unique(self):
+        """ Every time it is called, returns a unique integer.  Used in 
+        various places. """
+        self._unique_counter+=1
+        return self._unique_counter-1
+
+    def class_name(self, OOINSTANCE):
+        """ Returns the backend class name of the type corresponding
+        to OOINSTANCE"""
+        raise NotImplementedError
+
+    # ____________________________________________________________
+    # Generation phases
+
+    def gen_constants(self, ilasm):
+        """ Renders the constants uncovered during the graph walk"""
+
+        # Now, emit the initialization code:
+        all_constants = self._const_cache.values()
+        gen = self._begin_gen_constants(ilasm, all_constants)
+        gen.add_section("Create Pointer Phase")
+        ctr = 0
+        for const in all_constants:
+            gen.add_comment("Constant: %s" % const.name)
+            const.create_pointer(gen)
+            ctr = self._consider_interrupt(gen, ctr)
+        gen.add_section("Initialize Opaque Phase")
+        for const in all_constants:
+            gen.add_comment("Constant: %s" % const.name)
+            const.initialize_opaque(gen)
+            ctr = self._consider_interrupt(gen, ctr)
+        gen.add_section("Initialize Full Phase")
+        for const in all_constants:
+            gen.add_comment("Constant: %s" % const.name)
+            const.initialize_full(gen)
+            ctr = self._consider_interrupt(gen, ctr)
+        self._end_gen_constants(gen)
+
+    def _consider_interrupt(self, gen, ctr):
+        ctr += 1
+        if (ctr % 100) == 0: self._interrupt_gen_constants(gen)
+        return ctr
+
+    def _begin_gen_constants(self):
+        # returns a generator
+        raise NotImplementedError
+
+    def _interrupt_gen_constants(self):
+        # invoked every so often so as to break up the generated
+        # code and not create one massive function
+        pass
+    
+    def _end_gen_constants(self, gen):
+        raise NotImplementedError        
+
+    # ____________________________________________________________
+    # Node creation
+    #
+    # Creates nodes for various kinds of things.
+    
+    def pending_class(self, INSTANCE):
+        """ Returns a Node representing the ootype.Instance provided """
+        raise NotImplementedError
+    
+    def pending_function(self, graph):
+        """ Returns a Node representing the graph, which is being used as
+        a static function """
+        raise NotImplementedError
+
+    # ____________________________________________________________
+    # Basic Worklist Manipulation
+
+    def pending_node(self, node):
+        """ Adds a node to the worklist, so long as it is not already there
+        and has not already been rendered. """
+        if node not in self._rendered_nodes:
+            self._pending_nodes.add(node)
+            
+    def len_pending(self):
+        return len(self._pending_nodes)
+
+    def pop(self):
+        return self._pending_nodes.pop()
+
+    # ____________________________________________________________
+    # Constants
+
+    # Defines the subclasses used to represent complex constants by
+    # _create_complex_const:
+    
+    InstanceConst = None
+    RecordConst = None
+    ClassConst = None
+
+    def record_const(self, value):
+        """ Returns an object representing the constant, remembering also
+        any details needed to initialize the constant.  value should be an
+        ootype constant value """
+        assert not is_primitive(value)
+        if value in self._const_cache:
+            return self._const_cache[value]
+        const = self._create_complex_const(value)
+        self._const_cache[value] = const
+        const.record_dependencies()
+        return const
+
+    def push_primitive_const(self, gen, value):
+        """ Helper which pushes a primitive constant onto the stack """ 
+        raise NotImplementedException
+
+    def _create_complex_const(self, value):
+
+        """ A helper method which creates a Constant wrapper object for
+        the given value.  Uses the types defined in the sub-class. """
+        
+        # Determine if the static type differs from the dynamic type.
+        if isinstance(value, ootype._view):
+            static_type = value._TYPE
+            value = value._inst
+        else:
+            static_type = None
+
+        # Find the appropriate kind of Const object.
+        if isinstance(value, ootype._instance):
+            return self.InstanceConst(self, value, static_type, self.unique())
+        elif isinstance(value, ootype._record):
+            return self.RecordConst(self, value, self.unique())
+        elif isinstance(value, ootype._class):
+            return self.ClassConst(self, value, self.unique())
+        #elif isinstance(value, ootype._list):
+        #    return ListConst(db, value, count)
+        #elif isinstance(value, ootype._static_meth):
+        #    return StaticMethodConst(db, value, count)
+        #elif isinstance(value, ootype._custom_dict):
+        #    return CustomDictConst(db, value, count)
+        #elif isinstance(value, ootype._dict):
+        #    return DictConst(db, value, count)
+        #elif isinstance(value, llmemory.fakeweakaddress):
+        #    return WeakRefConst(db, value, count)
+        else:
+            assert False, 'Unknown constant: %s' % value
+

Modified: pypy/dist/pypy/translator/oosupport/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/oosupport/metavm.py	(original)
+++ pypy/dist/pypy/translator/oosupport/metavm.py	Sun Nov  5 15:55:06 2006
@@ -23,6 +23,20 @@
         """
         pass
 
+    def add_section(self, text):
+        """
+        Prints a distinguished comment
+        """
+        self.add_comment("_" * 70)
+        self.add_comment(text)
+
+    def pop(self, TYPE):
+        """ Pops a value off the top of the stack, which is of the
+        given TYPE.
+
+        Stack: val, ... -> ..."""
+        raise NotImplementedError
+
     def dup(self, TYPE):
         """ Duplicates the top of the stack, which is of the given TYPE.
 
@@ -83,7 +97,14 @@
         Stack: obj, ... -> obj, ...
         """
         raise NotImplementedError
-        
+
+    def getclassobject(self, OOINSTANCE):
+        """
+        Gets the class object for the OOINSTANCE.  The type of the class
+        object will depend on the backend, of course; for example in JVM
+        it is java.lang.Class.
+        """
+        raise NotImplementedError
 
     def instantiate(self):
         """
@@ -146,9 +167,18 @@
         Stack: ... -> newobj, ... """
         raise NotImplementedError
 
-    def push_null(self):
+    def push_null(self, TYPE):
+        """ Push a NULL value onto the stack (the NULL value represents
+        a pointer to an instance of OOType TYPE, if it matters to you). """
         raise NotImplementedError
 
+    def push_primitive_constant(self, TYPE, value):
+        """ Push an instance of TYPE onto the stack with the given
+        value.  TYPE will be one of the types enumerated in
+        oosupport.constant.PRIMITIVE_TYPES.  value will be its
+        corresponding ootype implementation. """
+        raise NotImplementedError        
+
 class InstructionList(list):
     def render(self, generator, op):
         for instr in self:



More information about the Pypy-commit mailing list