[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