[pypy-svn] r14566 - in pypy/dist/pypy/rpython: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Jul 12 21:47:39 CEST 2005
Author: arigo
Date: Tue Jul 12 21:47:34 2005
New Revision: 14566
Added:
pypy/dist/pypy/rpython/objectmodel.py (contents, props changed)
Modified:
pypy/dist/pypy/rpython/normalizecalls.py
pypy/dist/pypy/rpython/rbuiltin.py
pypy/dist/pypy/rpython/rclass.py
pypy/dist/pypy/rpython/rpbc.py
pypy/dist/pypy/rpython/rspecialcase.py
pypy/dist/pypy/rpython/test/test_rbuiltin.py
pypy/dist/pypy/rpython/test/test_rspecialcase.py
Log:
More strangeness, more progress: test_rbuiltin.test_instantiate_multiple().
instantiate() is now a "built-in" from the point of view of the annotator,
which is progress.
All vtables have an entry 'instantiate' that points to a function that
instantiates the corresponding class. Building this function is actually "a
bit" messy. Then instantiate() can just be implemented by calling it.
We are reusing a trick we already used in the previous check-in: here, the
function that instantiate a class are defined (in normalizecalls) as
def my_instantiate():
return instantiate(cls)
which means that instantiate() is actually implemented as follows: if the
argument is a known constant class, we instantiate it in the normal way
(rclass.py, rtype_new_instance()). Otherwise, we load and call the
appropriate version of my_instantiate(), which itself contains again a call to
instantiate() -- but this time with a constant 'cls'...
For reference, the previous check-in used the same trick for calling classes.
A call to a constant class was already implemented some time ago, so a call to
a non-constant class can be done by calling a helper function __new__() that
is defined as calling a constant class.
Modified: pypy/dist/pypy/rpython/normalizecalls.py
==============================================================================
--- pypy/dist/pypy/rpython/normalizecalls.py (original)
+++ pypy/dist/pypy/rpython/normalizecalls.py Tue Jul 12 21:47:34 2005
@@ -5,7 +5,9 @@
from pypy.objspace.flow.model import SpaceOperation, checkgraph
from pypy.annotation import model as annmodel
from pypy.tool.sourcetools import has_varargs, valid_identifier
+from pypy.tool.sourcetools import func_with_new_name
from pypy.rpython.rmodel import TyperError
+from pypy.rpython.objectmodel import instantiate
def normalize_function_signatures(annotator):
@@ -310,6 +312,24 @@
new_call_family.patterns = patterns
+def create_instantiate_functions(annotator):
+ # build the 'instantiate() -> instance of C' functions for the vtables
+ for cls, classdef in annotator.getuserclasses().items():
+ create_instantiate_function(annotator, cls, classdef)
+
+def create_instantiate_function(annotator, cls, classdef):
+ def my_instantiate():
+ return instantiate(cls)
+ my_instantiate = func_with_new_name(my_instantiate,
+ valid_identifier('instantiate_'+cls.__name__))
+ annotator.build_types(my_instantiate, [])
+ # force the result to be converted to a generic OBJECTPTR
+ generalizedresult = annmodel.SomeInstance(classdef=None)
+ graph = annotator.translator.getflowgraph(my_instantiate)
+ annotator.setbinding(graph.getreturnvar(), generalizedresult)
+ classdef.my_instantiate = my_instantiate
+
+
def perform_normalizations(rtyper):
create_class_constructors(rtyper)
rtyper.annotator.frozen += 1
@@ -319,3 +339,4 @@
merge_classpbc_getattr_into_classdef(rtyper)
finally:
rtyper.annotator.frozen -= 1
+ create_instantiate_functions(rtyper.annotator)
Added: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/objectmodel.py Tue Jul 12 21:47:34 2005
@@ -0,0 +1,14 @@
+"""
+This file defines utilities for manipulating objects in an
+RPython-compliant way.
+"""
+
+import new
+
+
+def instantiate(cls):
+ "Create an empty instance of 'cls'."
+ if isinstance(cls, type):
+ return object.__new__(cls)
+ else:
+ return new.instance(cls)
Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py (original)
+++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jul 12 21:47:34 2005
@@ -1,7 +1,7 @@
from pypy.annotation.pairtype import pairtype
from pypy.annotation import model as annmodel
from pypy.rpython import lltype
-from pypy.rpython import rarithmetic
+from pypy.rpython import rarithmetic, objectmodel
from pypy.rpython.rtyper import TyperError
from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange
from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, Constant
@@ -180,6 +180,23 @@
vlist = hop.inputargs(lltype.Float, lltype.Float)
return hop.genop('float_fmod', vlist, resulttype=lltype.Float)
+def ll_instantiate(typeptr, RESULT):
+ my_instantiate = typeptr.instantiate
+ return lltype.cast_pointer(RESULT, my_instantiate())
+
+def rtype_instantiate(hop):
+ s_class = hop.args_s[0]
+ assert isinstance(s_class, annmodel.SomePBC)
+ if len(s_class.prebuiltinstances) != 1:
+ # instantiate() on a variable class
+ vtypeptr, = hop.inputargs(rclass.get_type_repr(hop.rtyper))
+ cresult = hop.inputconst(lltype.Void, hop.r_result.lowleveltype)
+ return hop.gendirectcall(ll_instantiate, vtypeptr, cresult)
+
+ klass = s_class.const
+ return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops)
+
+
import math
##def ll_floor(f1):
## return float(int((f1)
@@ -234,6 +251,7 @@
BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info
BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint
+BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate
import time
Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py (original)
+++ pypy/dist/pypy/rpython/rclass.py Tue Jul 12 21:47:34 2005
@@ -8,6 +8,7 @@
from pypy.rpython.lltype import cast_pointer, castable, nullptr
from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf
from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo
+from pypy.rpython.lltype import FuncType
#
# There is one "vtable" per user class, with the following structure:
@@ -17,6 +18,7 @@
# struct object_vtable* parenttypeptr;
# RuntimeTypeInfo * rtti;
# array { char } * name;
+# struct object * instantiate();
# }
#
# Every other class X, with parent Y, has the structure:
@@ -40,13 +42,13 @@
OBJECT_VTABLE = ForwardReference()
TYPEPTR = Ptr(OBJECT_VTABLE)
+OBJECT = GcStruct('object', ('typeptr', TYPEPTR))
+OBJECTPTR = Ptr(OBJECT)
OBJECT_VTABLE.become(Struct('object_vtable',
('parenttypeptr', TYPEPTR),
('rtti', Ptr(RuntimeTypeInfo)),
- ('name', Ptr(Array(Char)))))
-
-OBJECT = GcStruct('object', ('typeptr', TYPEPTR))
-OBJECTPTR = Ptr(OBJECT)
+ ('name', Ptr(Array(Char))),
+ ('instantiate', Ptr(FuncType([], OBJECTPTR)))))
def getclassrepr(rtyper, classdef):
try:
@@ -231,6 +233,11 @@
for i in range(len(name)):
vtable.name[i] = name[i]
vtable.name[len(name)] = '\x00'
+ if hasattr(rsubcls.classdef, 'my_instantiate'):
+ fn = rsubcls.classdef.my_instantiate
+ vtable.instantiate = self.rtyper.getfunctionptr(fn)
+ #else: the classdef was created recently, so no instantiate()
+ # could reach it
else:
# setup class attributes: for each attribute name at the level
# of 'self', look up its value in the subclass rsubcls
Modified: pypy/dist/pypy/rpython/rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/rpbc.py (original)
+++ pypy/dist/pypy/rpython/rpbc.py Tue Jul 12 21:47:34 2005
@@ -459,37 +459,49 @@
assert None not in s_pbc.prebuiltinstances, "XXX not implemented"
if s_pbc.is_constant():
self.lowleveltype = Void
- self.class_repr = None
else:
self.lowleveltype = rclass.TYPEPTR
- access_sets = rtyper.annotator.getpbcaccesssets()
- classes = s_pbc.prebuiltinstances.keys()
+ self._access_set = None
+ self._class_repr = None
+
+ def get_access_set(self):
+ if self._access_set is None:
+ access_sets = self.rtyper.annotator.getpbcaccesssets()
+ classes = self.s_pbc.prebuiltinstances.keys()
_, _, access = access_sets.find(classes[0])
for obj in classes[1:]:
_, _, access1 = access_sets.find(obj)
assert access1 is access # XXX not implemented
commonbase = access.commonbase
- self.class_repr = rclass.getclassrepr(rtyper, commonbase)
- self.access_set = access
+ self._class_repr = rclass.getclassrepr(self.rtyper, commonbase)
+ self._access_set = access
+ return self._access_set
+
+ def get_class_repr(self):
+ self.get_access_set()
+ return self._class_repr
def convert_const(self, cls):
if cls not in self.s_pbc.prebuiltinstances:
raise TyperError("%r not in %r" % (cls, self))
if self.lowleveltype == Void:
return cls
- return self.class_repr.convert_const(cls)
+ return rclass.get_type_repr(self.rtyper).convert_const(cls)
def rtype_simple_call(self, hop):
- if self.class_repr is not None:
+ if self.lowleveltype != Void:
+ # instantiating a class from multiple possible classes
vcls = hop.inputarg(self, arg=0)
- vnewfn = self.class_repr.getpbcfield(vcls, self.access_set,
- '__new__', hop.llops)
+ access_set = self.get_access_set()
+ vnewfn = self.get_class_repr().getpbcfield(vcls, access_set,
+ '__new__', hop.llops)
hop2 = hop.copy()
hop2.r_s_popfirstarg() # discard the class pointer argument
- hop2.v_s_insertfirstarg(vnewfn, self.access_set.attrs['__new__'])
+ hop2.v_s_insertfirstarg(vnewfn, access_set.attrs['__new__'])
# now hop2 looks like simple_call(klass__new__, args...)
return hop2.dispatch()
+ # instantiating a single class
klass = self.s_pbc.const
v_instance = rclass.rtype_new_instance(hop.rtyper, klass, hop.llops)
try:
@@ -520,7 +532,15 @@
return self.getfield(vcls, attr, hop.llops)
def getfield(self, vcls, attr, llops):
- return self.class_repr.getpbcfield(vcls, self.access_set, attr, llops)
+ access_set = self.get_access_set()
+ class_repr = self.get_class_repr()
+ return class_repr.getpbcfield(vcls, access_set, attr, llops)
+
+class __extend__(pairtype(ClassesPBCRepr, rclass.ClassRepr)):
+ def convert_from_to((r_clspbc, r_cls), v, llops):
+ if r_cls.lowleveltype != r_clspbc.lowleveltype:
+ return NotImplemented # good enough for now
+ return v
# ____________________________________________________________
Modified: pypy/dist/pypy/rpython/rspecialcase.py
==============================================================================
--- pypy/dist/pypy/rpython/rspecialcase.py (original)
+++ pypy/dist/pypy/rpython/rspecialcase.py Tue Jul 12 21:47:34 2005
@@ -2,6 +2,7 @@
from pypy.annotation import model as annmodel
from pypy.objspace.flow.model import Constant
from pypy.rpython import rclass
+from pypy.rpython.rmodel import TyperError
def rtype_call_specialcase(hop):
@@ -22,11 +23,4 @@
return rtype_override_fn(hop2)
-def rtype_override_instantiate(hop):
- s_class = hop.args_s[0]
- assert isinstance(s_class, annmodel.SomePBC)
- if len(s_class.prebuiltinstances) != 1:
- raise TyperError("instantiate() on a variable class")
-
- klass = s_class.const
- return rclass.rtype_new_instance(hop.rtyper, klass, hop.llops)
+# def rtype_override_XXX to be added later
Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rbuiltin.py (original)
+++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Tue Jul 12 21:47:34 2005
@@ -1,5 +1,6 @@
from pypy.rpython.test.test_llinterp import interpret
from pypy.rpython.test import test_llinterp
+from pypy.rpython.objectmodel import instantiate
from pypy.objspace.flow import model as flowmodel
from pypy.tool import udir
@@ -132,4 +133,27 @@
c = None
return g(c)
assert not interpret(fn, [True])
-
+
+def test_instantiate():
+ class A:
+ pass
+ def f():
+ return instantiate(A)
+ res = interpret(f, [])
+ assert res.super.typeptr.name[0] == 'A'
+
+def test_instantiate_multiple():
+ class A:
+ pass
+ class B(A):
+ pass
+ def f(i):
+ if i == 1:
+ cls = A
+ else:
+ cls = B
+ return instantiate(cls)
+ res = interpret(f, [1])
+ assert res.super.typeptr.name[0] == 'A'
+ res = interpret(f, [2])
+ assert res.super.typeptr.name[0] == 'B'
Modified: pypy/dist/pypy/rpython/test/test_rspecialcase.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rspecialcase.py (original)
+++ pypy/dist/pypy/rpython/test/test_rspecialcase.py Tue Jul 12 21:47:34 2005
@@ -2,13 +2,6 @@
from pypy.rpython.test.test_llinterp import interpret
from pypy.translator.ann_override import PyPyAnnotatorPolicy
-from pypy.interpreter.typedef import instantiate
-def test_instantiate():
- class A:
- pass
- def f():
- return instantiate(A)
- res = interpret(f, [], policy=PyPyAnnotatorPolicy())
- assert res.super.typeptr.name[0] == 'A'
+# nothing to test here at the moment
More information about the Pypy-commit
mailing list