[pypy-svn] r36372 - pypy/dist/pypy/translator/jvm

niko at codespeak.net niko at codespeak.net
Tue Jan 9 16:53:40 CET 2007


Author: niko
Date: Tue Jan  9 16:53:38 2007
New Revision: 36372

Modified:
   pypy/dist/pypy/translator/jvm/database.py
   pypy/dist/pypy/translator/jvm/generator.py
   pypy/dist/pypy/translator/jvm/node.py
Log:
fix two tests:

	1. default field values 
	2. recursive pbc



Modified: pypy/dist/pypy/translator/jvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/database.py	(original)
+++ pypy/dist/pypy/translator/jvm/database.py	Tue Jan  9 16:53:38 2007
@@ -95,38 +95,39 @@
         # Create class object if it does not already exist:
         if OOTYPE in self._classes:
             return self._classes[OOTYPE]
-        
-        # Resolve super class first
-        assert OOTYPE._superclass
-        supercls = self.pending_class(OOTYPE._superclass)
 
-        # Create the class object
+        # Create the class object first
         clsnm = self._pkg(self._uniq(OOTYPE._name))
-        clsobj = node.Class(clsnm, supercls)
-
-        print "Class %s has super %s" % (
-            clsnm, supercls.name)
-
-        # Store the class object for future calls
+        clsobj = node.Class(clsnm)
         self._classes[OOTYPE] = clsobj
 
+        # Resolve super class 
+        assert OOTYPE._superclass
+        supercls = self.pending_class(OOTYPE._superclass)
+        clsobj.set_super_class(supercls)
+
         # TODO --- mangle field and method names?  Must be
         # deterministic, or use hashtable to avoid conflicts between
         # classes?
         
         # Add fields:
         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))
+            clsobj.add_field(
+                jvmgen.Field(clsnm, fieldnm, fieldty, False, FIELDOOTY),
+                fielddef)
             
         # Add methods:
         for mname, mimpl in OOTYPE._methods.iteritems():
             if not hasattr(mimpl, 'graph'):
                 # Abstract method
-                TODO
+                METH = mimpl._TYPE
+                arglist = [self.lltype_to_cts(ARG) for ARG in METH.ARGS
+                           if ARG is not ootype.Void]
+                returntype = self.lltype_to_cts(METH.RESULT)
+                clsobj.add_abstract_method(jvmgen.Method.v(
+                    clsobj, mname, arglist, returntype))
             else:
                 # if the first argument's type is not a supertype of
                 # this class it means that this method this method is

Modified: pypy/dist/pypy/translator/jvm/generator.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/generator.py	(original)
+++ pypy/dist/pypy/translator/jvm/generator.py	Tue Jan  9 16:53:38 2007
@@ -276,7 +276,8 @@
 # methobj is its Method instance.
 
 class Method(object):
-    
+
+    # Create a virtual method:
     def v(classty, methnm, argtypes, rettype):
         """
         Shorthand to create a virtual method.
@@ -288,12 +289,10 @@
         """
         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)
+        return Method(classnm, methnm, argtypes, rettype, opcode=INVOKEVIRTUAL)
     v = staticmethod(v)
     
+    # Create a static method:
     def s(classty, methnm, argtypes, rettype):
         """
         Shorthand to create a static method.
@@ -305,16 +304,20 @@
         """
         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))
+        return Method(classnm, methnm, argtypes, rettype)
     s = staticmethod(s)
     
-    def __init__(self, classnm, methnm, desc, opcode=INVOKESTATIC):
+    def __init__(self, classnm, methnm, argtypes, rettype, opcode=INVOKESTATIC):
         self.opcode = opcode
         self.class_name = classnm  # String, ie. "java.lang.Math"
         self.method_name = methnm  # String "abs"
-        self.descriptor = desc     # String, (I)I
+        self.argument_types = argtypes # List of jvmtypes
+        self.return_type = rettype     # jvmtype
+
+        # Compute the method descriptior, which is a string like "()I":
+        argtypesdesc = [a.descriptor for a in argtypes]
+        rettypedesc = rettype.descriptor
+        self.descriptor = desc_for_method(argtypesdesc, rettypedesc)  
     def invoke(self, gen):
         gen._instr(self.opcode, self)
     def jasmin_syntax(self):
@@ -362,10 +365,11 @@
 # Field objects encode information about fields.
 
 class Field(object):
