[pypy-svn] r12224 - in pypy/dist/pypy: annotation rpython rpython/test translator translator/genc translator/tool
arigo at codespeak.net
arigo at codespeak.net
Thu May 12 19:41:41 CEST 2005
Author: arigo
Date: Thu May 12 19:41:40 2005
New Revision: 12224
Added:
pypy/dist/pypy/rpython/rlist.py (contents, props changed)
pypy/dist/pypy/rpython/test/test_rlist.py (contents, props changed)
pypy/dist/pypy/rpython/test/test_typer.py (contents, props changed)
pypy/dist/pypy/rpython/typer.py (contents, props changed)
Modified:
pypy/dist/pypy/annotation/model.py
pypy/dist/pypy/rpython/lltypes.py
pypy/dist/pypy/translator/genc/basetype.py
pypy/dist/pypy/translator/tool/graphpage.py
pypy/dist/pypy/translator/typer.py
Log:
Started to write a Typer for the low-level types. The goal is to get rid of
the CTyper, but we can still use the abstract base Typer.
- new low-level types: PyObject (as an opaque container, not a pointer)
and ForwardReference, used temporarily while building recursive data
structures.
- started the implementation of the RPython list.
- minor changes in translator/ to accomodate our new stuff.
Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py (original)
+++ pypy/dist/pypy/annotation/model.py Thu May 12 19:41:40 2005
@@ -283,14 +283,18 @@
(SomeChar(), lltypes.Char),
]
-def annotation_to_lltype(s_val):
+def annotation_to_lltype(s_val, info=None):
if isinstance(s_val, SomePtr):
return s_val.ll_ptrtype
for witness, lltype in annotation_to_ll_map:
if witness.contains(s_val):
return lltype
- raise AssertionError("trying find a matching low-level type for unexpected"
- "%r" % s_val)
+ if info is None:
+ info = ''
+ else:
+ info = '%s: ' % info
+ raise ValueError("%sshould return a low-level type,\ngot instead %r" % (
+ info, s_val))
ll_to_annotation_map = dict([(ll, ann) for ann,ll in annotation_to_ll_map])
Modified: pypy/dist/pypy/rpython/lltypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypes.py (original)
+++ pypy/dist/pypy/rpython/lltypes.py Thu May 12 19:41:40 2005
@@ -132,7 +132,17 @@
def ex(*args):
return self.RESULT._example()
return _func(self, _callable=ex)
-
+
+class PyObjectType(ContainerType):
+ def __str__(self):
+ return "PyObject"
+PyObject = PyObjectType()
+
+class ForwardReference(ContainerType):
+ def become(self, realcontainertype):
+ self.__class__ = realcontainertype.__class__
+ self.__dict__ = realcontainertype.__dict__
+
class Primitive(LowLevelType):
def __init__(self, name, default):
Added: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rlist.py Thu May 12 19:41:40 2005
@@ -0,0 +1,68 @@
+import py
+from pypy.annotation.model import *
+from pypy.rpython.lltypes import *
+
+
+def substitute_newlist(typer, op):
+ s_result = typer.annotator.binding(op.result)
+ LIST = getlisttype(typer, s_result)
+ T = getlistitemtype(typer, s_result)
+ n = len(op.args)
+ inputsignature = (T,) * n
+ try:
+ newlist = typer.newlistcache[LIST, n]
+ except KeyError:
+ # Make an implementation of newlist(x1,..,xn) which allocates
+ # a list with n elements and initialize them.
+
+ args = ', '.join(['arg%d' % i for i in range(n)])
+ lines = []
+ lines.append( 'def newlist(%s):' % args)
+ lines.append( ' l = malloc(List_typ)')
+ lines.append( ' l.items = malloc(List_typ.items.TO, %d)' % n)
+ for i in range(n):
+ lines.append(' l.items[%d].item = arg%d' % (i, i))
+ lines.append( ' return l')
+ lines.append( '')
+ miniglobal = {'List_typ': LIST.TO, 'malloc': malloc}
+ exec py.code.Source('\n'.join(lines)).compile() in miniglobal
+ newlist = typer.newlistcache[LIST, n] = miniglobal['newlist']
+ return typer.substitute_op(op, (newlist,) + inputsignature + (LIST,))
+
+def getlisttype(typer, s_list):
+ assert isinstance(s_list, SomeList)
+ listdef = s_list.listdef
+ try:
+ return typer.listtypecache[listdef]
+ except KeyError:
+ List_typ = ForwardReference()
+ result = typer.listtypecache[listdef] = GcPtr(List_typ)
+ define_list(typer, s_list, List_typ)
+ return result
+
+def getlistitemtype(typer, s_list):
+ return typer.annotation2concretetype(s_list.listdef.listitem.s_value)
+
+
+def define_list(typer, s_list, List_typ):
+ T = getlistitemtype(typer, s_list)
+ List_typ.become(Struct("list",
+ ("items", GcPtr(Array(('item',T))))))
+
+ def getitem(l, i):
+ return l.items[i].item
+
+ typer['getitem', s_list, SomeInteger()] = (
+ getitem, GcPtr(List_typ), Signed, T)
+
+## def append(l, newitem):
+## length = len(l.items)
+## newitems = malloc(List_typ.items.TO, length+1)
+## i = 0
+## while i<length:
+## newitems[i].item = l.items[i].item
+## i += 1
+## newitems[length].item = newitem
+## l.items = newitems
+
+## Registry['getattr', ...
Added: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/test/test_rlist.py Thu May 12 19:41:40 2005
@@ -0,0 +1,16 @@
+from pypy.translator.translator import Translator
+from pypy.rpython.lltypes import *
+from pypy.rpython.typer import RPythonTyper
+
+
+def test_simple():
+ def dummyfn():
+ l = [10,20,30]
+ return l[2]
+
+ t = Translator(dummyfn)
+ t.annotate([])
+ typer = RPythonTyper(t.annotator)
+ typer.specialize()
+ #t.view()
+ assert "did not crash"
Added: pypy/dist/pypy/rpython/test/test_typer.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/test/test_typer.py Thu May 12 19:41:40 2005
@@ -0,0 +1,15 @@
+from pypy.translator.translator import Translator
+from pypy.rpython.lltypes import *
+from pypy.rpython.typer import RPythonTyper
+
+
+def test_simple():
+ def dummyfn(x):
+ return x+1
+
+ t = Translator(dummyfn)
+ t.annotate([int])
+ typer = RPythonTyper(t.annotator)
+ typer.specialize()
+ #t.view()
+ assert "did not crash"
Added: pypy/dist/pypy/rpython/typer.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/typer.py Thu May 12 19:41:40 2005
@@ -0,0 +1,184 @@
+import types
+from pypy.rpython.lltypes import *
+from pypy.annotation.model import *
+from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
+from pypy.translator.typer import Specializer, flatten_ops, TyperError
+from pypy.rpython.rlist import substitute_newlist, getlisttype
+
+
+PyObjPtr = GcPtr(PyObject)
+
+
+class RPythonTyper(Specializer):
+
+ def __init__(self, annotator):
+ # initialization
+ Specializer.__init__(self, annotator, defaultconcretetype=PyObjPtr,
+ typematches = [], specializationtable = [],
+ )
+ self.registry = {}
+ SINT = SomeInteger()
+ self['add', SINT, SINT] = 'int_add', Signed, Signed, Signed
+ #self['add', UINT, UINT] = 'int_add', Unsigned, Unsigned, Unsigned
+
+ s_malloc = annotator.bookkeeper.immutablevalue(malloc)
+ self['simple_call', s_malloc, ...] = substitute_malloc
+
+ # ____________________ lists ____________________
+ self.listtypecache = {}
+ self.newlistcache = {}
+ self['newlist', ...] = substitute_newlist
+
+ # ____________________ conversions ____________________
+ self.concreteconversions = {
+ (Signed, PyObjPtr): ('int2obj', Signed, PyObjPtr),
+ (PyObjPtr, Signed): ('obj2int', PyObjPtr, Signed),
+ }
+
+ def __setitem__(self, pattern, substitution):
+ patternlist = self.registry.setdefault(pattern[0], [])
+ patternlist.append((pattern[1:], substitution))
+
+ def annotation2concretetype(self, s_value):
+ try:
+ return annotation_to_lltype(s_value)
+ except ValueError:
+ if isinstance(s_value, SomeList):
+ return getlisttype(self, s_value)
+ return PyObjPtr
+
+ def convertvar(self, v, concretetype):
+ """Get the operation(s) needed to convert 'v' to the given type."""
+ ops = []
+ v_concretetype = getattr(v, 'concretetype', PyObjPtr)
+ if isinstance(v, Constant):
+ # we should never modify a Constant in-place
+ v = Constant(v.value)
+ v.concretetype = concretetype
+
+ elif v_concretetype != concretetype:
+ try:
+ subst = self.concreteconversions[v_concretetype, concretetype]
+ except KeyError:
+ raise TyperError("cannot convert from %r\n"
+ "to %r" % (v_concretetype, concretetype))
+ vresult = Variable()
+ op = SpaceOperation('?', [v], vresult)
+ flatten_ops(self.substitute_op(op, subst), ops)
+ v = vresult
+
+ return v, ops
+
+ def specialized_op(self, op, bindings):
+ assert len(op.args) == len(bindings)
+
+ # first check for direct low-level operations on pointers
+ if op.args and isinstance(bindings[0], SomePtr):
+ PTR = bindings[0].ll_ptrtype
+
+ if op.opname == 'getitem':
+ s_result = self.annotator.binding(op.result)
+ T = annotation_to_lltype(s_result, 'getitem')
+ return self.typed_op(op, [PTR, Signed], T,
+ newopname='getarrayitem')
+
+ if op.opname == 'len':
+ return self.typed_op(op, [PTR], Signed,
+ newopname='getarraysize')
+
+ if op.opname == 'getattr':
+ assert isinstance(op.args[1], Constant)
+ s_result = self.annotator.binding(op.result)
+ FIELD_TYPE = PTR.TO._flds[op.args[1].value]
+ T = annotation_to_lltype(s_result, 'getattr')
+ if isinstance(FIELD_TYPE, ContainerType):
+ newopname = 'getsubstruct'
+ else:
+ newopname = 'getfield'
+ return self.typed_op(op, [PTR, Void], T, newopname=newopname)
+
+ if op.opname == 'setattr':
+ assert isinstance(op.args[1], Constant)
+ FIELD_TYPE = PTR.TO._flds[op.args[1].value]
+ assert not isinstance(FIELD_TYPE, ContainerType)
+ return self.typed_op(op, [PTR, Void, FIELD_TYPE], Void,
+ newopname='setfield')
+
+ if op.opname == 'eq':
+ return self.typed_op(op, [PTR, PTR], Bool,
+ newopname='ptr_eq')
+ if op.opname == 'ne':
+ return self.typed_op(op, [PTR, PTR], Bool,
+ newopname='ptr_ne')
+
+ # generic specialization based on the registration table
+ patternlist = self.registry.get(op.opname, [])
+ for pattern, substitution in patternlist:
+ if pattern and pattern[-1] is Ellipsis:
+ pattern = pattern[:-1]
+ if len(pattern) > len(op.args):
+ continue
+ elif len(pattern) != len(op.args):
+ continue
+ for s_match, s_value in zip(pattern, bindings):
+ if not s_match.contains(s_value):
+ break
+ else:
+ # match!
+ return self.substitute_op(op, substitution)
+ # specialization not found
+ argtypes = [self.defaultconcretetype] * len(op.args)
+ return self.typed_op(op, argtypes, self.defaultconcretetype)
+
+ def substitute_op(self, op, substitution):
+ if isinstance(substitution, tuple):
+ newopname = substitution[0]
+ argtypes = substitution[1:-1]
+ resulttype = substitution[-1]
+ assert len(argtypes) == len(op.args)
+ # None in the substitution list means "remove this argument"
+ while None in argtypes:
+ argtypes = list(argtypes)
+ i = argtypes.index(None)
+ del argtypes[i]
+ args = list(op.args)
+ del args[i]
+ op = SpaceOperation(op.opname, args, op.result)
+ return self.typed_op(op, argtypes, resulttype,
+ newopname = newopname)
+ else:
+ assert callable(substitution), "type error in the registry tables"
+ return substitution(self, op)
+
+ def typed_op(self, op, argtypes, restype, newopname=None):
+ if isinstance(newopname, types.FunctionType):
+ python_function = newopname
+ newargs = [Constant(python_function)] + op.args
+ op = SpaceOperation('simple_call', newargs, op.result)
+ try:
+ functyp = python_function.TYPE
+ except AttributeError:
+ s_returnvalue = self.annotator.build_types(python_function,
+ argtypes)
+ inferred_type = annotation_to_lltype(s_returnvalue,
+ info=python_function)
+ if inferred_type != restype:
+ raise TyperError("%r return type mismatch:\n"
+ "declared %r\n"
+ "inferred %r" % (python_function,
+ inferred_type, restype))
+ functyp = NonGcPtr(FuncType(argtypes, restype))
+ python_function.TYPE = functyp
+ argtypes = [functyp] + list(argtypes)
+ newopname = None
+ return Specializer.typed_op(self, op, argtypes, restype, newopname)
+
+
+def substitute_malloc(typer, op):
+ s_result = typer.annotator.binding(op.result)
+ T = annotation_to_lltype(s_result, 'malloc')
+ if len(op.args) == 2:
+ substitution = 'malloc', None, Void, T
+ else:
+ substitution = 'malloc_varsize', None, Void, Signed, T
+ return typer.substitute_op(op, substitution)
Modified: pypy/dist/pypy/translator/genc/basetype.py
==============================================================================
--- pypy/dist/pypy/translator/genc/basetype.py (original)
+++ pypy/dist/pypy/translator/genc/basetype.py Thu May 12 19:41:40 2005
@@ -10,6 +10,9 @@
def debugname(self):
return self.typename
+ def __str__(self):
+ return self.debugname()
+
def genc():
"""A hack to get at the currently running GenC instance."""
from pypy.translator.genc.genc import TLS
Modified: pypy/dist/pypy/translator/tool/graphpage.py
==============================================================================
--- pypy/dist/pypy/translator/tool/graphpage.py (original)
+++ pypy/dist/pypy/translator/tool/graphpage.py Thu May 12 19:41:40 2005
@@ -128,9 +128,8 @@
if isinstance(node, Block):
for var in node.getvariables():
if hasattr(var, 'concretetype'):
- typename = var.concretetype.debugname()
info = self.links.get(var.name, var.name)
- info = '(%s) %s' % (typename, info)
+ info = '(%s) %s' % (var.concretetype, info)
self.links[var.name] = info
for graph in graphs:
traverse(visit, graph)
Modified: pypy/dist/pypy/translator/typer.py
==============================================================================
--- pypy/dist/pypy/translator/typer.py (original)
+++ pypy/dist/pypy/translator/typer.py Thu May 12 19:41:40 2005
@@ -29,9 +29,18 @@
self.specializationdict = d
def specialize(self):
- for block in self.annotator.annotated:
- if block.operations != ():
- self.specialize_block(block)
+ """Main entry point: specialize all annotated blocks of the program."""
+ # new blocks can be created as a result of specialize_block(), so
+ # we need to be careful about the loop here.
+ already_seen = {}
+ pending = self.annotator.annotated.keys()
+ while pending:
+ for block in pending:
+ if block.operations != ():
+ self.specialize_block(block)
+ already_seen[block] = True
+ pending = [block for block in self.annotator.annotated
+ if block not in already_seen]
def settype(self, a, concretetype):
"""Set the concretetype of a Variable."""
More information about the Pypy-commit
mailing list