-    def __init__(self, classnm, fieldnm, jtype, static):
+    def __init__(self, classnm, fieldnm, jtype, static, OOTYPE=None):
         # All fields are public
         self.class_name = classnm  # String, ie. "java.lang.Math"
         self.field_name = fieldnm  # String "someField"
+        self.OOTYPE = OOTYPE       # OOTYPE equivalent of JvmType, may be None
         self.jtype = jtype         # JvmType
         self.is_static = static    # True or False
     def load(self, gen):
@@ -450,14 +454,14 @@
     # If the name does not begin with '_', it will be called from
     # outside the generator.
 
-    def begin_class(self, classty, superclsty):
+    def begin_class(self, classty, superclsty, abstract=False):
         """
         Begins a class declaration.  Overall flow of class declaration
         looks like:
 
         begin_class()
         [add_field()]
-        emit_constructor()
+        begin_constructor()...end_constructor()
         [begin_function()...end_function()]
         end_class()
 
@@ -468,14 +472,14 @@
         """
         assert not self.curclass
         self.curclass = ClassState(classty, superclsty)
-        self._begin_class()
+        self._begin_class(abstract)
 
     def end_class(self):
         self._end_class()
         self.curclass = None
         self.curfunc = None
 
-    def _begin_class(self):
+    def _begin_class(self, abstract):
         """ Main implementation of begin_class """
         raise NotImplementedError
 
@@ -489,7 +493,7 @@
         """
         unimplemented
 
-    def emit_constructor(self):
+    def begin_constructor(self):
         """
         Emits the constructor for this class, which merely invokes the
         parent constructor.
@@ -498,14 +502,16 @@
         """
         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 = Method(self.curclass.superclass_type.name, "<init>",
+                         (), jVoid, opcode=INVOKESPECIAL)
         jmethod.invoke(self)
+
+    def end_constructor(self):
         self.return_val(jVoid)
         self.end_function()
 
     def begin_function(self, funcname, argvars, argtypes, rettype,
-                       static=False):
+                       static=False, abstract=False):
         """
         funcname --- name of the function
         argvars --- list of objects passed to load() that represent arguments;
@@ -529,9 +535,9 @@
         # Prepare a map for the local variable indices we will add
         # Let the subclass do the rest of the work; note that it does
         # not need to know the argvars parameter, so don't pass it
-        self._begin_function(funcname, argtypes, rettype, static)
+        self._begin_function(funcname, argtypes, rettype, static, abstract)
 
-    def _begin_function(self, funcname, argtypes, rettype, static):
+    def _begin_function(self, funcname, argtypes, rettype, static, abstract):
         """
         Main implementation of begin_function.  The begin_function()
         does some generic handling of args.
@@ -792,7 +798,7 @@
         
     def new(self, TYPE):
         jtype = self.db.lltype_to_cts(TYPE)
-        ctor = Method(jtype.name, "<init>", "()V", opcode=INVOKESPECIAL)
+        ctor = Method(jtype.name, "<init>", (), jVoid, opcode=INVOKESPECIAL)
         self.emit(NEW, jtype)
         self.emit(DUP)
         self.emit(ctor)
@@ -978,7 +984,7 @@
         JVMGenerator.__init__(self, db)
         self.outdir = outdir
 
-    def _begin_class(self):
+    def _begin_class(self, abstract):
         """
         classnm --- full Java name of the class (i.e., "java.lang.String")
         """
@@ -996,7 +1002,9 @@
         self.db.add_jasmin_file(jfile)
 
         # Write the JasminXT header
-        self.curclass.out(".class public %s\n" % iclassnm)
+        fields = ["public"]
+        if abstract: fields.append('abstract')
+        self.curclass.out(".class %s %s\n" % (" ".join(fields), iclassnm))
         self.curclass.out(".super %s\n" % isuper)
         
     def _end_class(self):
@@ -1014,22 +1022,25 @@
         self.curclass.out('.field %s %s %s\n' % (
             " ".join(kw), fobj.field_name, fobj.jtype.descriptor))
 
-    def _begin_function(self, funcname, argtypes, rettype, static):
+    def _begin_function(self, funcname, argtypes, rettype, static, abstract):
 
         if not static: argtypes = argtypes[1:]
 
         # Throws clause?  Only use RuntimeExceptions?
         kw = ['public']
         if static: kw.append('static')
+        if abstract: kw.append('abstract')
         self.curclass.out('.method %s %s(%s)%s\n' % (
             " ".join(kw),
             funcname,
             "".join([a.descriptor for a in argtypes]),
             rettype.descriptor))
+        self._abstract_method = abstract
 
     def _end_function(self):
-        self.curclass.out('.limit stack 100\n') # HACK, track max offset
-        self.curclass.out('.limit locals %d\n' % self.curfunc.next_offset)
+        if not self._abstract_method:
+            self.curclass.out('.limit stack 100\n') # HACK, track max offset
+            self.curclass.out('.limit locals %d\n' % self.curfunc.next_offset)
         self.curclass.out('.end method\n')
 
     def mark(self, lbl):

Modified: pypy/dist/pypy/translator/jvm/node.py
==============================================================================
--- pypy/dist/pypy/translator/jvm/node.py	(original)
+++ pypy/dist/pypy/translator/jvm/node.py	Tue Jan  9 16:53:38 2007
@@ -22,6 +22,7 @@
 from pypy.translator.jvm.opcodes import opcodes
 from pypy.translator.jvm.option import getoption
 from pypy.translator.oosupport.function import Function as OOFunction
+from pypy.translator.oosupport.constant import push_constant
 import pypy.translator.jvm.generator as jvmgen
 
 class Node(object):
@@ -237,33 +238,40 @@
     """ Represents a class to be emitted.  Note that currently, classes
     are emitted all in one shot, not piecemeal. """
 
-    def __init__(self, name, supercls):
+    def __init__(self, name, supercls=None):
         """
         'name' should be a fully qualified Java class name like
         "java.lang.String", supercls is a Class object
         """
         JvmClassType.__init__(self, name)
-        self.super_class = supercls
+        self.super_class = supercls # can also be set later with set_super_class
         self.fields = {}
         self.rendered = False
+        self.abstract = False
         self.methods = {}
+        self.abstract_methods = {}
+
+    def set_super_class(self, supercls):
+        self.super_class = supercls
 
-    def add_field(self, fieldobj):
+    def add_field(self, fieldobj, fielddef):
         """ Creates a new field accessed via the jvmgen.Field
         descriptor 'fieldobj'.  Must be called before render()."""
         assert not self.rendered and isinstance(fieldobj, jvmgen.Field)
-        self.fields[fieldobj.field_name] = fieldobj
+        self.fields[fieldobj.field_name] = (fieldobj, fielddef)
 
     def lookup_field(self, fieldnm):
         """ Given a field name, returns a jvmgen.Field object """
         if fieldnm in self.fields:
-            return self.fields[fieldnm]
+            return self.fields[fieldnm][0]
         return self.super_class.lookup_field(fieldnm)
 
     def lookup_method(self, methodnm):
         """ Given the method name, returns a jvmgen.Method object """
         if methodnm in self.methods:
             return self.methods[methodnm].method()
+        if methodnm in self.abstract_methods:
+            return self.abstract_methods[methodnm]
         return self.super_class.lookup_method(methodnm)
 
     def add_method(self, func):
@@ -273,21 +281,43 @@
         'methods' may actually represent static functions. """
         self.methods[func.name] = func
 
+    def add_abstract_method(self, jmethod):
+        """ Adds an abstract method to our list of methods; jmethod should
+        be a jvmgen.Method object """
+        assert jmethod.method_name not in self.methods
+        self.abstract = True
+        self.abstract_methods[jmethod.method_name] = jmethod
+
     def add_dump_method(self, dm):
         self.dump_method = dm # public attribute for reading
         self.add_method(dm)
         
     def render(self, gen):
         self.rendered = True
-        gen.begin_class(self, self.super_class)
+        gen.begin_class(self, self.super_class, abstract=self.abstract)
 
-        for field in self.fields.values():
+        for field, fielddef in self.fields.values():
             gen.add_field(field)
 
-        gen.emit_constructor()
+        # Emit the constructor:
+        gen.begin_constructor()
+        # set default values for fields
+        for field, f_default in self.fields.values():
+            if field.jtype is not jVoid:
+                gen.load_jvm_var(self, 0) # load this ptr
+                # load default value of field
+                push_constant(gen.db, field.OOTYPE, f_default, gen)
+                field.store(gen)           # store value into field
+        gen.end_constructor()
 
         for method in self.methods.values():
             method.render(gen)
+
+        for method in self.abstract_methods.values():
+            gen.begin_function(
+                method.method_name, None, method.argument_types,
+                method.return_type, abstract=True)
+            gen.end_function()
         
         gen.end_class()
 



More information about the Pypy-commit mailing list