From arigo at codespeak.net Wed Jun 1 00:08:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 00:08:37 +0200 (CEST) Subject: [pypy-svn] r12961 - in pypy/dist/pypy/rpython: . test Message-ID: <20050531220837.2772127BF2@code1.codespeak.net> Author: arigo Date: Wed Jun 1 00:08:36 2005 New Revision: 12961 Added: pypy/dist/pypy/rpython/rclass.py (contents, props changed) pypy/dist/pypy/rpython/test/test_rclass.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_lltype.py Log: Starting the object model implementation. For now, we have classes and instances with no attribute at all. Added: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 1 00:08:36 2005 @@ -0,0 +1,120 @@ +from pypy.annotation.pairtype import pair, pairtype +from pypy.annotation.model import SomePBC, SomeInstance +from pypy.rpython.lltype import * +from pypy.rpython.rtyper import inputconst + + +# +# There is one "vtable" per user class, with the following structure: +# A root class "object" has: +# +# struct object_vtable { +# struct object_vtable* parenttypeptr; +# } +# +# Every other class X, with parent Y, has the structure: +# +# struct vtable_X { +# struct vtable_Y super; // inlined +# ... // extra class attributes +# } + +# The type of the instances is: +# +# struct object { // for the root class +# struct object_vtable* typeptr; +# } +# +# struct X { +# struct Y super; // inlined +# ... // extra instance attributes +# } +# + +OBJECT_VTABLE = ForwardReference() +TYPEPTR = NonGcPtr(OBJECT_VTABLE) +OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR))) + +OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) + + +class RClassDef: + + def __init__(self, classdef): + self.classdef = classdef + if classdef.basedef is None: + self.depth = 1 + parent_vtable_type = OBJECT_VTABLE + parent_typeptr = nullptr(OBJECT_VTABLE) + parent_object_type = OBJECT + else: + rbasedef = getrclassdef(classdef.basedef) + self.depth = rbasedef.depth + 1 + parent_vtable_type = rbasedef.vtable_type + parent_typeptr = rbasedef.typeptr + parent_object_type = rbasedef.object_type + self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, + ('super', parent_vtable_type), + # XXX class attributes + ) + self.vtable = malloc(self.vtable_type, immortal=True) + # cast the vtable pointer from "vtable_type" to "parent_vtable_type" + # to "parent_parent_vtable_type" to .... to OBJECT_VTABLE + p = self.vtable + for i in range(self.depth): + p = p.super + self.typeptr = cast_flags(TYPEPTR, p) + p.parenttypeptr = parent_typeptr + # + self.parent_object_type = parent_object_type + self.object_type = GcStruct(classdef.cls.__name__, + ('super', parent_object_type), + # XXX instance attributes + ) + + def parent_cast(self, targetclassdef, v, llops): + classdef = self.classdef + super_name = inputconst(Void, "super") + while classdef is not targetclassdef: + rclassdef = getrclassdef(classdef) + parent_object_type = rclassdef.parent_object_type + v = llops.genop('getsubstruct', [v, super_name], + resulttype = GcPtr(parent_object_type)) + classdef = classdef.basedef + return v + + def rtype_new_instance(self, llops): + ctype = inputconst(Void, self.object_type) + vptr = llops.genop('malloc', [ctype], + resulttype = GcPtr(self.object_type)) + vptr_as_object = self.parent_cast(None, vptr, llops) + typeptr_name = inputconst(Void, "typeptr") + ctypeptr = inputconst(TYPEPTR, self.typeptr) + llops.genop('setfield', [vptr_as_object, typeptr_name, ctypeptr]) + # XXX call __init__ somewhere + return vptr + + +def getrclassdef(classdef): + try: + return classdef._rtype_rclassdef_ + except AttributeError: + classdef._rtype_rclassdef_ = result = RClassDef(classdef) + return result + + +def rtype_new_instance(s_cls, hop): + assert s_cls.is_constant() + cls = s_cls.const + classdef = hop.rtyper.annotator.getuserclasses()[cls] + rclassdef = getrclassdef(classdef) + return rclassdef.rtype_new_instance(hop.llops) + + +# ____________________________________________________________ + +class __extend__(SomeInstance): + + def lowleveltype(s_ins): + rclassdef = getrclassdef(s_ins.classdef) + return GcPtr(rclassdef.object_type) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jun 1 00:08:36 2005 @@ -2,6 +2,7 @@ from pypy.annotation.pairtype import pair, pairtype from pypy.annotation.model import SomePBC from pypy.rpython.lltype import typeOf +from pypy.rpython import rclass class __extend__(SomePBC): @@ -18,12 +19,13 @@ if not s_func.is_constant(): NotImplementedYet func = s_func.const - if not isinstance(func, types.FunctionType): - NotImplementedYet - # XXX hackish - f = hop.rtyper.getfunctionptr(func) - FUNCPTR = typeOf(f) - args_v = hop.inputargs(*FUNCPTR.TO.ARGS) - c = hop.inputconst(FUNCPTR, f) - return hop.genop('direct_call', [c] + args_v, - resulttype = FUNCPTR.TO.RESULT) + if isinstance(func, types.FunctionType): + # XXX hackish + f = hop.rtyper.getfunctionptr(func) + FUNCPTR = typeOf(f) + args_v = hop.inputargs(*FUNCPTR.TO.ARGS) + c = hop.inputconst(FUNCPTR, f) + return hop.genop('direct_call', [c] + args_v, + resulttype = FUNCPTR.TO.RESULT) + elif isinstance(func, (types.ClassType, type)): + return rclass.rtype_new_instance(s_func, hop) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 1 00:08:36 2005 @@ -26,6 +26,7 @@ def __init__(self, annotator): self.annotator = annotator self.specialized_ll_functions = {} + self.rclassdefs = {} self.typererror = None def specialize(self): Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Wed Jun 1 00:08:36 2005 @@ -112,11 +112,15 @@ py.test.raises(TypeError, "Struct('invalid', ('x', S1))") def test_substructure_ptr(): - S2 = Struct("s2", ('a', Signed)) + S3 = Struct("s3", ('a', Signed)) + S2 = Struct("s2", ('s3', S3)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1) assert typeOf(p1.sub1) == _TmpPtr(S2) assert typeOf(p1.sub2) == _TmpPtr(S2) + assert typeOf(p1.sub1.s3) == _TmpPtr(S3) + p2 = cast_flags(NonGcPtr(S2), p1.sub1) + assert typeOf(p2.s3) == _TmpPtr(S3) def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) Added: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rclass.py Wed Jun 1 00:08:36 2005 @@ -0,0 +1,21 @@ +from pypy.translator.translator import Translator +from pypy.rpython.lltype import * +from pypy.rpython.rtyper import RPythonTyper + + + +class EmptyBase(object): + pass + + +def test_simple(): + def dummyfn(): + x = EmptyBase() + return x + + t = Translator(dummyfn) + t.annotate([]) + typer = RPythonTyper(t.annotator) + typer.specialize() + t.view() + t.checkgraphs() From arigo at codespeak.net Wed Jun 1 13:23:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 13:23:09 +0200 (CEST) Subject: [pypy-svn] r12964 - in pypy/dist/pypy: objspace/flow translator translator/tool Message-ID: <20050601112309.4BB5627B5E@code1.codespeak.net> Author: arigo Date: Wed Jun 1 13:23:09 2005 New Revision: 12964 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/simplify.py pypy/dist/pypy/translator/tool/graphpage.py pypy/dist/pypy/translator/transform.py Log: Made the flow model more precise about the extra vars attached to Links (last_exception and last_exc_value): they are considered as "created by the Link", so they should be globally unique. Fixed simplify_exception() to preserve the uniqueness. Completed the annotation of these vars in the except link in the annotator. Teached the graph viewer about these extra vars. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Wed Jun 1 13:23:09 2005 @@ -90,6 +90,15 @@ self.last_exception = last_exception self.last_exc_value = last_exc_value + def getextravars(self): + "Return the extra vars created by this Link." + result = [] + if isinstance(self.last_exception, Variable): + result.append(self.last_exception) + if isinstance(self.last_exc_value, Variable): + result.append(self.last_exc_value) + return result + def copy(self, rename=lambda x: x): newargs = [rename(a) for a in self.args] newlink = Link(newargs, self.target, self.exitcase) @@ -354,21 +363,32 @@ if not block.exits: assert block in exitblocks vars = {} - resultvars = [op.result for op in block.operations] - for v in block.inputargs + resultvars: + + def definevar(v, only_in_link=None): assert isinstance(v, Variable) assert v not in vars, "duplicate variable %r" % (v,) assert v not in vars_previous_blocks, ( "variable %r used in more than one block" % (v,)) - vars[v] = True + vars[v] = only_in_link + + def usevar(v, in_link=None): + assert v in vars + if in_link is not None: + assert vars[v] is None or vars[v] is in_link + + for v in block.inputargs: + definevar(v) + for op in block.operations: for v in op.args: assert isinstance(v, (Constant, Variable)) if isinstance(v, Variable): - assert v in vars + usevar(v) else: assert v.value is not last_exception #assert v.value != last_exc_value + definevar(op.result) + exc_links = {} if block.exitswitch is None: assert len(block.exits) <= 1 @@ -384,26 +404,29 @@ else: assert isinstance(block.exitswitch, Variable) assert block.exitswitch in vars + for link in block.exits: assert len(link.args) == len(link.target.inputargs) assert link.prevblock is block exc_link = link in exc_links if exc_link: - assert link.last_exception is not None - assert link.last_exc_value is not None + for v in [link.last_exception, link.last_exc_value]: + assert isinstance(v, (Variable, Constant)) + if isinstance(v, Variable): + definevar(v, only_in_link=link) else: assert link.last_exception is None assert link.last_exc_value is None for v in link.args: assert isinstance(v, (Constant, Variable)) if isinstance(v, Variable): - assert v in vars or (exc_link and v in (link.last_exception, link.last_exc_value)) + usevar(v, in_link=link) if exc_link: assert v != block.operations[-1].result - else: - if not exc_link: - assert v.value is not last_exception - #assert v.value != last_exc_value + #else: + # if not exc_link: + # assert v.value is not last_exception + # #assert v.value != last_exc_value vars_previous_blocks.update(vars) try: Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Wed Jun 1 13:23:09 2005 @@ -436,6 +436,16 @@ if isinstance(link.exitcase, (types.ClassType, type)) \ and issubclass(link.exitcase, Exception): assert last_exception_var and last_exc_value_var + last_exc_value_object = self.bookkeeper.valueoftype(link.exitcase) + last_exception_object = annmodel.SomeObject() + last_exception_object.knowntype = type + if isinstance(last_exception_var, Constant): + last_exception_object.const = last_exception_var.value + last_exception_object.is_type_of = [last_exc_value_var] + + self.setbinding(last_exception_var, last_exception_object) + self.setbinding(last_exc_value_var, last_exc_value_object) + last_exception_object = annmodel.SomeObject() last_exception_object.knowntype = type if isinstance(last_exception_var, Constant): @@ -443,12 +453,8 @@ #if link.exitcase is Exception: # last_exc_value_object = annmodel.SomeObject() #else: - last_exc_value_object = self.bookkeeper.valueoftype(link.exitcase) last_exc_value_vars = [] in_except_block = True - # not needed! - #self.setbinding(last_exception_var, last_exception_object) - #self.setbinding(last_exc_value_var, last_exc_value_object) cells = [] renaming = {} Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Wed Jun 1 13:23:09 2005 @@ -209,6 +209,13 @@ if case is not None: link.last_exception = last_exception link.last_exc_value = last_exc_value + # make the above two variables unique + renaming2 = {} + def rename2(v): + return renaming2.get(v, v) + for v in link.getextravars(): + renaming2[v] = Variable(v) + link = link.copy(rename2) link.exitcase = case link.prevblock = block exits.append(link) Modified: pypy/dist/pypy/translator/tool/graphpage.py ============================================================================== --- pypy/dist/pypy/translator/tool/graphpage.py (original) +++ pypy/dist/pypy/translator/tool/graphpage.py Wed Jun 1 13:23:09 2005 @@ -1,5 +1,5 @@ import inspect, types -from pypy.objspace.flow.model import traverse, Block +from pypy.objspace.flow.model import traverse, Block, Link from pypy.translator.tool.make_dot import DotGen, make_dot, make_dot_graphs from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS from pypy.annotation import model @@ -126,11 +126,16 @@ def visit(node): if isinstance(node, Block): - for var in node.getvariables(): - if hasattr(var, 'concretetype'): - info = self.links.get(var.name, var.name) - info = '(%s) %s' % (var.concretetype, info) - self.links[var.name] = info + vars = node.getvariables() + elif isinstance(node, Link): + vars = node.getextravars() + else: + return + for var in vars: + if hasattr(var, 'concretetype'): + info = self.links.get(var.name, var.name) + info = '(%s) %s' % (var.concretetype, info) + self.links[var.name] = info for graph in graphs: traverse(visit, graph) Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Wed Jun 1 13:23:09 2005 @@ -274,6 +274,12 @@ if len(block.exits) == 1: block.exitswitch = None block.exits[0].exitcase = None + # make sure that the return variables of all graphs is annotated + if self.translator is not None: + for graph in self.translator.flowgraphs.values(): + v = graph.getreturnvar() + if v not in self.bindings: + self.setbinding(v, annmodel.SomeImpossibleValue()) def cutoff_alwaysraising_block(self, block): "Fix a block whose end can never be reached at run-time." @@ -303,8 +309,14 @@ c2 = Constant(AssertionError(msg)) errlink = Link([c1, c2], graph.exceptblock) block.recloseblock(errlink, *block.exits) - # XXX do something about the annotation of the - # exceptblock.inputargs + # fix the annotation of the exceptblock.inputargs + etype, evalue = graph.exceptblock.inputargs + s_type = annmodel.SomeObject() + s_type.knowntype = type + s_type.is_type_of = [evalue] + s_value = annmodel.SomeInstance(self.bookkeeper.getclassdef(Exception)) + self.setbinding(etype, s_type) + self.setbinding(evalue, s_value) def transform_graph(ann): From arigo at codespeak.net Wed Jun 1 13:29:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 13:29:08 +0200 (CEST) Subject: [pypy-svn] r12965 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050601112908.82C6B27B75@code1.codespeak.net> Author: arigo Date: Wed Jun 1 13:29:08 2005 New Revision: 12965 Added: pypy/dist/pypy/rpython/test/test_exception.py (contents, props changed) Modified: pypy/dist/pypy/annotation/model.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Support for the 'type' operation in the rtyper. Small changes and bug fixes triggered by it. Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Wed Jun 1 13:29:08 2005 @@ -324,12 +324,12 @@ from pypy.rpython import lltype annotation_to_ll_map = [ + (SomePBC({None: True}), lltype.Void), # also matches SomeImpossibleValue() (SomeBool(), lltype.Bool), (SomeInteger(), lltype.Signed), (SomeInteger(nonneg=True, unsigned=True), lltype.Unsigned), (SomeFloat(), lltype.Float), (SomeChar(), lltype.Char), - (SomePBC({None: True}), lltype.Void), ] def annotation_to_lltype(s_val, info=None): Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 1 13:29:08 2005 @@ -118,3 +118,11 @@ def lowleveltype(s_ins): rclassdef = getrclassdef(s_ins.classdef) return GcPtr(rclassdef.object_type) + + def rtype_type(s_ins, hop): + rclassdef = getrclassdef(s_ins.classdef) + vptr, = hop.inputargs(s_ins) + vptr_as_object = rclassdef.parent_cast(None, vptr, hop.llops) + typeptr_name = inputconst(Void, "typeptr") + return hop.genop('getfield', [vptr_as_object, typeptr_name], + resulttype=TYPEPTR) Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Wed Jun 1 13:29:08 2005 @@ -3,6 +3,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltype import PyObject, GcPtr, Void, Bool from pypy.rpython.rtyper import TyperError, inputconst +from pypy.rpython import rclass PyObjPtr = GcPtr(PyObject) @@ -27,6 +28,8 @@ except ValueError: if s_obj.is_constant(): return Void + elif s_obj.knowntype is type: + return rclass.TYPEPTR else: return PyObjPtr @@ -60,7 +63,7 @@ def rtype_convert_from_to((s_from, s_to), v, llops): FROM = s_from.lowleveltype() TO = s_to.lowleveltype() - if PyObjPtr == FROM == TO: + if (PyObjPtr == FROM == TO) or (rclass.TYPEPTR == FROM == TO): return v elif FROM == Void and s_from.is_constant() and s_to.contains(s_from): # convert from a constant to a non-constant Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jun 1 13:29:08 2005 @@ -9,9 +9,7 @@ # struct str { # hash: Signed # chars: array { -# item { -# Char ch -# } +# Char ch # } # } Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 1 13:29:08 2005 @@ -87,10 +87,11 @@ # insert the needed conversions on the links can_insert_here = block.exitswitch is None and len(block.exits) == 1 for link in block.exits: + for a in [link.last_exception, link.last_exc_value]: + if isinstance(a, Variable): + self.setconcretetype(a) for i in range(len(link.args)): a1 = link.args[i] - ##if a1 in (link.last_exception, link.last_exc_value):# treated specially in gen_link - ## continue a2 = link.target.inputargs[i] s_a2 = self.annotator.binding(a2) if isinstance(a1, Constant): Added: pypy/dist/pypy/rpython/test/test_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_exception.py Wed Jun 1 13:29:08 2005 @@ -0,0 +1,25 @@ +from pypy.translator.translator import Translator +from pypy.rpython.lltype import * +from pypy.rpython.rtyper import RPythonTyper + + +class MyException(Exception): + pass + + +def test_simple(): + def g(): + raise MyException + def dummyfn(): + try: + return g() + except MyException: + pass + + t = Translator(dummyfn) + a = t.annotate([]) + a.simplify() + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Wed Jun 1 13:29:08 2005 @@ -17,5 +17,5 @@ t.annotate([]) typer = RPythonTyper(t.annotator) typer.specialize() - t.view() + #t.view() t.checkgraphs() From arigo at codespeak.net Wed Jun 1 15:59:10 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 15:59:10 +0200 (CEST) Subject: [pypy-svn] r12968 - pypy/branch/typeinference Message-ID: <20050601135910.F1E4A27B4D@code1.codespeak.net> Author: arigo Date: Wed Jun 1 15:59:10 2005 New Revision: 12968 Removed: pypy/branch/typeinference/ Log: Remove old successful branch. From arigo at codespeak.net Wed Jun 1 16:04:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 16:04:46 +0200 (CEST) Subject: [pypy-svn] r12970 - pypy/branch/translation-snapshot Message-ID: <20050601140446.BEC1D27B55@code1.codespeak.net> Author: arigo Date: Wed Jun 1 16:04:46 2005 New Revision: 12970 Added: pypy/branch/translation-snapshot/ - copied from r12888, pypy/dist/ Log: Creating a snapshot of the PyPy core, to be used as a stable base to try translation on. translate_pypy.py works on the revision this shapshot was created from. This branch is NOT MEANT for development. The translator directories are going to be removed and replaced by svn:external links to their trunk version, so that working on them actually makes the trunk progress. No check-ins really go into the branch, apart from small fixes that might be needed to make translate_pypy happy (usually as merges from the head). From arigo at codespeak.net Wed Jun 1 16:07:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 16:07:31 +0200 (CEST) Subject: [pypy-svn] r12972 - in pypy/branch/translation-snapshot/pypy: annotation bin documentation objspace/flow rpython tool translator Message-ID: <20050601140731.62C4427B57@code1.codespeak.net> Author: arigo Date: Wed Jun 1 16:07:31 2005 New Revision: 12972 Removed: pypy/branch/translation-snapshot/pypy/annotation/ pypy/branch/translation-snapshot/pypy/bin/ pypy/branch/translation-snapshot/pypy/documentation/ pypy/branch/translation-snapshot/pypy/objspace/flow/ pypy/branch/translation-snapshot/pypy/rpython/ pypy/branch/translation-snapshot/pypy/tool/ pypy/branch/translation-snapshot/pypy/translator/ Log: These directories will be replaced by svn:externals. From arigo at codespeak.net Wed Jun 1 16:12:28 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 16:12:28 +0200 (CEST) Subject: [pypy-svn] r12973 - in pypy/branch/translation-snapshot/pypy: . objspace Message-ID: <20050601141228.BF6EE27B4A@code1.codespeak.net> Author: arigo Date: Wed Jun 1 16:12:28 2005 New Revision: 12973 Modified: pypy/branch/translation-snapshot/pypy/ (props changed) pypy/branch/translation-snapshot/pypy/objspace/ (props changed) Log: svn:externals. From arigo at codespeak.net Wed Jun 1 16:27:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 16:27:25 +0200 (CEST) Subject: [pypy-svn] r12974 - in pypy/branch/translation-snapshot/pypy: . objspace Message-ID: <20050601142725.85FD327B4A@code1.codespeak.net> Author: arigo Date: Wed Jun 1 16:27:25 2005 New Revision: 12974 Modified: pypy/branch/translation-snapshot/pypy/ (props changed) pypy/branch/translation-snapshot/pypy/objspace/ (props changed) Log: Removing the svn:externals after all. New approach in mind. From pedronis at codespeak.net Wed Jun 1 16:32:23 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 16:32:23 +0200 (CEST) Subject: [pypy-svn] r12975 - pypy/branch/pypy-translation-snapshot Message-ID: <20050601143223.8506C27B55@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 16:32:23 2005 New Revision: 12975 Added: pypy/branch/pypy-translation-snapshot/ - copied from r12974, pypy/branch/translation-snapshot/pypy/ Log: create snap-shot branch with only pypy/ content. From pedronis at codespeak.net Wed Jun 1 16:32:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 16:32:53 +0200 (CEST) Subject: [pypy-svn] r12976 - pypy/branch/translation-snapshot Message-ID: <20050601143253.6103F27B56@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 16:32:53 2005 New Revision: 12976 Removed: pypy/branch/translation-snapshot/ Log: too much stuff in this one. From tismer at codespeak.net Wed Jun 1 16:35:38 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 1 Jun 2005 16:35:38 +0200 (CEST) Subject: [pypy-svn] r12977 - pypy/dist/pypy/translator/pickle Message-ID: <20050601143538.5CB6527B55@code1.codespeak.net> Author: tismer Date: Wed Jun 1 16:35:38 2005 New Revision: 12977 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: an almost working flowgraph pickler. just missing are - an interface - a couple of __reduce_ex__ methods Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Wed Jun 1 16:35:38 2005 @@ -4,131 +4,495 @@ to restart code generation after flowing and maybe annotation. """ -import autopath, os -from pypy.objspace.flow.model import Constant, Variable, Block, Link -from pypy.objspace.flow.flowcontext import SpamBlock, EggBlock -from pypy.objspace.flow.model import SpaceOperation, FunctionGraph - -from pypy.tool.tls import tlsobject -from pypy.translator.gensupp import uniquemodulename, NameManager - -from pypy.translator.c.pyobj import PyObjMaker - -# XXX the latter import is temporary. -# I think we will refactor again and -# put a slightly more general module -# into ./.. +import autopath, os, sys, new, __builtin__ + +from pypy.translator.gensupp import uniquemodulename, NameManager, UniqueList +from pypy.translator.gensupp import builtin_base +from pypy.rpython.rarithmetic import r_int, r_uint +from pypy.objspace.flow.model import Variable, Constant, SpaceOperation +from pypy.objspace.flow.model import FunctionGraph, Block, Link +from pypy.interpreter.baseobjspace import ObjSpace + +from pickle import whichmodule, PicklingError +import pickle + +from types import * # ____________________________________________________________ -class GenPickle(PyObjMaker): +class GenPickle: def __init__(self, translator): self.translator = translator - PyObjMaker.__init__(self, NameManager(), None) - self.initcode.append("""\ -from pypy.objspace.flow.model import Constant, Variable, Block, Link -from pypy.objspace.flow.model import SpaceOperation, FunctionGraph -from pypy.translator.translator import Translator""") + self.initcode = UniqueList([ + 'import new, types, sys', + ]) + + self.latercode = [] # list of generators generating extra lines + self.debugstack = () # linked list of nested nameof() + self.initcode = UniqueList(self.initcode) + + self.picklenames = {Constant(None): 'None', + Constant(False): 'False', + Constant(True): 'True', + } + self.namespace = NameManager() + self.namespace.make_reserved_names('None False True') - def nameof(self, obj): + def nameof(self, obj, debug=None, namehint=None): + key = Constant(obj) try: - return self.dispatch[type(obj)](self, obj) + return self.picklenames[key] except KeyError: - return self.computenameof(obj) + if debug: + stackentry = debug, obj + else: + stackentry = obj + self.debugstack = (self.debugstack, stackentry) + obj_builtin_base = builtin_base(obj) + if obj_builtin_base in (object, int, long) and type(obj) is not obj_builtin_base: + # assume it's a user defined thingy + name = self.nameof_instance(obj) + else: + for cls in type(obj).__mro__: + meth = getattr(self, + 'nameof_' + cls.__name__.replace(' ', ''), + None) + if meth: + break + else: + raise Exception, "nameof(%r)" % (obj,) + + code = meth.im_func.func_code + if namehint and 'namehint' in code.co_varnames[:code.co_argcount]: + name = meth(obj, namehint=namehint) + else: + name = meth(obj) + self.debugstack, x = self.debugstack + assert x is stackentry + self.picklenames[key] = name + return name + + def uniquename(self, basename): + return self.namespace.uniquename(basename) + + def initcode_python(self, name, pyexpr): + # generate init code that will evaluate the given Python expression + #self.initcode.append("print 'setting up', %r" % name) + self.initcode.append("%s = %s" % (name, pyexpr)) + + def nameof_object(self, value): + if type(value) is not object: + raise Exception, "nameof(%r)" % (value,) + name = self.uniquename('g_object') + self.initcode_python(name, "object()") + return name - def computenameof(self, obj): - # XXX PyObjMaker should probably be less greedy - if type(obj) in self.dispatch: - return self.dispatch[type(obj)](self, obj) - return PyObjMaker.computenameof(self, obj) - - dispatch = {} - - def nameof_Constant(self, obj): - name = self.uniquename("gcon") - value = self.nameof(obj.value) - self.initcode.append("%s = Constant(%s)" % (name, value)) - if hasattr(obj, "concretetype"): - concrete = self.nameof(obj.concretetype) - self.initcode.append("%s.concretetype=%s" % (name, concrete)) - return name - dispatch[Constant] = nameof_Constant - - def nameof_Variable(self, obj): - name = self.uniquename("gvar") - self.initcode.append("%s = Variable(%r)" % (name, obj.name)) - if hasattr(obj, "concretetype"): - concrete = self.nameof(obj.concretetype) - self.initcode.append("%s.concretetype=%s" % (name, concrete)) - return name - dispatch[Variable] = nameof_Variable - - def nameof_Link(self, obj): - name = self.uniquename("glink") - args = self.nameof(obj.args) - target = self.nameof(obj.target) - exitcase = self.nameof(obj.exitcase) - ia = self.initcode.append - ia("%s = Link(%s, %s, %s)" % (args, target, exitcase)) - if obj.last_exception: - ia("%s.last_exception = %s" % self.nameof(obj.last_exception)) - ia("%s.last_exc_value = %s" % self.nameof(obj.last_exc_value)) - return name - dispatch[Link] = nameof_Link - - def nameof_Block(self, obj): - name = self.uniquename("gblock") - inputargs = self.nameof(obj.inputargs) - operations = self.nameof(obj.operations) - exitswitch = self.nameof(obj.exitswitch) - exits = self.nameof(obj.exits) - ia = self.initcode.append - ia("%s = Block(%s)" % (name, inputargs,) ) - ia("%s.operations = %s" % (name, operations) ) - ia("%s.exitswitch = %s" % (name, exitswitch) ) - ia("%s.exits = %s" % (name, exits) ) - if obj.isstartblock: ia("%s.exits = True" % (name, ) ) - if obj.exc_handler: ia("%s.exc_handler = True" % (name, ) ) - return name - dispatch[Block] = dispatch[SpamBlock] = dispatch[EggBlock] = nameof_Block - - def nameof_SpaceOperation(self, obj): - name = self.uniquename("gsop") - opname = self.nameof(intern(obj.opname)) - args = self.nameof(obj.args) - result = self.nameof(obj.result) - ia = self.initcode.append - ia("%s = SpaceOperation(%s, %s, %s)" % (name, opname, args, result) ) - if obj.offset != -1: ia("%s.offset= %d" % (name, obj.offset) ) + def nameof_module(self, value): + assert value is os or not hasattr(value, "__file__") or \ + not (value.__file__.endswith('.pyc') or + value.__file__.endswith('.py') or + value.__file__.endswith('.pyo')), \ + "%r is not a builtin module (probably :)"%value + name = self.uniquename('mod%s'%value.__name__) + self.initcode_python(name, "__import__(%r)" % (value.__name__,)) return name - dispatch[SpaceOperation] = nameof_SpaceOperation + + + def nameof_int(self, value): + return repr(value) - def nameof_FunctionGraph(self,obj): - name = self.uniquename("gfgraph") + # we don't need to name the following const types. + # the compiler folds the consts the same way as we do. + # note that true pickling is more exact, here. + nameof_long = nameof_float = nameof_bool = nameof_NoneType = nameof_int + + def nameof_str(self, value): + name = self.uniquename('gstr_' + value[:32]) + self.initcode_python(name, repr(value)) + return name + + def nameof_unicode(self, value): + name = self.uniquename('guni_' + str(value[:32])) + self.initcode_python(name, repr(value)) + return name + + def skipped_function(self, func): + # debugging only! Generates a placeholder for missing functions + # that raises an exception when called. + if self.translator.frozen: + warning = 'NOT GENERATING' + else: + warning = 'skipped' + printable_name = '(%s:%d) %s' % ( + func.func_globals.get('__name__', '?'), + func.func_code.co_firstlineno, + func.__name__) + print warning, printable_name + name = self.uniquename('gskippedfunc_' + func.__name__) + self.initcode.append('def %s(*a,**k):' % name) + self.initcode.append(' raise NotImplementedError') + return name + + def nameof_staticmethod(self, sm): + # XXX XXX XXXX + func = sm.__get__(42.5) + name = self.uniquename('gsm_' + func.__name__) + functionname = self.nameof(func) + self.initcode_python(name, 'staticmethod(%s)' % functionname) + return name + + def nameof_instancemethod(self, meth): + if meth.im_self is None: + # no error checking here + return self.nameof(meth.im_func) + else: + ob = self.nameof(meth.im_self) + func = self.nameof(meth.im_func) + typ = self.nameof(meth.im_class) + name = self.uniquename('gmeth_'+meth.im_func.__name__) + self.initcode_python(name, 'new.instancemethod(%s, %s, %s)' % ( + func, ob, typ)) + return name + + def should_translate_attr(self, pbc, attr): + ann = self.translator.annotator + if ann is None or isinstance(pbc, ObjSpace): + ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', []) + if attr in ignore: + return False + else: + return "probably" # True + classdef = ann.getuserclasses().get(pbc.__class__) + if classdef and classdef.about_attribute(attr) is not None: + return True + return False + + def nameof_builtin_function_or_method(self, func): + if func.__self__ is None: + # builtin function + # where does it come from? Python2.2 doesn't have func.__module__ + for modname, module in sys.modules.items(): + if hasattr(module, '__file__'): + if (module.__file__.endswith('.py') or + module.__file__.endswith('.pyc') or + module.__file__.endswith('.pyo')): + continue # skip non-builtin modules + if func is getattr(module, func.__name__, None): + break + else: + raise Exception, '%r not found in any built-in module' % (func,) + name = self.uniquename('gbltin_' + func.__name__) + if modname == '__builtin__': + self.initcode_python(name, func.__name__) + else: + modname = self.nameof(module) + self.initcode_python(name, '%s.%s' % (modname, func.__name__)) + else: + # builtin (bound) method + name = self.uniquename('gbltinmethod_' + func.__name__) + selfname = self.nameof(func.__self__) + self.initcode_python(name, '%s.%s' % (selfname, func.__name__)) + return name + + def nameof_classobj(self, cls): + if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'): + raise Exception, "%r should never be reached" % (cls,) - def nameofconst(self, c, debug=None): try: - concretetype = c.concretetype - except AttributeError: - concretetype = self.pyobjtype - return concretetype.nameof(c.value, debug=debug) - - def nameofvalue(self, value, concretetype=None, debug=None): - return (concretetype or self.pyobjtype).nameof(value, debug=debug) - - def getfuncdef(self, func): - if func not in self.funcdefs: - if self.translator.frozen: - if func not in self.translator.flowgraphs: - return None - else: - if (func.func_doc and - func.func_doc.lstrip().startswith('NOT_RPYTHON')): - return None - funcdef = FunctionDef(func, self) - self.funcdefs[func] = funcdef - self.allfuncdefs.append(funcdef) - self.pendingfunctions.append(funcdef) - return self.funcdefs[func] + return self.save_global(cls) + except PicklingError: + pass + + metaclass = "type" + if issubclass(cls, Exception): + # if cls.__module__ == 'exceptions': + # don't rely on this, py.magic redefines AssertionError + if getattr(__builtin__,cls.__name__,None) is cls: + name = self.uniquename('gexc_' + cls.__name__) + self.initcode_python(name, cls.__name__) + return name + #else: + # # exceptions must be old-style classes (grr!) + # metaclass = "&PyClass_Type" + # For the moment, use old-style classes exactly when the + # pypy source uses old-style classes, to avoid strange problems. + if not isinstance(cls, type): + assert type(cls) is ClassType + metaclass = "types.ClassType" + + name = self.uniquename('gcls_' + cls.__name__) + basenames = [self.nameof(base) for base in cls.__bases__] + def initclassobj(): + content = cls.__dict__.items() + content.sort() + ignore = getattr(cls, 'NOT_RPYTHON_ATTRIBUTES', []) + for key, value in content: + if key.startswith('__'): + if key in ['__module__', '__doc__', '__dict__', + '__weakref__', '__repr__', '__metaclass__']: + continue + # XXX some __NAMES__ are important... nicer solution sought + #raise Exception, "unexpected name %r in class %s"%(key, cls) + if isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen: + print value + continue + if isinstance(value, classmethod): + doc = value.__get__(cls).__doc__ + if doc and doc.lstrip().startswith("NOT_RPYTHON"): + continue + if isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen: + print value + continue + if key in ignore: + continue + + yield '%s.%s = %s' % (name, key, self.nameof(value)) + + baseargs = ", ".join(basenames) + if baseargs: + baseargs = '(%s)' % baseargs + self.initcode.append('class %s%s:' % (name, baseargs)) + self.initcode.append(' __metaclass__ = %s' % metaclass) + self.later(initclassobj()) + return name + + nameof_class = nameof_classobj # for Python 2.2 + + typename_mapping = { + InstanceType: 'types.InstanceType', + type(None): 'type(None)', + CodeType: 'types.CodeType', + type(sys): 'type(new)', + + r_int: 'r_int', + r_uint: 'r_uint', + + # XXX more hacks + # type 'builtin_function_or_method': + type(len): 'type(len)', + # type 'method_descriptor': + type(list.append): 'type(list.append)', + # type 'wrapper_descriptor': + type(type(None).__repr__): 'type(type(None).__repr__)', + # type 'getset_descriptor': + type(type.__dict__['__dict__']): "type(type.__dict__['__dict__'])", + # type 'member_descriptor': + type(type.__dict__['__basicsize__']): "type(type.__dict__['__basicsize__'])", + } + + def nameof_type(self, cls): + if cls.__module__ != '__builtin__': + return self.nameof_classobj(cls) # user-defined type + name = self.uniquename('gtype_%s' % cls.__name__) + if getattr(__builtin__, cls.__name__, None) is cls: + expr = cls.__name__ # type available from __builtin__ + else: + expr = self.typename_mapping[cls] + self.initcode_python(name, expr) + return name + + def nameof_tuple(self, tup): + name = self.uniquename('g%dtuple' % len(tup)) + args = [self.nameof(x) for x in tup] + args = ', '.join(args) + if args: + args += ',' + self.initcode_python(name, '(%s)' % args) + return name + + def nameof_list(self, lis): + name = self.uniquename('g%dlist' % len(lis)) + def initlist(): + for i in range(len(lis)): + item = self.nameof(lis[i]) + yield '%s.append(%s)' % (name, item) + self.initcode_python(name, '[]') + self.later(initlist()) + return name + + def nameof_dict(self, dic): + if '__name__' in dic: + module = dic['__name__'] + try: + __import__(module) + mod = sys.modules[module] + except (ImportError, KeyError): + pass + else: + if dic is mod.__dict__: + dictname = module.split('.')[-1] + '__dict__' + dictname = self.uniquename(dictname) + self.initcode.append('from %s import __dict__ as %s' % ( + module, dictname) ) + self.picklenames[Constant(dic)] = dictname + return dictname + name = self.uniquename('g%ddict' % len(dic)) + def initdict(): + for k in dic: + if type(k) is str: + yield '%s[%r] = %s' % (name, k, self.nameof(dic[k])) + else: + yield '%s[%s] = %s' % (name, self.nameof(k), + self.nameof(dic[k])) + self.initcode_python(name, '{}') + self.later(initdict()) + return name + + # strange prebuilt instances below, don't look too closely + # XXX oh well. + def nameof_member_descriptor(self, md): + name = self.uniquename('gdescriptor_%s_%s' % ( + md.__objclass__.__name__, md.__name__)) + cls = self.nameof(md.__objclass__) + self.initcode_python(name, '%s.__dict__[%r]' % (cls, md.__name__)) + return name + nameof_getset_descriptor = nameof_member_descriptor + nameof_method_descriptor = nameof_member_descriptor + nameof_wrapper_descriptor = nameof_member_descriptor + + def nameof_instance(self, instance): + klass = instance.__class__ + name = self.uniquename('ginst_' + klass.__name__) + cls = self.nameof(klass) + if hasattr(klass, '__base__'): + base_class = builtin_base(instance) + base = self.nameof(base_class) + else: + base_class = None + base = cls + def initinstance(): + content = instance.__dict__.items() + content.sort() + for key, value in content: + if self.should_translate_attr(instance, key): + line = '%s.%s = %s' % (name, key, self.nameof(value)) + yield line + if hasattr(instance, '__reduce_ex__'): + reduced = instance.__reduce_ex__() + restorer = reduced[0] + restorename = self.save_global(restorer) + restoreargs = reduced[1] + # ignore possible dict, handled later by initinstance filtering + # in other cases, we expect that the class knows what to pickle. + else: + restoreargs = (base, cls) + restorename = '%s.__new__' % base + restoreargsname = self.nameof(restoreargs) + if isinstance(cls, type): + self.initcode.append('%s = %s(*%s)' % (name, restorename, + restoreargsname)) + else: + self.initcode.append('%s = new.instance(%s)' % (name, cls)) + if hasattr(instance, '__dict__'): + self.later(initinstance()) + return name + + def save_global(self, obj): + # this is almost similar to pickle.py + name = obj.__name__ + key = Constant(obj) + if key not in self.picklenames: + module = getattr(obj, "__module__", None) + if module is None: + module = whichmodule(obj, name) + + try: + __import__(module) + mod = sys.modules[module] + klass = getattr(mod, name) + except (ImportError, KeyError, AttributeError): + raise PicklingError( + "Can't pickle %r: it's not found as %s.%s" % + (obj, module, name)) + else: + if klass is not obj: + raise PicklingError( + "Can't pickle %r: it's not the same object as %s.%s" % + (obj, module, name)) + # from here we do our own stuff + restorename = self.uniquename(obj.__name__) + if restorename != obj.__name__: + self.initcode.append('from %s import %s as %s' % ( + module, obj.__name__, restorename) ) + else: + self.initcode.append('from %s import %s' % ( + module, obj.__name__) ) + self.picklenames[key] = restorename + return self.picklenames[key] + + def nameof_function(self, func): + # look for skipped functions + if self.translator.frozen: + if func not in self.translator.flowgraphs: + return self.skipped_function(func) + else: + if (func.func_doc and + func.func_doc.lstrip().startswith('NOT_RPYTHON')): + return self.skipped_function(func) + # we produce an almost equivalent function, + # omitting the closure for now (how to do cells?) + args = (func.func_code, func.func_globals, func.func_name, + func.func_defaults, ) #func.func_closure) # closure omitted + pyfuncobj = self.uniquename('gfunc_' + func.__name__) + self.initcode.append('%s = new.function(*%s)' % (pyfuncobj, + self.nameof(args)) ) + return pyfuncobj + + def nameof_code(self, code): + args = (code.co_argcount, code.co_nlocals, code.co_stacksize, + code.co_flags, code.co_code, code.co_consts, code.co_names, + code.co_varnames, code.co_filename, code.co_name, + code.co_firstlineno, code.co_lnotab, code.co_freevars, + code.co_cellvars) + # make the code, filename and lnotab strings nicer + codestr = code.co_code + codestrname = self.uniquename('gcodestr_' + code.co_name) + self.picklenames[Constant(codestr)] = codestrname + self.initcode.append('%s = %r' % (codestrname, codestr)) + fnstr = code.co_filename + fnstrname = self.uniquename('gfname_' + code.co_name) + self.picklenames[Constant(fnstr)] = fnstrname + self.initcode.append('%s = %r' % (fnstrname, fnstr)) + lnostr = code.co_lnotab + lnostrname = self.uniquename('glnotab_' + code.co_name) + self.picklenames[Constant(lnostr)] = lnostrname + self.initcode.append('%s = %r' % (lnostrname, lnostr)) + argobj = self.nameof(args) + codeobj = self.uniquename('gcode_' + code.co_name) + self.initcode.append('%s = new.code(%s)' % (codeobj, argobj)) + return codeobj + + def nameof_file(self, fil): + if fil is sys.stdin: return "sys.stdin" + if fil is sys.stdout: return "sys.stdout" + if fil is sys.stderr: return "sys.stderr" + raise Exception, 'Cannot translate an already-open file: %r' % (fil,) + + def later(self, gen): + self.latercode.append((gen, self.debugstack)) + + def collect_initcode(self): + while self.latercode: + gen, self.debugstack = self.latercode.pop() + #self.initcode.extend(gen) -- eats TypeError! bad CPython! + for line in gen: + self.initcode.append(line) + self.debugstack = () + + def getfrozenbytecode(self): + self.initcode.append('') + source = '\n'.join(self.initcode) + del self.initcode[:] + co = compile(source, '', 'exec') + originalsource = source + small = zlib.compress(marshal.dumps(co)) + source = """if 1: + import zlib, marshal + exec marshal.loads(zlib.decompress(%r))""" % small + # Python 2.2 SyntaxError without newline: Bug #501622 + source += '\n' + co = compile(source, '', 'exec') + del source + return marshal.dumps(co), originalsource From pedronis at codespeak.net Wed Jun 1 16:59:52 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 16:59:52 +0200 (CEST) Subject: [pypy-svn] r12979 - in pypy/branch/pypy-translation-snapshot: . lib Message-ID: <20050601145952.05CAD27B57@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 16:59:51 2005 New Revision: 12979 Removed: pypy/branch/pypy-translation-snapshot/__init__.py pypy/branch/pypy-translation-snapshot/conftest.py pypy/branch/pypy-translation-snapshot/lib/ pypy/branch/pypy-translation-snapshot/test_all.py Log: removing lib because it should only be app-level stuff. removing original conftest and test_all.py we will need a conftest disabling test collection. Deleted: /pypy/branch/pypy-translation-snapshot/__init__.py ============================================================================== --- /pypy/branch/pypy-translation-snapshot/__init__.py Wed Jun 1 16:59:51 2005 +++ (empty file) @@ -1 +0,0 @@ -# empty Deleted: /pypy/branch/pypy-translation-snapshot/conftest.py ============================================================================== --- /pypy/branch/pypy-translation-snapshot/conftest.py Wed Jun 1 16:59:51 2005 +++ (empty file) @@ -1,184 +0,0 @@ -import py -from pypy.interpreter.gateway import app2interp_temp -from pypy.interpreter.error import OperationError -from pypy.tool.pytest import appsupport -from inspect import isclass - -rootdir = py.magic.autopath().dirpath() - -# -# PyPy's command line extra options (these are added -# to py.test's standard options) -# -Option = py.test.Config.Option - -#class Options: -# group = "pypy options" -# optionlist = - -option = py.test.Config.addoptions("pypy options", - Option('-O', '--objspace', action="store", default=None, - type="string", dest="objspacename", - help="object space to run tests on."), - Option('--oldstyle', action="store_true",dest="oldstyle", default=False, - help="enable oldstyle classes as default metaclass (std objspace only)"), - Option('--file', action="store_true",dest="uselibfile", default=False, - help="enable our custom file implementation"), - Option('--allpypy', action="store_true",dest="allpypy", default=False, - help="run everything possible on top of PyPy."), - ) - -def getobjspace(name=None, _spacecache={}): - """ helper for instantiating and caching space's for testing. - """ - if name is None: - name = option.objspacename - if name is None: - name = py.std.os.environ.get('OBJSPACE', 'std') - else: - optionname = option.objspacename - if optionname is not None and optionname != name: - return None - try: - return _spacecache[name] - except KeyError: - #py.magic.invoke(compile=True) - module = __import__("pypy.objspace.%s" % name, None, None, ["Space"]) - try: - space = module.Space() - except KeyboardInterrupt: - raise - except OperationError, e: - # we cannot easily convert w_KeyboardInterrupt to - # KeyboardInterrupt so we have to jump through hoops - try: - if e.w_type.name == 'KeyboardInterrupt': - raise KeyboardInterrupt - except AttributeError: - pass - if option.verbose: - import traceback - traceback.print_exc() - py.test.fail("fatal: cannot initialize objspace: %r" %(module.Space,)) - _spacecache[name] = space - if name == 'std' and option.oldstyle: - space.enable_old_style_classes_as_default_metaclass() - if option.uselibfile: - space.appexec([], '''(): - from _file import file - __builtins__.file = __builtins__.open = file - ''') - if name != 'flow': # not sensible for flow objspace case - space.setitem(space.builtin.w_dict, space.wrap('AssertionError'), - appsupport.build_pytest_assertion(space)) - space.setitem(space.builtin.w_dict, space.wrap('raises'), - space.wrap(appsupport.app_raises)) - space.setitem(space.builtin.w_dict, space.wrap('skip'), - space.wrap(appsupport.app_skip)) - space.raises_w = appsupport.raises_w.__get__(space) - space.eq_w = appsupport.eq_w.__get__(space) - return space - -# -# Interfacing/Integrating with py.test's collection process -# - -class Module(py.test.collect.Module): - """ we take care of collecting classes both at app level - and at interp-level (because we need to stick a space - at the class) ourselves. - """ - def funcnamefilter(self, name): - return name.startswith('test_') or name.startswith('app_test_') - def classnamefilter(self, name): - return name.startswith('Test') or name.startswith('AppTest') - - def setup(self): - # stick py.test raise in module globals - self.obj.raises = py.test.raises - super(Module, self).setup() - # if hasattr(mod, 'objspacename'): - # mod.space = getttestobjspace(mod.objspacename) - - def join(self, name): - obj = getattr(self.obj, name) - if isclass(obj): - if name.startswith('AppTest'): - return AppClassCollector(name, parent=self) - else: - return IntClassCollector(name, parent=self) - elif hasattr(obj, 'func_code'): - if name.startswith('app_test_'): - assert not obj.func_code.co_flags & 32, \ - "generator app level functions? you must be joking" - return AppTestFunction(name, parent=self) - elif obj.func_code.co_flags & 32: # generator function - return self.Generator(name, parent=self) - else: - return IntTestFunction(name, parent=self) - -def gettestobjspace(name=None): - space = getobjspace(name) - if space is None: - py.test.skip('test requires object space %r' % (name,)) - return space - - -class PyPyTestFunction(py.test.Function): - # All PyPy test items catch and display OperationErrors specially. - - def execute_appex(self, space, target, *args): - try: - target(*args) - except OperationError, e: - if e.match(space, space.w_KeyboardInterrupt): - raise KeyboardInterrupt - appexcinfo = appsupport.AppExceptionInfo(space, e) - if appexcinfo.traceback: - raise self.Failed(excinfo=appsupport.AppExceptionInfo(space, e)) - raise - -class IntTestFunction(PyPyTestFunction): - def execute(self, target, *args): - co = target.func_code - if 'space' in co.co_varnames[:co.co_argcount]: - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) - target(space, *args) - else: - target(*args) - -class AppTestFunction(PyPyTestFunction): - def execute(self, target, *args): - assert not args - name = target.func_globals.get('objspacename', None) - space = gettestobjspace(name) - func = app2interp_temp(target) - print "executing", func - self.execute_appex(space, func, space) - -class AppTestMethod(PyPyTestFunction): - def execute(self, target, *args): - assert not args - space = target.im_self.space - func = app2interp_temp(target.im_func) - self.execute_appex(space, func, space, space.w_None) - -class IntClassCollector(py.test.collect.Class): - Function = IntTestFunction - - def setup(self): - cls = self.obj - name = getattr(cls, 'objspacename', None) - if name is None: - m = __import__(cls.__module__, {}, {}, ["objspacename"]) - name = getattr(m, 'objspacename', None) - cls.space = gettestobjspace(name) - super(IntClassCollector, self).setup() - -class AppClassInstance(py.test.collect.Instance): - Function = AppTestMethod - -class AppClassCollector(IntClassCollector): - Instance = AppClassInstance - Deleted: /pypy/branch/pypy-translation-snapshot/test_all.py ============================================================================== --- /pypy/branch/pypy-translation-snapshot/test_all.py Wed Jun 1 16:59:51 2005 +++ (empty file) @@ -1,6 +0,0 @@ -#! /usr/bin/env python - -if __name__ == '__main__': - import tool.autopath - import py - py.test.cmdline.main() From pedronis at codespeak.net Wed Jun 1 17:07:56 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 17:07:56 +0200 (CEST) Subject: [pypy-svn] r12980 - pypy/branch/pypy-translation-snapshot Message-ID: <20050601150756.5D9F627B55@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 17:07:56 2005 New Revision: 12980 Added: pypy/branch/pypy-translation-snapshot/conftest.py Log: conftest disabling test collection Added: pypy/branch/pypy-translation-snapshot/conftest.py ============================================================================== --- (empty file) +++ pypy/branch/pypy-translation-snapshot/conftest.py Wed Jun 1 17:07:56 2005 @@ -0,0 +1,4 @@ +import py +class Directory(py.test.collect.Directory): + def run(self): + return [] From pedronis at codespeak.net Wed Jun 1 17:11:21 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 17:11:21 +0200 (CEST) Subject: [pypy-svn] r12981 - pypy/dist/pypy/translator/goal Message-ID: <20050601151121.A752427B55@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 17:11:21 2005 New Revision: 12981 Modified: pypy/dist/pypy/translator/goal/ (props changed) pypy/dist/pypy/translator/goal/translate_pypy.py Log: __path__ surgery such that translation_pypy will operate on interpreter/ module/ objspace/ (apart flow) content from a snapshot branch that should be checked out in goal. Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Wed Jun 1 17:11:21 2005 @@ -26,7 +26,37 @@ -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed """ -import autopath, sys, threading, pdb, os +import autopath, sys, os + +# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +basedir = autopath.this_dir + +pypy_translation_snapshot_dir = os.path.join(basedir, 'pypy-translation-snapshot') + +if not os.path.isdir(pypy_translation_snapshot_dir): + print """ +Translation is performed on a specific revision of PyPy which lives on +a branch. This needs to be checked out into translator/goal with: + +svn co http://codespeak.net/svn/pypy/branch/pypy-translation-snapshot +"""[1:] + sys.exit(2) + +# override imports from pypy head with imports from pypy-translation-snapshot +import pypy +pypy.__path__.insert(0, pypy_translation_snapshot_dir) + +# complement imports from pypy.objspace (from pypy-translation-snapshot) +# with pypy head objspace/ +import pypy.objspace +pypy.objspace.__path__.append(os.path.join(autopath.pypydir, 'objspace')) + +print "imports redirected to pypy-translation-snapshot." + +# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + + +import threading, pdb from pypy.translator.translator import Translator from pypy.translator.ann_override import pypy_overrides From pedronis at codespeak.net Wed Jun 1 17:37:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 17:37:57 +0200 (CEST) Subject: [pypy-svn] r12983 - pypy/dist/pypy/translator Message-ID: <20050601153757.2269E27B56@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 17:37:56 2005 New Revision: 12983 Modified: pypy/dist/pypy/translator/annrpython.py Log: set bindings for last_exc* extra vars only if they are indeed vars. Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Wed Jun 1 17:37:56 2005 @@ -443,8 +443,10 @@ last_exception_object.const = last_exception_var.value last_exception_object.is_type_of = [last_exc_value_var] - self.setbinding(last_exception_var, last_exception_object) - self.setbinding(last_exc_value_var, last_exc_value_object) + if isinstance(last_exception_var, Variable): + self.setbinding(last_exception_var, last_exception_object) + if isinstance(last_exc_value_var, Variable): + self.setbinding(last_exc_value_var, last_exc_value_object) last_exception_object = annmodel.SomeObject() last_exception_object.knowntype = type From pedronis at codespeak.net Wed Jun 1 19:39:41 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 19:39:41 +0200 (CEST) Subject: [pypy-svn] r12984 - pypy/dist/pypy/annotation Message-ID: <20050601173941.58A3927B4A@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 19:39:41 2005 New Revision: 12984 Modified: pypy/dist/pypy/annotation/unaryop.py Log: "annotation" for delattr Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Wed Jun 1 19:39:41 2005 @@ -22,7 +22,7 @@ def immutablevalue(x): return getbookkeeper().immutablevalue(x) -UNARY_OPERATIONS = set(['len', 'is_true', 'getattr', 'setattr', 'hash', +UNARY_OPERATIONS = set(['len', 'is_true', 'getattr', 'setattr', 'delattr', 'hash', 'simple_call', 'call_args', 'str', 'repr', 'iter', 'next', 'invert', 'type', 'issubtype', 'pos', 'neg', 'nonzero', 'abs', 'hex', 'oct', @@ -99,6 +99,12 @@ def long(obj): return SomeObject() # XXX + def delattr(obj, s_attr): + if obj.__class__ != SomeObject or obj.knowntype != object: + getbookkeeper().warning( + ("delattr on potentally non-SomeObjects is not RPythonic: delattr(%r,%r)" % + (obj, s_attr))) + def find_method(obj, name): "Look for a special-case implementation for the named method." analyser = getattr(obj.__class__, 'method_' + name) From pedronis at codespeak.net Wed Jun 1 19:40:33 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 1 Jun 2005 19:40:33 +0200 (CEST) Subject: [pypy-svn] r12985 - pypy/dist/pypy/objspace/std Message-ID: <20050601174033.7E33927B53@code1.codespeak.net> Author: pedronis Date: Wed Jun 1 19:40:33 2005 New Revision: 12985 Modified: pypy/dist/pypy/objspace/std/listobject.py Log: delitem for list and slices not using range with not-constant step and non quadratic Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Wed Jun 1 19:40:33 2005 @@ -236,21 +236,48 @@ def delitem__List_Slice(space, w_list, w_slice): start, stop, step, slicelength = slicetype.indices4(space, w_slice, w_list.ob_size) + + if slicelength==0: + return + + if step<0: + start = start+step*(slicelength-1) + step = -step + # stop is invalid + if step == 1: - return _setitem_slice_helper(space, w_list, w_slice, [], 0) + _del_slice(w_list, start, start+slicelength) + else: + items = w_list.ob_item + n = w_list.ob_size + + recycle = [None] * slicelength + i = start + + # keep a reference to the objects to be removed, + # preventing side effects during destruction + recycle[0] = items[i] + + for discard in range(1, slicelength): + j = i+1 + i += step + while j 0: - r.reverse() - for i in r: - _del_slice(w_list, i, i+1) return space.w_None def setitem__List_ANY_ANY(space, w_list, w_index, w_any): From arigo at codespeak.net Wed Jun 1 20:04:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 20:04:59 +0200 (CEST) Subject: [pypy-svn] r12986 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050601180459.C8E2827B95@code1.codespeak.net> Author: arigo Date: Wed Jun 1 20:04:59 2005 New Revision: 12986 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Log: svn merge -r12888:12985 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Wed Jun 1 20:04:59 2005 @@ -236,21 +236,48 @@ def delitem__List_Slice(space, w_list, w_slice): start, stop, step, slicelength = slicetype.indices4(space, w_slice, w_list.ob_size) + + if slicelength==0: + return + + if step<0: + start = start+step*(slicelength-1) + step = -step + # stop is invalid + if step == 1: - return _setitem_slice_helper(space, w_list, w_slice, [], 0) + _del_slice(w_list, start, start+slicelength) + else: + items = w_list.ob_item + n = w_list.ob_size + + recycle = [None] * slicelength + i = start + + # keep a reference to the objects to be removed, + # preventing side effects during destruction + recycle[0] = items[i] + + for discard in range(1, slicelength): + j = i+1 + i += step + while j 0: - r.reverse() - for i in r: - _del_slice(w_list, i, i+1) return space.w_None def setitem__List_ANY_ANY(space, w_list, w_index, w_any): From arigo at codespeak.net Wed Jun 1 20:05:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 1 Jun 2005 20:05:59 +0200 (CEST) Subject: [pypy-svn] r12987 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050601180559.2D4F527B97@code1.codespeak.net> Author: arigo Date: Wed Jun 1 20:05:58 2005 New Revision: 12987 Modified: pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_listobject.py Log: More tests for lists, including random tests for getitem, setitem and delitem with strange slice bounds and steps. Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Jun 1 20:05:58 2005 @@ -219,6 +219,10 @@ if isinstance(x, long): from pypy.objspace.std.longobject import args_from_long return W_LongObject(self, *args_from_long(x)) + if isinstance(x, slice): + return W_SliceObject(self, self.wrap(x.start), + self.wrap(x.stop), + self.wrap(x.step)) if isinstance(x, complex): # XXX is this right? YYY no, this is wrong right now (CT) # ZZZ hum, seems necessary for complex literals in co_consts (AR) Modified: pypy/dist/pypy/objspace/std/test/test_listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_listobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_listobject.py Wed Jun 1 20:05:58 2005 @@ -1,5 +1,5 @@ #from __future__ import nested_scopes -import autopath +import autopath, random from pypy.objspace.std.listobject import W_ListObject from pypy.interpreter.error import OperationError @@ -40,6 +40,30 @@ self.space.raises_w(self.space.w_IndexError, self.space.getitem, w_list, w(-3)) + def test_random_getitem(self): + w = self.space.wrap + s = list('qedx387tn3uixhvt 7fh387fymh3dh238 dwd-wq.dwq9') + w_list = W_ListObject(self.space, map(w, s)) + keys = range(-len(s)-5, len(s)+5) + choices = keys + [None]*12 + stepchoices = [None, None, None, 1, 1, -1, -1, 2, -2, + len(s)-1, len(s), len(s)+1, + -len(s)-1, -len(s), -len(s)+1] + for i in range(40): + keys.append(slice(random.choice(choices), + random.choice(choices), + random.choice(stepchoices))) + random.shuffle(keys) + for key in keys: + try: + expected = s[key] + except IndexError: + self.space.raises_w(self.space.w_IndexError, + self.space.getitem, w_list, w(key)) + else: + w_result = self.space.getitem(w_list, w(key)) + assert self.space.unwrap(w_result) == expected + def test_iter(self): w = self.space.wrap w_list = W_ListObject(self.space, [w(5), w(3), w(99)]) @@ -142,6 +166,58 @@ self.space.raises_w(self.space.w_IndexError, self.space.setitem, w_list, w(-3), w(5)) + def test_random_setitem_delitem(self): + w = self.space.wrap + s = range(39) + w_list = W_ListObject(self.space, map(w, s)) + expected = list(s) + keys = range(-len(s)-5, len(s)+5) + choices = keys + [None]*12 + stepchoices = [None, None, None, 1, 1, -1, -1, 2, -2, + len(s)-1, len(s), len(s)+1, + -len(s)-1, -len(s), -len(s)+1] + for i in range(50): + keys.append(slice(random.choice(choices), + random.choice(choices), + random.choice(stepchoices))) + random.shuffle(keys) + n = len(s) + for key in keys: + if random.random() < 0.15: + random.shuffle(s) + w_list = W_ListObject(self.space, map(w, s)) + expected = list(s) + try: + value = expected[key] + except IndexError: + self.space.raises_w(self.space.w_IndexError, + self.space.setitem, w_list, w(key), w(42)) + else: + if isinstance(value, int): # non-slicing + if random.random() < 0.25: # deleting + self.space.delitem(w_list, w(key)) + del expected[key] + else: + self.space.setitem(w_list, w(key), w(n)) + expected[key] = n + n += 1 + else: # slice assignment + mode = random.choice(['samesize', 'resize', 'delete']) + if mode == 'delete': + self.space.delitem(w_list, w(key)) + del expected[key] + elif mode == 'samesize': + newvalue = range(n, n+len(value)) + self.space.setitem(w_list, w(key), w(newvalue)) + expected[key] = newvalue + n += len(newvalue) + elif mode == 'resize' and key.step is None: + newvalue = range(n, n+random.randrange(0, 20)) + self.space.setitem(w_list, w(key), w(newvalue)) + expected[key] = newvalue + n += len(newvalue) + assert self.space.unwrap(w_list) == expected + def test_eq(self): w = self.space.wrap @@ -288,6 +364,13 @@ assert w_list.ob_item == [None]*len(w_list.ob_item) class AppTestW_ListObject: + def test_call_list(self): + assert list('') == [] + assert list('abc') == ['a', 'b', 'c'] + assert list((1, 2)) == [1, 2] + l = [] + assert list(l) is not l + def test_explicit_new_init(self): l = l0 = list.__new__(list) l.__init__([1,2]) @@ -401,9 +484,20 @@ assert l == [] def test_index(self): - l = ['a', 'b', 'c', 'd', 'e', 'f'] - raises(TypeError, l.index, 'c', 0, 4.3) - raises(TypeError, l.index, 'c', 1.0, 5.6) + c = list('hello world') + assert c.index('l') == 2 + raises(ValueError, c.index, '!') + assert c.index('l', 3) == 3 + assert c.index('l', 4) == 9 + raises(ValueError, c.index, 'l', 10) + assert c.index('l', -5) == 9 + assert c.index('l', -25) == 2 + assert c.index('o', 1, 5) == 4 + raises(ValueError, c.index, 'o', 1, 4) + assert c.index('o', 1, 5-11) == 4 + raises(ValueError, c.index, 'o', 1, 4-11) + raises(TypeError, c.index, 'c', 0, 4.3) + raises(TypeError, c.index, 'c', 1.0, 5.6) def test_ass_slice(self): l = range(6) @@ -418,4 +512,50 @@ assert repr(l) == '[]' l.append(l) assert repr(l) == '[[...]]' - + + def test_append(self): + l = [] + l.append('X') + assert l == ['X'] + l.append('Y') + l.append('Z') + assert l == ['X', 'Y', 'Z'] + + def test_count(self): + c = list('hello') + assert c.count('l') == 2 + assert c.count('h') == 1 + assert c.count('w') == 0 + + def test_insert(self): + c = list('hello world') + c.insert(0, 'X') + assert c[:4] == ['X', 'h', 'e', 'l'] + c.insert(2, 'Y') + c.insert(-2, 'Z') + assert ''.join(c) == 'XhYello worZld' + + def test_pop(self): + c = list('hello world') + s = '' + for i in range(11): + s += c.pop() + assert s == 'dlrow olleh' + raises(IndexError, c.pop) + assert len(c) == 0 + + def test_remove(self): + c = list('hello world') + c.remove('l') + assert ''.join(c) == 'helo world' + c.remove('l') + assert ''.join(c) == 'heo world' + c.remove('l') + assert ''.join(c) == 'heo word' + raises(ValueError, c.remove, 'l') + assert ''.join(c) == 'heo word' + + def test_reverse(self): + c = list('hello world') + c.reverse() + assert ''.join(c) == 'dlrow olleh' From tismer at codespeak.net Wed Jun 1 21:52:12 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 1 Jun 2005 21:52:12 +0200 (CEST) Subject: [pypy-svn] r12988 - in pypy/dist/pypy: objspace/flow translator/pickle Message-ID: <20050601195212.C2E4B27B9A@code1.codespeak.net> Author: tismer Date: Wed Jun 1 21:52:12 2005 New Revision: 12988 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/pickle/genpickle.py Log: pickling works in principle. todo: - add something to translator that reduces what we save - add tests (makes only sense after the monster fits into memory) Big problem: I generate a 50 MB python file. When I try to import this, python grows toalmost 1.6 GB, swaps itself to death, and finally crashes with an error that I cannot debug since my space is filled. No idea why it crashes, maybe the code object is just too large. The crash happens, *before* a .pyc file is created! Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Wed Jun 1 21:52:12 2005 @@ -8,7 +8,7 @@ """ memory size before and after introduction of __slots__ - using targetpypymain + using targetpypymain with -no-c slottified annotation ann+genc ------------------------------------------- @@ -26,9 +26,28 @@ Probably an effect of less fragmentation. """ +COUNTOBJECTS = False + __metaclass__ = type -class FunctionGraph: +class Missing: + pass + +class Slotted: + __slots__ = [] + from copy_reg import _slotnames + _slotnames = classmethod(_slotnames) + def __getstate__(self): + names = self._slotnames() + return tuple([getattr(self, name, Missing) for name in names]) + def __setstate__(self, args): + names = self._slotnames() + [setattr(self, name, value) for name, value in zip(names, args) + if value is not Missing] + +class FunctionGraph(Slotted): + __slots__ = """func source name startblock returnblock exceptblock""".split() + def __init__(self, name, startblock, return_var=None): self.name = name # function name (possibly mangled already) self.startblock = startblock @@ -69,7 +88,7 @@ from pypy.translator.tool.graphpage import SingleGraphPage SingleGraphPage(self).display() -class Link: +class Link(Slotted): __slots__ = """args target exitcase prevblock last_exception last_exc_value""".split() @@ -110,7 +129,7 @@ def __repr__(self): return "link from %s to %s" % (str(self.prevblock), str(self.target)) -class Block: +class Block(Slotted): __slots__ = """isstartblock inputargs operations exitswitch exits exc_handler""".split() @@ -180,12 +199,13 @@ self.exits = exits -class Variable: +class Variable(Slotted): __slots__ = ["_name", "concretetype"] - + countall = 0 - countmax = 0 - countcurr = 0 + if COUNTOBJECTS: + countmax = 0 + countcurr = 0 def name(self): name = self._name @@ -201,13 +221,15 @@ def __init__(self, name=None): self._name = Variable.countall Variable.countall += 1 - Variable.countcurr += 1 - Variable.countmax = max(Variable.countmax, Variable.countcurr) + if COUNTOBJECTS: + Variable.countcurr += 1 + Variable.countmax = max(Variable.countmax, Variable.countcurr) if name is not None: self.rename(name) - def __del__(self): - Variable.countcurr -= 1 + if COUNTOBJECTS: + def __del__(self): + Variable.countcurr -= 1 def __repr__(self): return '%s' % self.name @@ -228,18 +250,18 @@ self._name = name + '_' + self.name[1:] -class Constant(Hashable): +class Constant(Hashable, Slotted): __slots__ = ["concretetype"] -class SpaceOperation: +class SpaceOperation(Slotted): __slots__ = "opname args result offset".split() - - def __init__(self, opname, args, result): + + def __init__(self, opname, args, result, offset=-1): self.opname = opname # operation name self.args = list(args) # mixed list of var/const self.result = result # either Variable or Constant instance - self.offset = -1 # offset in code string, to be added later + self.offset = offset # offset in code string def __eq__(self, other): return (self.__class__ is other.__class__ and @@ -256,11 +278,12 @@ def __repr__(self): return "%r = %s(%s)" % (self.result, self.opname, ", ".join(map(repr, self.args))) -class Atom(object): +class Atom: def __init__(self, name): self.name = name def __repr__(self): return self.name + last_exception = Atom('last_exception') # if Block().exitswitch == Constant(last_exception), it means that we are # interested in catching the exception that the *last operation* of the Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Wed Jun 1 21:52:12 2005 @@ -17,6 +17,7 @@ import pickle from types import * +import types # ____________________________________________________________ @@ -90,15 +91,10 @@ return name def nameof_module(self, value): - assert value is os or not hasattr(value, "__file__") or \ - not (value.__file__.endswith('.pyc') or - value.__file__.endswith('.py') or - value.__file__.endswith('.pyo')), \ - "%r is not a builtin module (probably :)"%value + # all allowed here, we reproduce ourselves name = self.uniquename('mod%s'%value.__name__) self.initcode_python(name, "__import__(%r)" % (value.__name__,)) return name - def nameof_int(self, value): return repr(value) @@ -156,6 +152,7 @@ func, ob, typ)) return name + # old version: def should_translate_attr(self, pbc, attr): ann = self.translator.annotator if ann is None or isinstance(pbc, ObjSpace): @@ -169,16 +166,27 @@ return True return False + # new version: save if we don't know + def should_translate_attr(self, pbc, attr): + ann = self.translator.annotator + if ann: + classdef = ann.getuserclasses().get(pbc.__class__) + else: + classdef = None + ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', []) + if attr in ignore: + return False + if classdef: + return classdef.about_attribute(attr) is not None + # by default, render if we don't know anything + return True + def nameof_builtin_function_or_method(self, func): if func.__self__ is None: # builtin function # where does it come from? Python2.2 doesn't have func.__module__ for modname, module in sys.modules.items(): - if hasattr(module, '__file__'): - if (module.__file__.endswith('.py') or - module.__file__.endswith('.pyc') or - module.__file__.endswith('.pyo')): - continue # skip non-builtin modules + # here we don't ignore extension modules if func is getattr(module, func.__name__, None): break else: @@ -280,6 +288,8 @@ type(type.__dict__['__dict__']): "type(type.__dict__['__dict__'])", # type 'member_descriptor': type(type.__dict__['__basicsize__']): "type(type.__dict__['__basicsize__'])", + # type 'instancemethod': + type(Exception().__init__): 'type(Exception().__init__)', } def nameof_type(self, cls): @@ -288,6 +298,13 @@ name = self.uniquename('gtype_%s' % cls.__name__) if getattr(__builtin__, cls.__name__, None) is cls: expr = cls.__name__ # type available from __builtin__ + elif cls in types.__dict__.values(): + for key, value in types.__dict__.items(): + if value is cls: + break + self.initcode.append('from types import %s as %s' % ( + key, name)) + return name else: expr = self.typename_mapping[cls] self.initcode_python(name, expr) @@ -318,7 +335,7 @@ try: __import__(module) mod = sys.modules[module] - except (ImportError, KeyError): + except (ImportError, KeyError, TypeError): pass else: if dic is mod.__dict__: @@ -363,7 +380,14 @@ base_class = None base = cls def initinstance(): - content = instance.__dict__.items() + if hasattr(instance, '__setstate__'): + # the instance knows what to do + args = self.nameof(restorestate) + yield '%s.__setstate__(%s)' % (name, args) + return + assert type(restorestate) is dict, ( + "%s has no dict and no __setstate__" % name) + content = restorestate.items() content.sort() for key, value in content: if self.should_translate_attr(instance, key): @@ -374,18 +398,23 @@ restorer = reduced[0] restorename = self.save_global(restorer) restoreargs = reduced[1] + if len(reduced) > 2: + restorestate = reduced[2] + else: + restorestate = None # ignore possible dict, handled later by initinstance filtering # in other cases, we expect that the class knows what to pickle. else: restoreargs = (base, cls) restorename = '%s.__new__' % base + restorestate = instance.__dict__ restoreargsname = self.nameof(restoreargs) - if isinstance(cls, type): + if isinstance(klass, type): self.initcode.append('%s = %s(*%s)' % (name, restorename, restoreargsname)) else: self.initcode.append('%s = new.instance(%s)' % (name, cls)) - if hasattr(instance, '__dict__'): + if restorestate is not None: self.later(initinstance()) return name @@ -461,7 +490,7 @@ self.initcode.append('%s = %r' % (lnostrname, lnostr)) argobj = self.nameof(args) codeobj = self.uniquename('gcode_' + code.co_name) - self.initcode.append('%s = new.code(%s)' % (codeobj, argobj)) + self.initcode.append('%s = new.code(*%s)' % (codeobj, argobj)) return codeobj def nameof_file(self, fil): From tismer at codespeak.net Wed Jun 1 23:00:30 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 1 Jun 2005 23:00:30 +0200 (CEST) Subject: [pypy-svn] r12989 - pypy/dist/pypy/translator/pickle Message-ID: <20050601210030.019E627B9E@code1.codespeak.net> Author: tismer Date: Wed Jun 1 23:00:30 2005 New Revision: 12989 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: added cell support. pickling of function objects may be slightly overdone, but it was quite easy. We can shrink that down if size of that matters. Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Wed Jun 1 23:00:30 2005 @@ -4,7 +4,7 @@ to restart code generation after flowing and maybe annotation. """ -import autopath, os, sys, new, __builtin__ +import os, sys, new, __builtin__ from pypy.translator.gensupp import uniquemodulename, NameManager, UniqueList from pypy.translator.gensupp import builtin_base @@ -460,15 +460,19 @@ if (func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON')): return self.skipped_function(func) - # we produce an almost equivalent function, - # omitting the closure for now (how to do cells?) args = (func.func_code, func.func_globals, func.func_name, - func.func_defaults, ) #func.func_closure) # closure omitted + func.func_defaults, func.func_closure) pyfuncobj = self.uniquename('gfunc_' + func.__name__) self.initcode.append('%s = new.function(*%s)' % (pyfuncobj, self.nameof(args)) ) return pyfuncobj + def nameof_cell(self, cel): + obj = break_cell(cel) + pycell = self.uniquename('gcell_' + self.nameof(obj)) + self.initcode.append('%s = %s(%s)' % (pycell, self.nameof(make_cell), + self.nameof(obj)) + def nameof_code(self, code): args = (code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, code.co_consts, code.co_names, @@ -525,3 +529,17 @@ co = compile(source, '', 'exec') del source return marshal.dumps(co), originalsource + +def make_cell(obj): + def func(): + return obj + return func.func_closure[0] + +def break_cell(cel): + obj = None + def func(): + return obj + args = (func.func_code, func.func_globals, func.func_name, + func.func_defaults, (cel,)) + func = new.function(*args) + return func() \ No newline at end of file From pedronis at codespeak.net Thu Jun 2 01:46:10 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 01:46:10 +0200 (CEST) Subject: [pypy-svn] r12990 - pypy/dist/pypy/annotation Message-ID: <20050601234610.9783E27B58@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 01:46:10 2005 New Revision: 12990 Modified: pypy/dist/pypy/annotation/model.py Log: cover with default also SomeObject(knowntype=tuple) etc Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Thu Jun 2 01:46:10 2005 @@ -420,7 +420,7 @@ else: flattened = args for arg in flattened: - if arg.__class__ == SomeObject and arg.knowntype == object: + if arg.__class__ == SomeObject and arg.knowntype != type: return SomeObject() bookkeeper = pypy.annotation.bookkeeper.getbookkeeper() bookkeeper.warning("no precise annotation supplied for %s%r" % (name, args)) From ale at codespeak.net Thu Jun 2 02:25:05 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 2 Jun 2005 02:25:05 +0200 (CEST) Subject: [pypy-svn] r12991 - pypy/dist/pypy/lib Message-ID: <20050602002505.D68E827B5D@code1.codespeak.net> Author: ale Date: Thu Jun 2 02:25:05 2005 New Revision: 12991 Modified: pypy/dist/pypy/lib/unicodecodec.py Log: Nailed a few more bugs Modified: pypy/dist/pypy/lib/unicodecodec.py ============================================================================== --- pypy/dist/pypy/lib/unicodecodec.py (original) +++ pypy/dist/pypy/lib/unicodecodec.py Thu Jun 2 02:25:05 2005 @@ -54,22 +54,6 @@ else: raise TypeError("handler must be callable") - -def PyUnicode_Check(op): - return type(op) == unicode -def PyUnicode_CheckExact(op): - return (type(op) == unicode) - - -def PyUnicode_GET_SIZE(op): - return len(unicode(op)) -def PyUnicode_GET_DATA_SIZE(op): - return len(unicode(op)) * len(u' ') -def PyUnicode_AS_UNICODE(op): - unicode(op) -def PyUnicode_AS_DATA(op): - buffer(unicode(op)) #XXX This is a read only buffer - def SPECIAL(c, encodeO, encodeWS): c = ord(c) return (c>127 or utf7_special[c] == 1) or \ @@ -220,7 +204,7 @@ out += p inShift = bitsleft > 0 else: - out += ch + out += chr(ord(ch)) else: if (not SPECIAL(ch, encodeSetO, encodeWhiteSpace)): out += B64((charsleft) << (6-bitsleft)) @@ -231,7 +215,7 @@ if (B64CHAR(ch) or ch == '-'): out += '-' inShift = False - out += ch + out += chr(ord(ch)) else: bitsleft += 16 charsleft = (((charsleft) << 16) | ord(ch)) @@ -264,46 +248,8 @@ return out -def PyUnicode_FromOrdinal(ordinal): - - if (ordinal < 0 or ordinal > 0x10ffff): - raise ValueError, "unichr() arg not in range(0x110000) (wide Python build)" - -## if (ordinal < 0 or ordinal > 0xffff): -## raise ValueError, "unichr() arg not in range(0x1000) (narrow Python build)" - - s = unichr(ordinal) - return s,1 - -def PyUnicode_FromObject(obj): - -## /* XXX Perhaps we should make this API an alias of -## PyObject_Unicode() instead ?! */ - if (PyUnicode_CheckExact(obj)): - return obj - - if (PyUnicode_Check(obj)): -## /* For a Unicode subtype that's not a Unicode object, -## return a true Unicode object with the same data. */ - return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(obj),PyUnicode_GET_SIZE(obj)) - return PyUnicode_FromEncodedObject(obj, None, "strict") - unicode_empty=u'' -def PyUnicode_FromUnicode(u, size): - -## /* If the Unicode data is known at construction time, we can apply -## some optimizations which share commonly used objects. */ - if (u): - -## /* Optimization for empty strings */ - if (size == 0 and unicode_empty != None) : - return unicode_empty - - ## /* Single character Unicode objects in the Latin-1 range are - ## shared when using this constructor */ - return unicode(u) - def PyUnicode_Decode(s,size,encoding,errors): if (encoding == None): @@ -316,16 +262,10 @@ ## /* Decode via the codec registry */ buf = buffer(s) result = PyCodec_Decode(buf, encoding, errors); - if (not PyUnicode_Check(result)): + if (not isinstance(result,unicode)): raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result) return result -def PyUnicode_FromEncodedObject(obj, encoding,errors): - - s = str(obj) - v = PyUnicode_Decode(s, len(s), encoding, errors) - return v - def unicodeescape_string(s, size, quotes): p = [] @@ -342,6 +282,7 @@ if (quotes and (ch == p[1] or ch == '\\')): p += '\\' p += ch + pos += 1 continue #ifdef Py_UNICODE_WIDE @@ -350,6 +291,7 @@ p += '\\' p += 'U' p += '%08x'%ord(ch) + pos += 1 continue #endif #/* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */ @@ -395,7 +337,7 @@ #/* Copy everything else as-is */ else: p += ch - + pos += 1 if (quotes): p += p[1] return p @@ -430,8 +372,8 @@ def PyUnicode_AsASCIIString(unistr): if not type(unistr) == unicode: - raise BadArgumnentError - return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(unistr), + raise TypeError + return PyUnicode_EncodeASCII(unicode(unistr), len(unicode), None) @@ -462,20 +404,20 @@ if (size >= 2): bom = (ord(s[ihi]) << 8) | ord(s[ilo]) #ifdef BYTEORDER_IS_LITTLE_ENDIAN - if sys.byteorder == 'little': - if (bom == 0xFEFF): - q += 2 - bo = -1 - elif bom == 0xFFFE: - q += 2 - bo = 1 - else: - if bom == 0xFEFF: - q += 2 - bo = 1 - elif bom == 0xFFFE: - q += 2 - bo = -1 + if sys.byteorder == 'little': + if (bom == 0xFEFF): + q += 2 + bo = -1 + elif bom == 0xFFFE: + q += 2 + bo = 1 + else: + if bom == 0xFEFF: + q += 2 + bo = 1 + elif bom == 0xFFFE: + q += 2 + bo = -1 elif byteorder == 'little': bo = -1 else: @@ -1050,7 +992,7 @@ message = "\\ at end of string" handler = lookup_error(errors) x = handler(UnicodeDecodeError("unicodeescape",s,pos, - pos+digits,message)) + size,message)) p += x[0] pos = x[1] else: @@ -1061,7 +1003,7 @@ def PyUnicode_EncodeRawUnicodeEscape(s,size): if (size == 0): - return u'' + return '' p = [] for ch in s: @@ -1077,9 +1019,9 @@ p += hex(ord(ch)) # /* Copy everything else as-is */ else: - p += ch + p += chr(ord(ch)) - p += '\0' + p += '\\0' return p def charmapencode_output(c,mapping): @@ -1187,9 +1129,10 @@ #/* Non-escape characters are interpreted as Unicode ordinals */ if (ch != '\\'): p += ch - + pos += 1 + continue startinpos = pos - + pos += 1 ## /* \u-escapes are only interpreted iff the number of leading ## backslashes is odd */ bs = pos From ericvrp at codespeak.net Thu Jun 2 12:08:50 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 2 Jun 2005 12:08:50 +0200 (CEST) Subject: [pypy-svn] r12993 - pypy/dist/pypy/translator/test Message-ID: <20050602100850.A985327B49@code1.codespeak.net> Author: ericvrp Date: Thu Jun 2 12:08:50 2005 New Revision: 12993 Added: pypy/dist/pypy/translator/test/test_backends.py Log: These tests get run by all existing backends. Currently it contains just one test (can backends regenerate identical sourcecode). XXX We need to think about self-registering the backends, so we don't endup hardcoding their names at various places! Added: pypy/dist/pypy/translator/test/test_backends.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/test/test_backends.py Thu Jun 2 12:08:50 2005 @@ -0,0 +1,32 @@ +''' +Test conditions that all backends should do correct. +''' + +import autopath, os, sys +from pypy.translator.translator import Translator +from pypy.rpython.rtyper import * +from pypy.rpython.rarithmetic import * +from pypy.translator.test.snippet import * + + +backends = 'source c cl llvm pyrex'.split() +functions = 'forty_two'.split() #XXX add more functions here when RPythonTyper can handle them + +regenerate_code = '''def test_regenerate_%(function)s_%(backend)s(): + t = Translator(%(function)s) + t.simplify() + a = t.annotate([]) + a.simplify() + typer = RPythonTyper(t.annotator) + typer.specialize() + first = t.%(backend)s() + second = t.%(backend)s() + if first != second: + print '\\n' + first + '\\n\\n' + print '\\n' + second + '\\n\\n' + #t.view() + assert first == second''' + +for backend in backends: + for function in functions: + exec regenerate_code % vars() From pedronis at codespeak.net Thu Jun 2 12:44:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 12:44:53 +0200 (CEST) Subject: [pypy-svn] r12994 - pypy/dist/pypy/annotation Message-ID: <20050602104453.DC9B327B4A@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 12:44:53 2005 New Revision: 12994 Modified: pypy/dist/pypy/annotation/binaryop.py Log: mixing of pbcs and instances is not really supported anymore, the behavior of pbc methods is not captured in the possible parent classdefs. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 2 12:44:53 2005 @@ -9,7 +9,7 @@ from pypy.annotation.model import SomeTuple, SomeImpossibleValue from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator from pypy.annotation.model import SomePBC, SomeSlice, SomeFloat -from pypy.annotation.model import unionof, UnionError, set, missing_operation +from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation.classdef import isclassdef from pypy.objspace.flow.model import Constant @@ -463,6 +463,8 @@ if classdef is None: # print warning? return SomeObject() + if not getattr(TLS, 'no_side_effects_in_union', 0): + raise UnionError("mixing pbc and instance not supported anymore: %s %s" % (pbc, ins)) return SomeInstance(classdef) class __extend__(pairtype(SomePBC, SomeInstance)): From ludal at codespeak.net Thu Jun 2 12:48:39 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 2 Jun 2005 12:48:39 +0200 (CEST) Subject: [pypy-svn] r12995 - pypy/branch/pycompiler/module/recparser Message-ID: <20050602104839.6783C27B4A@code1.codespeak.net> Author: ludal Date: Thu Jun 2 12:48:39 2005 New Revision: 12995 Added: pypy/branch/pycompiler/module/recparser/codegen.py Log: * starting a rpython compiler implementation based on compiler module Added: pypy/branch/pycompiler/module/recparser/codegen.py ============================================================================== --- (empty file) +++ pypy/branch/pycompiler/module/recparser/codegen.py Thu Jun 2 12:48:39 2005 @@ -0,0 +1,108 @@ + +import pythonutil +from compiler.visitor import ASTVisitor +from compiler.bytecode import * + +def compile(source, filename, mode, flags=None, dont_inherit=None): + """Replacement for builtin compile() function""" + # source to ast conversion + if mode == "single": + tree = pythonutil.ast_single_input( source ) + elif mode == "eval": + tree = pythonutil.ast_eval_input( source ) + elif mode == "exec": + tree = pythonutil.ast_srcfile_input( source, filename ) + else: + raise RuntimeError("Not found") + return compile_ast( tree, filename, flags=None, dont_inherit=None) + + +def compile_ast( tree, filename, flags=None, dont_inherit=None ): + v = CompilerVisitor( filename, flags, dont_inherit ) + tree.visit(v) + return tree, v + + +class PrintContext(object): + def __init__(self): + self.lineno = 0 + + def emit(self, insn ): + print "% 5d %s" % (self.lineno, insn) + + def emit_arg(self, insn, arg ): + print "% 5d %8s %s" % (self.lineno, insn, arg) + + def set_lineno(self, lineno): + self.lineno = lineno + + +class Block(object): + def __init__(self): + self.insns = [] + self.start_pos = 0 + + def append(self, insn ): + self.insns.append( insn ) + + def get_size(self): + s = 0 + for i in insns: + s += i.size() + return s + + def set_start_pos(self, pos ): + self.start_pos = pos + + + +class CompilerVisitor(ASTVisitor): + """Basic code generator for Python Bytecode""" + def __init__(self, filename, flags, dont_inherit ): + self.scopes = [] + self.blocks = [] + self.code = None + self.current_block = None + + ### Visitor functions + + def visitModule( self, node ): + # setup doc + self.newBlock() + node.node.visit( self ) + + # build code object + for block in self.blocks: + pass + + def visitExpression(self, node): + pass + + def visitFunction(self, node): + pass + + def visitIf(self, node): + end = Block() + for test, suite in node.tests: + if is_constant_false(test): + continue + test.visit(self) # emit test code in current block + self.a + nextTest = Block() + + ### Block handling functions + def newBlock(self): + """Create a new block and make it current""" + b = Block() + self.blocks.append(b) + self.current_block = b + return b + + + +if __name__ == "__main__": + testf = file("pycodegen2.py").read() + ast, v = compile(testf,"pycodegen2.py","exec") + print ast + print v + From ludal at codespeak.net Thu Jun 2 12:52:16 2005 From: ludal at codespeak.net (ludal at codespeak.net) Date: Thu, 2 Jun 2005 12:52:16 +0200 (CEST) Subject: [pypy-svn] r12996 - pypy/branch/pycompiler/module/recparser/compiler Message-ID: <20050602105216.2BDEC27B4A@code1.codespeak.net> Author: ludal Date: Thu Jun 2 12:52:15 2005 New Revision: 12996 Added: pypy/branch/pycompiler/module/recparser/compiler/bytecode.py Log: * objects for bytecode generation Added: pypy/branch/pycompiler/module/recparser/compiler/bytecode.py ============================================================================== --- (empty file) +++ pypy/branch/pycompiler/module/recparser/compiler/bytecode.py Thu Jun 2 12:52:15 2005 @@ -0,0 +1,50 @@ + + + +class ByteCode(object): + def __init__(self, insn, node): + self.insn = insn + self.node = node + + def emit(self, ctx): + """Emit bytecode given context""" + ctx.set_lineno( node.lineno ) + ctx.emit( insn ) + + def size(self): + return 1 + + +class LoadValue(ByteCode): + def __init__(self, name, node): + self.name = name + self.node = node + + def emit(self, ctx): + ctx.set_lineno( node.lineno ) + name_scope = ctx.get_name( self.name ) + if name_scope == "global": + ctx.emit_arg('LOAD_GLOBAL', self.name ) + elif name_scope == "local": + idx = ctx.get_local_idx( self.name ) + ctx.emit_arg('LOAD_FAST', idx ) + +class LoadConst(ByteCode): + def __init__(self, cst, node ): + self.cst = cst + self.node = node + + def emit(self, ctx): + ctx.set_lineno( node.lineno ) + ctx.emit_arg('LOAD_CONST', self.cst) + + def size(self): + return 3 + +class CondJump(object): + def __init__(self, cond, block ): + self.nextBlock = block + self.cond = cond # FWD, IF_TRUE, IF_FALSE, ABSOLUTE + + def emit(self, ctx): + pass From pedronis at codespeak.net Thu Jun 2 13:51:18 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 13:51:18 +0200 (CEST) Subject: [pypy-svn] r12999 - pypy/dist/pypy/annotation Message-ID: <20050602115118.2528527B3D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 13:51:17 2005 New Revision: 12999 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/model.py Log: - don't add redudant .knowtype = object to SomeObjects - valueoftype should try not to create classdefs for pbc types Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 2 13:51:17 2005 @@ -240,12 +240,13 @@ elif t is dict: return SomeDict(MOST_GENERAL_DICTDEF) # can't do tuple - elif t.__module__ != '__builtin__': + elif t.__module__ != '__builtin__' and t not in self.pbctypes: classdef = self.getclassdef(t) return SomeInstance(classdef) else: o = SomeObject() - o.knowntype = t + if t != object: + o.knowntype = t return o def pbc_getattr(self, pbc, s_attr): Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Thu Jun 2 13:51:17 2005 @@ -263,12 +263,14 @@ if self.isNone(): self.knowntype = type(None) else: - self.knowntype = reduce(commonbase, - [new_or_old_class(x) - for x in prebuiltinstances - if x is not None]) - if self.knowntype == type(Exception): - self.knowntype = type + knowntype = reduce(commonbase, + [new_or_old_class(x) + for x in prebuiltinstances + if x is not None]) + if knowntype == type(Exception): + knowntype = type + if knowntype != object: + self.knowntype = knowntype if prebuiltinstances.values() == [True]: # hack for the convenience of direct callers to SomePBC(): # only if there is a single object in prebuiltinstances and From pedronis at codespeak.net Thu Jun 2 13:52:17 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 13:52:17 +0200 (CEST) Subject: [pypy-svn] r13000 - in pypy/dist/pypy/translator: . test Message-ID: <20050602115217.6EBD827B3D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 13:52:17 2005 New Revision: 13000 Modified: pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/test/test_annrpython.py Log: sanity check, fixing slightly wrong test Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Thu Jun 2 13:52:17 2005 @@ -474,7 +474,8 @@ cell = self.binding(a) if link.exitcase is True and knownvars is not None and a in knownvars \ and not knownvarvalue.contains(cell): - cell = knownvarvalue + if cell.contains(knownvarvalue): # sanity check + cell = knownvarvalue if hasattr(cell,'is_type_of'): renamed_is_type_of = [] for v in cell.is_type_of: Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Thu Jun 2 13:52:17 2005 @@ -364,7 +364,7 @@ def test_is_and_knowntype_data(self): a = self.RPythonAnnotator() - s = a.build_types(snippet.is_and_knowntype, [bool]) + s = a.build_types(snippet.is_and_knowntype, [str]) #a.simplify() #a.translator.view() assert s == a.bookkeeper.immutablevalue(None) From pedronis at codespeak.net Thu Jun 2 13:59:17 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 13:59:17 +0200 (CEST) Subject: [pypy-svn] r13001 - pypy/dist/pypy/interpreter Message-ID: <20050602115917.76EB627B3D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 13:59:17 2005 New Revision: 13001 Modified: pypy/dist/pypy/interpreter/gateway.py Log: don't use funky FuncBoxes anymore, just staticmethods Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Thu Jun 2 13:59:17 2005 @@ -261,9 +261,6 @@ """Subclasses with behavior specific for an unwrap spec are generated""" raise TypeError, "abstract" -class FuncBox(object): - pass - class BuiltinCodeSignature(Signature): "NOT_RPYTHON" @@ -279,9 +276,9 @@ def _make_unwrap_frame_class(self, cache={}): try: key = tuple(self.unwrap_spec) - frame_cls, box_cls, run_args = cache[key] + frame_cls, run_args = cache[key] assert run_args == self.run_args,"unexpected: same spec, different run_args" - return frame_cls, box_cls + return frame_cls except KeyError: parts = [] for el in self.unwrap_spec: @@ -309,22 +306,19 @@ self.miniglobals['OperationError'] = OperationError source = """if 1: def _run_UWS_%s(self): - return self.box.func(%s) + return self.behavior(%s) \n""" % (label, ','.join(self.run_args)) exec compile2(source) in self.miniglobals, d d['_run'] = d['_run_UWS_%s' % label] del d['_run_UWS_%s' % label] frame_cls = type("BuiltinFrame_UWS_%s" % label, (BuiltinFrame,), d) - box_cls = type("FuncBox_UWS_%s" % label, (FuncBox,), {}) - cache[key] = frame_cls, box_cls, self.run_args - return frame_cls, box_cls + cache[key] = frame_cls, self.run_args + return frame_cls def make_frame_class(self, func, cache={}): - frame_uw_cls, box_cls = self._make_unwrap_frame_class() - box = box_cls() - box.func = func + frame_uw_cls = self._make_unwrap_frame_class() return type("BuiltinFrame_for_%s" % self.name, - (frame_uw_cls,),{'box': box}) + (frame_uw_cls,),{'behavior': staticmethod(func)}) def make_builtin_frame_class(func, orig_sig, unwrap_spec): "NOT_RPYTHON" @@ -403,7 +397,6 @@ def getdocstring(self): return self.docstring - class interp2app(Wrappable): """Build a gateway that calls 'f' at interp-level.""" From pedronis at codespeak.net Thu Jun 2 14:02:10 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 14:02:10 +0200 (CEST) Subject: [pypy-svn] r13002 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050602120210.EA0BE27B3E@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 14:02:10 2005 New Revision: 13002 Modified: pypy/branch/pypy-translation-snapshot/interpreter/gateway.py Log: merge from trunk switch from FuncBoxes to staticmethods Modified: pypy/branch/pypy-translation-snapshot/interpreter/gateway.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/gateway.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/gateway.py Thu Jun 2 14:02:10 2005 @@ -261,9 +261,6 @@ """Subclasses with behavior specific for an unwrap spec are generated""" raise TypeError, "abstract" -class FuncBox(object): - pass - class BuiltinCodeSignature(Signature): "NOT_RPYTHON" @@ -279,9 +276,9 @@ def _make_unwrap_frame_class(self, cache={}): try: key = tuple(self.unwrap_spec) - frame_cls, box_cls, run_args = cache[key] + frame_cls, run_args = cache[key] assert run_args == self.run_args,"unexpected: same spec, different run_args" - return frame_cls, box_cls + return frame_cls except KeyError: parts = [] for el in self.unwrap_spec: @@ -309,22 +306,19 @@ self.miniglobals['OperationError'] = OperationError source = """if 1: def _run_UWS_%s(self): - return self.box.func(%s) + return self.behavior(%s) \n""" % (label, ','.join(self.run_args)) exec compile2(source) in self.miniglobals, d d['_run'] = d['_run_UWS_%s' % label] del d['_run_UWS_%s' % label] frame_cls = type("BuiltinFrame_UWS_%s" % label, (BuiltinFrame,), d) - box_cls = type("FuncBox_UWS_%s" % label, (FuncBox,), {}) - cache[key] = frame_cls, box_cls, self.run_args - return frame_cls, box_cls + cache[key] = frame_cls, self.run_args + return frame_cls def make_frame_class(self, func, cache={}): - frame_uw_cls, box_cls = self._make_unwrap_frame_class() - box = box_cls() - box.func = func + frame_uw_cls = self._make_unwrap_frame_class() return type("BuiltinFrame_for_%s" % self.name, - (frame_uw_cls,),{'box': box}) + (frame_uw_cls,),{'behavior': staticmethod(func)}) def make_builtin_frame_class(func, orig_sig, unwrap_spec): "NOT_RPYTHON" @@ -403,7 +397,6 @@ def getdocstring(self): return self.docstring - class interp2app(Wrappable): """Build a gateway that calls 'f' at interp-level.""" From pedronis at codespeak.net Thu Jun 2 14:15:42 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 14:15:42 +0200 (CEST) Subject: [pypy-svn] r13003 - pypy/dist/pypy/translator/goal Message-ID: <20050602121542.457BA27B44@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 14:15:42 2005 New Revision: 13003 Added: pypy/dist/pypy/translator/goal/query.py (contents, props changed) Log: start of collection of functions to query information out of the translator and annotator from the debug prompt of translate_pypy for example (Pdb) from pypy.translator.goal import query as ry (Pdb) ry.polluted(t) ... Added: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 2 14:15:42 2005 @@ -0,0 +1,51 @@ +# functions to query information out of the translator and annotator from the debug prompt of translate_pypy + +import pypy.annotation.model as annmodel +import pypy.objspace.flow.model as flowmodel + +#def sources(translator): +# annotator = translator.annotator +# d = {} +# for v, s in annotator.bindings.iteritems(): +# if s.__class__ == annmodel.SomeObject and s.knowntype != type: +# if s.origin: +# d[s.origin[0]] = 1 +# for func in d: +# print func.__module__ or '?', func.__name__ +# print len(d) +# return d.keys() + +class Found(Exception): + pass + +def sovars(translator, g): + annotator = translator.annotator + def visit(block): + if isinstance(block, flowmodel.Block): + for v in block.getvariables(): + s = annotator.binding(v, extquery=True) + if s and s.__class__ == annmodel.SomeObject and s.knowntype != type: + print v,s + flowmodel.traverse(visit, g) + +def polluted(translator): + """list functions with still real SomeObject variables""" + annotator = translator.annotator + def visit(block): + if isinstance(block, flowmodel.Block): + for v in block.getvariables(): + s = annotator.binding(v, extquery=True) + if s and s.__class__ == annmodel.SomeObject and s.knowntype != type: + raise Found + c = 0 + for f,g in translator.flowgraphs.iteritems(): + try: + flowmodel.traverse(visit, g) + except Found: + print f.__module__ or '?', f.__name__ + c += 1 + print c + + + + From hpk at codespeak.net Thu Jun 2 17:13:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 2 Jun 2005 17:13:43 +0200 (CEST) Subject: [pypy-svn] r13006 - pypy/extradoc/irclog Message-ID: <20050602151343.BB9A527B47@code1.codespeak.net> Author: hpk Date: Thu Jun 2 17:13:43 2005 New Revision: 13006 Added: pypy/extradoc/irclog/pypy-dev-meeting-06-02-2005.txt Modified: pypy/extradoc/irclog/ (props changed) Log: minutes of the pypy-dev IRC meeting 2nd June 2005 Added: pypy/extradoc/irclog/pypy-dev-meeting-06-02-2005.txt ============================================================================== --- (empty file) +++ pypy/extradoc/irclog/pypy-dev-meeting-06-02-2005.txt Thu Jun 2 17:13:43 2005 @@ -0,0 +1,86 @@ +pypy-dev meeting on #pypy at irc.freenode.net + + Thursday, 2nd June, 3pm (CEST == GMT+2) + +attendees: Armin Rigo, Samuele Pedroni, Carl Friedrich Bolz, + Holger Krekel, Anders Chrigstroem, Anders Lehmann, + Adrien di Mascio, Stelios Xanthakis, Bert Freudenberg + +topics and decisions: + +.. contents:: +.. sectnum:: + +------------------------------------------- +news/infos +------------------------------------------- + +Bert Freudenberg introduces himself as a Squeak Developer +since '97 who intends to enter the EU project and to come +to the Post-EuroPython sprint. + +Stelios Xanthakis (mayall) has been watching PyPy from the sideline. +He is the author of 'pyvm', a python virtual machine experiment. + +------------------------------------------- +short-term release planning +------------------------------------------- + +around 23rd of June we'd like to do a 0.6.2 release +which includes moving our lib-python base to 2.4.1 and +improved documentation (especially for newcomers). + +------------------------------------------- +sprint announcement/topics +------------------------------------------- + +although times and city are fixed already, the actual sprint +topics for the post-europython sprint from 1st-7th July (both +including) July in Goetheborg (Sweden) are not yet decided and +announced. However, almost all active developers will come and +it's already safe to reserve the time and book your flights +if you want to attend a newcomer-friendly sprint. + +Sprint topics (Armin has already formulated a more detailed topic +announcement draft in extradoc/sprintinfo/EP2005-announcement.txt): + +- translation : - rtyper (low-level impl of RPython objects) + - genc/genllvm (might be well advanced by EP) +- integrate parser module (possibly making it RPython + conformant) + +- various topics (name some examples from the tracker) + depending on people's interests + +------------------------------------------- +Advancing Issue Tracking: +------------------------------------------- + +Holger will extend/modify issue tracking so that + +- each issue is classsified as requiring hard, medium or easy efforts + (maybe name that 'effort' or something) + +- milestones should go in favour of a release-field which should + initially contain '0.6.2', '1.0' (mainly reflecting Milestone 1 + stuff) and 'general' (not yet tied to any release in particular) + + later we add release values like a possible 0.7 etc.pp. + +------------------------------------------- +stable base for Translation efforts +------------------------------------------- +giving the translation efforts a stable base: + +One problem with ongoing development of PyPy is that +the translation process is still somewhat fragile with +respect to type inference (annotation) on our source tree. + +-> resolved already before the meeting: see +Armin's pypy-dev posting. + +[current approach: pypy/translator/goal contains a stable +snapshot of interpreter, module and objspace directories +so that main-line changes don't disturb translation work, +run 'python translate_pypy.py targetpypy1.py' to get interactive +advise] From hpk at codespeak.net Thu Jun 2 17:14:18 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 2 Jun 2005 17:14:18 +0200 (CEST) Subject: [pypy-svn] r13007 - pypy/extradoc/sprintinfo Message-ID: <20050602151418.0CB6B27B4C@code1.codespeak.net> Author: hpk Date: Thu Jun 2 17:14:18 2005 New Revision: 13007 Added: pypy/extradoc/sprintinfo/EP2005-announcement.txt Log: Armin's draft topic announcement (logistics still missing) after our pypy-dev IRC discussion today. Added: pypy/extradoc/sprintinfo/EP2005-announcement.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/EP2005-announcement.txt Thu Jun 2 17:14:18 2005 @@ -0,0 +1,40 @@ + +Post-EuroPython 2005 PyPy Sprint Announcement +============================================== + +Time: 1st-7th July 2005 (both days including) +Location: Goetheborg, Sweden (more details to follow) + + +Draft topic announcement + +The main, though not the only, focus of the sprint will be on the +"translation" aspect of PyPy. We will progress towards a completely +translated PyPy. How much will already have been done before EuroPython +is unknown; as a guess, we will be left with: + +- completing the "rtyper", the piece of code that assigns low-level + C-like types to high-level RPython objects (lists, dicts, instances, + etc.) and low-level control flow graphs to high-level ones; + +- polish off the GenC and GenLLVM back-ends, responsible for turning + the low-level C-like flow graphs into real C or LLVM source code. + +Non-translation-related topics are welcome too. Here are some suggestions +from the issue tracker: + +- integrate the parser module, possibly making it RPython + conformant; + +- rewrite in Python a C module you are familiar with + (partial list of missing/incomplete modules: os, math, array, + regular expressions, binascii...) + +- implement Python 2.3's import hook extensions (zip-imports etc.) + +- fix Windows-related issues, '%'-formatting rounding errors, + add missing docstrings on app-level built-in types and functions, + etc. + +- weakrefs (but this requires discussion and planning on pypy-dev + before the sprint! feel free to start such a discussion, though.) From pedronis at codespeak.net Thu Jun 2 17:32:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 17:32:07 +0200 (CEST) Subject: [pypy-svn] r13008 - pypy/dist/pypy/annotation Message-ID: <20050602153207.C837427B4C@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 17:32:07 2005 New Revision: 13008 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: ignore None when computing the pbc maximal access sets, note that whether None reach a PBC access site should be recorded in the annotation of the site itself Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 2 17:32:07 2005 @@ -255,21 +255,32 @@ access_sets = self.pbc_maximal_access_sets objects = pbc.prebuiltinstances.keys() - - change, rep, access = access_sets.find(objects[0]) + access = None + first = None + change = False + for obj in objects: - change1, rep, access = access_sets.union(rep, obj) - change = change or change1 - - access.attrs[attr] = True - position = self.position_key - access.read_locations[position] = True + if obj is not None: + first = obj + break + + if first is not None: + change, rep, access = access_sets.find(objects[0]) + for obj in objects: + if obj is not None: + change1, rep, access = access_sets.union(rep, obj) + change = change or change1 + + access.attrs[attr] = True + position = self.position_key + access.read_locations[position] = True actuals = [] - for c in access.objects: - if hasattr(c, attr): - actuals.append(self.immutablevalue(getattr(c, attr))) + if access: + for c in access.objects: + if hasattr(c, attr): + actuals.append(self.immutablevalue(getattr(c, attr))) if change: for position in access.read_locations: From pedronis at codespeak.net Thu Jun 2 17:33:19 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 17:33:19 +0200 (CEST) Subject: [pypy-svn] r13009 - pypy/dist/pypy/translator/goal Message-ID: <20050602153319.1E7B227B4C@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 17:33:18 2005 New Revision: 13009 Modified: pypy/dist/pypy/translator/goal/query.py Log: pbcaccess() print nicely info about getattr access to PBCs Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 2 17:33:18 2005 @@ -45,7 +45,17 @@ print f.__module__ or '?', f.__name__ c += 1 print c - +def rep(bunch): + if len(bunch) == 1: + return "one", iter(bunch).next() + else: + t = dict.fromkeys([getattr(x, '__class__', type(x)) for x in bunch]).keys() + return "of types", t +def pbcaccess(translator): + bk = translator.annotator.bookkeeper + for inf in bk.pbc_maximal_access_sets.root_info.itervalues(): + objs = inf.objects + print len(objs), ' '.join(map(str,rep(objs))), inf.attrs.keys() From pedronis at codespeak.net Thu Jun 2 18:17:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 18:17:55 +0200 (CEST) Subject: [pypy-svn] r13010 - pypy/dist/pypy/translator/goal Message-ID: <20050602161755.0508527B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 18:17:55 2005 New Revision: 13010 Modified: pypy/dist/pypy/translator/goal/query.py Log: queries about PBCs (pbcs()) and captured mutables (mutables()) Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 2 18:17:55 2005 @@ -1,4 +1,5 @@ # functions to query information out of the translator and annotator from the debug prompt of translate_pypy +import types import pypy.annotation.model as annmodel import pypy.objspace.flow.model as flowmodel @@ -48,14 +49,37 @@ def rep(bunch): if len(bunch) == 1: - return "one", iter(bunch).next() + return ["one", iter(bunch).next()] else: t = dict.fromkeys([getattr(x, '__class__', type(x)) for x in bunch]).keys() - return "of types", t + return ["of type(s)"] + t + +def strfy(x): + try: + return x.__name__ + except AttributeError: + return str(x) def pbcaccess(translator): bk = translator.annotator.bookkeeper for inf in bk.pbc_maximal_access_sets.root_info.itervalues(): objs = inf.objects - print len(objs), ' '.join(map(str,rep(objs))), inf.attrs.keys() - + print len(objs), ' '.join(map(strfy,rep(objs))), inf.attrs.keys() + +# PBCs +def pbcs(translator): + bk = translator.annotator.bookkeeper + xs = bk.pbccache.keys() + funcs = [x for x in xs if isinstance(x, types.FunctionType)] + staticmethods = [x for x in xs if isinstance(x, staticmethod)] + instancemethods = [x for x in xs if isinstance(x, types.MethodType)] + typs = [x for x in xs if isinstance(x, (type, types.ClassType))] + rest = [x for x in xs if not isinstance(x, (types.FunctionType, staticmethod, types.MethodType, type, types.ClassType))] + for objs in (funcs, staticmethods, instancemethods, typs, rest): + print len(objs), ' '.join(map(strfy,rep(objs))) + +# mutable captured "constants") +def mutables(translator): + bk = translator.annotator.bookkeeper + xs = bk.seen_mutable.keys() + print len(xs), ' '.join(map(strfy,rep(xs))) From pedronis at codespeak.net Thu Jun 2 18:18:31 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 18:18:31 +0200 (CEST) Subject: [pypy-svn] r13011 - pypy/dist/pypy/annotation Message-ID: <20050602161831.D0E9F27B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 18:18:31 2005 New Revision: 13011 Modified: pypy/dist/pypy/annotation/binaryop.py Log: getitem on PBCs (especially None) fails Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 2 18:18:31 2005 @@ -494,6 +494,12 @@ def union((pbc, s)): return pair(s, pbc).union() +# getitem on SomePBCs, in particular None fails + +class __extend__(pairtype(SomePBC, SomeObject)): + def getitem((pbc, o)): + return SomeImpossibleValue() + # annotation of low-level types from pypy.annotation.model import SomePtr, ll_to_annotation From pedronis at codespeak.net Thu Jun 2 19:50:15 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 19:50:15 +0200 (CEST) Subject: [pypy-svn] r13012 - pypy/dist/pypy/translator/goal Message-ID: <20050602175015.5786427B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 19:50:15 2005 New Revision: 13012 Modified: pypy/dist/pypy/translator/goal/query.py Log: use the official way to get the pbcaccesssets Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 2 19:50:15 2005 @@ -61,8 +61,8 @@ return str(x) def pbcaccess(translator): - bk = translator.annotator.bookkeeper - for inf in bk.pbc_maximal_access_sets.root_info.itervalues(): + annotator = translator.annotator + for inf in annotator.getpbcaccesssets().root_info.itervalues(): objs = inf.objects print len(objs), ' '.join(map(strfy,rep(objs))), inf.attrs.keys() From pedronis at codespeak.net Thu Jun 2 20:15:31 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 20:15:31 +0200 (CEST) Subject: [pypy-svn] r13013 - pypy/dist/pypy/interpreter Message-ID: <20050602181531.0D10627B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 20:15:30 2005 New Revision: 13013 Modified: pypy/dist/pypy/interpreter/argument.py Log: helper method to retrieve the shape alone of a Arguments instance Modified: pypy/dist/pypy/interpreter/argument.py ============================================================================== --- pypy/dist/pypy/interpreter/argument.py (original) +++ pypy/dist/pypy/interpreter/argument.py Thu Jun 2 20:15:30 2005 @@ -222,17 +222,22 @@ ### Argument <-> list of w_objects together with "shape" information - def flatten(self): + def rawshape(self): shape_cnt = len(self.arguments_w) # Number of positional args shape_keys = self.kwds_w.keys() # List of keywords (strings) shape_star = self.w_stararg is not None # Flag: presence of *arg shape_stst = self.w_starstararg is not None # Flag: presence of **kwds + shape_keys.sort() + return shape_cnt, tuple(shape_keys), shape_star, shape_stst # shape_keys are sorted + + def flatten(self): + shape_cnt, shape_keys, shape_star, shape_stst = self.rawshape() data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys] if shape_star: data_w.append(self.w_stararg) if shape_stst: data_w.append(self.w_starstararg) - return (shape_cnt, tuple(shape_keys), shape_star, shape_stst), data_w + return (shape_cnt, shape_keys, shape_star, shape_stst), data_w def fromshape(space, (shape_cnt,shape_keys,shape_star,shape_stst), data_w): args_w = data_w[:shape_cnt] @@ -253,8 +258,6 @@ w_starstar = None return Arguments(space, args_w, kwds_w, w_star, w_starstar) fromshape = staticmethod(fromshape) - # XXX the "shape" tuple should be considered as a black box from - # other code, but translator/genc.h examines it. # From pedronis at codespeak.net Thu Jun 2 20:17:32 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 20:17:32 +0200 (CEST) Subject: [pypy-svn] r13014 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050602181732.17E1B27B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 20:17:31 2005 New Revision: 13014 Modified: pypy/branch/pypy-translation-snapshot/interpreter/argument.py Log: merging new .rawshape helper from trunk Modified: pypy/branch/pypy-translation-snapshot/interpreter/argument.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/argument.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/argument.py Thu Jun 2 20:17:31 2005 @@ -222,17 +222,22 @@ ### Argument <-> list of w_objects together with "shape" information - def flatten(self): + def rawshape(self): shape_cnt = len(self.arguments_w) # Number of positional args shape_keys = self.kwds_w.keys() # List of keywords (strings) shape_star = self.w_stararg is not None # Flag: presence of *arg shape_stst = self.w_starstararg is not None # Flag: presence of **kwds + shape_keys.sort() + return shape_cnt, tuple(shape_keys), shape_star, shape_stst # shape_keys are sorted + + def flatten(self): + shape_cnt, shape_keys, shape_star, shape_stst = self.rawshape() data_w = self.arguments_w + [self.kwds_w[key] for key in shape_keys] if shape_star: data_w.append(self.w_stararg) if shape_stst: data_w.append(self.w_starstararg) - return (shape_cnt, tuple(shape_keys), shape_star, shape_stst), data_w + return (shape_cnt, shape_keys, shape_star, shape_stst), data_w def fromshape(space, (shape_cnt,shape_keys,shape_star,shape_stst), data_w): args_w = data_w[:shape_cnt] @@ -253,8 +258,6 @@ w_starstar = None return Arguments(space, args_w, kwds_w, w_star, w_starstar) fromshape = staticmethod(fromshape) - # XXX the "shape" tuple should be considered as a black box from - # other code, but translator/genc.h examines it. # From pedronis at codespeak.net Thu Jun 2 20:37:58 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 20:37:58 +0200 (CEST) Subject: [pypy-svn] r13015 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050602183758.4F87727B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 20:37:57 2005 New Revision: 13015 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/translator/test/test_annrpython.py Log: gather maximal pbc call-sites' families with corresponding call argument patterns. annotator.getpbccallfamilies() returns a mapping PBC -> PBCallFamily (defined in bookkeeper.py) a PBCCallFamily contains a .objects dict with callable objects as keys and a .patterns attribute with keys of the form (None|, ). classdef is present in the case of bound method calls supplying a classdef-typed self. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 2 20:37:57 2005 @@ -8,7 +8,7 @@ from types import BuiltinMethodType from pypy.tool.ansi_print import ansi_print from pypy.annotation.model import * -from pypy.annotation.classdef import ClassDef +from pypy.annotation.classdef import ClassDef, isclassdef from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF from pypy.tool.sourcetools import func_with_new_name @@ -31,6 +31,14 @@ self.read_locations.update(other.read_locations) self.attrs.update(other.attrs) +class PBCCallFamily: + def __init__(self, obj): + self.objects = { obj: True } + self.patterns = {} + + def update(self, other): + self.objects.update(other.objects) + self.patterns.update(other.patterns) class Bookkeeper: """The log of choices that have been made while analysing the operations. @@ -56,6 +64,7 @@ self.argtypes_spec_callsite_results = {} self.pbc_maximal_access_sets = UnionFind(PBCAccessSet) + self.pbc_maximal_call_families = UnionFind(PBCCallFamily) # import ordering hack global BUILTIN_ANALYZERS @@ -288,6 +297,39 @@ return unionof(*actuals) + def pbc_call(self, pbc, args): + nonnullcallables = [] + patterns = {} + results = [] + # extract args shape + shape = args.rawshape() + + for func, classdef in pbc.prebuiltinstances.items(): + if func is None: + continue + if isclassdef(classdef): + s_self = SomeInstance(classdef) + args1 = args.prepend(s_self) + pattern = (classdef, shape) + else: + args1 = args + pattern = (None, shape) + results.append(self.pycall(func, args1)) + + nonnullcallables.append(func) + patterns[pattern] = True + + if nonnullcallables: + call_families = self.pbc_maximal_call_families + + dontcare, rep, callfamily = call_families.find(nonnullcallables[0]) + for obj in nonnullcallables: + dontcare, rep, callfamily = call_families.union(rep, obj) + + callfamily.patterns.update(patterns) + + return unionof(*results) + def pycall(self, func, args): if func is None: # consider None as a NULL function pointer return SomeImpossibleValue() Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Thu Jun 2 20:37:57 2005 @@ -382,32 +382,23 @@ bookkeeper = getbookkeeper() return bookkeeper.pbc_getattr(pbc, s_attr) -## assert s_attr.is_constant() -## attr = s_attr.const -## actuals = [] -## for c in pbc.prebuiltinstances: -## if hasattr(c, attr): -## # force the attribute to be considered on the class -## ##classdef = bookkeeper.getclassdef(new_or_old_class(c)) -## ##classdef.find_attribute(attr).getvalue() -## # but only return the more precise result getattr(c, attr) -## actuals.append(immutablevalue(getattr(c, attr))) -## return unionof(*actuals) - def setattr(pbc, s_attr, s_value): getbookkeeper().warning("setattr not wanted on %r" % (pbc,)) def call(pbc, args): bookkeeper = getbookkeeper() - results = [] - for func, classdef in pbc.prebuiltinstances.items(): - if isclassdef(classdef): - s_self = SomeInstance(classdef) - args1 = args.prepend(s_self) - else: - args1 = args - results.append(bookkeeper.pycall(func, args1)) - return unionof(*results) + return bookkeeper.pbc_call(pbc, args) + + #bookkeeper = getbookkeeper() + #results = [] + #for func, classdef in pbc.prebuiltinstances.items(): + # if isclassdef(classdef): + # s_self = SomeInstance(classdef) + # args1 = args.prepend(s_self) + # else: + # args1 = args + # results.append(bookkeeper.pycall(func, args1)) + #return unionof(*results) def bindcallables(pbc, classdef): """ turn the callables in the given SomeCallable 'cal' Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Thu Jun 2 20:37:57 2005 @@ -806,6 +806,86 @@ assert access_sets[c1] is acc1 py.test.raises(KeyError, "access_sets[object()]") + + def test_simple_pbc_call(self): + def f1(x,y=0): + pass + def f2(x): + pass + def f3(x): + pass + def g(f): + f(1) + def h(): + f1(1) + f1(1,2) + g(f2) + g(f3) + + a = self.RPythonAnnotator() + s = a.build_types(h, []) + + call_families = a.getpbccallfamilies() + + ign, rep1, fam1 = call_families.find(f1) + ign, rep2, fam2 = call_families.find(f2) + ign, rep3, fam3 = call_families.find(f3) + + assert rep1 is not rep2 + assert rep1 is not rep3 + assert rep3 is rep2 + + assert fam1 is not fam2 + assert fam1 is not fam3 + assert fam3 is fam2 + + assert len(fam1.patterns) == 2 + assert len(fam2.patterns) == 1 + + assert fam1.patterns == {(None, (2, (), False, False)): True, (None, (1, (), False, False)): True} + assert fam2.patterns == {(None, (1, (), False, False)): True} + + def test_pbc_call_ins(self): + class A(object): + def m(self): + pass + class B(A): + def n(self): + pass + class C(A): + def m(self): + pass + def f(x): + b = B() + c = C() + b.n() + if x: + a = b + else: + a = c + a.m() + + a = self.RPythonAnnotator() + s = a.build_types(f, [bool]) + + call_families = a.getpbccallfamilies() + + ign, repA_m, famA_m = call_families.find(A.m.im_func) + ign, repC_m, famC_m = call_families.find(C.m.im_func) + ign, repB_n, famB_n = call_families.find(B.n.im_func) + + assert famA_m is famC_m + assert famB_n is not famA_m + + assert len(famB_n.patterns) == 1 + assert len(famC_m.patterns) == 2 + + Aclsdef = a.getuserclasses()[A] + Bclsdef = a.getuserclasses()[B] + Cclsdef = a.getuserclasses()[C] + + assert famB_n.patterns == {(Bclsdef, (0, (), False, False)): True} + assert famA_m.patterns == {(Aclsdef, (0, (), False, False)): True, (Cclsdef, (0, (), False, False)): True} def test_isinstance_usigned(self): def f(x): From pedronis at codespeak.net Thu Jun 2 22:24:35 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 22:24:35 +0200 (CEST) Subject: [pypy-svn] r13016 - pypy/dist/pypy/translator Message-ID: <20050602202435.29E4A27B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 22:24:34 2005 New Revision: 13016 Modified: pypy/dist/pypy/translator/annrpython.py Log: oops, missing from recent checkin Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Thu Jun 2 22:24:34 2005 @@ -120,6 +120,10 @@ def getpbcaccesssets(self): """Return mapping const obj -> PBCAccessSet""" return self.bookkeeper.pbc_maximal_access_sets + + def getpbccallfamilies(self): + """Return mapping const obj -> PBCCallFamily""" + return self.bookkeeper.pbc_maximal_call_families #___ medium-level interface ____________________________ From pedronis at codespeak.net Thu Jun 2 22:26:32 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 22:26:32 +0200 (CEST) Subject: [pypy-svn] r13017 - pypy/dist/pypy/translator/goal Message-ID: <20050602202632.D82DA27B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 22:26:32 2005 New Revision: 13017 Modified: pypy/dist/pypy/translator/goal/query.py Log: pbccall, query about pbc call families Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 2 22:26:32 2005 @@ -83,3 +83,81 @@ bk = translator.annotator.bookkeeper xs = bk.seen_mutable.keys() print len(xs), ' '.join(map(strfy,rep(xs))) + +def prettypatt(patts): + accum = [] + wslf = False + woslf = False + patts.sort() + for slf, (sh_cnt, sh_ks, sh_st, sh_stst) in patts: + arg = [] + if slf is None: + woslf = True + else: + wslf = True + arg.append(slf) + arg.append("+%d" % sh_cnt) + for kw in sh_ks: + arg.append("%s=" % kw) + if sh_st: + arg.append('*') + if sh_stst: + arg.append('**') + accum.append("(%s)" % ', '.join(arg)) + if wslf and woslf: + accum.append("!!!") + return ' '.join(accum) + + +def pbccall(translator): + fams = translator.annotator.getpbccallfamilies().root_info.itervalues() + one_pattern_fams = {} + rest = [] + for fam in fams: + patts = {} + for clsdef, sh in fam.patterns: + if clsdef is None: + slf = None + else: + slf = 'self' + patts[(slf, sh)] = True + if len(patts) != 1: + rest.append((len(fam.objects), fam.objects, patts.keys())) + else: + cntrs = one_pattern_fams.setdefault(patts.keys()[0], [0,0]) + cntrs[0] += 1 + cntrs[1] += len(fam.objects) + + def pretty_nfam(nfam): + if nfam == 1: + return "1 family" + else: + return "%d families" % nfam + + def pretty_nels(nels): + if nels == 1: + return "one callable" + else: + return "in total %d callables" % nels + + def pretty_els(objs): + accum = [] + for obj in objs: + if isinstance(obj, types.FunctionType): + accum.append("%s:%s" % (obj.__module__ or '?', obj.__name__)) + else: + accum.append(str(obj)) + return "{%s}" % ' '.join(accum) + + for patt, (nfam, nels) in one_pattern_fams.iteritems(): + print pretty_nfam(nfam), "with", pretty_nels(nels), "with one call-pattern:", prettypatt([patt]) + + print "- * -" + + rest.sort(lambda a,b: cmp(a[0], b[0])) + + for n, objs, patts in rest: + print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) + + + From pedronis at codespeak.net Thu Jun 2 22:39:20 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 22:39:20 +0200 (CEST) Subject: [pypy-svn] r13018 - pypy/dist/pypy/translator/goal Message-ID: <20050602203920.5A4E227B4D@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 22:39:20 2005 New Revision: 13018 Modified: pypy/dist/pypy/translator/goal/query.py Log: pbccall: a bit more info, in particular about the different kinds of callables in the families Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 2 22:39:20 2005 @@ -124,7 +124,12 @@ if len(patts) != 1: rest.append((len(fam.objects), fam.objects, patts.keys())) else: - cntrs = one_pattern_fams.setdefault(patts.keys()[0], [0,0]) + kinds = dict.fromkeys([getattr(obj, '__class__', type(obj)) for obj in fam.objects]).keys() + kinds.sort() + + flavor = tuple(kinds), patts.keys()[0] + + cntrs = one_pattern_fams.setdefault(flavor, [0,0]) cntrs[0] += 1 cntrs[1] += len(fam.objects) @@ -134,11 +139,11 @@ else: return "%d families" % nfam - def pretty_nels(nels): + def pretty_nels(kinds, nels): if nels == 1: - return "one callable" + return "one %s" % kinds[0].__name__.title() else: - return "in total %d callables" % nels + return "in total %d %s" % (nels, '|'.join([kind.__name__.title()+'(s)' for kind in kinds])) def pretty_els(objs): accum = [] @@ -149,8 +154,8 @@ accum.append(str(obj)) return "{%s}" % ' '.join(accum) - for patt, (nfam, nels) in one_pattern_fams.iteritems(): - print pretty_nfam(nfam), "with", pretty_nels(nels), "with one call-pattern:", prettypatt([patt]) + for (kinds, patt), (nfam, nels) in one_pattern_fams.iteritems(): + print pretty_nfam(nfam), "with", pretty_nels(kinds, nels), "with one call-pattern:", prettypatt([patt]) print "- * -" From arigo at codespeak.net Thu Jun 2 22:54:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Jun 2005 22:54:31 +0200 (CEST) Subject: [pypy-svn] r13019 - pypy/branch/rpython-refactoring Message-ID: <20050602205431.3684427B48@code1.codespeak.net> Author: arigo Date: Thu Jun 2 22:54:31 2005 New Revision: 13019 Added: pypy/branch/rpython-refactoring/ - copied from r13002, pypy/dist/pypy/rpython/ Modified: pypy/branch/rpython-refactoring/rbool.py pypy/branch/rpython-refactoring/rfloat.py pypy/branch/rpython-refactoring/rint.py pypy/branch/rpython-refactoring/robject.py pypy/branch/rpython-refactoring/rtyper.py Log: Intermediate branch check-in for the pypy/rpython subdirectory only. XXX Describe the refactoring in a later check-in Modified: pypy/branch/rpython-refactoring/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/branch/rpython-refactoring/rbool.py Thu Jun 2 22:54:31 2005 @@ -1,30 +1,19 @@ from pypy.annotation.pairtype import pairtype -from pypy.annotation.model import SomeFloat, SomeInteger, SomeBool, SomePBC +from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float -from pypy.rpython.rtyper import TyperError +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, BoolRepr debug = False -class __extend__(pairtype(SomeBool, SomeInteger)): +class __extend__(annmodel.SomeBool): + def rtyper_makerepr(self, rtyper): + return bool_repr - def rtype_convert_from_to((s_from, s_to), v, llops): - if s_to.unsigned: - if debug: print 'explicit cast_bool_to_uint' - return llops.genop('cast_bool_to_uint', [v], resulttype=Unsigned) - else: - if debug: print 'explicit cast_bool_to_int' - return llops.genop('cast_bool_to_int', [v], resulttype=Signed) - - -class __extend__(pairtype(SomeBool, SomeFloat)): - - def rtype_convert_from_to((s_from, s_to), v, llops): - if debug: print 'explicit cast_bool_to_float' - return llops.genop('cast_bool_to_float', [v], resulttype=Float) +bool_repr = BoolRepr() -class __extend__(SomeBool): +class __extend__(BoolRepr): def rtype_is_true(_, hop): vlist = hop.inputargs(Bool) @@ -37,3 +26,15 @@ def rtype_float(_, hop): vlist = hop.inputargs(Float) return vlist[0] + +# +# _________________________ Conversions _________________________ + +class __extend__(pairtype(BoolRepr, IntegerRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Unsigned: + if debug: print 'explicit cast_bool_to_uint' + return llops.genop('cast_bool_to_uint', [v], resulttype=Unsigned) + else: + if debug: print 'explicit cast_bool_to_int' + return llops.genop('cast_bool_to_int', [v], resulttype=Signed) Modified: pypy/branch/rpython-refactoring/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/branch/rpython-refactoring/rfloat.py Thu Jun 2 22:54:31 2005 @@ -1,12 +1,20 @@ from pypy.annotation.pairtype import pairtype -from pypy.annotation.model import SomeFloat, SomeInteger, SomeBool, SomePBC +from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void -from pypy.rpython.rtyper import TyperError +from pypy.rpython.rmodel import Repr, TyperError, FloatRepr +from pypy.rpython.rmodel import IntegerRepr, BoolRepr debug = False -class __extend__(pairtype(SomeFloat, SomeFloat)): +class __extend__(annmodel.SomeFloat): + def rtyper_makerepr(self, rtyper): + return float_repr + +float_repr = FloatRepr() + + +class __extend__(pairtype(FloatRepr, FloatRepr)): #Arithmetic @@ -64,7 +72,7 @@ return _rtype_compare_template(hop, 'ge') -#Helpers SomeFloat,Somefloat +#Helpers FloatRepr,FloatRepr def _rtype_template(hop, func): vlist = hop.inputargs(Float, Float) @@ -74,47 +82,9 @@ vlist = hop.inputargs(Float, Float) return hop.genop('float_'+func, vlist, resulttype=Bool) - -# - -## XXX we have probably no implicit casts from float to integer -##class __extend__(pairtype(SomeFloat, SomeInteger)): - -## def rtype_convert_from_to((s_from, s_to), v): -## if s_to.unsigned: -## if debug: print 'explicit cast_float_to_uint' -## return direct_op('cast_float_to_uint', [v], resulttype=Unsigned) -## else: -## if debug: print 'explicit cast_float_to_int' -## return direct_op('cast_float_to_int', [v], resulttype=Signed) - - # -class __extend__(pairtype(SomeInteger, SomeFloat)): - - def rtype_convert_from_to((s_from, s_to), v, llops): - if s_from.unsigned: - if debug: print 'explicit cast_uint_to_float' - return llops.genop('cast_uint_to_float', [v], resulttype=Float) - else: - if debug: print 'explicit cast_int_to_float' - return llops.genop('cast_int_to_float', [v], resulttype=Float) - - -# - -## XXX we have probably no implicit casts from float to bool -##class __extend__(pairtype(SomeFloat, SomeBool)): - -## def rtype_convert_from_to((s_from, s_to), v): -## if debug: print 'explicit cast_float_to_bool' -## return direct_op('cast_float_to_bool', [v], resulttype=Bool) #XXX or can 'float_is_true' be reused here? - - -# - -class __extend__(SomeFloat): +class __extend__(FloatRepr): def rtype_is_true(_, hop): vlist = hop.inputargs(Float) @@ -133,3 +103,20 @@ return hop.genop('cast_float_to_int', vlist, resulttype=Signed) rtype_float = rtype_pos + +# +# _________________________ Conversions _________________________ + +class __extend__(pairtype(IntegerRepr, FloatRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.unsigned: + if debug: print 'explicit cast_uint_to_float' + return llops.genop('cast_uint_to_float', [v], resulttype=Float) + else: + if debug: print 'explicit cast_int_to_float' + return llops.genop('cast_int_to_float', [v], resulttype=Float) + +class __extend__(pairtype(BoolRepr, FloatRepr)): + def convert_from_to(_, v, llops): + if debug: print 'explicit cast_bool_to_float' + return llops.genop('cast_bool_to_float', [v], resulttype=Float) Modified: pypy/branch/rpython-refactoring/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/branch/rpython-refactoring/rint.py Thu Jun 2 22:54:31 2005 @@ -1,18 +1,29 @@ from pypy.annotation.pairtype import pairtype -from pypy.annotation.model import SomeFloat, SomeInteger, SomeBool, SomePBC -from pypy.annotation.model import SomeObject +from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void -from pypy.rpython.rtyper import TyperError -from pypy.rpython.robject import PyObjPtr +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.robject import PyObjRepr debug = False -class __extend__(pairtype(SomeInteger, SomeInteger)): +class __extend__(annmodel.SomeInteger): + def rtyper_makerepr(self, rtyper): + if self.unsigned: + return unsigned_repr + else: + return signed_repr + +signed_repr = IntegerRepr() +unsigned_repr = IntegerRepr() +unsigned_repr.lowleveltype = Unsigned + + +class __extend__(pairtype(IntegerRepr, IntegerRepr)): - def rtype_convert_from_to((s_from, s_to), v, llops): - if s_from.unsigned != s_to.unsigned: - if s_to.unsigned: + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype != r_to.lowleveltype: + if r_to.lowleveltype == Unsigned: if debug: print 'explicit cast_int_to_uint' return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned) else: @@ -148,10 +159,14 @@ # -class __extend__(SomeInteger): +class __extend__(IntegerRepr): - def rtype_is_true(s_int, hop): - if s_int.unsigned: + def rtype_float(_, hop): + vlist = hop.inputargs(Float) + return vlist[0] + + def rtype_is_true(self, hop): + if self.lowleveltype == Unsigned: vlist = hop.inputargs(Unsigned) return hop.genop('uint_is_true', vlist, resulttype=Bool) else: @@ -210,28 +225,22 @@ return vlist[0] # +# _________________________ Conversions _________________________ -class __extend__(pairtype(SomeObject, SomeInteger)): - - def rtype_convert_from_to((s_obj, s_int), v, llops): - if s_obj.lowleveltype() != PyObjPtr: - return NotImplemented - if s_int.unsigned: +class __extend__(pairtype(PyObjRepr, IntegerRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Unsigned: return llops.gencapicall('PyLong_AsUnsignedLong', [v], resulttype=Unsigned) else: return llops.gencapicall('PyInt_AsLong', [v], resulttype=Signed) - -class __extend__(pairtype(SomeInteger, SomeObject)): - - def rtype_convert_from_to((s_int, s_obj), v, llops): - if s_obj.lowleveltype() != PyObjPtr: - return NotImplemented - if s_int.unsigned: +class __extend__(pairtype(IntegerRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Unsigned: return llops.gencapicall('PyLong_FromUnsignedLong', [v], resulttype=PyObjPtr) else: return llops.gencapicall('PyInt_FromLong', [v], - resulttype=PyObjPtr) + resulttype=PyObjRepr) Modified: pypy/branch/rpython-refactoring/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/branch/rpython-refactoring/robject.py Thu Jun 2 22:54:31 2005 @@ -1,72 +1,27 @@ from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeObject, annotation_to_lltype from pypy.annotation import model as annmodel from pypy.rpython.lltype import PyObject, GcPtr, Void, Bool -from pypy.rpython.rtyper import TyperError, inputconst -from pypy.rpython import rclass +from pypy.rpython.rmodel import Repr, TyperError +#from pypy.rpython import rclass -PyObjPtr = GcPtr(PyObject) - - -def missing_rtype_operation(args, hop): - raise TyperError("unimplemented operation: '%s' on %r" % ( - hop.spaceop.opname, args)) - -for opname in annmodel.UNARY_OPERATIONS: - setattr(SomeObject, 'rtype_' + opname, missing_rtype_operation) -for opname in annmodel.BINARY_OPERATIONS: - setattr(pairtype(SomeObject, SomeObject), - 'rtype_' + opname, missing_rtype_operation) - - -class __extend__(SomeObject): - - def lowleveltype(s_obj): - try: - return annotation_to_lltype(s_obj) - except ValueError: - if s_obj.is_constant(): - return Void - elif s_obj.knowntype is type: - return rclass.TYPEPTR - else: - return PyObjPtr - - def rtype_getattr(s_obj, hop): - s_attr = hop.args_s[1] - if s_attr.is_constant() and isinstance(s_attr.const, str): - attr = s_attr.const - try: - s_obj.find_method(attr) # just to check it is here - except AttributeError: - raise TyperError("no method %s on %r" % (attr, s_obj)) - else: - # implement methods (of a known name) as just their 'self' - return hop.inputarg(s_obj, arg=0) +class __extend__(annmodel.SomeObject): + def rtyper_makerepr(self, rtyper): + if self.is_constant(): + return constobj_repr + if self.knowntype is type: + return rclass.type_repr else: - raise TyperError("getattr() with a non-constant attribute name") + return pyobj_repr - def rtype_is_true(s_obj, hop): - if hasattr(s_obj, "rtype_len"): - vlen = s_obj.rtype_len(hop) - return hop.genop('int_is_true', [vlen], resulttype=Bool) - else: - return hop.inputconst(Bool, True) - def rtype_nonzero(s_obj, hop): - return s_obj.rtype_is_true(hop) # can call a subclass' rtype_is_true() +class PyObjRepr(Repr): + lowleveltype = GcPtr(PyObject) +pyobj_repr = PyObjRepr() -class __extend__(pairtype(SomeObject, SomeObject)): - def rtype_convert_from_to((s_from, s_to), v, llops): - FROM = s_from.lowleveltype() - TO = s_to.lowleveltype() - if (PyObjPtr == FROM == TO) or (rclass.TYPEPTR == FROM == TO): - return v - elif FROM == Void and s_from.is_constant() and s_to.contains(s_from): - # convert from a constant to a non-constant - return inputconst(TO, s_from.const) - else: - return NotImplemented +class ConstObjRepr(Repr): + lowleveltype = Void + +constobj_repr = ConstObjRepr() Modified: pypy/branch/rpython-refactoring/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/branch/rpython-refactoring/rtyper.py Thu Jun 2 22:54:31 2005 @@ -3,31 +3,68 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation -from pypy.rpython.lltype import Void, LowLevelType, NonGcPtr, ContainerType +from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void +from pypy.rpython.lltype import LowLevelType, NonGcPtr, ContainerType from pypy.rpython.lltype import FuncType, functionptr, typeOf from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block +from pypy.rpython.rmodel import Repr, inputconst, TyperError +debug = False +crash_on_first_typeerror = False + # XXX copied from pypy.translator.typer and modified. # We'll remove pypy.translator.typer at some point. # It also borrows a bit from pypy.translator.annrpython. -class TyperError(Exception): - def __str__(self): - result = Exception.__str__(self) - if hasattr(self, 'where'): - result += '\n.. %r\n.. %r' % self.where - return result - - class RPythonTyper: def __init__(self, annotator): self.annotator = annotator + self.reprs_by_id = {} + self.reprs_by_content = {} self.specialized_ll_functions = {} self.rclassdefs = {} self.typererror = None + # make the primitive_to_repr constant mapping + self.primitive_to_repr = {} + for s_primitive, lltype in annmodel.annotation_to_ll_map: + r = self.getrepr(s_primitive) + self.primitive_to_repr[r.lowleveltype] = r + + def getrepr(self, s_obj): + # s_objs are not hashable... try hard to find a hash anyway + try: + return self.reprs_by_id[id(s_obj)] + except KeyError: + key = [s_obj.__class__] + items = s_obj.__dict__.items() + items.sort() + for name, value in items: + key.append(name) + key.append(Constant(value)) + key = tuple(key) + try: + result = self.reprs_by_content[key] + except KeyError: + # here is the code that actually builds a Repr instance + result = s_obj.rtyper_makerepr(self) + assert not isinstance(result.lowleveltype, ContainerType), ( + "missing a GcPtr or NonGcPtr in the type specification " + "of %s:\n%r" % (s_obj, result.lowleveltype)) + self.reprs_by_content[key] = result + self.reprs_by_id[id(s_obj)] = result + return result + + def binding(self, var): + s_obj = self.annotator.binding(var, True) + if s_obj is None: + s_obj = annmodel.SomeObject() + return s_obj + + def bindingrepr(self, var): + return self.getrepr(self.binding(var)) def specialize(self): """Main entry point: specialize all annotated blocks of the program.""" @@ -49,9 +86,7 @@ def setconcretetype(self, v): assert isinstance(v, Variable) - s_value = self.annotator.binding(v, True) - if s_value is not None: - v.concretetype = s_value.lowleveltype() + v.concretetype = self.bindingrepr(v).lowleveltype def specialize_block(self, block): # give the best possible types to the input args @@ -69,6 +104,7 @@ self.translate_hl_to_ll(hop, varmapping) except TyperError, e: self.gottypererror(e, block, op, newops) + return # cannot continue this block: no op.result.concretetype block.operations[:] = newops # multiple renamings (v1->v2->v3->...) are possible @@ -93,16 +129,16 @@ for i in range(len(link.args)): a1 = link.args[i] a2 = link.target.inputargs[i] - s_a2 = self.annotator.binding(a2) + r_a2 = self.bindingrepr(a2) if isinstance(a1, Constant): - link.args[i] = inputconst(s_a2.lowleveltype(), a1.value) + link.args[i] = inputconst(r_a2, a1.value) continue # the Constant was typed, done - s_a1 = self.annotator.binding(a1) - if s_a1 == s_a2: + r_a1 = self.bindingrepr(a1) + if r_a1 == r_a2: continue # no conversion needed newops = LowLevelOpList(self) try: - a1 = newops.convertvar(a1, s_a1, s_a2) + a1 = newops.convertvar(a1, r_a1, r_a2) except TyperError, e: self.gottypererror(e, block, link, newops) @@ -120,6 +156,8 @@ link.args[i] = a1 def translate_hl_to_ll(self, hop, varmapping): + if debug: + print hop.spaceop.opname, hop.args_s op = hop.spaceop translate_meth = getattr(self, 'translate_op_'+op.opname, self.missing_operation) @@ -135,31 +173,35 @@ # op.result here. We have to replace resultvar with op.result # in all generated operations. resulttype = resultvar.concretetype - op.result.concretetype = hop.s_result.lowleveltype() + op.result.concretetype = hop.r_result.lowleveltype if op.result.concretetype != resulttype: raise TyperError("inconsistent type for the result of '%s':\n" - "annotator says %r\n" - " rtyper says %r" % (op.opname, - op.result.concretetype, - resulttype)) + "annotator says %s,\n" + "whose lltype is %r\n" + "but rtype* says %r" % ( + op.opname, hop.s_result, + op.result.concretetype, resulttype)) while resultvar in varmapping: resultvar = varmapping[resultvar] varmapping[resultvar] = op.result else: # translate_meth() returned a Constant + assert isinstance(resultvar, Constant) if not hop.s_result.is_constant(): raise TyperError("the annotator doesn't agree that '%s' " "returns a constant" % op.opname) if resultvar.value != hop.s_result.const: raise TyperError("constant mismatch: %r vs %r" % ( resultvar.value, hop.s_result.const)) - op.result.concretetype = hop.s_result.lowleveltype() + op.result.concretetype = hop.r_result.lowleveltype def gottypererror(self, e, block, position, llops): """Record a TyperError without crashing immediately. Put a 'TyperError' operation in the graph instead. """ e.where = (block, position) + if crash_on_first_typeerror: + raise if self.typererror is None: self.typererror = sys.exc_info() c1 = inputconst(Void, Exception.__str__(e)) @@ -172,16 +214,16 @@ for opname in annmodel.UNARY_OPERATIONS: exec """ def translate_op_%s(self, hop): - s_arg1 = hop.args_s[0] - return s_arg1.rtype_%s(hop) + r_arg1 = hop.args_r[0] + return r_arg1.rtype_%s(hop) """ % (opname, opname) in globals(), loc # All binary operations for opname in annmodel.BINARY_OPERATIONS: exec """ def translate_op_%s(self, hop): - s_arg1 = hop.args_s[0] - s_arg2 = hop.args_s[1] - return pair(s_arg1, s_arg2).rtype_%s(hop) + r_arg1 = hop.args_r[0] + r_arg2 = hop.args_r[1] + return pair(r_arg1, r_arg2).rtype_%s(hop) """ % (opname, opname) in globals(), loc _registeroperations(locals()) @@ -213,22 +255,6 @@ # ____________________________________________________________ -def inputconst(type, value): - """Return a Constant with the given value, of the requested type. - 'type' can be a SomeXxx annotation or a low-level type. - """ - if isinstance(type, LowLevelType): - lowleveltype = type - else: - lowleveltype = type.lowleveltype() - assert not isinstance(lowleveltype, ContainerType), ( - "missing a GcPtr or NonGcPtr in the type specification of %r" % - (lowleveltype,)) - c = Constant(value) - c.concretetype = lowleveltype - return c - -# ____________________________________________________________ class HighLevelOp: nb_popped = 0 @@ -238,28 +264,32 @@ self.spaceop = spaceop self.nb_args = len(spaceop.args) self.llops = llops - self.args_s = [rtyper.annotator.binding(a) for a in spaceop.args] - self.s_result = rtyper.annotator.binding(spaceop.result) + self.args_s = [rtyper.binding(a) for a in spaceop.args] + self.s_result = rtyper.binding(spaceop.result) + self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] + self.r_result = rtyper.getrepr(self.s_result) def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, as a Variable or Constant converted to the requested type. - 'converted_to' can be a SomeXxx annotation or a primitive low-level + 'converted_to' should be a Repr instance or a Primitive low-level type. """ v = self.spaceop.args[self.nb_popped + arg] if isinstance(v, Constant): return inputconst(converted_to, v.value) + assert hasattr(v, 'concretetype') s_binding = self.args_s[arg] - if s_binding is None: - s_binding = annmodel.SomeObject() if s_binding.is_constant(): return inputconst(converted_to, s_binding.const) - if isinstance(converted_to, LowLevelType): - converted_to = annmodel.lltype_to_annotation(converted_to) - return self.llops.convertvar(v, s_binding, converted_to) + if not isinstance(converted_to, Repr): + converted_to = self.rtyper.primitive_to_repr[converted_to] + r_binding = self.args_r[arg] + return self.llops.convertvar(v, r_binding, converted_to) + + inputconst = staticmethod(inputconst) # export via the HighLevelOp class def inputargs(self, *converted_to): assert len(converted_to) == self.nb_args, ( @@ -270,8 +300,6 @@ vars.append(self.inputarg(converted_to[i], i)) return vars - inputconst = staticmethod(inputconst) # export via the HighLevelOp class - def genop(self, opname, args_v, resulttype=None): return self.llops.genop(opname, args_v, resulttype) @@ -282,6 +310,7 @@ "Return and discard the first argument." self.nb_popped += 1 self.nb_args -= 1 + self.args_r.pop(0) return self.args_s.pop(0) # ____________________________________________________________ @@ -293,13 +322,13 @@ def __init__(self, rtyper): self.rtyper = rtyper - def convertvar(self, v, s_from, s_to): + def convertvar(self, v, r_from, r_to): assert isinstance(v, Variable) - if s_from != s_to: - v = pair(s_from, s_to).rtype_convert_from_to(v, self) + if r_from != r_to: + v = pair(r_from, r_to).convert_from_to(v, self) if v is NotImplemented: - raise TyperError("don't know how to convert from %r to %r" % ( - s_from, s_to)) + raise TyperError("don't know how to convert from %r to %r" % + (r_from, r_to)) return v def genop(self, opname, args_v, resulttype=None): @@ -309,20 +338,21 @@ vresult.concretetype = Void return None else: + if isinstance(resulttype, Repr): + resulttype = resulttype.lowleveltype + assert isinstance(resulttype, LowLevelType) vresult.concretetype = resulttype return vresult def gendirectcall(self, ll_function, *args_v): - annotator = self.rtyper.annotator + rtyper = self.rtyper spec_key = [ll_function] spec_name = [ll_function.func_name] args_s = [] for v in args_v: - s_value = annotator.binding(v, True) - if s_value is None: - s_value = annmodel.SomeObject() + r_value = rtyper.bindingrepr(v) if v.concretetype == Void: - if not s_value.is_constant(): + if not r_value.s_obj.is_constant(): raise TyperError("non-constant variable of type Void") key = s_value.const # specialize by constant value args_s.append(s_value) @@ -362,5 +392,8 @@ # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations -from pypy.rpython import robject, rlist, rptr, rbuiltin, rint, rbool, rfloat -from pypy.rpython import rpbc, rstr, riter +# and the rtyper_chooserepr() methods +#from pypy.rpython import robject, rlist, rptr, rbuiltin, rint, rbool, rfloat +#from pypy.rpython import rpbc, rstr, riter + +from pypy.rpython import robject, rint, rbool, rfloat From arigo at codespeak.net Thu Jun 2 22:55:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 2 Jun 2005 22:55:14 +0200 (CEST) Subject: [pypy-svn] r13020 - pypy/branch/rpython-refactoring Message-ID: <20050602205514.A482627B48@code1.codespeak.net> Author: arigo Date: Thu Jun 2 22:55:14 2005 New Revision: 13020 Added: pypy/branch/rpython-refactoring/rmodel.py (contents, props changed) Log: Forgot to check this file in. Added: pypy/branch/rpython-refactoring/rmodel.py ============================================================================== --- (empty file) +++ pypy/branch/rpython-refactoring/rmodel.py Thu Jun 2 22:55:14 2005 @@ -0,0 +1,113 @@ +from pypy.annotation.pairtype import pair, pairtype, extendabletype +from pypy.annotation import model as annmodel +from pypy.objspace.flow.model import Constant +from pypy.rpython.lltype import Void, Bool + + +class Repr: + """ An instance of Repr is associated with each instance of SomeXxx. + It defines the chosen representation for the SomeXxx. The Repr subclasses + generally follows the SomeXxx subclass hierarchy, but there are numerous + exceptions. For example, the anotator uses SomeIter for any iterator, but + we need different representations according to the type of container we are + iterating over. + """ + __metaclass__ = extendabletype + + def __repr__(self): + return '<%s %s>' % (self.__class__.__name__, self.lowleveltype) + + # default implementation of some operations + + def rtype_getattr(self, hop): + s_attr = hop.args_s[1] + if s_attr.is_constant() and isinstance(s_attr.const, str): + attr = s_attr.const + s_obj = hop.args_s[0] + try: + s_obj.find_method(attr) # just to check it is here + except AttributeError: + raise TyperError("no method %s on %r" % (attr, s_obj)) + else: + # implement methods (of a known name) as just their 'self' + return hop.inputarg(self, arg=0) + else: + raise TyperError("getattr() with a non-constant attribute name") + + def rtype_nonzero(self, hop): + return self.rtype_is_true(hop) # can call a subclass' rtype_is_true() + + def rtype_is_true(self, hop): + try: + vlen = self.rtype_len(hop) + except MissingRTypeOperation: + return hop.inputconst(Bool, True) + else: + return hop.genop('int_is_true', [vlen], resulttype=Bool) + +# ____________________________________________________________ + +class TyperError(Exception): + def __str__(self): + result = Exception.__str__(self) + if hasattr(self, 'where'): + result += '\n.. %r\n.. %r' % self.where + return result + +class MissingRTypeOperation(TyperError): + pass + +def missing_rtype_operation(self, hop): + raise MissingRTypeOperation("unimplemented operation: '%s' on %r" % ( + hop.spaceop.opname, self)) + +def setattr_default(obj, attr, value): + if not hasattr(obj, attr): + setattr(obj, attr, value) + +for opname in annmodel.UNARY_OPERATIONS: + setattr_default(Repr, 'rtype_' + opname, missing_rtype_operation) +for opname in annmodel.BINARY_OPERATIONS: + setattr_default(pairtype(Repr, Repr), + 'rtype_' + opname, missing_rtype_operation) + + +class __extend__(pairtype(Repr, Repr)): + def convert_from_to((r_from, r_to), v, llops): + return NotImplemented + +# ____________________________________________________________ +# Primitive Repr classes, in the same hierarchical order as +# the corresponding SomeObjects + +class FloatRepr(Repr): + lowleveltype = Float + +class IntegerRepr(FloatRepr): + lowleveltype = Signed + +class BoolRepr(IntegerRepr): + lowleveltype = Bool + +class StringRepr(Repr): + pass + +class CharRepr(StringRepr): + lowleveltype = Char + +# ____________________________________________________________ + +def inputconst(reqtype, value): + """Return a Constant with the given value, of the requested type, + which can be a Repr instance or a low-level type. + """ + if isinstance(reqtype, Repr): + reqtype = reqtype.lowleveltype + # Void Constants can hold any value; + # non-Void Constants must hold a correctly ll-typed value + # XXX ---- not enforced yet ---- + #if reqtype is not Void: + # assert typeOf(value) == reqtype + c = Constant(value) + c.concretetype = reqtype + return c From pedronis at codespeak.net Thu Jun 2 23:02:43 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 23:02:43 +0200 (CEST) Subject: [pypy-svn] r13021 - pypy/dist/pypy/interpreter Message-ID: <20050602210243.1CF9027B4C@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 23:02:42 2005 New Revision: 13021 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: don't use a common MISSING_OPCODE for both the w_arg and without tables Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Thu Jun 2 23:02:42 2005 @@ -692,7 +692,10 @@ raise pyframe.BytecodeCorruption fn(f, oparg) - def MISSING_OPCODE(f, oparg=-1): + def MISSING_OPCODE(f): + raise pyframe.BytecodeCorruption, "unknown opcode" + + def MISSING_OPCODE_W_ARG(f, oparg): raise pyframe.BytecodeCorruption, "unknown opcode" ### dispatch_table ### @@ -710,9 +713,10 @@ dispatch_table_no_arg = [] dispatch_table_w_arg = [] missing_opcode = cls.MISSING_OPCODE + missing_opcode_w_arg = cls.MISSING_OPCODE_W_ARG for i in range(256): opname = dis.opname[i].replace('+', '_') - fn = getattr(cls, opname, missing_opcode) + fn = getattr(cls, opname, None) fn = getattr(fn, 'im_func',fn) has_arg = i >= dis.HAVE_ARGUMENT #if fn is missing_opcode and not opname.startswith('<') and i>0: @@ -720,9 +724,11 @@ # warnings.warn("* Warning, missing opcode %s" % opname) opcode_has_arg.append(has_arg) if has_arg: + fn = fn or missing_opcode_w_arg dispatch_table_w_arg.append(fn) dispatch_table_no_arg.append(None) else: + fn = fn or missing_opcode dispatch_table_no_arg.append(fn) dispatch_table_w_arg.append(None) From pedronis at codespeak.net Thu Jun 2 23:22:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 23:22:08 +0200 (CEST) Subject: [pypy-svn] r13022 - pypy/dist/pypy/interpreter Message-ID: <20050602212208.DB00A27B4C@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 23:22:08 2005 New Revision: 13022 Modified: pypy/dist/pypy/interpreter/pyopcode.py Log: make them bare functions too Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Thu Jun 2 23:22:08 2005 @@ -712,8 +712,8 @@ opcode_has_arg = [] dispatch_table_no_arg = [] dispatch_table_w_arg = [] - missing_opcode = cls.MISSING_OPCODE - missing_opcode_w_arg = cls.MISSING_OPCODE_W_ARG + missing_opcode = cls.MISSING_OPCODE.im_func + missing_opcode_w_arg = cls.MISSING_OPCODE_W_ARG.im_func for i in range(256): opname = dis.opname[i].replace('+', '_') fn = getattr(cls, opname, None) From pedronis at codespeak.net Thu Jun 2 23:25:23 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 2 Jun 2005 23:25:23 +0200 (CEST) Subject: [pypy-svn] r13023 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050602212523.6DC9427B4C@code1.codespeak.net> Author: pedronis Date: Thu Jun 2 23:25:23 2005 New Revision: 13023 Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py Log: merge MISSING_OPCODE_W_ARG addition Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py Thu Jun 2 23:25:23 2005 @@ -692,7 +692,10 @@ raise pyframe.BytecodeCorruption fn(f, oparg) - def MISSING_OPCODE(f, oparg=-1): + def MISSING_OPCODE(f): + raise pyframe.BytecodeCorruption, "unknown opcode" + + def MISSING_OPCODE_W_ARG(f, oparg): raise pyframe.BytecodeCorruption, "unknown opcode" ### dispatch_table ### @@ -709,10 +712,11 @@ opcode_has_arg = [] dispatch_table_no_arg = [] dispatch_table_w_arg = [] - missing_opcode = cls.MISSING_OPCODE + missing_opcode = cls.MISSING_OPCODE.im_func + missing_opcode_w_arg = cls.MISSING_OPCODE_W_ARG.im_func for i in range(256): opname = dis.opname[i].replace('+', '_') - fn = getattr(cls, opname, missing_opcode) + fn = getattr(cls, opname, None) fn = getattr(fn, 'im_func',fn) has_arg = i >= dis.HAVE_ARGUMENT #if fn is missing_opcode and not opname.startswith('<') and i>0: @@ -720,9 +724,11 @@ # warnings.warn("* Warning, missing opcode %s" % opname) opcode_has_arg.append(has_arg) if has_arg: + fn = fn or missing_opcode_w_arg dispatch_table_w_arg.append(fn) dispatch_table_no_arg.append(None) else: + fn = fn or missing_opcode dispatch_table_no_arg.append(fn) dispatch_table_w_arg.append(None) From pedronis at codespeak.net Fri Jun 3 00:26:20 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 3 Jun 2005 00:26:20 +0200 (CEST) Subject: [pypy-svn] r13024 - pypy/dist/pypy/translator/goal Message-ID: <20050602222620.191F527B47@code1.codespeak.net> Author: pedronis Date: Fri Jun 3 00:26:19 2005 New Revision: 13024 Modified: pypy/dist/pypy/translator/goal/query.py Log: - distinguish bound and unbound methods - slitghtly more sorting in the outputs Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Fri Jun 3 00:26:19 2005 @@ -47,24 +47,47 @@ c += 1 print c +class typerep(object): + + def __init__(self, x): + self.typ = getattr(x, '__class__', type(x)) + self.bound = None + if hasattr(x, 'im_self'): + self.bound = x.im_self is not None + elif hasattr(x, '__self__'): + self.bound = x.__self__ is not None + + def __hash__(self): + return hash(self.typ) + + def __cmp__(self, other): + return cmp((self.typ.__name__, self.bound, self.typ), (other.typ.__name__, other.bound, other.typ)) + + def __str__(self): + if self.bound is None: + return self.typ.__name__ + elif self.bound: + return 'bound-%s' % self.typ.__name__ + else: + return 'unbound-%s' % self.typ.__name__ + +def typereps(bunch): + t = dict.fromkeys([typerep(x) for x in bunch]).keys() + t.sort() + return t + def rep(bunch): if len(bunch) == 1: - return ["one", iter(bunch).next()] + parts = ["one", iter(bunch).next()] else: - t = dict.fromkeys([getattr(x, '__class__', type(x)) for x in bunch]).keys() - return ["of type(s)"] + t - -def strfy(x): - try: - return x.__name__ - except AttributeError: - return str(x) + parts = ["of type(s)"] + typereps(bunch) + return ' '.join(map(str, parts)) def pbcaccess(translator): annotator = translator.annotator for inf in annotator.getpbcaccesssets().root_info.itervalues(): objs = inf.objects - print len(objs), ' '.join(map(strfy,rep(objs))), inf.attrs.keys() + print len(objs), rep(objs), inf.attrs.keys() # PBCs def pbcs(translator): @@ -72,17 +95,18 @@ xs = bk.pbccache.keys() funcs = [x for x in xs if isinstance(x, types.FunctionType)] staticmethods = [x for x in xs if isinstance(x, staticmethod)] - instancemethods = [x for x in xs if isinstance(x, types.MethodType)] + binstancemethods = [x for x in xs if isinstance(x, types.MethodType) and x.im_self] + ubinstancemethods = [x for x in xs if isinstance(x, types.MethodType) and not x.im_self] typs = [x for x in xs if isinstance(x, (type, types.ClassType))] rest = [x for x in xs if not isinstance(x, (types.FunctionType, staticmethod, types.MethodType, type, types.ClassType))] - for objs in (funcs, staticmethods, instancemethods, typs, rest): - print len(objs), ' '.join(map(strfy,rep(objs))) + for objs in (funcs, staticmethods, binstancemethods, ubinstancemethods, typs, rest): + print len(objs), rep(objs) # mutable captured "constants") def mutables(translator): bk = translator.annotator.bookkeeper xs = bk.seen_mutable.keys() - print len(xs), ' '.join(map(strfy,rep(xs))) + print len(xs), rep(xs) def prettypatt(patts): accum = [] @@ -105,7 +129,7 @@ arg.append('**') accum.append("(%s)" % ', '.join(arg)) if wslf and woslf: - accum.append("!!!") + accum.append("!with and without self") return ' '.join(accum) @@ -124,8 +148,7 @@ if len(patts) != 1: rest.append((len(fam.objects), fam.objects, patts.keys())) else: - kinds = dict.fromkeys([getattr(obj, '__class__', type(obj)) for obj in fam.objects]).keys() - kinds.sort() + kinds = typereps(fam.objects) flavor = tuple(kinds), patts.keys()[0] @@ -141,9 +164,9 @@ def pretty_nels(kinds, nels): if nels == 1: - return "one %s" % kinds[0].__name__.title() + return "one %s" % str(kinds[0]).title() else: - return "in total %d %s" % (nels, '|'.join([kind.__name__.title()+'(s)' for kind in kinds])) + return "in total %d %s" % (nels, '|'.join([str(kind).title()+'(s)' for kind in kinds])) def pretty_els(objs): accum = [] @@ -153,13 +176,17 @@ else: accum.append(str(obj)) return "{%s}" % ' '.join(accum) - - for (kinds, patt), (nfam, nels) in one_pattern_fams.iteritems(): + + items = one_pattern_fams.items() + + items.sort(lambda a,b: cmp((a[0][1],a[1][1]), (b[0][1],b[1][1]))) + + for (kinds, patt), (nfam, nels) in items: print pretty_nfam(nfam), "with", pretty_nels(kinds, nels), "with one call-pattern:", prettypatt([patt]) print "- * -" - rest.sort(lambda a,b: cmp(a[0], b[0])) + rest.sort(lambda a,b: cmp((a[0],a[2]), (b[0],b[2]))) for n, objs, patts in rest: print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) From ale at codespeak.net Fri Jun 3 00:43:47 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 3 Jun 2005 00:43:47 +0200 (CEST) Subject: [pypy-svn] r13025 - pypy/dist/pypy/lib Message-ID: <20050602224347.D2FD927B47@code1.codespeak.net> Author: ale Date: Fri Jun 3 00:43:47 2005 New Revision: 13025 Modified: pypy/dist/pypy/lib/unicodecodec.py Log: more bugs fixed in raw-unicode-escape Modified: pypy/dist/pypy/lib/unicodecodec.py ============================================================================== --- pypy/dist/pypy/lib/unicodecodec.py (original) +++ pypy/dist/pypy/lib/unicodecodec.py Fri Jun 3 00:43:47 2005 @@ -1011,17 +1011,17 @@ if (ord(ch) >= 0x10000): p += '\\' p += 'U' - p += hex(ord(ch)) + p += '%08x'%(ord(ch)) elif (ord(ch) >= 256) : # /* Map 16-bit characters to '\uxxxx' */ p += '\\' p += 'u' - p += hex(ord(ch)) + p += '%04x'%(ord(ch)) # /* Copy everything else as-is */ else: p += chr(ord(ch)) - p += '\\0' + #p += '\0' return p def charmapencode_output(c,mapping): @@ -1126,25 +1126,26 @@ p = [] while (pos < len(s)): ch = s[pos] - #/* Non-escape characters are interpreted as Unicode ordinals */ + #/* Non-escape characters are interpreted as Unicode ordinals */ if (ch != '\\'): - p += ch + p += unichr(ord(ch)) pos += 1 continue startinpos = pos - pos += 1 + #pos += 1 ## /* \u-escapes are only interpreted iff the number of leading ## backslashes is odd */ bs = pos while pos < size: if (s[pos] != '\\'): break; - p += s[pos] + p += unichr(ord(s[pos])) pos += 1 if (((pos - bs) & 1) == 0 or pos >= size or (s[pos] != 'u' and s[pos] != 'U')) : + p += s[pos] pos += 1 continue @@ -1156,9 +1157,9 @@ pos += 1 #/* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */ - - i = 0 - x = 0 + + i = 0 + x = 0 try: x = int(s[pos:pos+count],16) except ValueError: @@ -1189,5 +1190,5 @@ else: p += unichr(x) pos += count - + return p \ No newline at end of file From pedronis at codespeak.net Fri Jun 3 02:47:45 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 3 Jun 2005 02:47:45 +0200 (CEST) Subject: [pypy-svn] r13026 - pypy/branch/rpython-refactoring Message-ID: <20050603004745.EF93527B48@code1.codespeak.net> Author: pedronis Date: Fri Jun 3 02:47:45 2005 New Revision: 13026 Modified: pypy/branch/rpython-refactoring/rmodel.py Log: missing imports Modified: pypy/branch/rpython-refactoring/rmodel.py ============================================================================== --- pypy/branch/rpython-refactoring/rmodel.py (original) +++ pypy/branch/rpython-refactoring/rmodel.py Fri Jun 3 02:47:45 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pair, pairtype, extendabletype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import Void, Bool +from pypy.rpython.lltype import Void, Bool, Float, Signed, Char class Repr: From pedronis at codespeak.net Fri Jun 3 03:02:18 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 3 Jun 2005 03:02:18 +0200 (CEST) Subject: [pypy-svn] r13027 - pypy/branch/rpython-refactoring Message-ID: <20050603010218.D322E27B48@code1.codespeak.net> Author: pedronis Date: Fri Jun 3 03:02:18 2005 New Revision: 13027 Modified: pypy/branch/rpython-refactoring/rfloat.py Log: fix int->float conversion Modified: pypy/branch/rpython-refactoring/rfloat.py ============================================================================== --- pypy/branch/rpython-refactoring/rfloat.py (original) +++ pypy/branch/rpython-refactoring/rfloat.py Fri Jun 3 03:02:18 2005 @@ -109,7 +109,7 @@ class __extend__(pairtype(IntegerRepr, FloatRepr)): def convert_from_to((r_from, r_to), v, llops): - if r_from.unsigned: + if r_from.lowleveltype == Unsigned: if debug: print 'explicit cast_uint_to_float' return llops.genop('cast_uint_to_float', [v], resulttype=Float) else: From tismer at codespeak.net Fri Jun 3 06:04:51 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 3 Jun 2005 06:04:51 +0200 (CEST) Subject: [pypy-svn] r13028 - pypy/dist/pypy/translator/pickle Message-ID: <20050603040451.9486427B4C@code1.codespeak.net> Author: tismer Date: Fri Jun 3 06:04:51 2005 New Revision: 13028 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: avoiding creation of very many tiny tuples. still to do (plus tests): - break into medium sized functions - add an option to inline more objects, like strings - make save_global clearly distinguish between external functions, which should be imported, and application stuff (everything below pypy.objspace.std.) which should always be rendered without imports - reduce the data saved for translator and annotator - represent blocks etc. more compactly - if things tend to stay too huge, consider real pickle structure. Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Fri Jun 3 06:04:51 2005 @@ -75,6 +75,10 @@ self.picklenames[key] = name return name + def nameofargs(self, tup): + """ a string with the nameofs, concatenated """ + return ', '.join([self.nameof(arg) for arg in tup]) + def uniquename(self, basename): return self.namespace.uniquename(basename) @@ -322,9 +326,11 @@ def nameof_list(self, lis): name = self.uniquename('g%dlist' % len(lis)) def initlist(): - for i in range(len(lis)): - item = self.nameof(lis[i]) - yield '%s.append(%s)' % (name, item) + extname = self.nameof(extendlist) + for i in range(0, len(lis), 5): + items = lis[i:i+5] + itemstr = self.nameofargs(items) + yield '%s(%s, %s)' % (extname, name, itemstr) self.initcode_python(name, '[]') self.later(initlist()) return name @@ -382,8 +388,14 @@ def initinstance(): if hasattr(instance, '__setstate__'): # the instance knows what to do - args = self.nameof(restorestate) - yield '%s.__setstate__(%s)' % (name, args) + if type(restorestate) is tuple: + # be a little shorter + setstatename = self.nameof(setstate) + argstr = self.nameofargs(restorestate) + yield '%s(%s, %s)' % (setstatename, name, argstr) + else: + args = self.nameof(restorestate) + yield '%s.__setstate__(%s)' % (name, args) return assert type(restorestate) is dict, ( "%s has no dict and no __setstate__" % name) @@ -396,7 +408,7 @@ if hasattr(instance, '__reduce_ex__'): reduced = instance.__reduce_ex__() restorer = reduced[0] - restorename = self.save_global(restorer) + restorename = self.nameof(restorer) restoreargs = reduced[1] if len(reduced) > 2: restorestate = reduced[2] @@ -408,10 +420,10 @@ restoreargs = (base, cls) restorename = '%s.__new__' % base restorestate = instance.__dict__ - restoreargsname = self.nameof(restoreargs) + restoreargstr = self.nameofargs(restoreargs) if isinstance(klass, type): - self.initcode.append('%s = %s(*%s)' % (name, restorename, - restoreargsname)) + self.initcode.append('%s = %s(%s)' % (name, restorename, + restoreargstr)) else: self.initcode.append('%s = new.instance(%s)' % (name, cls)) if restorestate is not None: @@ -460,19 +472,27 @@ if (func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON')): return self.skipped_function(func) + try: + return self.save_global(func) + except PicklingError: + pass args = (func.func_code, func.func_globals, func.func_name, func.func_defaults, func.func_closure) pyfuncobj = self.uniquename('gfunc_' + func.__name__) - self.initcode.append('%s = new.function(*%s)' % (pyfuncobj, - self.nameof(args)) ) + self.initcode.append('%s = new.function(%s)' % (pyfuncobj, + self.nameofargs(args)) ) + if func.__dict__: + self.initcode.append('%s.__dict__.update(%s)' % ( + pyfuncobj, self.nameof(func.__dict__)) ) return pyfuncobj def nameof_cell(self, cel): obj = break_cell(cel) pycell = self.uniquename('gcell_' + self.nameof(obj)) self.initcode.append('%s = %s(%s)' % (pycell, self.nameof(make_cell), - self.nameof(obj)) - + self.nameof(obj)) ) + return pycell + def nameof_code(self, code): args = (code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, code.co_consts, code.co_names, @@ -492,9 +512,9 @@ lnostrname = self.uniquename('glnotab_' + code.co_name) self.picklenames[Constant(lnostr)] = lnostrname self.initcode.append('%s = %r' % (lnostrname, lnostr)) - argobj = self.nameof(args) + argstr = self.nameofargs(args) codeobj = self.uniquename('gcode_' + code.co_name) - self.initcode.append('%s = new.code(*%s)' % (codeobj, argobj)) + self.initcode.append('%s = new.code(%s)' % (codeobj, argstr)) return codeobj def nameof_file(self, fil): @@ -542,4 +562,12 @@ args = (func.func_code, func.func_globals, func.func_name, func.func_defaults, (cel,)) func = new.function(*args) - return func() \ No newline at end of file + return func() + +# save creation of many tuples + +def setstate(obj, *args): + obj.__setstate__(args) + +def extendlist(obj, *args): + obj.extend(args) From ale at codespeak.net Fri Jun 3 11:14:48 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 3 Jun 2005 11:14:48 +0200 (CEST) Subject: [pypy-svn] r13031 - pypy/dist/pypy/lib Message-ID: <20050603091448.539C927B4C@code1.codespeak.net> Author: ale Date: Fri Jun 3 11:14:48 2005 New Revision: 13031 Modified: pypy/dist/pypy/lib/inprogress__codecs.py Log: more bugs fixed in unicode-internal Modified: pypy/dist/pypy/lib/inprogress__codecs.py ============================================================================== --- pypy/dist/pypy/lib/inprogress__codecs.py (original) +++ pypy/dist/pypy/lib/inprogress__codecs.py Fri Jun 3 11:14:48 2005 @@ -159,7 +159,7 @@ """None """ res = PyUnicode_DecodeRawUnicodeEscape(data, len(data), errors) - res = ''.join(res) + res = u''.join(res) return res,len(res) def utf_7_decode( data,errors='strict'): @@ -212,14 +212,40 @@ res = ''.join(res) return res, len(res) +unicode_bytes = (len(hex(sys.maxunicode))-1)/2 + def unicode_internal_encode( obj,errors='strict'): """None """ if type(obj) == unicode: - return obj, len(obj) + p = [] + t = [ord(x) for x in obj] + for i in t: + for j in xrange(unicode_bytes): + p += chr(i%256) + i >>= 8 + res = ''.join(p) + return res, len(res) else: return ''.join(PyUnicode_FromUnicode(obj,size),size) +def unicode_internal_decode( unistr,errors='strict'): + """None + """ + if type(unistr) == unicode: + return unistr,len(unistr) + else: + p=[] + i=0 + while i < len(unistr)-unicode_bytes+1: + t = 0 + for j in range(unicode_bytes): + t += ord(unistr[i+j])<<(j*8) + i += j+1 + p += unichr(t) + res = u''.join(p) + return res, len(res) + def utf_16_ex_decode( data,errors='strict'): """None """ @@ -306,14 +332,6 @@ res = ''.join(res) return res, len(res) -def unicode_internal_decode( unistr,errors='strict'): - """None - """ - if type(unistr) == unicode: - return unistr,len(unistr) - else: - return unicode(unistr),len(unistr) - def utf_16_le_decode( data,errors='strict'): """None """ From cfbolz at codespeak.net Fri Jun 3 13:05:57 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 3 Jun 2005 13:05:57 +0200 (CEST) Subject: [pypy-svn] r13034 - pypy/dist/pypy/documentation Message-ID: <20050603110557.9689027B4C@code1.codespeak.net> Author: cfbolz Date: Fri Jun 3 13:05:57 2005 New Revision: 13034 Modified: pypy/dist/pypy/documentation/getting_started.txt Log: fixed wrong path Modified: pypy/dist/pypy/documentation/getting_started.txt ============================================================================== --- pypy/dist/pypy/documentation/getting_started.txt (original) +++ pypy/dist/pypy/documentation/getting_started.txt Fri Jun 3 13:05:57 2005 @@ -274,7 +274,7 @@ Finally, there are the CPython regression tests which you can run like this:: - cd lib-python-2.3.4/test + cd lib-python/2.3.4/test python ../../pypy/test_all.py -E or if you have `installed py.test`_ then you simply say:: From ericvrp at codespeak.net Fri Jun 3 13:09:58 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 3 Jun 2005 13:09:58 +0200 (CEST) Subject: [pypy-svn] r13035 - pypy/dist/pypy/documentation Message-ID: <20050603110958.CAC5427B4C@code1.codespeak.net> Author: ericvrp Date: Fri Jun 3 13:09:58 2005 New Revision: 13035 Modified: pypy/dist/pypy/documentation/getting_started.txt Log: Fixed other wrong path also Modified: pypy/dist/pypy/documentation/getting_started.txt ============================================================================== --- pypy/dist/pypy/documentation/getting_started.txt (original) +++ pypy/dist/pypy/documentation/getting_started.txt Fri Jun 3 13:09:58 2005 @@ -275,7 +275,7 @@ run like this:: cd lib-python/2.3.4/test - python ../../pypy/test_all.py -E + python ../../../pypy/test_all.py -E or if you have `installed py.test`_ then you simply say:: From hpk at codespeak.net Fri Jun 3 14:22:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 3 Jun 2005 14:22:43 +0200 (CEST) Subject: [pypy-svn] r13036 - pypy/extradoc/sprintinfo Message-ID: <20050603122243.1A9A827B56@code1.codespeak.net> Author: hpk Date: Fri Jun 3 14:22:42 2005 New Revision: 13036 Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt Log: progressing towards a full sprint announcement (we really should get this out some time soon) - introduction section with an explicit summer-of-code reference (please check if you like this) - some headers and shifting around - XXX marks the logistics/accomodation information that is missing Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-announcement.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-announcement.txt Fri Jun 3 14:22:42 2005 @@ -1,17 +1,29 @@ +Post-EuroPython 2005 PyPy Sprint 1st - 7th July 2005 +====================================================== -Post-EuroPython 2005 PyPy Sprint Announcement -============================================== - -Time: 1st-7th July 2005 (both days including) -Location: Goetheborg, Sweden (more details to follow) - - -Draft topic announcement - -The main, though not the only, focus of the sprint will be on the -"translation" aspect of PyPy. We will progress towards a completely -translated PyPy. How much will already have been done before EuroPython -is unknown; as a guess, we will be left with: +The next PyPy sprint is scheduled right after EuroPython 2005 +in Gothenborg, Sweden. It's main focus is translation to +lower level backends but there are also other possible topics. +We'll give newcomer-friendly introductions. To learn more +about the new PyPy Python-in-Python implementation look here: + + http://codespeak.net/pypy + +On a side note, there are a number of sub projects that may be +interesting for participating in google's summer-of-code +event. Apart from refining and discussing tasks, the sprint +could possibly serve as a good meeting and kick-off point with +mentors from the PyPy group. Further down you'll find some +first areas, but there are certainly more and bigger ones :-) + +Goals and topics of the sprint +------------------------------ + +The main, though not the only, focus of the sprint will be on +the "translation" aspect of PyPy. The goal here is to +progress towards a completely translated PyPy. How much will +already have been done before EuroPython is unknown; as a +guess, we will be left with: - completing the "rtyper", the piece of code that assigns low-level C-like types to high-level RPython objects (lists, dicts, instances, @@ -38,3 +50,9 @@ - weakrefs (but this requires discussion and planning on pypy-dev before the sprint! feel free to start such a discussion, though.) + + +Accomodation, Location and meeting points +------------------------------------------ + +XXX From pedronis at codespeak.net Fri Jun 3 20:51:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 3 Jun 2005 20:51:08 +0200 (CEST) Subject: [pypy-svn] r13038 - in pypy/dist/pypy: annotation translator translator/goal translator/test Message-ID: <20050603185108.4CE5527B45@code1.codespeak.net> Author: pedronis Date: Fri Jun 3 20:51:07 2005 New Revision: 13038 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/goal/query.py pypy/dist/pypy/translator/test/test_annrpython.py Log: don't naively identify PBC representing bound methods (which will carry self) and bare functions/unbound methods we treat SomePBC(func:True) vs SomePBC(func:ClassDef) separately, we use indices of the form (None,func) or (ClassDef, func) for pbc call families. there's a second table mapping bare callables (after identifying functions and unbound methods) to such tuples. reworked query.pbcall to deal with the more complex info, need more work to print information about the second auxiliary table. While a bit strange and compact the first table is giving useful information, from which for example from SomePBC(func:ClassDef...) it should be possible to reconstruct the corresponding method name or slot . Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Jun 3 20:51:07 2005 @@ -65,6 +65,7 @@ self.pbc_maximal_access_sets = UnionFind(PBCAccessSet) self.pbc_maximal_call_families = UnionFind(PBCCallFamily) + self.pbc_callables = {} # import ordering hack global BUILTIN_ANALYZERS @@ -297,6 +298,15 @@ return unionof(*actuals) + def mark_callable(self, callable): + classdef, func = callable + + if hasattr(func, 'im_func') and func.im_self is None: + # consider unbound methods and the undelying functions as the same + func = func.im_func + + self.pbc_callables.setdefault(func,{})[callable] = True + def pbc_call(self, pbc, args): nonnullcallables = [] patterns = {} @@ -310,14 +320,15 @@ if isclassdef(classdef): s_self = SomeInstance(classdef) args1 = args.prepend(s_self) - pattern = (classdef, shape) else: + classdef = None args1 = args - pattern = (None, shape) results.append(self.pycall(func, args1)) - - nonnullcallables.append(func) - patterns[pattern] = True + + callable = (classdef, func) + self.mark_callable(callable) + nonnullcallables.append(callable) + patterns[shape] = True if nonnullcallables: call_families = self.pbc_maximal_call_families Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Fri Jun 3 20:51:07 2005 @@ -120,9 +120,17 @@ def getpbcaccesssets(self): """Return mapping const obj -> PBCAccessSet""" return self.bookkeeper.pbc_maximal_access_sets + + def getpbccallables(self): + """Return mapping callable -> {(ClassDef|None, callable'): True...}, + callable' == callable unless callable' is an unbound method then callable is callable'.im_func. + + The tuples are indices in getpbcfamilies returned mapping + """ + return self.bookkeeper.pbc_callables def getpbccallfamilies(self): - """Return mapping const obj -> PBCCallFamily""" + """Return mapping (ClassDef|None, callable) -> PBCCallFamily""" return self.bookkeeper.pbc_maximal_call_families #___ medium-level interface ____________________________ Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Fri Jun 3 20:51:07 2005 @@ -43,7 +43,7 @@ try: flowmodel.traverse(visit, g) except Found: - print f.__module__ or '?', f.__name__ + print prettycallable((None, f)) c += 1 print c @@ -65,18 +65,90 @@ def __str__(self): if self.bound is None: - return self.typ.__name__ + s = self.typ.__name__ elif self.bound: - return 'bound-%s' % self.typ.__name__ + s = 'bound-%s' % self.typ.__name__ else: - return 'unbound-%s' % self.typ.__name__ + s = 'unbound-%s' % self.typ.__name__ + + if self.typ.__module__ == '__builtin__': + s = "*%s*" % s + + return s def typereps(bunch): t = dict.fromkeys([typerep(x) for x in bunch]).keys() t.sort() return t -def rep(bunch): +def roots(classes): + # find independent hierarchy roots in classes, + # preserve None if it's part of classes + work = list(classes) + res = [] + + notbound = False + + while None in work: + work.remove(None) + notbound = True + + if len(work) == 1: + return notbound, classes[0] + + while work: + cand = work.pop() + for cls in work: + if issubclass(cls, cand): + continue + if issubclass(cand, cls): + cand = cls + continue + res.append(cand) + work = [cls for cls in work if not issubclass(cls, cand)] + + + for x in res: + for y in res: + if x != y: + assert not issubclass(x, y), "%s %s %s" % (classes, x,y) + assert not issubclass(y, x), "%s %s %s" % (classes, x,y) + + return notbound, tuple(res) + +def callablereps(bunch): + callables = [func for clsdef, func in bunch] + classes = [clsdef and clsdef.cls for clsdef, func in bunch] + return roots(classes), tuple(typereps(callables)) + +def prettycallable((cls, obj)): + if cls is None or cls == (True, ()): + cls = None + else: + notbound = False + if isinstance(cls, tuple) and isinstance(cls[0], bool): + notbound, cls = cls + if isinstance(cls, tuple): + cls = "[%s]" % '|'.join([x.__name__ for x in cls]) + else: + cls = cls.__name__ + if notbound: + cls = "_|%s" % cls + + if isinstance(obj, types.FunctionType): + obj = "(%s)%s" % (getattr(obj, '__module__', None) or '?', getattr(obj, '__name__', None) or 'UNKNOWN') + elif isinstance(obj, tuple): + obj = "[%s]" % '|'.join([str(x) for x in obj]) + else: + obj = str(obj) + + if cls is None: + return str(obj) + else: + return "%s::%s" % (cls, obj) + + +def prettybunch(bunch): if len(bunch) == 1: parts = ["one", iter(bunch).next()] else: @@ -87,7 +159,7 @@ annotator = translator.annotator for inf in annotator.getpbcaccesssets().root_info.itervalues(): objs = inf.objects - print len(objs), rep(objs), inf.attrs.keys() + print len(objs), prettybunch(objs), inf.attrs.keys() # PBCs def pbcs(translator): @@ -100,26 +172,19 @@ typs = [x for x in xs if isinstance(x, (type, types.ClassType))] rest = [x for x in xs if not isinstance(x, (types.FunctionType, staticmethod, types.MethodType, type, types.ClassType))] for objs in (funcs, staticmethods, binstancemethods, ubinstancemethods, typs, rest): - print len(objs), rep(objs) + print len(objs), prettybunch(objs) # mutable captured "constants") def mutables(translator): bk = translator.annotator.bookkeeper xs = bk.seen_mutable.keys() - print len(xs), rep(xs) + print len(xs), prettybunch(xs) def prettypatt(patts): accum = [] - wslf = False - woslf = False patts.sort() - for slf, (sh_cnt, sh_ks, sh_st, sh_stst) in patts: + for (sh_cnt, sh_ks, sh_st, sh_stst) in patts: arg = [] - if slf is None: - woslf = True - else: - wslf = True - arg.append(slf) arg.append("+%d" % sh_cnt) for kw in sh_ks: arg.append("%s=" % kw) @@ -128,8 +193,6 @@ if sh_stst: arg.append('**') accum.append("(%s)" % ', '.join(arg)) - if wslf and woslf: - accum.append("!with and without self") return ' '.join(accum) @@ -138,20 +201,15 @@ one_pattern_fams = {} rest = [] for fam in fams: - patts = {} - for clsdef, sh in fam.patterns: - if clsdef is None: - slf = None - else: - slf = 'self' - patts[(slf, sh)] = True - if len(patts) != 1: - rest.append((len(fam.objects), fam.objects, patts.keys())) - else: - kinds = typereps(fam.objects) + shapes = fam.patterns - flavor = tuple(kinds), patts.keys()[0] + if len(shapes) != 1: + rest.append((len(fam.objects), fam.objects, shapes.keys())) + else: + kinds = callablereps(fam.objects) + flavor = tuple(kinds), shapes.keys()[0] + cntrs = one_pattern_fams.setdefault(flavor, [0,0]) cntrs[0] += 1 cntrs[1] += len(fam.objects) @@ -164,22 +222,20 @@ def pretty_nels(kinds, nels): if nels == 1: - return "one %s" % str(kinds[0]).title() + return "one %s" % prettycallable(kinds) else: - return "in total %d %s" % (nels, '|'.join([str(kind).title()+'(s)' for kind in kinds])) + return "in total %d %s" % (nels, prettycallable(kinds)) def pretty_els(objs): accum = [] - for obj in objs: - if isinstance(obj, types.FunctionType): - accum.append("%s:%s" % (obj.__module__ or '?', obj.__name__)) - else: - accum.append(str(obj)) + for classdef, obj in objs: + cls = classdef and classdef.cls + accum.append(prettycallable((cls, obj))) return "{%s}" % ' '.join(accum) items = one_pattern_fams.items() - items.sort(lambda a,b: cmp((a[0][1],a[1][1]), (b[0][1],b[1][1]))) + items.sort(lambda a,b: cmp((a[0][1],a[1][1]), (b[0][1],b[1][1]))) # sort by pattern and then by els for (kinds, patt), (nfam, nels) in items: print pretty_nfam(nfam), "with", pretty_nels(kinds, nels), "with one call-pattern:", prettypatt([patt]) @@ -190,6 +246,11 @@ for n, objs, patts in rest: print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) - - - + +# debug helper +def tryout(f, *args): + try: + f(*args) + except: + import traceback + traceback.print_exc() Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Fri Jun 3 20:51:07 2005 @@ -824,12 +824,18 @@ a = self.RPythonAnnotator() s = a.build_types(h, []) - + + callables = a.getpbccallables() call_families = a.getpbccallfamilies() + + fc = lambda x: {(None, x): True} + + assert len(callables) == 4 + assert callables == {g: fc(g), f1: fc(f1), f2: fc(f2), f3: fc(f3)} - ign, rep1, fam1 = call_families.find(f1) - ign, rep2, fam2 = call_families.find(f2) - ign, rep3, fam3 = call_families.find(f3) + ign, rep1, fam1 = call_families.find((None, f1)) + ign, rep2, fam2 = call_families.find((None, f2)) + ign, rep3, fam3 = call_families.find((None, f3)) assert rep1 is not rep2 assert rep1 is not rep3 @@ -842,8 +848,8 @@ assert len(fam1.patterns) == 2 assert len(fam2.patterns) == 1 - assert fam1.patterns == {(None, (2, (), False, False)): True, (None, (1, (), False, False)): True} - assert fam2.patterns == {(None, (1, (), False, False)): True} + assert fam1.patterns == {(2, (), False, False): True, (1, (), False, False): True} + assert fam2.patterns == {(1, (), False, False): True} def test_pbc_call_ins(self): class A(object): @@ -867,25 +873,33 @@ a = self.RPythonAnnotator() s = a.build_types(f, [bool]) - + + callables = a.getpbccallables() call_families = a.getpbccallfamilies() - - ign, repA_m, famA_m = call_families.find(A.m.im_func) - ign, repC_m, famC_m = call_families.find(C.m.im_func) - ign, repB_n, famB_n = call_families.find(B.n.im_func) + + clsdef = lambda cls: a.getuserclasses()[cls] + + fc = lambda x: {(None, x): True} + mc = lambda x: {(clsdef(x.im_class), x.im_func): True} + + assert len(callables) == 5 + assert callables == { B: fc(B), C: fc(C), + A.m.im_func: mc(A.m), + C.m.im_func: mc(C.m), + B.n.im_func: mc(B.n) } + + ign, repA_m, famA_m = call_families.find((clsdef(A), A.m.im_func)) + ign, repC_m, famC_m = call_families.find((clsdef(C), C.m.im_func)) + ign, repB_n, famB_n = call_families.find((clsdef(B), B.n.im_func)) assert famA_m is famC_m assert famB_n is not famA_m assert len(famB_n.patterns) == 1 - assert len(famC_m.patterns) == 2 - - Aclsdef = a.getuserclasses()[A] - Bclsdef = a.getuserclasses()[B] - Cclsdef = a.getuserclasses()[C] + assert len(famC_m.patterns) == 1 - assert famB_n.patterns == {(Bclsdef, (0, (), False, False)): True} - assert famA_m.patterns == {(Aclsdef, (0, (), False, False)): True, (Cclsdef, (0, (), False, False)): True} + assert famB_n.patterns == {(0, (), False, False): True } + assert famA_m.patterns == {(0, (), False, False): True } def test_isinstance_usigned(self): def f(x): From arigo at codespeak.net Fri Jun 3 21:09:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Jun 2005 21:09:43 +0200 (CEST) Subject: [pypy-svn] r13039 - in pypy/branch/rpython-refactoring: . test Message-ID: <20050603190943.EBD4D27B47@code1.codespeak.net> Author: arigo Date: Fri Jun 3 21:09:43 2005 New Revision: 13039 Added: pypy/branch/rpython-refactoring/rrange.py (contents, props changed) pypy/branch/rpython-refactoring/test/test_rrange.py (contents, props changed) Removed: pypy/branch/rpython-refactoring/riter.py Modified: pypy/branch/rpython-refactoring/rbuiltin.py pypy/branch/rpython-refactoring/rclass.py pypy/branch/rpython-refactoring/rlist.py pypy/branch/rpython-refactoring/rmodel.py pypy/branch/rpython-refactoring/rpbc.py pypy/branch/rpython-refactoring/rptr.py pypy/branch/rpython-refactoring/rstr.py pypy/branch/rpython-refactoring/rtyper.py pypy/branch/rpython-refactoring/test/test_rlist.py Log: Intermediate check-in. New rrange.py. Modified: pypy/branch/rpython-refactoring/rbuiltin.py ============================================================================== --- pypy/branch/rpython-refactoring/rbuiltin.py (original) +++ pypy/branch/rpython-refactoring/rbuiltin.py Fri Jun 3 21:09:43 2005 @@ -1,5 +1,5 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeBuiltin, SomeObject, SomeString +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import malloc, typeOf, nullptr, nullgcptr from pypy.rpython.lltype import Void, Signed from pypy.rpython.rtyper import TyperError Modified: pypy/branch/rpython-refactoring/rclass.py ============================================================================== --- pypy/branch/rpython-refactoring/rclass.py (original) +++ pypy/branch/rpython-refactoring/rclass.py Fri Jun 3 21:09:43 2005 @@ -1,5 +1,5 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomePBC, SomeInstance +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import * from pypy.rpython.rtyper import inputconst Deleted: /pypy/branch/rpython-refactoring/riter.py ============================================================================== --- /pypy/branch/rpython-refactoring/riter.py Fri Jun 3 21:09:43 2005 +++ (empty file) @@ -1,57 +0,0 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeIterator, SomeList -from pypy.rpython.lltype import * - - -class __extend__(SomeIterator): - - def getiteratorkind(s_itr): - s_cont = s_itr.s_container - if isinstance(s_cont, SomeList): - if not s_cont.ll_range_step(): - return PlainListIterator - else: - return RangeIterator - else: - raise TyperError("not implemented yet") - - def lowleveltype(s_itr): - kind = s_itr.getiteratorkind() - return kind.lowlevelitertype(s_itr.s_container) - - def rtype_next(s_itr, hop): - v_itr, = hop.inputargs(s_itr) - kind = s_itr.getiteratorkind() - return kind.next(v_itr, hop) - -# ____________________________________________________________ - -class Namespace(object): - def __init__(self, name, bases, dict): - assert not bases - self.__dict__.update(dict) - - -class PlainListIterator: - """__________ regular list iterator __________""" - __metaclass__ = Namespace - - def lowlevelitertype(s_lst): - return GcPtr(GcStruct('listiter', ('list', s_lst.lowleveltype()), - ('index', Signed))) - - def ll_listiter(ITERPTR, lst): - iter = malloc(ITERPTR.TO) - iter.list = lst - iter.index = 0 - return iter - - def rtype_new_iter(hop): - s_lst, = hop.args_s - v_lst, = hop.inputargs(s_lst) - ITERPTR = PlainListIterator.lowlevelitertype(s_lst) - citerptr = hop.inputconst(Void, ITERPTR) - return hop.gendirectcall(PlainListIterator.ll_listiter, citerptr, v_lst) - - def next(v_itr, hop): - XXX - NotImplementedYet Modified: pypy/branch/rpython-refactoring/rlist.py ============================================================================== --- pypy/branch/rpython-refactoring/rlist.py (original) +++ pypy/branch/rpython-refactoring/rlist.py Fri Jun 3 21:09:43 2005 @@ -1,7 +1,9 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeList, SomeInteger +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import * +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython import rrange # ____________________________________________________________ # @@ -14,68 +16,54 @@ # 'items' points to a C-like array in memory preceded by a 'length' header, # where each item contains a primitive value or pointer to the actual list # item. -# -# Lists returned by range() and never mutated use a simpler implementation: -# -# struct range { -# Signed start, stop; // step is always constant -# } - -RANGE = GcStruct("range", ("start", Signed), ("stop", Signed)) - -class __extend__(SomeList): - - def ll_range_step(s_list): - return (not s_list.listdef.listitem.mutated - and s_list.listdef.listitem.range_step) - - def lowleveltype(s_list): - if s_list.ll_range_step(): - assert isinstance(s_list.get_s_items(), SomeInteger) - return GcPtr(RANGE) - else: - ITEM = s_list.get_s_items().lowleveltype() - LIST = GcStruct("list", ("items", GcPtr(GcArray(("item", ITEM))))) - return GcPtr(LIST) - - def get_s_items(s_list): - return s_list.listdef.listitem.s_value - - def rtype_len(s_lst, hop): - v_lst, = hop.inputargs(s_lst) - step = s_lst.ll_range_step() - if step: - cstep = hop.inputconst(Signed, step) - return hop.gendirectcall(ll_rangelen, v_lst, cstep) +class __extend__(annmodel.SomeList): + def rtyper_makerepr(self, rtyper): + listitem = self.listdef.listitem + if listitem.range_step and not listitem.mutated: + return rrange.RangeRepr(listitem.range_step) else: - return hop.gendirectcall(ll_len, v_lst) + # cannot do the rtyper.getrepr() call immediately, for the case + # of recursive structures -- i.e. if the listdef contains itself + return ListRepr(lambda: rtyper.getrepr(listitem.s_value)) + + +class ListRepr(Repr): + + def __init__(self, item_repr): + self.LIST = GcForwardReference() + self.lowleveltype = GcPtr(self.LIST) + self.item_repr = item_repr # possibly uncomputed at this point! + + def setup(self): + if callable(self.item_repr): + self.item_repr = self.item_repr() + if isinstance(self.LIST, GcForwardReference): + ITEM = self.item_repr.lowleveltype + ITEMARRAY = GcArray(("item", ITEM)) + self.LIST.become(GcStruct("list", ("items", GcPtr(ITEMARRAY)))) + + def rtype_len(self, hop): + v_lst, = hop.inputargs(self) + return hop.gendirectcall(ll_len, v_lst) - def rtype_method_append(s_lst, hop): - assert not s_lst.ll_range_step() - v_lst, v_value = hop.inputargs(s_lst, s_lst.get_s_items()) + def rtype_method_append(self, hop): + v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) - def rtype_iter(s_lst): - s_itr = hop.s_result - return s_itr.getiteratorkind().rtype_new_iter(hop) + def make_iterator_repr(self): + return ListIteratorRepr(self) -class __extend__(pairtype(SomeList, SomeInteger)): - - def rtype_getitem((s_lst1, s_int2), hop): - v_lst, v_index = hop.inputargs(s_lst1, Signed) - step = s_lst1.ll_range_step() - if step: - cstep = hop.inputconst(Signed, step) - return hop.gendirectcall(ll_rangeitem, v_lst, v_index, cstep) - else: - if s_int2.nonneg: - llfn = ll_getitem_nonneg - else: - llfn = ll_getitem - return hop.gendirectcall(llfn, v_lst, v_index) +class __extend__(pairtype(ListRepr, IntegerRepr)): + def rtype_getitem((r_lst, r_int), hop): + v_lst, v_index = hop.inputargs(r_lst, Signed) + if hop.args_s[1].nonneg: + llfn = ll_getitem_nonneg + else: + llfn = ll_getitem + return hop.gendirectcall(llfn, v_lst, v_index) # ____________________________________________________________ # @@ -112,28 +100,6 @@ def ll_setitem_nonneg(l, i, newitem): l.items[i].item = newitem -# __________ range __________ - -def ll_rangelen(l, step): - if step > 0: - result = (l.stop - l.start + (step-1)) // step - else: - result = (l.start - l.stop - (step+1)) // (-step) - if result < 0: - result = 0 - return result - -def ll_rangeitem(l, i, step): - if i<0: - # XXX ack. cannot call ll_rangelen() here for now :-( - if step > 0: - length = (l.stop - l.start + (step-1)) // step - else: - length = (l.start - l.stop - (step+1)) // (-step) - #assert length >= 0 - i += length - return l.start + i*step - # ____________________________________________________________ # # Irregular operations. @@ -156,23 +122,37 @@ hop.gendirectcall(ll_setitem_nonneg, v_result, ci, v_item) return v_result -def ll_newrange(start, stop): - l = malloc(RANGE) - l.start = start - l.stop = stop - return l +# ____________________________________________________________ +# +# Iteration. + +class ListIteratorRepr(Repr): -def rtype_builtin_range(hop): - s_range = hop.s_result - step = s_range.listdef.listitem.range_step - if step is None: # cannot build a RANGE object, needs a real list - raise TyperError("range() list used too dynamically") - if hop.nb_args == 1: - vstart = hop.inputconst(Signed, 0) - vstop, = hop.inputargs(Signed) - elif hop.nb_args == 2: - vstart, vstop = hop.inputargs(Signed, Signed) - else: - vstart, vstop, vstep = hop.inputargs(Signed, Signed, Signed) - assert isinstance(vstep, Constant) and vstep.value == step - return hop.gendirectcall(ll_newrange, vstart, vstop) + def __init__(self, r_list): + self.r_list = r_list + self.lowleveltype = GcPtr(GcStruct('listiter', + ('list', r_list.lowleveltype), + ('index', Signed))) + + def newiter(self, hop): + v_lst, = hop.inputargs(self.r_list) + citerptr = hop.inputconst(Void, self.lowleveltype) + return hop.gendirectcall(ll_listiter, citerptr, v_lst) + + def next(self, hop): + v_iter = hop.inputargs(self) + return hop.gendirectcall(ll_listnext, v_iter) + +def ll_listiter(ITERPTR, lst): + iter = malloc(ITERPTR.TO) + iter.list = lst + iter.index = 0 + return iter + +def ll_listnext(iter): + l = iter.list + index = iter.index + if index >= len(l.items): + raise StopIteration + iter.index = index + 1 + return l.items[index] Modified: pypy/branch/rpython-refactoring/rmodel.py ============================================================================== --- pypy/branch/rpython-refactoring/rmodel.py (original) +++ pypy/branch/rpython-refactoring/rmodel.py Fri Jun 3 21:09:43 2005 @@ -17,6 +17,9 @@ def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.lowleveltype) + def setup(self): + "For recursive data structure, which must be initialized in two steps." + # default implementation of some operations def rtype_getattr(self, hop): @@ -45,6 +48,19 @@ else: return hop.genop('int_is_true', [vlen], resulttype=Bool) + def rtype_iter(self, hop): + r_iter = self.make_iterator_repr() + return r_iter.newiter(hop) + + def make_iterator_repr(self): + raise TyperError("%s is not iterable" % (self,)) + +class __extend__(annmodel.SomeIterator): + # NOTE: SomeIterator is for iterators over any container, not just list + def rtyper_makerepr(self, rtyper): + r_container = rtyper.getrepr(self.s_container) + return r_container.make_iterator_repr() + # ____________________________________________________________ class TyperError(Exception): Modified: pypy/branch/rpython-refactoring/rpbc.py ============================================================================== --- pypy/branch/rpython-refactoring/rpbc.py (original) +++ pypy/branch/rpython-refactoring/rpbc.py Fri Jun 3 21:09:43 2005 @@ -1,6 +1,6 @@ import types -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomePBC +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import typeOf from pypy.rpython import rclass Modified: pypy/branch/rpython-refactoring/rptr.py ============================================================================== --- pypy/branch/rpython-refactoring/rptr.py (original) +++ pypy/branch/rpython-refactoring/rptr.py Fri Jun 3 21:09:43 2005 @@ -1,5 +1,5 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomePtr, SomeInteger +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import ContainerType, Void, Signed, Bool Added: pypy/branch/rpython-refactoring/rrange.py ============================================================================== --- (empty file) +++ pypy/branch/rpython-refactoring/rrange.py Fri Jun 3 21:09:43 2005 @@ -0,0 +1,96 @@ +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.lltype import * + +# ____________________________________________________________ +# +# Concrete implementation of RPython lists that are returned by range() +# and never mutated afterwards: +# +# struct range { +# Signed start, stop; // step is always constant +# } + +RANGE = GcPtr(GcStruct("range", ("start", Signed), ("stop", Signed))) + +class RangeRepr(Repr): + lowlevelrepr = RANGE + + def __init__(self, step): + self.step = step + + def rtype_len(self, hop): + v_rng, = hop.inputargs(self) + cstep = hop.inputconst(Signed, self.step) + return hop.gendirectcall(ll_rangelen, v_rng, cstep) + + def make_iterator_repr(self): + return riter.RangeIteratorRepr(self) + +class __extend__(pairtype(RangeRepr, IntegerRepr)): + + def rtype_getitem((r_rng, r_int), hop): + v_lst, v_index = hop.inputargs(r_lst, Signed) + cstep = hop.inputconst(Signed, self.step) + if hop.args_s[1].nonneg: + llfn = ll_rangeitem_nonneg + else: + llfn = ll_rangeitem + return hop.gendirectcall(llfn, v_lst, v_index, cstep) + +# ____________________________________________________________ +# +# Low-level methods. + +def ll_rangelen(l, step): + if step > 0: + result = (l.stop - l.start + (step-1)) // step + else: + result = (l.start - l.stop - (step+1)) // (-step) + if result < 0: + result = 0 + return result + +def ll_rangeitem_nonneg(l, i, step): + return l.start + i*step + +def ll_rangeitem(l, i, step): + if i<0: + # XXX ack. cannot call ll_rangelen() here for now :-( + if step > 0: + length = (l.stop - l.start + (step-1)) // step + else: + length = (l.start - l.stop - (step+1)) // (-step) + #assert length >= 0 + i += length + return l.start + i*step + +# ____________________________________________________________ +# +# Irregular operations. + +def ll_newrange(start, stop): + l = malloc(RANGE.TO) + l.start = start + l.stop = stop + return l + +def rtype_builtin_range(hop): + vstep = hop.inputconst(Signed, 1) + if hop.nb_args == 1: + vstart = hop.inputconst(Signed, 0) + vstop, = hop.inputargs(Signed) + elif hop.nb_args == 2: + vstart, vstop = hop.inputargs(Signed, Signed) + else: + vstart, vstop, vstep = hop.inputargs(Signed, Signed, Signed) + assert isinstance(vstep, Constant) + + if isinstance(hop.r_result, RangeRepr): + return hop.gendirectcall(ll_newrange, vstart, vstop) + else: + # cannot build a RANGE object, needs a real list + raise TyperError("range() result used as a normal list: " + "XXX not implemented") + #return hop.gendirectcall(ll_range2list, vstart, vstop, vstep) Modified: pypy/branch/rpython-refactoring/rstr.py ============================================================================== --- pypy/branch/rpython-refactoring/rstr.py (original) +++ pypy/branch/rpython-refactoring/rstr.py Fri Jun 3 21:09:43 2005 @@ -1,5 +1,5 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeString, SomeChar, SomeInteger, SomeObject +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import * # ____________________________________________________________ Modified: pypy/branch/rpython-refactoring/rtyper.py ============================================================================== --- pypy/branch/rpython-refactoring/rtyper.py (original) +++ pypy/branch/rpython-refactoring/rtyper.py Fri Jun 3 21:09:43 2005 @@ -54,6 +54,7 @@ "missing a GcPtr or NonGcPtr in the type specification " "of %s:\n%r" % (s_obj, result.lowleveltype)) self.reprs_by_content[key] = result + result.setup() self.reprs_by_id[id(s_obj)] = result return result @@ -393,7 +394,8 @@ # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations # and the rtyper_chooserepr() methods -#from pypy.rpython import robject, rlist, rptr, rbuiltin, rint, rbool, rfloat -#from pypy.rpython import rpbc, rstr, riter - -from pypy.rpython import robject, rint, rbool, rfloat +from pypy.rpython import robject +from pypy.rpython import rint, rbool, rfloat +from pypy.rpython import rlist#, rstr +#from pypy.rpython import rbuiltin, rpbc +#from pypy.rpython import rptr Modified: pypy/branch/rpython-refactoring/test/test_rlist.py ============================================================================== --- pypy/branch/rpython-refactoring/test/test_rlist.py (original) +++ pypy/branch/rpython-refactoring/test/test_rlist.py Fri Jun 3 21:09:43 2005 @@ -1,13 +1,14 @@ from pypy.translator.translator import Translator -from pypy.annotation.listdef import ListDef from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rlist import * +from pypy.rpython.rint import signed_repr def test_rlist(): - s = SomeList(ListDef(None, SomeInteger())) - l = ll_newlist(s.lowleveltype(), 3) + rlist = ListRepr(signed_repr) + rlist.setup() + l = ll_newlist(rlist.lowleveltype, 3) ll_setitem(l, 0, 42) ll_setitem(l, -2, 43) ll_setitem_nonneg(l, 2, 44) @@ -18,23 +19,6 @@ assert ll_getitem(l, 3) == 45 assert ll_len(l) == 4 -def test_rlist_range(): - def test1(start, stop, step): - expected = range(start, stop, step) - length = len(expected) - l = ll_newrange(start, stop) - assert ll_rangelen(l, step) == length - lst = [ll_rangeitem(l, i, step) for i in range(length)] - assert lst == expected - lst = [ll_rangeitem(l, i-length, step) for i in range(length)] - assert lst == expected - - for start in (-10, 0, 1, 10): - for stop in (-8, 0, 4, 8, 25): - for step in (1, 2, 3, -1, -2): - test1(start, stop, step) - - # ____________________________________________________________ def test_simple(): Added: pypy/branch/rpython-refactoring/test/test_rrange.py ============================================================================== --- (empty file) +++ pypy/branch/rpython-refactoring/test/test_rrange.py Fri Jun 3 21:09:43 2005 @@ -0,0 +1,19 @@ +from pypy.rpython.rrange import * + +def test_rlist_range(): + def test1(start, stop, step): + expected = range(start, stop, step) + length = len(expected) + l = ll_newrange(start, stop) + assert ll_rangelen(l, step) == length + lst = [ll_rangeitem(l, i, step) for i in range(length)] + assert lst == expected + lst = [ll_rangeitem_nonneg(l, i, step) for i in range(length)] + assert lst == expected + lst = [ll_rangeitem(l, i-length, step) for i in range(length)] + assert lst == expected + + for start in (-10, 0, 1, 10): + for stop in (-8, 0, 4, 8, 25): + for step in (1, 2, 3, -1, -2): + test1(start, stop, step) From arigo at codespeak.net Fri Jun 3 22:10:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Jun 2005 22:10:36 +0200 (CEST) Subject: [pypy-svn] r13040 - pypy/branch/rpython-refactoring Message-ID: <20050603201036.1855C27B47@code1.codespeak.net> Author: arigo Date: Fri Jun 3 22:10:35 2005 New Revision: 13040 Modified: pypy/branch/rpython-refactoring/rbuiltin.py pypy/branch/rpython-refactoring/rint.py pypy/branch/rpython-refactoring/rlist.py pypy/branch/rpython-refactoring/robject.py pypy/branch/rpython-refactoring/rpbc.py pypy/branch/rpython-refactoring/rptr.py pypy/branch/rpython-refactoring/rtyper.py Log: Intermediate check-in. Modified: pypy/branch/rpython-refactoring/rbuiltin.py ============================================================================== --- pypy/branch/rpython-refactoring/rbuiltin.py (original) +++ pypy/branch/rpython-refactoring/rbuiltin.py Fri Jun 3 22:10:35 2005 @@ -3,65 +3,86 @@ from pypy.rpython.lltype import malloc, typeOf, nullptr, nullgcptr from pypy.rpython.lltype import Void, Signed from pypy.rpython.rtyper import TyperError -from pypy.rpython.rlist import rtype_builtin_range +from pypy.rpython.rrange import rtype_builtin_range +from pypy.rpython.rmodel import Repr, TyperError -class __extend__(SomeBuiltin): - - def lowleveltype(s_blt): - if s_blt.s_self is None: - assert s_blt.is_constant() - return Void - else: - # methods of a known name are implemented as just their 'self' - assert s_blt.methodname is not None - return s_blt.s_self.lowleveltype() - - def rtype_simple_call(s_blt, hop): - if s_blt.s_self is None: - if not s_blt.is_constant(): - raise TyperError("non-constant built-in") - try: - bltintyper = BUILTIN_TYPER[s_blt.const] - except KeyError: - raise TyperError("don't know about built-in function %r" % ( - s_blt.const,)) - hop.s_popfirstarg() +class __extend__(annmodel.SomeBuiltin): + def rtyper_makerepr(self, rtyper): + if self.s_self is None: + # built-in function case + if not self.is_constant(): + raise TyperError("non-constant built-in function!") + return BuiltinFunctionRepr(self.const) else: - # methods: look up the rtype_method_xxx() - name = 'rtype_method_' + s_blt.methodname - try: - bltintyper = getattr(s_blt.s_self, name) - except AttributeError: - raise TyperError("missing %s.%s" % ( - s_blt.s_self.__class__.__name__, name)) + # built-in method case + assert self.methodname is not None + return BuiltinMethodRepr(rtyper.getrepr(self.s_self), + self.methodname) + + +class BuiltinFunctionRepr(Repr): + lowleveltype = Void + + def __init__(self, builtinfunc): + self.builtinfunc = builtinfunc + + def rtype_simple_call(self, hop): + try: + bltintyper = BUILTIN_TYPER[self.builtinfunc] + except KeyError: + raise TyperError("don't know about built-in function %r" % ( + self.builtinfunc,)) + hop.r_s_popfirstarg() + return bltintyper(hop) + + +class BuiltinMethodRepr(Repr): + + def __init__(self, self_repr, methodname): + self.self_repr = self_repr + self.methodname = methodname + # methods of a known name are implemented as just their 'self' + self.lowleveltype = self_repr.lowleveltype + + def rtype_simple_call(self, hop): + # methods: look up the rtype_method_xxx() + name = 'rtype_method_' + self.methodname + try: + bltintyper = getattr(self.self_repr, name) + except AttributeError: + raise TyperError("missing %s.%s" % ( + self.self_repr.__class__.__name__, name)) + # hack based on the fact that 'lowleveltype == self_repr.lowleveltype' + assert hop.args_r[0] is self + hop.args_r[0] = self.self_repr return bltintyper(hop) -class __extend__(pairtype(SomeBuiltin, SomeObject)): +##class __extend__(pairtype(SomeBuiltin, SomeObject)): - def rtype_convert_from_to((s_blt, s_to), v, llops): - if s_blt.s_self is None: - raise TyperError("conversion requested on a built-in function") - return llops.convertvar(v, s_blt.s_self, s_to) +## def rtype_convert_from_to((s_blt, s_to), v, llops): +## if s_blt.s_self is None: +## raise TyperError("conversion requested on a built-in function") +## return llops.convertvar(v, s_blt.s_self, s_to) # ____________________________________________________________ def rtype_builtin_bool(hop): assert hop.nb_args == 1 - return hop.args_s[0].rtype_is_true(hop) + return hop.args_r[0].rtype_is_true(hop) def rtype_builtin_int(hop): - if isinstance(hop.args_s[0], SomeString): + if isinstance(hop.args_s[0], annmodel.SomeString): raise TyperError('int("string") not supported') assert hop.nb_args == 1 - return hop.args_s[0].rtype_int(hop) + return hop.args_r[0].rtype_int(hop) def rtype_builtin_float(hop): assert hop.nb_args == 1 - return hop.args_s[0].rtype_float(hop) + return hop.args_r[0].rtype_float(hop) -#def rtype_builtin_range(hop): see rlist.py +#def rtype_builtin_range(hop): see rrange.py # collect all functions @@ -79,11 +100,11 @@ if hop.nb_args == 1: vlist = hop.inputargs(Void) return hop.genop('malloc', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) else: vlist = hop.inputargs(Void, Signed) return hop.genop('malloc_varsize', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) def rtype_const_result(hop): return hop.inputconst(Void, hop.s_result.const) Modified: pypy/branch/rpython-refactoring/rint.py ============================================================================== --- pypy/branch/rpython-refactoring/rint.py (original) +++ pypy/branch/rpython-refactoring/rint.py Fri Jun 3 22:10:35 2005 @@ -214,8 +214,8 @@ vlist = hop.inputargs(Signed) return vlist[0] - def rtype_int(s_int, hop): - if s_int.unsigned: + def rtype_int(r_int, hop): + if r_int.lowleveltype == Unsigned: raise TyperError("use intmask() instead of int(r_uint(...))") vlist = hop.inputargs(Signed) return vlist[0] Modified: pypy/branch/rpython-refactoring/rlist.py ============================================================================== --- pypy/branch/rpython-refactoring/rlist.py (original) +++ pypy/branch/rpython-refactoring/rlist.py Fri Jun 3 22:10:35 2005 @@ -34,6 +34,7 @@ self.LIST = GcForwardReference() self.lowleveltype = GcPtr(self.LIST) self.item_repr = item_repr # possibly uncomputed at this point! + # setup() needs to be called to finish this initialization def setup(self): if callable(self.item_repr): @@ -111,14 +112,14 @@ def rtype_newlist(hop): nb_args = hop.nb_args - s_list = hop.s_result - s_listitem = s_list.get_s_items() - c1 = hop.inputconst(Void, s_list.lowleveltype()) + r_list = hop.r_result + r_listitem = r_list.item_repr + c1 = hop.inputconst(Void, r_list.lowleveltype) c2 = hop.inputconst(Signed, nb_args) v_result = hop.gendirectcall(ll_newlist, c1, c2) for i in range(nb_args): ci = hop.inputconst(Signed, i) - v_item = hop.inputarg(s_listitem, arg=i) + v_item = hop.inputarg(r_listitem, arg=i) hop.gendirectcall(ll_setitem_nonneg, v_result, ci, v_item) return v_result Modified: pypy/branch/rpython-refactoring/robject.py ============================================================================== --- pypy/branch/rpython-refactoring/robject.py (original) +++ pypy/branch/rpython-refactoring/robject.py Fri Jun 3 22:10:35 2005 @@ -8,7 +8,7 @@ class __extend__(annmodel.SomeObject): def rtyper_makerepr(self, rtyper): if self.is_constant(): - return constobj_repr + return constpyobj_repr if self.knowntype is type: return rclass.type_repr else: @@ -21,7 +21,7 @@ pyobj_repr = PyObjRepr() -class ConstObjRepr(Repr): +class ConstPyObjRepr(Repr): lowleveltype = Void -constobj_repr = ConstObjRepr() +constpyobj_repr = ConstPyObjRepr() Modified: pypy/branch/rpython-refactoring/rpbc.py ============================================================================== --- pypy/branch/rpython-refactoring/rpbc.py (original) +++ pypy/branch/rpython-refactoring/rpbc.py Fri Jun 3 22:10:35 2005 @@ -1,21 +1,31 @@ import types from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import typeOf -from pypy.rpython import rclass +from pypy.rpython.lltype import typeOf, Void +from pypy.rpython.rmodel import Repr, TyperError +#from pypy.rpython import rclass -class __extend__(SomePBC): +class __extend__(annmodel.SomePBC): + def rtyper_makerepr(self, rtyper): + return PBCRepr(self.prebuiltinstances) + + +class PBCRepr(Repr): + + def __init__(self, prebuiltinstances): + self.prebuiltinstances = prebuiltinstances + assert len(prebuiltinstances) == 1, "Not Implemented: multiPBCs" + self.lowleveltype = Void def rtype_getattr(_, hop): - attr = hop.args_s[1].const if hop.s_result.is_constant(): - return hop.inputconst(hop.s_result, hop.s_result.const) + return hop.inputconst(hop.r_result, hop.s_result.const) else: NotImplementedYet def rtype_simple_call(_, hop): - s_func = hop.s_popfirstarg() + r_func, s_func = hop.r_s_popfirstarg() if not s_func.is_constant(): NotImplementedYet func = s_func.const @@ -23,9 +33,14 @@ # XXX hackish f = hop.rtyper.getfunctionptr(func) FUNCPTR = typeOf(f) - args_v = hop.inputargs(*FUNCPTR.TO.ARGS) + rinputs = [hop.rtyper.bindingrepr(v) for v in f.graph.getargs()] + if FUNCPTR.TO.RESULT == Void: + rresult = Void + else: + rresult = hop.rtyper.bindingrepr(f.graph.getreturnvar()) + args_v = hop.inputargs(*rinputs) c = hop.inputconst(FUNCPTR, f) return hop.genop('direct_call', [c] + args_v, - resulttype = FUNCPTR.TO.RESULT) + resulttype = rresult) elif isinstance(func, (types.ClassType, type)): return rclass.rtype_new_instance(s_func, hop) Modified: pypy/branch/rpython-refactoring/rptr.py ============================================================================== --- pypy/branch/rpython-refactoring/rptr.py (original) +++ pypy/branch/rpython-refactoring/rptr.py Fri Jun 3 22:10:35 2005 @@ -1,58 +1,97 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel +from pypy.rpython.lltype import _PtrType, _ptr from pypy.rpython.lltype import ContainerType, Void, Signed, Bool +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst -class __extend__(SomePtr): - - def lowleveltype(s_ptr): - if s_ptr.is_constant(): # constant NULL - return Void +class __extend__(annmodel.SomePtr): + def rtyper_makerepr(self, rtyper): + if self.is_constant(): # constant NULL + return nullptr_repr else: - return s_ptr.ll_ptrtype + return PtrRepr(self.ll_ptrtype) + + +class PtrRepr(Repr): + + def __init__(self, ptrtype): + assert isinstance(ptrtype, _PtrType) + self.lowleveltype = ptrtype - def rtype_getattr(s_ptr, hop): + def rtype_getattr(self, hop): attr = hop.args_s[1].const - FIELD_TYPE = getattr(s_ptr.ll_ptrtype.TO, attr) + FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): newopname = 'getsubstruct' else: newopname = 'getfield' - vlist = hop.inputargs(s_ptr, Void) + vlist = hop.inputargs(self, Void) return hop.genop(newopname, vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) - def rtype_setattr(s_ptr, hop): + def rtype_setattr(self, hop): attr = hop.args_s[1].const - FIELD_TYPE = getattr(s_ptr.ll_ptrtype.TO, attr) + FIELD_TYPE = getattr(self.lowleveltype.TO, attr) assert not isinstance(FIELD_TYPE, ContainerType) - vlist = hop.inputargs(s_ptr, Void, FIELD_TYPE) + vlist = hop.inputargs(self, Void, hop.args_r[2]) hop.genop('setfield', vlist) - def rtype_len(s_ptr, hop): - vlist = hop.inputargs(s_ptr) + def rtype_len(self, hop): + vlist = hop.inputargs(self) return hop.genop('getarraysize', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) - def rtype_is_true(s_ptr, hop): - vlist = hop.inputargs(s_ptr) + def rtype_is_true(self, hop): + vlist = hop.inputargs(self) return hop.genop('ptr_nonzero', vlist, resulttype=Bool) -class __extend__(pairtype(SomePtr, SomeInteger)): +class __extend__(pairtype(PtrRepr, IntegerRepr)): - def rtype_getitem((s_ptr, s_int), hop): - vlist = hop.inputargs(s_ptr, Signed) + def rtype_getitem((r_ptr, r_int), hop): + vlist = hop.inputargs(r_ptr, Signed) return hop.genop('getarrayitem', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) + +# ____________________________________________________________ +# +# Null Pointers + +class NullPtrRepr(Repr): + lowleveltype = Void + + def rtype_is_true(self, hop): + return hop.inputconst(Bool, False) + +nullptr_repr = NullPtrRepr() + +class __extend__(pairtype(NullPtrRepr, PtrRepr)): + def convert_from_to((r_null, r_ptr), v, llops): + # nullptr to general pointer + return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) + +# ____________________________________________________________ +# +# Comparisons + +class __extend__(pairtype(PtrRepr, Repr)): + + def rtype_eq((r_ptr, r_any), hop): + vlist = hop.inputargs(r_ptr, r_ptr) + return hop.genop('ptr_eq', vlist, resulttype=Bool) + + def rtype_ne((r_ptr, r_any), hop): + vlist = hop.inputargs(r_ptr, r_ptr) + return hop.genop('ptr_ne', vlist, resulttype=Bool) -class __extend__(pairtype(SomePtr, SomePtr)): +class __extend__(pairtype(Repr, PtrRepr)): - def rtype_eq(_, hop): - vlist = hop.inputargs(SomePtr(), SomePtr()) + def rtype_eq((r_any, r_ptr), hop): + vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_eq', vlist, resulttype=Bool) - def rtype_ne(_, hop): - vlist = hop.inputargs(SomePtr(), SomePtr()) + def rtype_ne((r_any, r_ptr), hop): + vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_ne', vlist, resulttype=Bool) Modified: pypy/branch/rpython-refactoring/rtyper.py ============================================================================== --- pypy/branch/rpython-refactoring/rtyper.py (original) +++ pypy/branch/rpython-refactoring/rtyper.py Fri Jun 3 22:10:35 2005 @@ -36,7 +36,7 @@ def getrepr(self, s_obj): # s_objs are not hashable... try hard to find a hash anyway try: - return self.reprs_by_id[id(s_obj)] + result, s_obj = self.reprs_by_id[id(s_obj)] except KeyError: key = [s_obj.__class__] items = s_obj.__dict__.items() @@ -55,8 +55,8 @@ "of %s:\n%r" % (s_obj, result.lowleveltype)) self.reprs_by_content[key] = result result.setup() - self.reprs_by_id[id(s_obj)] = result - return result + self.reprs_by_id[id(s_obj)] = result, s_obj + return result def binding(self, var): s_obj = self.annotator.binding(var, True) @@ -244,12 +244,12 @@ """Make a functionptr from the given Python function.""" a = self.annotator graph = a.translator.getflowgraph(func) - llinputs = [a.binding(v).lowleveltype() for v in graph.getargs()] + llinputs = [self.bindingrepr(v).lowleveltype for v in graph.getargs()] s_output = a.binding(graph.getreturnvar(), None) if s_output is None: lloutput = Void else: - lloutput = s_output.lowleveltype() + lloutput = self.getrepr(s_output).lowleveltype FT = FuncType(llinputs, lloutput) return functionptr(FT, func.func_name, graph = graph, _callable = func) @@ -307,12 +307,11 @@ def gendirectcall(self, ll_function, *args_v): return self.llops.gendirectcall(ll_function, *args_v) - def s_popfirstarg(self): + def r_s_popfirstarg(self): "Return and discard the first argument." self.nb_popped += 1 self.nb_args -= 1 - self.args_r.pop(0) - return self.args_s.pop(0) + return self.args_r.pop(0), self.args_s.pop(0) # ____________________________________________________________ @@ -351,9 +350,9 @@ spec_name = [ll_function.func_name] args_s = [] for v in args_v: - r_value = rtyper.bindingrepr(v) if v.concretetype == Void: - if not r_value.s_obj.is_constant(): + s_value = rtyper.binding(v) + if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") key = s_value.const # specialize by constant value args_s.append(s_value) @@ -372,8 +371,8 @@ name = '_'.join(spec_name) spec_function = func_with_new_name(ll_function, name) # flow and annotate (the copy of) the low-level function - spec_graph = annotator.translator.getflowgraph(spec_function) - annotator.build_types(spec_function, args_s) + spec_graph = rtyper.annotator.translator.getflowgraph(spec_function) + rtyper.annotator.build_types(spec_function, args_s) # cache the result self.rtyper.specialized_ll_functions[spec_key] = spec_function @@ -397,5 +396,5 @@ from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat from pypy.rpython import rlist#, rstr -#from pypy.rpython import rbuiltin, rpbc -#from pypy.rpython import rptr +from pypy.rpython import rbuiltin, rpbc +from pypy.rpython import rptr From arigo at codespeak.net Fri Jun 3 22:23:12 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 3 Jun 2005 22:23:12 +0200 (CEST) Subject: [pypy-svn] r13041 - pypy/branch/rpython-refactoring Message-ID: <20050603202312.3C09D27B44@code1.codespeak.net> Author: arigo Date: Fri Jun 3 22:23:12 2005 New Revision: 13041 Modified: pypy/branch/rpython-refactoring/rpbc.py pypy/branch/rpython-refactoring/rrange.py pypy/branch/rpython-refactoring/rstr.py pypy/branch/rpython-refactoring/rtyper.py Log: Ported rstr.py. Modified: pypy/branch/rpython-refactoring/rpbc.py ============================================================================== --- pypy/branch/rpython-refactoring/rpbc.py (original) +++ pypy/branch/rpython-refactoring/rpbc.py Fri Jun 3 22:23:12 2005 @@ -32,12 +32,13 @@ if isinstance(func, types.FunctionType): # XXX hackish f = hop.rtyper.getfunctionptr(func) + graph = f._obj.graph FUNCPTR = typeOf(f) - rinputs = [hop.rtyper.bindingrepr(v) for v in f.graph.getargs()] + rinputs = [hop.rtyper.bindingrepr(v) for v in graph.getargs()] if FUNCPTR.TO.RESULT == Void: rresult = Void else: - rresult = hop.rtyper.bindingrepr(f.graph.getreturnvar()) + rresult = hop.rtyper.bindingrepr(graph.getreturnvar()) args_v = hop.inputargs(*rinputs) c = hop.inputconst(FUNCPTR, f) return hop.genop('direct_call', [c] + args_v, Modified: pypy/branch/rpython-refactoring/rrange.py ============================================================================== --- pypy/branch/rpython-refactoring/rrange.py (original) +++ pypy/branch/rpython-refactoring/rrange.py Fri Jun 3 22:23:12 2005 @@ -12,10 +12,11 @@ # Signed start, stop; // step is always constant # } -RANGE = GcPtr(GcStruct("range", ("start", Signed), ("stop", Signed))) +RANGE = GcStruct("range", ("start", Signed), ("stop", Signed)) + class RangeRepr(Repr): - lowlevelrepr = RANGE + lowlevelrepr = GcPtr(RANGE) def __init__(self, step): self.step = step @@ -71,7 +72,7 @@ # Irregular operations. def ll_newrange(start, stop): - l = malloc(RANGE.TO) + l = malloc(RANGE) l.start = start l.stop = stop return l Modified: pypy/branch/rpython-refactoring/rstr.py ============================================================================== --- pypy/branch/rpython-refactoring/rstr.py (original) +++ pypy/branch/rpython-refactoring/rstr.py Fri Jun 3 22:23:12 2005 @@ -1,6 +1,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.lltype import * +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.rmodel import StringRepr, CharRepr # ____________________________________________________________ # @@ -15,79 +17,75 @@ STR = GcStruct('str', ('hash', Signed), ('chars', Array(('ch', Char)))) -STRPTR = GcPtr(STR) -class __extend__(SomeString): +class __extend__(annmodel.SomeString): + def rtyper_makerepr(self, rtyper): + return string_repr - def lowleveltype(self): - return STRPTR +class __extend__(annmodel.SomeChar): + def rtyper_makerepr(self, rtyper): + return char_repr + + +class __extend__(StringRepr): + lowleveltype = GcPtr(STR) def rtype_len(_, hop): - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strlen, v_str) - def rtype_is_true(s_str, hop): + def rtype_is_true(self, hop): + s_str = hop.args_s[0] if s_str.can_be_None: - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_str_is_true, v_str) else: # defaults to checking the length - return SomeObject.rtype_is_true(s_str, hop) + return super(StringRepr, self).rtype_is_true(hop) def rtype_ord(_, hop): - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) c_zero = inputconst(Signed, 0) v_chr = hop.gendirectcall(ll_stritem_nonneg, v_str, c_zero) return hop.genop('cast_char_to_int', [v_chr], resulttype=Signed) def rtype_hash(_, hop): - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strhash, v_str) -class __extend__(pairtype(SomeString, SomeInteger)): - - def rtype_getitem((_, s_int), hop): - v_str, v_index = hop.inputargs(SomeString(), Signed) - if s_int.nonneg: +class __extend__(pairtype(StringRepr, IntegerRepr)): + def rtype_getitem(_, hop): + v_str, v_index = hop.inputargs(string_repr, Signed) + if hop.args_s[1].nonneg: llfn = ll_stritem_nonneg else: llfn = ll_stritem return hop.gendirectcall(llfn, v_str, v_index) -class __extend__(SomeChar): - - def lowleveltype(self): - return Char +class __extend__(CharRepr): def rtype_len(_, hop): return hop.inputconst(Signed, 1) - def rtype_is_true(s_chr, hop): - assert not s_chr.can_be_None + def rtype_is_true(_, hop): + assert not hop.args_s[0].can_be_None return hop.inputconst(Bool, True) def rtype_ord(_, hop): - vlist = hop.inputargs(Char) + vlist = hop.inputargs(char_repr) return hop.genop('cast_char_to_int', vlist, resulttype=Signed) -class __extend__(pairtype(SomeChar, SomeString)): - - def rtype_convert_from_to((s_chr, s_str), v, llops): +class __extend__(pairtype(CharRepr, StringRepr)): + def convert_from_to(_, v, llops): return hop.gendirectcall(ll_chr2str, v) -class __extend__(pairtype(SomeString, SomeString)): - - def rtype_convert_from_to((s_str1, s_str2), v, llops): - # converting between SomeString(can_be_None=False) - # and SomeString(can_be_None=True) - assert s_str1.__class__ is s_str2.__class__ is SomeString - return v - +string_repr = StringRepr() +char_repr = CharRepr() # ____________________________________________________________ # Modified: pypy/branch/rpython-refactoring/rtyper.py ============================================================================== --- pypy/branch/rpython-refactoring/rtyper.py (original) +++ pypy/branch/rpython-refactoring/rtyper.py Fri Jun 3 22:23:12 2005 @@ -395,6 +395,6 @@ # and the rtyper_chooserepr() methods from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat -from pypy.rpython import rlist#, rstr +from pypy.rpython import rlist, rstr from pypy.rpython import rbuiltin, rpbc from pypy.rpython import rptr From arigo at codespeak.net Sat Jun 4 00:36:44 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 00:36:44 +0200 (CEST) Subject: [pypy-svn] r13042 - pypy/branch/rpython-refactoring Message-ID: <20050603223644.BF30027B43@code1.codespeak.net> Author: arigo Date: Sat Jun 4 00:36:44 2005 New Revision: 13042 Modified: pypy/branch/rpython-refactoring/rclass.py pypy/branch/rpython-refactoring/robject.py pypy/branch/rpython-refactoring/rpbc.py Log: Almost finished. Modified: pypy/branch/rpython-refactoring/rclass.py ============================================================================== --- pypy/branch/rpython-refactoring/rclass.py (original) +++ pypy/branch/rpython-refactoring/rclass.py Sat Jun 4 00:36:44 2005 @@ -1,8 +1,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.lltype import * -from pypy.rpython.rtyper import inputconst - +from pypy.rpython.rmodel import Repr, TyperError, inputconst # # There is one "vtable" per user class, with the following structure: @@ -103,9 +102,7 @@ return result -def rtype_new_instance(s_cls, hop): - assert s_cls.is_constant() - cls = s_cls.const +def rtype_new_instance(cls, hop): classdef = hop.rtyper.annotator.getuserclasses()[cls] rclassdef = getrclassdef(classdef) return rclassdef.rtype_new_instance(hop.llops) @@ -113,16 +110,26 @@ # ____________________________________________________________ -class __extend__(SomeInstance): +class __extend__(annmodel.SomeInstance): + def rtyper_makerepr(self, rtyper): + return InstanceRepr(self.classdef) - def lowleveltype(s_ins): - rclassdef = getrclassdef(s_ins.classdef) - return GcPtr(rclassdef.object_type) - - def rtype_type(s_ins, hop): - rclassdef = getrclassdef(s_ins.classdef) - vptr, = hop.inputargs(s_ins) - vptr_as_object = rclassdef.parent_cast(None, vptr, hop.llops) - typeptr_name = inputconst(Void, "typeptr") + +class InstanceRepr(Repr): + + def __init__(self, classdef): + self.rclassdef = getrclassdef(classdef) + self.lowleveltype = GcPtr(self.rclassdef.object_type) + + def rtype_type(self, hop): + vptr, = hop.inputargs(self) + vptr_as_object = self.rclassdef.parent_cast(None, vptr, hop.llops) + typeptr_name = hop.inputconst(Void, "typeptr") return hop.genop('getfield', [vptr_as_object, typeptr_name], resulttype=TYPEPTR) + + +class TypeRepr(Repr): + lowleveltype = TYPEPTR + +type_repr = TypeRepr() Modified: pypy/branch/rpython-refactoring/robject.py ============================================================================== --- pypy/branch/rpython-refactoring/robject.py (original) +++ pypy/branch/rpython-refactoring/robject.py Sat Jun 4 00:36:44 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltype import PyObject, GcPtr, Void, Bool from pypy.rpython.rmodel import Repr, TyperError -#from pypy.rpython import rclass +from pypy.rpython import rclass class __extend__(annmodel.SomeObject): Modified: pypy/branch/rpython-refactoring/rpbc.py ============================================================================== --- pypy/branch/rpython-refactoring/rpbc.py (original) +++ pypy/branch/rpython-refactoring/rpbc.py Sat Jun 4 00:36:44 2005 @@ -3,7 +3,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltype import typeOf, Void from pypy.rpython.rmodel import Repr, TyperError -#from pypy.rpython import rclass +from pypy.rpython import rclass class __extend__(annmodel.SomePBC): @@ -44,4 +44,4 @@ return hop.genop('direct_call', [c] + args_v, resulttype = rresult) elif isinstance(func, (types.ClassType, type)): - return rclass.rtype_new_instance(s_func, hop) + return rclass.rtype_new_instance(s_func.const, hop) From arigo at codespeak.net Sat Jun 4 00:39:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 00:39:22 +0200 (CEST) Subject: [pypy-svn] r13043 - pypy/dist/pypy/annotation Message-ID: <20050603223922.686E427B43@code1.codespeak.net> Author: arigo Date: Sat Jun 4 00:39:22 2005 New Revision: 13043 Modified: pypy/dist/pypy/annotation/model.py Log: Small sanitization. Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sat Jun 4 00:39:22 2005 @@ -349,19 +349,17 @@ ll_to_annotation_map = dict([(ll, ann) for ann,ll in annotation_to_ll_map]) -def ll_to_annotation(v): - if v is None: - raise ValueError, "cannot retrieve Void low-level type value" - typ = lltype.typeOf(v) - s = ll_to_annotation_map.get(typ) - if s is None: - return SomePtr(typ) - else: - return s - def lltype_to_annotation(T): - return ll_to_annotation(T._example()) + s = ll_to_annotation_map.get(T) + if s is None: + return SomePtr(T) + else: + return s +def ll_to_annotation(v): + if v is None: + raise ValueError, "cannot retrieve Void low-level type value" + return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ From pedronis at codespeak.net Sat Jun 4 01:25:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 01:25:53 +0200 (CEST) Subject: [pypy-svn] r13044 - pypy/dist/pypy/translator/goal Message-ID: <20050603232553.1D17F27B44@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 01:25:52 2005 New Revision: 13044 Modified: pypy/dist/pypy/translator/goal/query.py Log: slightly nicer output Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Sat Jun 4 01:25:52 2005 @@ -141,6 +141,8 @@ obj = "[%s]" % '|'.join([str(x) for x in obj]) else: obj = str(obj) + if obj.startswith('<'): + obj = obj[1:-1] if cls is None: return str(obj) @@ -220,8 +222,8 @@ else: return "%d families" % nfam - def pretty_nels(kinds, nels): - if nels == 1: + def pretty_nels(kinds, nels, nfam): + if nels == 1 or nels == nfam: return "one %s" % prettycallable(kinds) else: return "in total %d %s" % (nels, prettycallable(kinds)) @@ -231,14 +233,18 @@ for classdef, obj in objs: cls = classdef and classdef.cls accum.append(prettycallable((cls, obj))) - return "{%s}" % ' '.join(accum) + els = ' '.join(accum) + if len(accum) == 1: + return els + else: + return "{%s}" % els items = one_pattern_fams.items() items.sort(lambda a,b: cmp((a[0][1],a[1][1]), (b[0][1],b[1][1]))) # sort by pattern and then by els for (kinds, patt), (nfam, nels) in items: - print pretty_nfam(nfam), "with", pretty_nels(kinds, nels), "with one call-pattern:", prettypatt([patt]) + print pretty_nfam(nfam), "with", pretty_nels(kinds, nels, nfam), "with one call-pattern:", prettypatt([patt]) print "- * -" From arigo at codespeak.net Sat Jun 4 01:34:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 01:34:27 +0200 (CEST) Subject: [pypy-svn] r13045 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050603233427.8D92A27B44@code1.codespeak.net> Author: arigo Date: Sat Jun 4 01:34:27 2005 New Revision: 13045 Modified: pypy/dist/pypy/objspace/std/stringobject.py pypy/dist/pypy/objspace/std/test/test_stringformat.py Log: Bug in string formatting: 'empty' % UserDefinedMapping() => TypeError Thanks xorAxAx on #pypy for this one. Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Sat Jun 4 01:34:27 2005 @@ -1015,7 +1015,10 @@ if isinstance(values, tuple): return _formatting.format(format, values, None) else: - if hasattr(values, 'keys'): + # CPython's logic for deciding if ""%values is + # an error (1 value, 0 %-formatters) or not + # (values is of a mapping type) + if hasattr(values, '__getitem__') and not isinstance(values, str): return _formatting.format(format, (values,), values) else: return _formatting.format(format, (values,), None) Modified: pypy/dist/pypy/objspace/std/test/test_stringformat.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_stringformat.py (original) +++ pypy/dist/pypy/objspace/std/test/test_stringformat.py Sat Jun 4 01:34:27 2005 @@ -31,6 +31,14 @@ d = {'i': 23} raises(KeyError, 'a%(x)sb'.__mod__, d) + def test_format_error(self): + assert '' % {} == '' + raises(TypeError, "'' % 5") + class MyMapping(object): + def __getitem__(self, key): + py.test.fail('should not be here') + assert '' % MyMapping() == '' + class AppTestStringObject: def test_format_item(self): From pedronis at codespeak.net Sat Jun 4 01:54:24 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 01:54:24 +0200 (CEST) Subject: [pypy-svn] r13046 - pypy/dist/pypy/translator/tool/pygame Message-ID: <20050603235424.14AC827B41@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 01:54:23 2005 New Revision: 13046 Modified: pypy/dist/pypy/translator/tool/pygame/graphdisplay.py Log: issue85 testing done the selective masking based on the mod bits we really care about Modified: pypy/dist/pypy/translator/tool/pygame/graphdisplay.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/graphdisplay.py (original) +++ pypy/dist/pypy/translator/tool/pygame/graphdisplay.py Sat Jun 4 01:54:23 2005 @@ -156,6 +156,9 @@ def initialize_keys(self): pygame.key.set_repeat(*self.KEY_REPEAT) + + mask = 0 + for strnames, methodname in self.KEYS.iteritems(): names = strnames.split() if not isinstance(methodname, basestring): @@ -190,11 +193,15 @@ if isinstance(key, int): for mod in permute_mods(basemod, mods): self.key_cache[(key, mod)] = (method, args) + mask |= mod else: for mod in permute_mods(basemod, mods): char = key.lower() mod = mod & ~KMOD_SHIFT self.ascii_key_cache[(char, mod)] = (method, args) + mask |= mod + + self.key_mask = mask def help(self): """Show a help window and wait for a key or a mouse press.""" @@ -610,10 +617,11 @@ self.notifymousepos(event.pos) def process_KeyDown(self, event): - method, args = self.key_cache.get((event.key, event.mod), (None, None)) + mod = event.mod & self.key_mask + method, args = self.key_cache.get((event.key, mod), (None, None)) if method is None and event.unicode: char = event.unicode.lower() - mod = event.mod & ~ KMOD_SHIFT + mod = mod & ~ KMOD_SHIFT method, args = self.ascii_key_cache.get((char, mod), (None, None)) if method is not None: method(*args) From pedronis at codespeak.net Sat Jun 4 03:19:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 03:19:55 +0200 (CEST) Subject: [pypy-svn] r13047 - pypy/dist/pypy/annotation Message-ID: <20050604011955.B7D9F27B48@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 03:19:55 2005 New Revision: 13047 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: give distingushed names to function/classes specialized by location too Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sat Jun 4 03:19:55 2005 @@ -11,7 +11,7 @@ from pypy.annotation.classdef import ClassDef, isclassdef from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF -from pypy.tool.sourcetools import func_with_new_name +from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.interpreter.pycode import CO_VARARGS from pypy.interpreter.pycode import cpython_code_signature from pypy.interpreter.argument import ArgErr @@ -350,7 +350,9 @@ specialize = getattr(cls, "_specialize_", False) if specialize: if specialize == "location": - cls = self.specialize_by_key(cls, self.position_key) + cls = self.specialize_by_key(cls, self.position_key, + name="%s__At_%s" % (cls.__name__, + position_name(self.position_key))) else: raise Exception, \ "unsupported specialization type '%s'"%(specialize,) @@ -402,7 +404,9 @@ func.__name__+'__'+key) elif specialize == "location": # fully specialize: create one version per call position - func = self.specialize_by_key(func, self.position_key) + func = self.specialize_by_key(func, self.position_key, + name="%s__At_%s" % (func.__name__, + position_name(self.position_key))) elif specialize == "memo": # call the function now, and collect possible results arglist_s, kwds_s = args.unpack() @@ -537,6 +541,11 @@ l.append(name) return "__".join(l) +def position_name((fn, block, i)): + mod = valid_identifier(getattr(fn, '__module__', 'SYNTH')) + name = valid_identifier(getattr(fn, '__name__', 'UNKNOWN')) + return "%s_%s_Giving_%s" % (mod, name, block.operations[i].result) + def possible_arguments(args): # enumerate all tuples (x1,..xn) of concrete values that are contained # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either From arigo at codespeak.net Sat Jun 4 12:10:50 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 12:10:50 +0200 (CEST) Subject: [pypy-svn] r13050 - pypy/branch/rpython-refactoring Message-ID: <20050604101050.662E227B42@code1.codespeak.net> Author: arigo Date: Sat Jun 4 12:10:50 2005 New Revision: 13050 Modified: pypy/branch/rpython-refactoring/rclass.py pypy/branch/rpython-refactoring/rpbc.py Log: A nice and clean -- if still quite strange -- version of rclass.py. Modified: pypy/branch/rpython-refactoring/rclass.py ============================================================================== --- pypy/branch/rpython-refactoring/rclass.py (original) +++ pypy/branch/rpython-refactoring/rclass.py Sat Jun 4 12:10:50 2005 @@ -37,99 +37,153 @@ OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) -class RClassDef: - - def __init__(self, classdef): - self.classdef = classdef - if classdef.basedef is None: - self.depth = 1 - parent_vtable_type = OBJECT_VTABLE - parent_typeptr = nullptr(OBJECT_VTABLE) - parent_object_type = OBJECT - else: - rbasedef = getrclassdef(classdef.basedef) - self.depth = rbasedef.depth + 1 - parent_vtable_type = rbasedef.vtable_type - parent_typeptr = rbasedef.typeptr - parent_object_type = rbasedef.object_type - self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, - ('super', parent_vtable_type), - # XXX class attributes - ) - self.vtable = malloc(self.vtable_type, immortal=True) - # cast the vtable pointer from "vtable_type" to "parent_vtable_type" - # to "parent_parent_vtable_type" to .... to OBJECT_VTABLE - p = self.vtable - for i in range(self.depth): - p = p.super - self.typeptr = cast_flags(TYPEPTR, p) - p.parenttypeptr = parent_typeptr - # - self.parent_object_type = parent_object_type - self.object_type = GcStruct(classdef.cls.__name__, - ('super', parent_object_type), - # XXX instance attributes - ) - - def parent_cast(self, targetclassdef, v, llops): - classdef = self.classdef - super_name = inputconst(Void, "super") - while classdef is not targetclassdef: - rclassdef = getrclassdef(classdef) - parent_object_type = rclassdef.parent_object_type - v = llops.genop('getsubstruct', [v, super_name], - resulttype = GcPtr(parent_object_type)) - classdef = classdef.basedef - return v - - def rtype_new_instance(self, llops): - ctype = inputconst(Void, self.object_type) - vptr = llops.genop('malloc', [ctype], - resulttype = GcPtr(self.object_type)) - vptr_as_object = self.parent_cast(None, vptr, llops) - typeptr_name = inputconst(Void, "typeptr") - ctypeptr = inputconst(TYPEPTR, self.typeptr) - llops.genop('setfield', [vptr_as_object, typeptr_name, ctypeptr]) - # XXX call __init__ somewhere - return vptr - +def getclassrepr(classdef): + if classdef is None: + return root_class_repr + try: + return classdef._rtype_classrepr_ + except AttributeError: + classdef._rtype_classrepr_ = result = ClassRepr(classdef) + return result -def getrclassdef(classdef): +def getinstancerepr(classdef): + if classdef is None: + return root_instance_repr try: - return classdef._rtype_rclassdef_ + return classdef._rtype_instancerepr_ except AttributeError: - classdef._rtype_rclassdef_ = result = RClassDef(classdef) + classdef._rtype_instancerepr_ = result = InstanceRepr(classdef) return result -def rtype_new_instance(cls, hop): - classdef = hop.rtyper.annotator.getuserclasses()[cls] - rclassdef = getrclassdef(classdef) - return rclassdef.rtype_new_instance(hop.llops) +class ClassRepr(Repr): + + def __init__(self, classdef): + self.classdef = classdef + if classdef is None: + # 'object' root type + self.vtable_type = OBJECT_VTABLE + self.typeptr = nullptr(OBJECT_VTABLE) + else: + self.rbase = getclassrepr(classdef.basedef) + self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, + ('super', self.rbase.vtable_type), + # XXX class attributes + ) + self.lowleveltype = NonGcPtr(self.vtable_type) + self.vtable = None + + def getvtable(self, cast_to_typeptr=True): + """Return a ptr to the vtable of this type.""" + if self.vtable is None: + self.vtable = malloc(self.vtable_type, immortal=True) + if self.classdef is not None: + self.setup_vtable(self.vtable, self.classdef) + # + vtable = self.vtable + if cast_to_typeptr: + r = self + while r is not root_class_repr: + r = r.rbase + vtable = cast_flags(r.lowleveltype, vtable.super) + return vtable + + def setup_vtable(self, vtable, subclsdef): + """Initialize the 'self' portion of the 'vtable' belonging to the + 'subclsdef'.""" + if self.classdef is None: + # initialize the 'parenttypeptr' field + rbase = getclassrepr(subclsdef.basedef) + vtable.parenttypeptr = rbase.getvtable() + else: + # XXX setup class attributes + # then initialize the 'super' portion of the vtable + self.rbase.setup_vtable(vtable.super, subclsdef) +root_class_repr = ClassRepr(None) +type_repr = root_class_repr + # ____________________________________________________________ + class __extend__(annmodel.SomeInstance): def rtyper_makerepr(self, rtyper): - return InstanceRepr(self.classdef) + return getinstancerepr(self.classdef) class InstanceRepr(Repr): def __init__(self, classdef): - self.rclassdef = getrclassdef(classdef) - self.lowleveltype = GcPtr(self.rclassdef.object_type) + self.classdef = classdef + self.rclass = getclassrepr(classdef) + if self.classdef is None: + self.object_type = OBJECT + else: + self.rbase = getinstancerepr(classdef.basedef) + self.object_type = GcStruct(classdef.cls.__name__, + ('super', self.rbase.object_type), + # XXX instance attributes + ) + self.lowleveltype = GcPtr(self.object_type) + + def parentpart(self, vinst, llops): + """Return the pointer 'vinst' cast to the parent type.""" + try: + supercache = llops.__super_cache + except AttributeError: + supercache = llops.__super_cache = {} + # + if vinst not in supercache: + cname = inputconst(Void, 'super') + supercache[vinst] = llops.genop('getsubstruct', [vinst, cname], + resulttype=self.rbase.lowleveltype) + return supercache[vinst] + + def getfield(self, vinst, attr, llops): + """Read the given attribute (or __class__ for the type) of 'vinst'.""" + if self.classdef is None: + if attr != '__class__': + raise TyperError("attribute error: %s" % attr) + cname = inputconst(Void, 'typeptr') + return llops.genop('getfield', [vinst, cname], resulttype=TYPEPTR) + else: + # XXX instance attributes + vsuper = self.parentpart(vinst, llops) + return self.rbase.getfield(vsuper, attr, llops) + + def setfield(self, vinst, attr, vvalue, llops): + """Write the given attribute (or __class__ for the type) of 'vinst'.""" + if self.classdef is None: + if attr != '__class__': + raise TyperError("attribute error: %s" % attr) + cname = inputconst(Void, 'typeptr') + llops.genop('setfield', [vinst, cname, vvalue]) + else: + # XXX instance attributes + vsuper = self.parentpart(vinst, llops) + self.rbase.getfield(vsuper, attr, llops) + + def new_instance(self, llops): + """Build a new instance, without calling __init__.""" + ctype = inputconst(Void, self.object_type) + vptr = llops.genop('malloc', [ctype], + resulttype = GcPtr(self.object_type)) + ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable()) + self.setfield(vptr, '__class__', ctypeptr, llops) + # XXX instance attributes + return vptr def rtype_type(self, hop): - vptr, = hop.inputargs(self) - vptr_as_object = self.rclassdef.parent_cast(None, vptr, hop.llops) - typeptr_name = hop.inputconst(Void, "typeptr") - return hop.genop('getfield', [vptr_as_object, typeptr_name], - resulttype=TYPEPTR) + vinst, = hop.inputargs(self) + return self.getfield(vinst, '__class__', hop.llops) -class TypeRepr(Repr): - lowleveltype = TYPEPTR +root_instance_repr = InstanceRepr(None) -type_repr = TypeRepr() +# ____________________________________________________________ + +def rtype_new_instance(cls, hop): + classdef = hop.rtyper.annotator.getuserclasses()[cls] + rinstance = getinstancerepr(classdef) + return rinstance.new_instance(hop.llops) Modified: pypy/branch/rpython-refactoring/rpbc.py ============================================================================== --- pypy/branch/rpython-refactoring/rpbc.py (original) +++ pypy/branch/rpython-refactoring/rpbc.py Sat Jun 4 12:10:50 2005 @@ -45,3 +45,4 @@ resulttype = rresult) elif isinstance(func, (types.ClassType, type)): return rclass.rtype_new_instance(s_func.const, hop) + # XXX call __init__ somewhere From arigo at codespeak.net Sat Jun 4 12:14:37 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 12:14:37 +0200 (CEST) Subject: [pypy-svn] r13051 - pypy/branch/rpython-refactoring Message-ID: <20050604101437.3F45B27B52@code1.codespeak.net> Author: arigo Date: Sat Jun 4 12:14:37 2005 New Revision: 13051 Removed: pypy/branch/rpython-refactoring/ Log: Branch finished and about to be merged. From arigo at codespeak.net Sat Jun 4 12:39:56 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 12:39:56 +0200 (CEST) Subject: [pypy-svn] r13052 - in pypy/dist/pypy: rpython rpython/test translator/c Message-ID: <20050604103956.5443B27B47@code1.codespeak.net> Author: arigo Date: Sat Jun 4 12:39:56 2005 New Revision: 13052 Added: pypy/dist/pypy/rpython/rmodel.py (props changed) - copied unchanged from r13050, pypy/branch/rpython-refactoring/rmodel.py pypy/dist/pypy/rpython/rrange.py (props changed) - copied unchanged from r13050, pypy/branch/rpython-refactoring/rrange.py pypy/dist/pypy/rpython/test/test_rrange.py (props changed) - copied unchanged from r13050, pypy/branch/rpython-refactoring/test/test_rrange.py Removed: pypy/dist/pypy/rpython/riter.py Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/translator/c/wrapper.py Log: Merged a small branch for a rpython refactoring: - Introduced the XxxRepr class hierarchy, similar to the SomeXxx hierarchy but oriented towards low-level representation. Each XxxRepr has a .lowleveltype attribute, and contains the rtype_*() methods that know how to manipulate data in this low-level representation. Each SomeXxx has a single new method, rtyper_makerepr(), that choose the best XxxRepr representation. While a SomeXxx often corresponds directly to one XxxRepr, sometimes there is a real choice -- e.g. the single SomeIterator is good enough for the annotator, but the rtyper needs different kind of iterator reprs depending on the container that is iterated over. Similarily, SomeList can correspond to ListRepr or RangeRepr. This makes a number of things nicer; in particular rclass.py no longer has to invent it own concept of RClassDef and just uses the ClassRepr and InstanceRepr to cache information about the OOP structures and vtables. - Small fixes in translator/c to account for the changes. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sat Jun 4 12:39:56 2005 @@ -160,9 +160,11 @@ __name__ = 'func' def __init__(self, args, result): for arg in args: + assert isinstance(arg, LowLevelType) if isinstance(arg, ContainerType): raise TypeError, "function arguments can only be primitives or pointers" self.ARGS = tuple(args) + assert isinstance(result, LowLevelType) if isinstance(result, ContainerType): raise TypeError, "function result can only be primitive or pointer" self.RESULT = result Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Sat Jun 4 12:39:56 2005 @@ -1,30 +1,19 @@ from pypy.annotation.pairtype import pairtype -from pypy.annotation.model import SomeFloat, SomeInteger, SomeBool, SomePBC +from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float -from pypy.rpython.rtyper import TyperError +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, BoolRepr debug = False -class __extend__(pairtype(SomeBool, SomeInteger)): +class __extend__(annmodel.SomeBool): + def rtyper_makerepr(self, rtyper): + return bool_repr - def rtype_convert_from_to((s_from, s_to), v, llops): - if s_to.unsigned: - if debug: print 'explicit cast_bool_to_uint' - return llops.genop('cast_bool_to_uint', [v], resulttype=Unsigned) - else: - if debug: print 'explicit cast_bool_to_int' - return llops.genop('cast_bool_to_int', [v], resulttype=Signed) - - -class __extend__(pairtype(SomeBool, SomeFloat)): - - def rtype_convert_from_to((s_from, s_to), v, llops): - if debug: print 'explicit cast_bool_to_float' - return llops.genop('cast_bool_to_float', [v], resulttype=Float) +bool_repr = BoolRepr() -class __extend__(SomeBool): +class __extend__(BoolRepr): def rtype_is_true(_, hop): vlist = hop.inputargs(Bool) @@ -37,3 +26,15 @@ def rtype_float(_, hop): vlist = hop.inputargs(Float) return vlist[0] + +# +# _________________________ Conversions _________________________ + +class __extend__(pairtype(BoolRepr, IntegerRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Unsigned: + if debug: print 'explicit cast_bool_to_uint' + return llops.genop('cast_bool_to_uint', [v], resulttype=Unsigned) + else: + if debug: print 'explicit cast_bool_to_int' + return llops.genop('cast_bool_to_int', [v], resulttype=Signed) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 4 12:39:56 2005 @@ -1,67 +1,88 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeBuiltin, SomeObject, SomeString +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import malloc, typeOf, nullptr, nullgcptr from pypy.rpython.lltype import Void, Signed from pypy.rpython.rtyper import TyperError -from pypy.rpython.rlist import rtype_builtin_range +from pypy.rpython.rrange import rtype_builtin_range +from pypy.rpython.rmodel import Repr, TyperError -class __extend__(SomeBuiltin): - - def lowleveltype(s_blt): - if s_blt.s_self is None: - assert s_blt.is_constant() - return Void - else: - # methods of a known name are implemented as just their 'self' - assert s_blt.methodname is not None - return s_blt.s_self.lowleveltype() - - def rtype_simple_call(s_blt, hop): - if s_blt.s_self is None: - if not s_blt.is_constant(): - raise TyperError("non-constant built-in") - try: - bltintyper = BUILTIN_TYPER[s_blt.const] - except KeyError: - raise TyperError("don't know about built-in function %r" % ( - s_blt.const,)) - hop.s_popfirstarg() +class __extend__(annmodel.SomeBuiltin): + def rtyper_makerepr(self, rtyper): + if self.s_self is None: + # built-in function case + if not self.is_constant(): + raise TyperError("non-constant built-in function!") + return BuiltinFunctionRepr(self.const) else: - # methods: look up the rtype_method_xxx() - name = 'rtype_method_' + s_blt.methodname - try: - bltintyper = getattr(s_blt.s_self, name) - except AttributeError: - raise TyperError("missing %s.%s" % ( - s_blt.s_self.__class__.__name__, name)) + # built-in method case + assert self.methodname is not None + return BuiltinMethodRepr(rtyper.getrepr(self.s_self), + self.methodname) + + +class BuiltinFunctionRepr(Repr): + lowleveltype = Void + + def __init__(self, builtinfunc): + self.builtinfunc = builtinfunc + + def rtype_simple_call(self, hop): + try: + bltintyper = BUILTIN_TYPER[self.builtinfunc] + except KeyError: + raise TyperError("don't know about built-in function %r" % ( + self.builtinfunc,)) + hop.r_s_popfirstarg() + return bltintyper(hop) + + +class BuiltinMethodRepr(Repr): + + def __init__(self, self_repr, methodname): + self.self_repr = self_repr + self.methodname = methodname + # methods of a known name are implemented as just their 'self' + self.lowleveltype = self_repr.lowleveltype + + def rtype_simple_call(self, hop): + # methods: look up the rtype_method_xxx() + name = 'rtype_method_' + self.methodname + try: + bltintyper = getattr(self.self_repr, name) + except AttributeError: + raise TyperError("missing %s.%s" % ( + self.self_repr.__class__.__name__, name)) + # hack based on the fact that 'lowleveltype == self_repr.lowleveltype' + assert hop.args_r[0] is self + hop.args_r[0] = self.self_repr return bltintyper(hop) -class __extend__(pairtype(SomeBuiltin, SomeObject)): +##class __extend__(pairtype(SomeBuiltin, SomeObject)): - def rtype_convert_from_to((s_blt, s_to), v, llops): - if s_blt.s_self is None: - raise TyperError("conversion requested on a built-in function") - return llops.convertvar(v, s_blt.s_self, s_to) +## def rtype_convert_from_to((s_blt, s_to), v, llops): +## if s_blt.s_self is None: +## raise TyperError("conversion requested on a built-in function") +## return llops.convertvar(v, s_blt.s_self, s_to) # ____________________________________________________________ def rtype_builtin_bool(hop): assert hop.nb_args == 1 - return hop.args_s[0].rtype_is_true(hop) + return hop.args_r[0].rtype_is_true(hop) def rtype_builtin_int(hop): - if isinstance(hop.args_s[0], SomeString): + if isinstance(hop.args_s[0], annmodel.SomeString): raise TyperError('int("string") not supported') assert hop.nb_args == 1 - return hop.args_s[0].rtype_int(hop) + return hop.args_r[0].rtype_int(hop) def rtype_builtin_float(hop): assert hop.nb_args == 1 - return hop.args_s[0].rtype_float(hop) + return hop.args_r[0].rtype_float(hop) -#def rtype_builtin_range(hop): see rlist.py +#def rtype_builtin_range(hop): see rrange.py # collect all functions @@ -79,11 +100,11 @@ if hop.nb_args == 1: vlist = hop.inputargs(Void) return hop.genop('malloc', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) else: vlist = hop.inputargs(Void, Signed) return hop.genop('malloc_varsize', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) def rtype_const_result(hop): return hop.inputconst(Void, hop.s_result.const) Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sat Jun 4 12:39:56 2005 @@ -1,8 +1,7 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomePBC, SomeInstance +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import * -from pypy.rpython.rtyper import inputconst - +from pypy.rpython.rmodel import Repr, TyperError, inputconst # # There is one "vtable" per user class, with the following structure: @@ -38,91 +37,153 @@ OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) -class RClassDef: +def getclassrepr(classdef): + if classdef is None: + return root_class_repr + try: + return classdef._rtype_classrepr_ + except AttributeError: + classdef._rtype_classrepr_ = result = ClassRepr(classdef) + return result + +def getinstancerepr(classdef): + if classdef is None: + return root_instance_repr + try: + return classdef._rtype_instancerepr_ + except AttributeError: + classdef._rtype_instancerepr_ = result = InstanceRepr(classdef) + return result + + +class ClassRepr(Repr): + + def __init__(self, classdef): + self.classdef = classdef + if classdef is None: + # 'object' root type + self.vtable_type = OBJECT_VTABLE + self.typeptr = nullptr(OBJECT_VTABLE) + else: + self.rbase = getclassrepr(classdef.basedef) + self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, + ('super', self.rbase.vtable_type), + # XXX class attributes + ) + self.lowleveltype = NonGcPtr(self.vtable_type) + self.vtable = None + + def getvtable(self, cast_to_typeptr=True): + """Return a ptr to the vtable of this type.""" + if self.vtable is None: + self.vtable = malloc(self.vtable_type, immortal=True) + if self.classdef is not None: + self.setup_vtable(self.vtable, self.classdef) + # + vtable = self.vtable + if cast_to_typeptr: + r = self + while r is not root_class_repr: + r = r.rbase + vtable = cast_flags(r.lowleveltype, vtable.super) + return vtable + + def setup_vtable(self, vtable, subclsdef): + """Initialize the 'self' portion of the 'vtable' belonging to the + 'subclsdef'.""" + if self.classdef is None: + # initialize the 'parenttypeptr' field + rbase = getclassrepr(subclsdef.basedef) + vtable.parenttypeptr = rbase.getvtable() + else: + # XXX setup class attributes + # then initialize the 'super' portion of the vtable + self.rbase.setup_vtable(vtable.super, subclsdef) + + +root_class_repr = ClassRepr(None) +type_repr = root_class_repr + +# ____________________________________________________________ + + +class __extend__(annmodel.SomeInstance): + def rtyper_makerepr(self, rtyper): + return getinstancerepr(self.classdef) + + +class InstanceRepr(Repr): def __init__(self, classdef): self.classdef = classdef - if classdef.basedef is None: - self.depth = 1 - parent_vtable_type = OBJECT_VTABLE - parent_typeptr = nullptr(OBJECT_VTABLE) - parent_object_type = OBJECT + self.rclass = getclassrepr(classdef) + if self.classdef is None: + self.object_type = OBJECT else: - rbasedef = getrclassdef(classdef.basedef) - self.depth = rbasedef.depth + 1 - parent_vtable_type = rbasedef.vtable_type - parent_typeptr = rbasedef.typeptr - parent_object_type = rbasedef.object_type - self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, - ('super', parent_vtable_type), - # XXX class attributes - ) - self.vtable = malloc(self.vtable_type, immortal=True) - # cast the vtable pointer from "vtable_type" to "parent_vtable_type" - # to "parent_parent_vtable_type" to .... to OBJECT_VTABLE - p = self.vtable - for i in range(self.depth): - p = p.super - self.typeptr = cast_flags(TYPEPTR, p) - p.parenttypeptr = parent_typeptr + self.rbase = getinstancerepr(classdef.basedef) + self.object_type = GcStruct(classdef.cls.__name__, + ('super', self.rbase.object_type), + # XXX instance attributes + ) + self.lowleveltype = GcPtr(self.object_type) + + def parentpart(self, vinst, llops): + """Return the pointer 'vinst' cast to the parent type.""" + try: + supercache = llops.__super_cache + except AttributeError: + supercache = llops.__super_cache = {} # - self.parent_object_type = parent_object_type - self.object_type = GcStruct(classdef.cls.__name__, - ('super', parent_object_type), - # XXX instance attributes - ) - - def parent_cast(self, targetclassdef, v, llops): - classdef = self.classdef - super_name = inputconst(Void, "super") - while classdef is not targetclassdef: - rclassdef = getrclassdef(classdef) - parent_object_type = rclassdef.parent_object_type - v = llops.genop('getsubstruct', [v, super_name], - resulttype = GcPtr(parent_object_type)) - classdef = classdef.basedef - return v + if vinst not in supercache: + cname = inputconst(Void, 'super') + supercache[vinst] = llops.genop('getsubstruct', [vinst, cname], + resulttype=self.rbase.lowleveltype) + return supercache[vinst] + + def getfield(self, vinst, attr, llops): + """Read the given attribute (or __class__ for the type) of 'vinst'.""" + if self.classdef is None: + if attr != '__class__': + raise TyperError("attribute error: %s" % attr) + cname = inputconst(Void, 'typeptr') + return llops.genop('getfield', [vinst, cname], resulttype=TYPEPTR) + else: + # XXX instance attributes + vsuper = self.parentpart(vinst, llops) + return self.rbase.getfield(vsuper, attr, llops) + + def setfield(self, vinst, attr, vvalue, llops): + """Write the given attribute (or __class__ for the type) of 'vinst'.""" + if self.classdef is None: + if attr != '__class__': + raise TyperError("attribute error: %s" % attr) + cname = inputconst(Void, 'typeptr') + llops.genop('setfield', [vinst, cname, vvalue]) + else: + # XXX instance attributes + vsuper = self.parentpart(vinst, llops) + self.rbase.getfield(vsuper, attr, llops) - def rtype_new_instance(self, llops): + def new_instance(self, llops): + """Build a new instance, without calling __init__.""" ctype = inputconst(Void, self.object_type) vptr = llops.genop('malloc', [ctype], resulttype = GcPtr(self.object_type)) - vptr_as_object = self.parent_cast(None, vptr, llops) - typeptr_name = inputconst(Void, "typeptr") - ctypeptr = inputconst(TYPEPTR, self.typeptr) - llops.genop('setfield', [vptr_as_object, typeptr_name, ctypeptr]) - # XXX call __init__ somewhere + ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable()) + self.setfield(vptr, '__class__', ctypeptr, llops) + # XXX instance attributes return vptr - -def getrclassdef(classdef): - try: - return classdef._rtype_rclassdef_ - except AttributeError: - classdef._rtype_rclassdef_ = result = RClassDef(classdef) - return result + def rtype_type(self, hop): + vinst, = hop.inputargs(self) + return self.getfield(vinst, '__class__', hop.llops) -def rtype_new_instance(s_cls, hop): - assert s_cls.is_constant() - cls = s_cls.const - classdef = hop.rtyper.annotator.getuserclasses()[cls] - rclassdef = getrclassdef(classdef) - return rclassdef.rtype_new_instance(hop.llops) - +root_instance_repr = InstanceRepr(None) # ____________________________________________________________ -class __extend__(SomeInstance): - - def lowleveltype(s_ins): - rclassdef = getrclassdef(s_ins.classdef) - return GcPtr(rclassdef.object_type) - - def rtype_type(s_ins, hop): - rclassdef = getrclassdef(s_ins.classdef) - vptr, = hop.inputargs(s_ins) - vptr_as_object = rclassdef.parent_cast(None, vptr, hop.llops) - typeptr_name = inputconst(Void, "typeptr") - return hop.genop('getfield', [vptr_as_object, typeptr_name], - resulttype=TYPEPTR) +def rtype_new_instance(cls, hop): + classdef = hop.rtyper.annotator.getuserclasses()[cls] + rinstance = getinstancerepr(classdef) + return rinstance.new_instance(hop.llops) Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sat Jun 4 12:39:56 2005 @@ -1,12 +1,20 @@ from pypy.annotation.pairtype import pairtype -from pypy.annotation.model import SomeFloat, SomeInteger, SomeBool, SomePBC +from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void -from pypy.rpython.rtyper import TyperError +from pypy.rpython.rmodel import Repr, TyperError, FloatRepr +from pypy.rpython.rmodel import IntegerRepr, BoolRepr debug = False -class __extend__(pairtype(SomeFloat, SomeFloat)): +class __extend__(annmodel.SomeFloat): + def rtyper_makerepr(self, rtyper): + return float_repr + +float_repr = FloatRepr() + + +class __extend__(pairtype(FloatRepr, FloatRepr)): #Arithmetic @@ -64,7 +72,7 @@ return _rtype_compare_template(hop, 'ge') -#Helpers SomeFloat,Somefloat +#Helpers FloatRepr,FloatRepr def _rtype_template(hop, func): vlist = hop.inputargs(Float, Float) @@ -74,47 +82,9 @@ vlist = hop.inputargs(Float, Float) return hop.genop('float_'+func, vlist, resulttype=Bool) - -# - -## XXX we have probably no implicit casts from float to integer -##class __extend__(pairtype(SomeFloat, SomeInteger)): - -## def rtype_convert_from_to((s_from, s_to), v): -## if s_to.unsigned: -## if debug: print 'explicit cast_float_to_uint' -## return direct_op('cast_float_to_uint', [v], resulttype=Unsigned) -## else: -## if debug: print 'explicit cast_float_to_int' -## return direct_op('cast_float_to_int', [v], resulttype=Signed) - - # -class __extend__(pairtype(SomeInteger, SomeFloat)): - - def rtype_convert_from_to((s_from, s_to), v, llops): - if s_from.unsigned: - if debug: print 'explicit cast_uint_to_float' - return llops.genop('cast_uint_to_float', [v], resulttype=Float) - else: - if debug: print 'explicit cast_int_to_float' - return llops.genop('cast_int_to_float', [v], resulttype=Float) - - -# - -## XXX we have probably no implicit casts from float to bool -##class __extend__(pairtype(SomeFloat, SomeBool)): - -## def rtype_convert_from_to((s_from, s_to), v): -## if debug: print 'explicit cast_float_to_bool' -## return direct_op('cast_float_to_bool', [v], resulttype=Bool) #XXX or can 'float_is_true' be reused here? - - -# - -class __extend__(SomeFloat): +class __extend__(FloatRepr): def rtype_is_true(_, hop): vlist = hop.inputargs(Float) @@ -133,3 +103,20 @@ return hop.genop('cast_float_to_int', vlist, resulttype=Signed) rtype_float = rtype_pos + +# +# _________________________ Conversions _________________________ + +class __extend__(pairtype(IntegerRepr, FloatRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Unsigned: + if debug: print 'explicit cast_uint_to_float' + return llops.genop('cast_uint_to_float', [v], resulttype=Float) + else: + if debug: print 'explicit cast_int_to_float' + return llops.genop('cast_int_to_float', [v], resulttype=Float) + +class __extend__(pairtype(BoolRepr, FloatRepr)): + def convert_from_to(_, v, llops): + if debug: print 'explicit cast_bool_to_float' + return llops.genop('cast_bool_to_float', [v], resulttype=Float) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Sat Jun 4 12:39:56 2005 @@ -1,18 +1,29 @@ from pypy.annotation.pairtype import pairtype -from pypy.annotation.model import SomeFloat, SomeInteger, SomeBool, SomePBC -from pypy.annotation.model import SomeObject +from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void -from pypy.rpython.rtyper import TyperError -from pypy.rpython.robject import PyObjPtr +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.robject import PyObjRepr, pyobj_repr debug = False -class __extend__(pairtype(SomeInteger, SomeInteger)): +class __extend__(annmodel.SomeInteger): + def rtyper_makerepr(self, rtyper): + if self.unsigned: + return unsigned_repr + else: + return signed_repr + +signed_repr = IntegerRepr() +unsigned_repr = IntegerRepr() +unsigned_repr.lowleveltype = Unsigned + - def rtype_convert_from_to((s_from, s_to), v, llops): - if s_from.unsigned != s_to.unsigned: - if s_to.unsigned: +class __extend__(pairtype(IntegerRepr, IntegerRepr)): + + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype != r_to.lowleveltype: + if r_to.lowleveltype == Unsigned: if debug: print 'explicit cast_int_to_uint' return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned) else: @@ -148,10 +159,14 @@ # -class __extend__(SomeInteger): +class __extend__(IntegerRepr): - def rtype_is_true(s_int, hop): - if s_int.unsigned: + def rtype_float(_, hop): + vlist = hop.inputargs(Float) + return vlist[0] + + def rtype_is_true(self, hop): + if self.lowleveltype == Unsigned: vlist = hop.inputargs(Unsigned) return hop.genop('uint_is_true', vlist, resulttype=Bool) else: @@ -199,8 +214,8 @@ vlist = hop.inputargs(Signed) return vlist[0] - def rtype_int(s_int, hop): - if s_int.unsigned: + def rtype_int(r_int, hop): + if r_int.lowleveltype == Unsigned: raise TyperError("use intmask() instead of int(r_uint(...))") vlist = hop.inputargs(Signed) return vlist[0] @@ -210,28 +225,22 @@ return vlist[0] # +# _________________________ Conversions _________________________ -class __extend__(pairtype(SomeObject, SomeInteger)): - - def rtype_convert_from_to((s_obj, s_int), v, llops): - if s_obj.lowleveltype() != PyObjPtr: - return NotImplemented - if s_int.unsigned: +class __extend__(pairtype(PyObjRepr, IntegerRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Unsigned: return llops.gencapicall('PyLong_AsUnsignedLong', [v], resulttype=Unsigned) else: return llops.gencapicall('PyInt_AsLong', [v], resulttype=Signed) - -class __extend__(pairtype(SomeInteger, SomeObject)): - - def rtype_convert_from_to((s_int, s_obj), v, llops): - if s_obj.lowleveltype() != PyObjPtr: - return NotImplemented - if s_int.unsigned: +class __extend__(pairtype(IntegerRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Unsigned: return llops.gencapicall('PyLong_FromUnsignedLong', [v], - resulttype=PyObjPtr) + resulttype=pyobj_repr) else: return llops.gencapicall('PyInt_FromLong', [v], - resulttype=PyObjPtr) + resulttype=pyobj_repr) Deleted: /pypy/dist/pypy/rpython/riter.py ============================================================================== --- /pypy/dist/pypy/rpython/riter.py Sat Jun 4 12:39:56 2005 +++ (empty file) @@ -1,57 +0,0 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeIterator, SomeList -from pypy.rpython.lltype import * - - -class __extend__(SomeIterator): - - def getiteratorkind(s_itr): - s_cont = s_itr.s_container - if isinstance(s_cont, SomeList): - if not s_cont.ll_range_step(): - return PlainListIterator - else: - return RangeIterator - else: - raise TyperError("not implemented yet") - - def lowleveltype(s_itr): - kind = s_itr.getiteratorkind() - return kind.lowlevelitertype(s_itr.s_container) - - def rtype_next(s_itr, hop): - v_itr, = hop.inputargs(s_itr) - kind = s_itr.getiteratorkind() - return kind.next(v_itr, hop) - -# ____________________________________________________________ - -class Namespace(object): - def __init__(self, name, bases, dict): - assert not bases - self.__dict__.update(dict) - - -class PlainListIterator: - """__________ regular list iterator __________""" - __metaclass__ = Namespace - - def lowlevelitertype(s_lst): - return GcPtr(GcStruct('listiter', ('list', s_lst.lowleveltype()), - ('index', Signed))) - - def ll_listiter(ITERPTR, lst): - iter = malloc(ITERPTR.TO) - iter.list = lst - iter.index = 0 - return iter - - def rtype_new_iter(hop): - s_lst, = hop.args_s - v_lst, = hop.inputargs(s_lst) - ITERPTR = PlainListIterator.lowlevelitertype(s_lst) - citerptr = hop.inputconst(Void, ITERPTR) - return hop.gendirectcall(PlainListIterator.ll_listiter, citerptr, v_lst) - - def next(v_itr, hop): - XXX - NotImplementedYet Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Jun 4 12:39:56 2005 @@ -1,7 +1,9 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeList, SomeInteger +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import * +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython import rrange # ____________________________________________________________ # @@ -14,68 +16,55 @@ # 'items' points to a C-like array in memory preceded by a 'length' header, # where each item contains a primitive value or pointer to the actual list # item. -# -# Lists returned by range() and never mutated use a simpler implementation: -# -# struct range { -# Signed start, stop; // step is always constant -# } - -RANGE = GcStruct("range", ("start", Signed), ("stop", Signed)) - -class __extend__(SomeList): - - def ll_range_step(s_list): - return (not s_list.listdef.listitem.mutated - and s_list.listdef.listitem.range_step) - - def lowleveltype(s_list): - if s_list.ll_range_step(): - assert isinstance(s_list.get_s_items(), SomeInteger) - return GcPtr(RANGE) - else: - ITEM = s_list.get_s_items().lowleveltype() - LIST = GcStruct("list", ("items", GcPtr(GcArray(("item", ITEM))))) - return GcPtr(LIST) - - def get_s_items(s_list): - return s_list.listdef.listitem.s_value - - def rtype_len(s_lst, hop): - v_lst, = hop.inputargs(s_lst) - step = s_lst.ll_range_step() - if step: - cstep = hop.inputconst(Signed, step) - return hop.gendirectcall(ll_rangelen, v_lst, cstep) +class __extend__(annmodel.SomeList): + def rtyper_makerepr(self, rtyper): + listitem = self.listdef.listitem + if listitem.range_step and not listitem.mutated: + return rrange.RangeRepr(listitem.range_step) else: - return hop.gendirectcall(ll_len, v_lst) + # cannot do the rtyper.getrepr() call immediately, for the case + # of recursive structures -- i.e. if the listdef contains itself + return ListRepr(lambda: rtyper.getrepr(listitem.s_value)) + + +class ListRepr(Repr): + + def __init__(self, item_repr): + self.LIST = GcForwardReference() + self.lowleveltype = GcPtr(self.LIST) + self.item_repr = item_repr # possibly uncomputed at this point! + # setup() needs to be called to finish this initialization + + def setup(self): + if callable(self.item_repr): + self.item_repr = self.item_repr() + if isinstance(self.LIST, GcForwardReference): + ITEM = self.item_repr.lowleveltype + ITEMARRAY = GcArray(("item", ITEM)) + self.LIST.become(GcStruct("list", ("items", GcPtr(ITEMARRAY)))) + + def rtype_len(self, hop): + v_lst, = hop.inputargs(self) + return hop.gendirectcall(ll_len, v_lst) - def rtype_method_append(s_lst, hop): - assert not s_lst.ll_range_step() - v_lst, v_value = hop.inputargs(s_lst, s_lst.get_s_items()) + def rtype_method_append(self, hop): + v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) - def rtype_iter(s_lst): - s_itr = hop.s_result - return s_itr.getiteratorkind().rtype_new_iter(hop) + def make_iterator_repr(self): + return ListIteratorRepr(self) -class __extend__(pairtype(SomeList, SomeInteger)): - - def rtype_getitem((s_lst1, s_int2), hop): - v_lst, v_index = hop.inputargs(s_lst1, Signed) - step = s_lst1.ll_range_step() - if step: - cstep = hop.inputconst(Signed, step) - return hop.gendirectcall(ll_rangeitem, v_lst, v_index, cstep) - else: - if s_int2.nonneg: - llfn = ll_getitem_nonneg - else: - llfn = ll_getitem - return hop.gendirectcall(llfn, v_lst, v_index) +class __extend__(pairtype(ListRepr, IntegerRepr)): + def rtype_getitem((r_lst, r_int), hop): + v_lst, v_index = hop.inputargs(r_lst, Signed) + if hop.args_s[1].nonneg: + llfn = ll_getitem_nonneg + else: + llfn = ll_getitem + return hop.gendirectcall(llfn, v_lst, v_index) # ____________________________________________________________ # @@ -112,28 +101,6 @@ def ll_setitem_nonneg(l, i, newitem): l.items[i].item = newitem -# __________ range __________ - -def ll_rangelen(l, step): - if step > 0: - result = (l.stop - l.start + (step-1)) // step - else: - result = (l.start - l.stop - (step+1)) // (-step) - if result < 0: - result = 0 - return result - -def ll_rangeitem(l, i, step): - if i<0: - # XXX ack. cannot call ll_rangelen() here for now :-( - if step > 0: - length = (l.stop - l.start + (step-1)) // step - else: - length = (l.start - l.stop - (step+1)) // (-step) - #assert length >= 0 - i += length - return l.start + i*step - # ____________________________________________________________ # # Irregular operations. @@ -145,34 +112,48 @@ def rtype_newlist(hop): nb_args = hop.nb_args - s_list = hop.s_result - s_listitem = s_list.get_s_items() - c1 = hop.inputconst(Void, s_list.lowleveltype()) + r_list = hop.r_result + r_listitem = r_list.item_repr + c1 = hop.inputconst(Void, r_list.lowleveltype) c2 = hop.inputconst(Signed, nb_args) v_result = hop.gendirectcall(ll_newlist, c1, c2) for i in range(nb_args): ci = hop.inputconst(Signed, i) - v_item = hop.inputarg(s_listitem, arg=i) + v_item = hop.inputarg(r_listitem, arg=i) hop.gendirectcall(ll_setitem_nonneg, v_result, ci, v_item) return v_result -def ll_newrange(start, stop): - l = malloc(RANGE) - l.start = start - l.stop = stop - return l +# ____________________________________________________________ +# +# Iteration. + +class ListIteratorRepr(Repr): -def rtype_builtin_range(hop): - s_range = hop.s_result - step = s_range.listdef.listitem.range_step - if step is None: # cannot build a RANGE object, needs a real list - raise TyperError("range() list used too dynamically") - if hop.nb_args == 1: - vstart = hop.inputconst(Signed, 0) - vstop, = hop.inputargs(Signed) - elif hop.nb_args == 2: - vstart, vstop = hop.inputargs(Signed, Signed) - else: - vstart, vstop, vstep = hop.inputargs(Signed, Signed, Signed) - assert isinstance(vstep, Constant) and vstep.value == step - return hop.gendirectcall(ll_newrange, vstart, vstop) + def __init__(self, r_list): + self.r_list = r_list + self.lowleveltype = GcPtr(GcStruct('listiter', + ('list', r_list.lowleveltype), + ('index', Signed))) + + def newiter(self, hop): + v_lst, = hop.inputargs(self.r_list) + citerptr = hop.inputconst(Void, self.lowleveltype) + return hop.gendirectcall(ll_listiter, citerptr, v_lst) + + def next(self, hop): + v_iter = hop.inputargs(self) + return hop.gendirectcall(ll_listnext, v_iter) + +def ll_listiter(ITERPTR, lst): + iter = malloc(ITERPTR.TO) + iter.list = lst + iter.index = 0 + return iter + +def ll_listnext(iter): + l = iter.list + index = iter.index + if index >= len(l.items): + raise StopIteration + iter.index = index + 1 + return l.items[index] Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Sat Jun 4 12:39:56 2005 @@ -1,72 +1,27 @@ from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeObject, annotation_to_lltype from pypy.annotation import model as annmodel from pypy.rpython.lltype import PyObject, GcPtr, Void, Bool -from pypy.rpython.rtyper import TyperError, inputconst +from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass -PyObjPtr = GcPtr(PyObject) - - -def missing_rtype_operation(args, hop): - raise TyperError("unimplemented operation: '%s' on %r" % ( - hop.spaceop.opname, args)) - -for opname in annmodel.UNARY_OPERATIONS: - setattr(SomeObject, 'rtype_' + opname, missing_rtype_operation) -for opname in annmodel.BINARY_OPERATIONS: - setattr(pairtype(SomeObject, SomeObject), - 'rtype_' + opname, missing_rtype_operation) - - -class __extend__(SomeObject): - - def lowleveltype(s_obj): - try: - return annotation_to_lltype(s_obj) - except ValueError: - if s_obj.is_constant(): - return Void - elif s_obj.knowntype is type: - return rclass.TYPEPTR - else: - return PyObjPtr - - def rtype_getattr(s_obj, hop): - s_attr = hop.args_s[1] - if s_attr.is_constant() and isinstance(s_attr.const, str): - attr = s_attr.const - try: - s_obj.find_method(attr) # just to check it is here - except AttributeError: - raise TyperError("no method %s on %r" % (attr, s_obj)) - else: - # implement methods (of a known name) as just their 'self' - return hop.inputarg(s_obj, arg=0) +class __extend__(annmodel.SomeObject): + def rtyper_makerepr(self, rtyper): + if self.is_constant(): + return constpyobj_repr + if self.knowntype is type: + return rclass.type_repr else: - raise TyperError("getattr() with a non-constant attribute name") + return pyobj_repr - def rtype_is_true(s_obj, hop): - if hasattr(s_obj, "rtype_len"): - vlen = s_obj.rtype_len(hop) - return hop.genop('int_is_true', [vlen], resulttype=Bool) - else: - return hop.inputconst(Bool, True) - def rtype_nonzero(s_obj, hop): - return s_obj.rtype_is_true(hop) # can call a subclass' rtype_is_true() +class PyObjRepr(Repr): + lowleveltype = GcPtr(PyObject) +pyobj_repr = PyObjRepr() -class __extend__(pairtype(SomeObject, SomeObject)): - def rtype_convert_from_to((s_from, s_to), v, llops): - FROM = s_from.lowleveltype() - TO = s_to.lowleveltype() - if (PyObjPtr == FROM == TO) or (rclass.TYPEPTR == FROM == TO): - return v - elif FROM == Void and s_from.is_constant() and s_to.contains(s_from): - # convert from a constant to a non-constant - return inputconst(TO, s_from.const) - else: - return NotImplemented +class ConstPyObjRepr(Repr): + lowleveltype = Void + +constpyobj_repr = ConstPyObjRepr() Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 4 12:39:56 2005 @@ -1,31 +1,48 @@ import types -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomePBC -from pypy.rpython.lltype import typeOf +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.rpython.lltype import typeOf, Void +from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass -class __extend__(SomePBC): +class __extend__(annmodel.SomePBC): + def rtyper_makerepr(self, rtyper): + return PBCRepr(self.prebuiltinstances) + + +class PBCRepr(Repr): + + def __init__(self, prebuiltinstances): + self.prebuiltinstances = prebuiltinstances + assert len(prebuiltinstances) == 1, "Not Implemented: multiPBCs" + self.lowleveltype = Void def rtype_getattr(_, hop): - attr = hop.args_s[1].const if hop.s_result.is_constant(): - return hop.inputconst(hop.s_result, hop.s_result.const) + return hop.inputconst(hop.r_result, hop.s_result.const) else: NotImplementedYet def rtype_simple_call(_, hop): - s_func = hop.s_popfirstarg() + r_func, s_func = hop.r_s_popfirstarg() if not s_func.is_constant(): NotImplementedYet func = s_func.const if isinstance(func, types.FunctionType): # XXX hackish f = hop.rtyper.getfunctionptr(func) + graph = f._obj.graph FUNCPTR = typeOf(f) - args_v = hop.inputargs(*FUNCPTR.TO.ARGS) + rinputs = [hop.rtyper.bindingrepr(v) for v in graph.getargs()] + if FUNCPTR.TO.RESULT == Void: + rresult = Void + else: + rresult = hop.rtyper.bindingrepr(graph.getreturnvar()) + args_v = hop.inputargs(*rinputs) c = hop.inputconst(FUNCPTR, f) return hop.genop('direct_call', [c] + args_v, - resulttype = FUNCPTR.TO.RESULT) + resulttype = rresult) elif isinstance(func, (types.ClassType, type)): - return rclass.rtype_new_instance(s_func, hop) + return rclass.rtype_new_instance(s_func.const, hop) + # XXX call __init__ somewhere Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Sat Jun 4 12:39:56 2005 @@ -1,58 +1,97 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomePtr, SomeInteger +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.rpython.lltype import _PtrType, _ptr from pypy.rpython.lltype import ContainerType, Void, Signed, Bool +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst -class __extend__(SomePtr): - - def lowleveltype(s_ptr): - if s_ptr.is_constant(): # constant NULL - return Void +class __extend__(annmodel.SomePtr): + def rtyper_makerepr(self, rtyper): + if self.is_constant(): # constant NULL + return nullptr_repr else: - return s_ptr.ll_ptrtype + return PtrRepr(self.ll_ptrtype) + + +class PtrRepr(Repr): + + def __init__(self, ptrtype): + assert isinstance(ptrtype, _PtrType) + self.lowleveltype = ptrtype - def rtype_getattr(s_ptr, hop): + def rtype_getattr(self, hop): attr = hop.args_s[1].const - FIELD_TYPE = getattr(s_ptr.ll_ptrtype.TO, attr) + FIELD_TYPE = getattr(self.lowleveltype.TO, attr) if isinstance(FIELD_TYPE, ContainerType): newopname = 'getsubstruct' else: newopname = 'getfield' - vlist = hop.inputargs(s_ptr, Void) + vlist = hop.inputargs(self, Void) return hop.genop(newopname, vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) - def rtype_setattr(s_ptr, hop): + def rtype_setattr(self, hop): attr = hop.args_s[1].const - FIELD_TYPE = getattr(s_ptr.ll_ptrtype.TO, attr) + FIELD_TYPE = getattr(self.lowleveltype.TO, attr) assert not isinstance(FIELD_TYPE, ContainerType) - vlist = hop.inputargs(s_ptr, Void, FIELD_TYPE) + vlist = hop.inputargs(self, Void, hop.args_r[2]) hop.genop('setfield', vlist) - def rtype_len(s_ptr, hop): - vlist = hop.inputargs(s_ptr) + def rtype_len(self, hop): + vlist = hop.inputargs(self) return hop.genop('getarraysize', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) - def rtype_is_true(s_ptr, hop): - vlist = hop.inputargs(s_ptr) + def rtype_is_true(self, hop): + vlist = hop.inputargs(self) return hop.genop('ptr_nonzero', vlist, resulttype=Bool) -class __extend__(pairtype(SomePtr, SomeInteger)): +class __extend__(pairtype(PtrRepr, IntegerRepr)): - def rtype_getitem((s_ptr, s_int), hop): - vlist = hop.inputargs(s_ptr, Signed) + def rtype_getitem((r_ptr, r_int), hop): + vlist = hop.inputargs(r_ptr, Signed) return hop.genop('getarrayitem', vlist, - resulttype = hop.s_result.lowleveltype()) + resulttype = hop.r_result.lowleveltype) + +# ____________________________________________________________ +# +# Null Pointers + +class NullPtrRepr(Repr): + lowleveltype = Void + + def rtype_is_true(self, hop): + return hop.inputconst(Bool, False) + +nullptr_repr = NullPtrRepr() + +class __extend__(pairtype(NullPtrRepr, PtrRepr)): + def convert_from_to((r_null, r_ptr), v, llops): + # nullptr to general pointer + return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) + +# ____________________________________________________________ +# +# Comparisons + +class __extend__(pairtype(PtrRepr, Repr)): + + def rtype_eq((r_ptr, r_any), hop): + vlist = hop.inputargs(r_ptr, r_ptr) + return hop.genop('ptr_eq', vlist, resulttype=Bool) + + def rtype_ne((r_ptr, r_any), hop): + vlist = hop.inputargs(r_ptr, r_ptr) + return hop.genop('ptr_ne', vlist, resulttype=Bool) -class __extend__(pairtype(SomePtr, SomePtr)): +class __extend__(pairtype(Repr, PtrRepr)): - def rtype_eq(_, hop): - vlist = hop.inputargs(SomePtr(), SomePtr()) + def rtype_eq((r_any, r_ptr), hop): + vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_eq', vlist, resulttype=Bool) - def rtype_ne(_, hop): - vlist = hop.inputargs(SomePtr(), SomePtr()) + def rtype_ne((r_any, r_ptr), hop): + vlist = hop.inputargs(r_ptr, r_ptr) return hop.genop('ptr_ne', vlist, resulttype=Bool) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jun 4 12:39:56 2005 @@ -1,6 +1,8 @@ -from pypy.annotation.pairtype import pair, pairtype -from pypy.annotation.model import SomeString, SomeChar, SomeInteger, SomeObject +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel from pypy.rpython.lltype import * +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.rmodel import StringRepr, CharRepr # ____________________________________________________________ # @@ -15,79 +17,75 @@ STR = GcStruct('str', ('hash', Signed), ('chars', Array(('ch', Char)))) -STRPTR = GcPtr(STR) -class __extend__(SomeString): +class __extend__(annmodel.SomeString): + def rtyper_makerepr(self, rtyper): + return string_repr - def lowleveltype(self): - return STRPTR +class __extend__(annmodel.SomeChar): + def rtyper_makerepr(self, rtyper): + return char_repr + + +class __extend__(StringRepr): + lowleveltype = GcPtr(STR) def rtype_len(_, hop): - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strlen, v_str) - def rtype_is_true(s_str, hop): + def rtype_is_true(self, hop): + s_str = hop.args_s[0] if s_str.can_be_None: - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_str_is_true, v_str) else: # defaults to checking the length - return SomeObject.rtype_is_true(s_str, hop) + return super(StringRepr, self).rtype_is_true(hop) def rtype_ord(_, hop): - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) c_zero = inputconst(Signed, 0) v_chr = hop.gendirectcall(ll_stritem_nonneg, v_str, c_zero) return hop.genop('cast_char_to_int', [v_chr], resulttype=Signed) def rtype_hash(_, hop): - v_str, = hop.inputargs(SomeString()) + v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strhash, v_str) -class __extend__(pairtype(SomeString, SomeInteger)): - - def rtype_getitem((_, s_int), hop): - v_str, v_index = hop.inputargs(SomeString(), Signed) - if s_int.nonneg: +class __extend__(pairtype(StringRepr, IntegerRepr)): + def rtype_getitem(_, hop): + v_str, v_index = hop.inputargs(string_repr, Signed) + if hop.args_s[1].nonneg: llfn = ll_stritem_nonneg else: llfn = ll_stritem return hop.gendirectcall(llfn, v_str, v_index) -class __extend__(SomeChar): - - def lowleveltype(self): - return Char +class __extend__(CharRepr): def rtype_len(_, hop): return hop.inputconst(Signed, 1) - def rtype_is_true(s_chr, hop): - assert not s_chr.can_be_None + def rtype_is_true(_, hop): + assert not hop.args_s[0].can_be_None return hop.inputconst(Bool, True) def rtype_ord(_, hop): - vlist = hop.inputargs(Char) + vlist = hop.inputargs(char_repr) return hop.genop('cast_char_to_int', vlist, resulttype=Signed) -class __extend__(pairtype(SomeChar, SomeString)): - - def rtype_convert_from_to((s_chr, s_str), v, llops): +class __extend__(pairtype(CharRepr, StringRepr)): + def convert_from_to(_, v, llops): return hop.gendirectcall(ll_chr2str, v) -class __extend__(pairtype(SomeString, SomeString)): - - def rtype_convert_from_to((s_str1, s_str2), v, llops): - # converting between SomeString(can_be_None=False) - # and SomeString(can_be_None=True) - assert s_str1.__class__ is s_str2.__class__ is SomeString - return v - +string_repr = StringRepr() +char_repr = CharRepr() # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sat Jun 4 12:39:56 2005 @@ -3,31 +3,69 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation -from pypy.rpython.lltype import Void, LowLevelType, NonGcPtr, ContainerType +from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void +from pypy.rpython.lltype import LowLevelType, NonGcPtr, ContainerType from pypy.rpython.lltype import FuncType, functionptr, typeOf from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block +from pypy.rpython.rmodel import Repr, inputconst, TyperError +debug = False +crash_on_first_typeerror = False + # XXX copied from pypy.translator.typer and modified. # We'll remove pypy.translator.typer at some point. # It also borrows a bit from pypy.translator.annrpython. -class TyperError(Exception): - def __str__(self): - result = Exception.__str__(self) - if hasattr(self, 'where'): - result += '\n.. %r\n.. %r' % self.where - return result - - class RPythonTyper: def __init__(self, annotator): self.annotator = annotator + self.reprs_by_id = {} + self.reprs_by_content = {} self.specialized_ll_functions = {} self.rclassdefs = {} self.typererror = None + # make the primitive_to_repr constant mapping + self.primitive_to_repr = {} + for s_primitive, lltype in annmodel.annotation_to_ll_map: + r = self.getrepr(s_primitive) + self.primitive_to_repr[r.lowleveltype] = r + + def getrepr(self, s_obj): + # s_objs are not hashable... try hard to find a hash anyway + try: + result, s_obj = self.reprs_by_id[id(s_obj)] + except KeyError: + key = [s_obj.__class__] + items = s_obj.__dict__.items() + items.sort() + for name, value in items: + key.append(name) + key.append(Constant(value)) + key = tuple(key) + try: + result = self.reprs_by_content[key] + except KeyError: + # here is the code that actually builds a Repr instance + result = s_obj.rtyper_makerepr(self) + assert not isinstance(result.lowleveltype, ContainerType), ( + "missing a GcPtr or NonGcPtr in the type specification " + "of %s:\n%r" % (s_obj, result.lowleveltype)) + self.reprs_by_content[key] = result + result.setup() + self.reprs_by_id[id(s_obj)] = result, s_obj + return result + + def binding(self, var): + s_obj = self.annotator.binding(var, True) + if s_obj is None: + s_obj = annmodel.SomeObject() + return s_obj + + def bindingrepr(self, var): + return self.getrepr(self.binding(var)) def specialize(self): """Main entry point: specialize all annotated blocks of the program.""" @@ -49,9 +87,7 @@ def setconcretetype(self, v): assert isinstance(v, Variable) - s_value = self.annotator.binding(v, True) - if s_value is not None: - v.concretetype = s_value.lowleveltype() + v.concretetype = self.bindingrepr(v).lowleveltype def specialize_block(self, block): # give the best possible types to the input args @@ -69,6 +105,7 @@ self.translate_hl_to_ll(hop, varmapping) except TyperError, e: self.gottypererror(e, block, op, newops) + return # cannot continue this block: no op.result.concretetype block.operations[:] = newops # multiple renamings (v1->v2->v3->...) are possible @@ -93,16 +130,16 @@ for i in range(len(link.args)): a1 = link.args[i] a2 = link.target.inputargs[i] - s_a2 = self.annotator.binding(a2) + r_a2 = self.bindingrepr(a2) if isinstance(a1, Constant): - link.args[i] = inputconst(s_a2.lowleveltype(), a1.value) + link.args[i] = inputconst(r_a2, a1.value) continue # the Constant was typed, done - s_a1 = self.annotator.binding(a1) - if s_a1 == s_a2: + r_a1 = self.bindingrepr(a1) + if r_a1 == r_a2: continue # no conversion needed newops = LowLevelOpList(self) try: - a1 = newops.convertvar(a1, s_a1, s_a2) + a1 = newops.convertvar(a1, r_a1, r_a2) except TyperError, e: self.gottypererror(e, block, link, newops) @@ -120,6 +157,8 @@ link.args[i] = a1 def translate_hl_to_ll(self, hop, varmapping): + if debug: + print hop.spaceop.opname, hop.args_s op = hop.spaceop translate_meth = getattr(self, 'translate_op_'+op.opname, self.missing_operation) @@ -135,31 +174,35 @@ # op.result here. We have to replace resultvar with op.result # in all generated operations. resulttype = resultvar.concretetype - op.result.concretetype = hop.s_result.lowleveltype() + op.result.concretetype = hop.r_result.lowleveltype if op.result.concretetype != resulttype: raise TyperError("inconsistent type for the result of '%s':\n" - "annotator says %r\n" - " rtyper says %r" % (op.opname, - op.result.concretetype, - resulttype)) + "annotator says %s,\n" + "whose lltype is %r\n" + "but rtype* says %r" % ( + op.opname, hop.s_result, + op.result.concretetype, resulttype)) while resultvar in varmapping: resultvar = varmapping[resultvar] varmapping[resultvar] = op.result else: # translate_meth() returned a Constant + assert isinstance(resultvar, Constant) if not hop.s_result.is_constant(): raise TyperError("the annotator doesn't agree that '%s' " "returns a constant" % op.opname) if resultvar.value != hop.s_result.const: raise TyperError("constant mismatch: %r vs %r" % ( resultvar.value, hop.s_result.const)) - op.result.concretetype = hop.s_result.lowleveltype() + op.result.concretetype = hop.r_result.lowleveltype def gottypererror(self, e, block, position, llops): """Record a TyperError without crashing immediately. Put a 'TyperError' operation in the graph instead. """ e.where = (block, position) + if crash_on_first_typeerror: + raise if self.typererror is None: self.typererror = sys.exc_info() c1 = inputconst(Void, Exception.__str__(e)) @@ -172,16 +215,16 @@ for opname in annmodel.UNARY_OPERATIONS: exec """ def translate_op_%s(self, hop): - s_arg1 = hop.args_s[0] - return s_arg1.rtype_%s(hop) + r_arg1 = hop.args_r[0] + return r_arg1.rtype_%s(hop) """ % (opname, opname) in globals(), loc # All binary operations for opname in annmodel.BINARY_OPERATIONS: exec """ def translate_op_%s(self, hop): - s_arg1 = hop.args_s[0] - s_arg2 = hop.args_s[1] - return pair(s_arg1, s_arg2).rtype_%s(hop) + r_arg1 = hop.args_r[0] + r_arg2 = hop.args_r[1] + return pair(r_arg1, r_arg2).rtype_%s(hop) """ % (opname, opname) in globals(), loc _registeroperations(locals()) @@ -201,34 +244,18 @@ """Make a functionptr from the given Python function.""" a = self.annotator graph = a.translator.getflowgraph(func) - llinputs = [a.binding(v).lowleveltype() for v in graph.getargs()] + llinputs = [self.bindingrepr(v).lowleveltype for v in graph.getargs()] s_output = a.binding(graph.getreturnvar(), None) if s_output is None: lloutput = Void else: - lloutput = s_output.lowleveltype() + lloutput = self.getrepr(s_output).lowleveltype FT = FuncType(llinputs, lloutput) return functionptr(FT, func.func_name, graph = graph, _callable = func) # ____________________________________________________________ -def inputconst(type, value): - """Return a Constant with the given value, of the requested type. - 'type' can be a SomeXxx annotation or a low-level type. - """ - if isinstance(type, LowLevelType): - lowleveltype = type - else: - lowleveltype = type.lowleveltype() - assert not isinstance(lowleveltype, ContainerType), ( - "missing a GcPtr or NonGcPtr in the type specification of %r" % - (lowleveltype,)) - c = Constant(value) - c.concretetype = lowleveltype - return c - -# ____________________________________________________________ class HighLevelOp: nb_popped = 0 @@ -238,28 +265,32 @@ self.spaceop = spaceop self.nb_args = len(spaceop.args) self.llops = llops - self.args_s = [rtyper.annotator.binding(a) for a in spaceop.args] - self.s_result = rtyper.annotator.binding(spaceop.result) + self.args_s = [rtyper.binding(a) for a in spaceop.args] + self.s_result = rtyper.binding(spaceop.result) + self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] + self.r_result = rtyper.getrepr(self.s_result) def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, as a Variable or Constant converted to the requested type. - 'converted_to' can be a SomeXxx annotation or a primitive low-level + 'converted_to' should be a Repr instance or a Primitive low-level type. """ v = self.spaceop.args[self.nb_popped + arg] if isinstance(v, Constant): return inputconst(converted_to, v.value) + assert hasattr(v, 'concretetype') s_binding = self.args_s[arg] - if s_binding is None: - s_binding = annmodel.SomeObject() if s_binding.is_constant(): return inputconst(converted_to, s_binding.const) - if isinstance(converted_to, LowLevelType): - converted_to = annmodel.lltype_to_annotation(converted_to) - return self.llops.convertvar(v, s_binding, converted_to) + if not isinstance(converted_to, Repr): + converted_to = self.rtyper.primitive_to_repr[converted_to] + r_binding = self.args_r[arg] + return self.llops.convertvar(v, r_binding, converted_to) + + inputconst = staticmethod(inputconst) # export via the HighLevelOp class def inputargs(self, *converted_to): assert len(converted_to) == self.nb_args, ( @@ -270,19 +301,17 @@ vars.append(self.inputarg(converted_to[i], i)) return vars - inputconst = staticmethod(inputconst) # export via the HighLevelOp class - def genop(self, opname, args_v, resulttype=None): return self.llops.genop(opname, args_v, resulttype) def gendirectcall(self, ll_function, *args_v): return self.llops.gendirectcall(ll_function, *args_v) - def s_popfirstarg(self): + def r_s_popfirstarg(self): "Return and discard the first argument." self.nb_popped += 1 self.nb_args -= 1 - return self.args_s.pop(0) + return self.args_r.pop(0), self.args_s.pop(0) # ____________________________________________________________ @@ -293,13 +322,13 @@ def __init__(self, rtyper): self.rtyper = rtyper - def convertvar(self, v, s_from, s_to): + def convertvar(self, v, r_from, r_to): assert isinstance(v, Variable) - if s_from != s_to: - v = pair(s_from, s_to).rtype_convert_from_to(v, self) + if r_from != r_to: + v = pair(r_from, r_to).convert_from_to(v, self) if v is NotImplemented: - raise TyperError("don't know how to convert from %r to %r" % ( - s_from, s_to)) + raise TyperError("don't know how to convert from %r to %r" % + (r_from, r_to)) return v def genop(self, opname, args_v, resulttype=None): @@ -309,19 +338,20 @@ vresult.concretetype = Void return None else: + if isinstance(resulttype, Repr): + resulttype = resulttype.lowleveltype + assert isinstance(resulttype, LowLevelType) vresult.concretetype = resulttype return vresult def gendirectcall(self, ll_function, *args_v): - annotator = self.rtyper.annotator + rtyper = self.rtyper spec_key = [ll_function] spec_name = [ll_function.func_name] args_s = [] for v in args_v: - s_value = annotator.binding(v, True) - if s_value is None: - s_value = annmodel.SomeObject() if v.concretetype == Void: + s_value = rtyper.binding(v) if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") key = s_value.const # specialize by constant value @@ -341,8 +371,8 @@ name = '_'.join(spec_name) spec_function = func_with_new_name(ll_function, name) # flow and annotate (the copy of) the low-level function - spec_graph = annotator.translator.getflowgraph(spec_function) - annotator.build_types(spec_function, args_s) + spec_graph = rtyper.annotator.translator.getflowgraph(spec_function) + rtyper.annotator.build_types(spec_function, args_s) # cache the result self.rtyper.specialized_ll_functions[spec_key] = spec_function @@ -353,6 +383,8 @@ resulttype = typeOf(f).TO.RESULT) def gencapicall(self, cfnname, args_v, resulttype): + if isinstance(resulttype, Repr): + resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype) f = functionptr(FUNCTYPE, cfnname, external="C") @@ -362,5 +394,9 @@ # _______________________________________________________________________ # this has the side-effect of registering the unary and binary operations -from pypy.rpython import robject, rlist, rptr, rbuiltin, rint, rbool, rfloat -from pypy.rpython import rpbc, rstr, riter +# and the rtyper_chooserepr() methods +from pypy.rpython import robject +from pypy.rpython import rint, rbool, rfloat +from pypy.rpython import rlist, rstr +from pypy.rpython import rbuiltin, rpbc +from pypy.rpython import rptr Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Sat Jun 4 12:39:56 2005 @@ -1,13 +1,14 @@ from pypy.translator.translator import Translator -from pypy.annotation.listdef import ListDef from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rlist import * +from pypy.rpython.rint import signed_repr def test_rlist(): - s = SomeList(ListDef(None, SomeInteger())) - l = ll_newlist(s.lowleveltype(), 3) + rlist = ListRepr(signed_repr) + rlist.setup() + l = ll_newlist(rlist.lowleveltype, 3) ll_setitem(l, 0, 42) ll_setitem(l, -2, 43) ll_setitem_nonneg(l, 2, 44) @@ -18,23 +19,6 @@ assert ll_getitem(l, 3) == 45 assert ll_len(l) == 4 -def test_rlist_range(): - def test1(start, stop, step): - expected = range(start, stop, step) - length = len(expected) - l = ll_newrange(start, stop) - assert ll_rangelen(l, step) == length - lst = [ll_rangeitem(l, i, step) for i in range(length)] - assert lst == expected - lst = [ll_rangeitem(l, i-length, step) for i in range(length)] - assert lst == expected - - for start in (-10, 0, 1, 10): - for stop in (-8, 0, 4, 8, 25): - for step in (1, 2, 3, -1, -2): - test1(start, stop, step) - - # ____________________________________________________________ def test_simple(): Modified: pypy/dist/pypy/translator/c/wrapper.py ============================================================================== --- pypy/dist/pypy/translator/c/wrapper.py (original) +++ pypy/dist/pypy/translator/c/wrapper.py Sat Jun 4 12:39:56 2005 @@ -4,6 +4,7 @@ from pypy.rpython.lltype import GcPtr, NonGcPtr, PyObject, typeOf, Signed, Void from pypy.rpython.lltype import FuncType, functionptr from pypy.rpython.rtyper import LowLevelOpList, inputconst +from pypy.rpython.robject import pyobj_repr from pypy.interpreter.pycode import CO_VARARGS @@ -80,22 +81,20 @@ inputargs = f._obj.graph.getargs() for i in range(len(varguments)): # "argument_i = type_conversion_operations(argument_i)" - s_arg = rtyper.annotator.binding(inputargs[i], True) - if s_arg is not None: - varguments[i] = newops.convertvar(varguments[i], - s_from = annmodel.SomeObject(), - s_to = s_arg) + r_arg = rtyper.bindingrepr(inputargs[i]) + varguments[i] = newops.convertvar(varguments[i], + r_from = pyobj_repr, + r_to = r_arg) # "result = direct_call(func, argument_0, argument_1, ..)" vlist = [inputconst(typeOf(f), f)] + varguments vresult = newops.genop('direct_call', vlist, resulttype=FUNCTYPE.RESULT) # convert "result" back to a PyObject - s_result = rtyper.annotator.binding(f._obj.graph.getreturnvar(), True) - if s_result is not None: - vresult = newops.convertvar(vresult, - s_from = s_result, - s_to = annmodel.SomeObject()) + r_result = rtyper.bindingrepr(f._obj.graph.getreturnvar()) + vresult = newops.convertvar(vresult, + r_from = r_result, + r_to = pyobj_repr) # "return result" block = Block([vself, vargs, vkwds]) From arigo at codespeak.net Sat Jun 4 12:53:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 12:53:20 +0200 (CEST) Subject: [pypy-svn] r13053 - pypy/dist/pypy/translator/test Message-ID: <20050604105320.9D44027B4C@code1.codespeak.net> Author: arigo Date: Sat Jun 4 12:53:20 2005 New Revision: 13053 Modified: pypy/dist/pypy/translator/test/test_backends.py Log: Ignore the (old genc) C back-end in this test for now. Modified: pypy/dist/pypy/translator/test/test_backends.py ============================================================================== --- pypy/dist/pypy/translator/test/test_backends.py (original) +++ pypy/dist/pypy/translator/test/test_backends.py Sat Jun 4 12:53:20 2005 @@ -2,7 +2,7 @@ Test conditions that all backends should do correct. ''' -import autopath, os, sys +import autopath, os, sys, py from pypy.translator.translator import Translator from pypy.rpython.rtyper import * from pypy.rpython.rarithmetic import * @@ -13,6 +13,8 @@ functions = 'forty_two'.split() #XXX add more functions here when RPythonTyper can handle them regenerate_code = '''def test_regenerate_%(function)s_%(backend)s(): + if %(backend)r == "c": + py.test.skip("the old genc back-end is on the way out") t = Translator(%(function)s) t.simplify() a = t.annotate([]) From arigo at codespeak.net Sat Jun 4 13:33:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 13:33:16 +0200 (CEST) Subject: [pypy-svn] r13054 - in pypy/dist/pypy/rpython: . test Message-ID: <20050604113316.D412627B4C@code1.codespeak.net> Author: arigo Date: Sat Jun 4 13:33:16 2005 New Revision: 13054 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rclass.py Log: rclass.py progress: - support for instance attributes - some other bug fixes. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sat Jun 4 13:33:16 2005 @@ -37,35 +37,38 @@ OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) -def getclassrepr(classdef): +def getclassrepr(rtyper, classdef): if classdef is None: return root_class_repr try: - return classdef._rtype_classrepr_ - except AttributeError: - classdef._rtype_classrepr_ = result = ClassRepr(classdef) - return result + result = rtyper.class_reprs[classdef] + except KeyError: + result = rtyper.class_reprs[classdef] = ClassRepr(rtyper, classdef) + return result -def getinstancerepr(classdef): +def getinstancerepr(rtyper, classdef): if classdef is None: return root_instance_repr try: - return classdef._rtype_instancerepr_ - except AttributeError: - classdef._rtype_instancerepr_ = result = InstanceRepr(classdef) - return result + result = rtyper.instance_reprs[classdef] + except KeyError: + result = rtyper.instance_reprs[classdef] = InstanceRepr(rtyper,classdef) + return result + +class MissingRTypeAttribute(TyperError): + pass class ClassRepr(Repr): - def __init__(self, classdef): + def __init__(self, rtyper, classdef): self.classdef = classdef if classdef is None: # 'object' root type self.vtable_type = OBJECT_VTABLE self.typeptr = nullptr(OBJECT_VTABLE) else: - self.rbase = getclassrepr(classdef.basedef) + self.rbase = getclassrepr(rtyper, classdef.basedef) self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, ('super', self.rbase.vtable_type), # XXX class attributes @@ -78,7 +81,7 @@ if self.vtable is None: self.vtable = malloc(self.vtable_type, immortal=True) if self.classdef is not None: - self.setup_vtable(self.vtable, self.classdef) + self.setup_vtable(self.vtable, self) # vtable = self.vtable if cast_to_typeptr: @@ -88,20 +91,19 @@ vtable = cast_flags(r.lowleveltype, vtable.super) return vtable - def setup_vtable(self, vtable, subclsdef): + def setup_vtable(self, vtable, rsubcls): """Initialize the 'self' portion of the 'vtable' belonging to the - 'subclsdef'.""" + given subclass.""" if self.classdef is None: # initialize the 'parenttypeptr' field - rbase = getclassrepr(subclsdef.basedef) - vtable.parenttypeptr = rbase.getvtable() + vtable.parenttypeptr = rsubcls.rbase.getvtable() else: # XXX setup class attributes # then initialize the 'super' portion of the vtable - self.rbase.setup_vtable(vtable.super, subclsdef) + self.rbase.setup_vtable(vtable.super, rsubcls) -root_class_repr = ClassRepr(None) +root_class_repr = ClassRepr(None, None) type_repr = root_class_repr # ____________________________________________________________ @@ -109,22 +111,33 @@ class __extend__(annmodel.SomeInstance): def rtyper_makerepr(self, rtyper): - return getinstancerepr(self.classdef) + return getinstancerepr(rtyper, self.classdef) class InstanceRepr(Repr): - def __init__(self, classdef): + def __init__(self, rtyper, classdef): self.classdef = classdef - self.rclass = getclassrepr(classdef) + self.rclass = getclassrepr(rtyper, classdef) + self.fields = {} if self.classdef is None: + self.fields['__class__'] = 'typeptr', TYPEPTR self.object_type = OBJECT else: - self.rbase = getinstancerepr(classdef.basedef) + # instance attributes (XXX remove class attributes from here) + llfields = [] + attrs = classdef.attrs.items() + attrs.sort() + for name, attrdef in attrs: + r = rtyper.getrepr(attrdef.s_value) + mangled_name = name + '_' + self.fields[name] = mangled_name, r + llfields.append((mangled_name, r.lowleveltype)) + # + self.rbase = getinstancerepr(rtyper, classdef.basedef) self.object_type = GcStruct(classdef.cls.__name__, ('super', self.rbase.object_type), - # XXX instance attributes - ) + *llfields) self.lowleveltype = GcPtr(self.object_type) def parentpart(self, vinst, llops): @@ -140,29 +153,41 @@ resulttype=self.rbase.lowleveltype) return supercache[vinst] + def getfieldrepr(self, attr): + """Return the repr used for the given attribute.""" + if self.classdef is None: + if attr == '__class__': + return TYPEPTR + raise MissingRTypeAttribute(attr) + elif attr in self.fields: + mangled_name, r = self.fields[attr] + return r + else: + return self.rbase.getfieldrepr(attr) + def getfield(self, vinst, attr, llops): """Read the given attribute (or __class__ for the type) of 'vinst'.""" - if self.classdef is None: - if attr != '__class__': - raise TyperError("attribute error: %s" % attr) - cname = inputconst(Void, 'typeptr') - return llops.genop('getfield', [vinst, cname], resulttype=TYPEPTR) + if attr in self.fields: + mangled_name, r = self.fields[attr] + cname = inputconst(Void, mangled_name) + return llops.genop('getfield', [vinst, cname], resulttype=r) else: - # XXX instance attributes + if self.classdef is None: + raise MissingRTypeAttribute(attr) vsuper = self.parentpart(vinst, llops) return self.rbase.getfield(vsuper, attr, llops) def setfield(self, vinst, attr, vvalue, llops): """Write the given attribute (or __class__ for the type) of 'vinst'.""" - if self.classdef is None: - if attr != '__class__': - raise TyperError("attribute error: %s" % attr) - cname = inputconst(Void, 'typeptr') + if attr in self.fields: + mangled_name, r = self.fields[attr] + cname = inputconst(Void, mangled_name) llops.genop('setfield', [vinst, cname, vvalue]) else: - # XXX instance attributes + if self.classdef is None: + raise MissingRTypeAttribute(attr) vsuper = self.parentpart(vinst, llops) - self.rbase.getfield(vsuper, attr, llops) + self.rbase.setfield(vsuper, attr, vvalue, llops) def new_instance(self, llops): """Build a new instance, without calling __init__.""" @@ -178,12 +203,23 @@ vinst, = hop.inputargs(self) return self.getfield(vinst, '__class__', hop.llops) + def rtype_getattr(self, hop): + attr = hop.args_s[1].const + vinst, vattr = hop.inputargs(self, Void) + return self.getfield(vinst, attr, hop.llops) + + def rtype_setattr(self, hop): + attr = hop.args_s[1].const + r_value = self.getfieldrepr(attr) + vinst, vattr, vvalue = hop.inputargs(self, Void, r_value) + self.setfield(vinst, attr, vvalue, hop.llops) + -root_instance_repr = InstanceRepr(None) +root_instance_repr = InstanceRepr(None, None) # ____________________________________________________________ def rtype_new_instance(cls, hop): classdef = hop.rtyper.annotator.getuserclasses()[cls] - rinstance = getinstancerepr(classdef) + rinstance = getinstancerepr(hop.rtyper, classdef) return rinstance.new_instance(hop.llops) Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sat Jun 4 13:33:16 2005 @@ -61,6 +61,10 @@ r_container = rtyper.getrepr(self.s_container) return r_container.make_iterator_repr() +class __extend__(annmodel.SomeImpossibleValue): + def rtyper_makerepr(self, rtyper): + return impossible_repr + # ____________________________________________________________ class TyperError(Exception): @@ -111,6 +115,10 @@ class CharRepr(StringRepr): lowleveltype = Char +class VoidRepr(Repr): + lowleveltype = Void +impossible_repr = VoidRepr() + # ____________________________________________________________ def inputconst(reqtype, value): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sat Jun 4 13:33:16 2005 @@ -25,7 +25,8 @@ self.reprs_by_id = {} self.reprs_by_content = {} self.specialized_ll_functions = {} - self.rclassdefs = {} + self.class_reprs = {} + self.instance_reprs = {} self.typererror = None # make the primitive_to_repr constant mapping self.primitive_to_repr = {} Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Sat Jun 4 13:33:16 2005 @@ -19,3 +19,17 @@ typer.specialize() #t.view() t.checkgraphs() + +def test_instanceattr(): + def dummyfn(): + x = EmptyBase() + x.a = 5 + x.a += 1 + return x.a + + t = Translator(dummyfn) + t.annotate([]) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() From arigo at codespeak.net Sat Jun 4 14:03:00 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 4 Jun 2005 14:03:00 +0200 (CEST) Subject: [pypy-svn] r13055 - in pypy/dist/pypy/rpython: . test Message-ID: <20050604120300.6871327B4C@code1.codespeak.net> Author: arigo Date: Sat Jun 4 14:03:00 2005 New Revision: 13055 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Simple class attributes. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sat Jun 4 14:03:00 2005 @@ -63,16 +63,27 @@ def __init__(self, rtyper, classdef): self.classdef = classdef + self.clsfields = {} if classdef is None: # 'object' root type self.vtable_type = OBJECT_VTABLE self.typeptr = nullptr(OBJECT_VTABLE) else: + # instance attributes + llfields = [] + attrs = classdef.attrs.items() + attrs.sort() + for name, attrdef in attrs: + if attrdef.readonly: + r = rtyper.getrepr(attrdef.s_value) + mangled_name = name + '_C' + self.clsfields[name] = mangled_name, r + llfields.append((mangled_name, r.lowleveltype)) + # self.rbase = getclassrepr(rtyper, classdef.basedef) self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, ('super', self.rbase.vtable_type), - # XXX class attributes - ) + *llfields) self.lowleveltype = NonGcPtr(self.vtable_type) self.vtable = None @@ -102,6 +113,55 @@ # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls) + def fromparentpart(self, v_vtableptr, llops): + """Return the vtable pointer cast from the parent vtable's type + to self's vtable type.""" + ctype = inputconst(Void, self.lowleveltype) + return llops.genop('cast_parent', [ctype, v_vtableptr], + resulttype=self.lowleveltype) + + def fromtypeptr(self, vcls, llops): + """Return the type pointer cast to self's vtable type.""" + if self.classdef is None: + return vcls + else: + v_vtableptr = self.rbase.fromtypeptr(vcls, llops) + return self.fromparentpart(v_vtableptr, llops) + + def getclsfieldrepr(self, attr): + """Return the repr used for the given attribute.""" + if attr in self.clsfields: + mangled_name, r = self.clsfields[attr] + return r + else: + if self.classdef is None: + raise MissingRTypeAttribute(attr) + return self.rbase.getfieldrepr(attr) + + def getclsfield(self, vcls, attr, llops): + """Read the given attribute of 'vcls'.""" + if attr in self.clsfields: + mangled_name, r = self.clsfields[attr] + v_vtable = self.fromtypeptr(vcls, llops) + cname = inputconst(Void, mangled_name) + return llops.genop('getfield', [v_vtable, cname], resulttype=r) + else: + if self.classdef is None: + raise MissingRTypeAttribute(attr) + return self.rbase.getclsfield(vcls, attr, llops) + + def setclsfield(self, vcls, attr, vvalue, llops): + """Write the given attribute of 'vcls'.""" + if attr in self.clsfields: + mangled_name, r = self.clsfields[attr] + v_vtable = self.fromtypeptr(vcls, llops) + cname = inputconst(Void, mangled_name) + llops.genop('setfield', [v_vtable, cname, vvalue]) + else: + if self.classdef is None: + raise MissingRTypeAttribute(attr) + self.rbase.setclsfield(vcls, attr, vvalue, llops) + root_class_repr = ClassRepr(None, None) type_repr = root_class_repr @@ -120,49 +180,44 @@ self.classdef = classdef self.rclass = getclassrepr(rtyper, classdef) self.fields = {} + self.allinstancefields = {} if self.classdef is None: self.fields['__class__'] = 'typeptr', TYPEPTR self.object_type = OBJECT else: - # instance attributes (XXX remove class attributes from here) + # instance attributes llfields = [] attrs = classdef.attrs.items() attrs.sort() for name, attrdef in attrs: - r = rtyper.getrepr(attrdef.s_value) - mangled_name = name + '_' - self.fields[name] = mangled_name, r - llfields.append((mangled_name, r.lowleveltype)) + if not attrdef.readonly: + r = rtyper.getrepr(attrdef.s_value) + mangled_name = name + '_' + self.fields[name] = mangled_name, r + llfields.append((mangled_name, r.lowleveltype)) # self.rbase = getinstancerepr(rtyper, classdef.basedef) self.object_type = GcStruct(classdef.cls.__name__, ('super', self.rbase.object_type), *llfields) + self.allinstancefields.update(self.rbase.allinstancefields) self.lowleveltype = GcPtr(self.object_type) + self.allinstancefields.update(self.fields) def parentpart(self, vinst, llops): """Return the pointer 'vinst' cast to the parent type.""" - try: - supercache = llops.__super_cache - except AttributeError: - supercache = llops.__super_cache = {} - # - if vinst not in supercache: - cname = inputconst(Void, 'super') - supercache[vinst] = llops.genop('getsubstruct', [vinst, cname], - resulttype=self.rbase.lowleveltype) - return supercache[vinst] + cname = inputconst(Void, 'super') + return llops.genop('getsubstruct', [vinst, cname], + resulttype=self.rbase.lowleveltype) def getfieldrepr(self, attr): """Return the repr used for the given attribute.""" - if self.classdef is None: - if attr == '__class__': - return TYPEPTR - raise MissingRTypeAttribute(attr) - elif attr in self.fields: + if attr in self.fields: mangled_name, r = self.fields[attr] return r else: + if self.classdef is None: + raise MissingRTypeAttribute(attr) return self.rbase.getfieldrepr(attr) def getfield(self, vinst, attr, llops): @@ -206,7 +261,11 @@ def rtype_getattr(self, hop): attr = hop.args_s[1].const vinst, vattr = hop.inputargs(self, Void) - return self.getfield(vinst, attr, hop.llops) + if attr in self.allinstancefields: + return self.getfield(vinst, attr, hop.llops) + else: + vcls = self.getfield(vinst, '__class__', hop.llops) + return self.rclass.getclsfield(vcls, attr, hop.llops) def rtype_setattr(self, hop): attr = hop.args_s[1].const Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Sat Jun 4 14:03:00 2005 @@ -33,3 +33,20 @@ typer.specialize() #t.view() t.checkgraphs() + + +class Random: + xyzzy = 12 + yadda = 21 + +def test_classattr(): + def dummyfn(): + x = Random() + return x.xyzzy + + t = Translator(dummyfn) + t.annotate([]) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() From pedronis at codespeak.net Sat Jun 4 16:06:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 16:06:57 +0200 (CEST) Subject: [pypy-svn] r13056 - pypy/dist/pypy/annotation Message-ID: <20050604140657.9693327B4C@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 16:06:57 2005 New Revision: 13056 Modified: pypy/dist/pypy/annotation/binaryop.py Log: try to mantain the invariant that in SomePBC(func:classDef) func is really present on classDef.cls Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sat Jun 4 16:06:57 2005 @@ -437,6 +437,7 @@ classdef = classdef.commonbase(d[x]) for cand in classdef.getmro(): if x in cand.cls.__dict__.values(): + classdef = cand break else: raise UnionError( From pedronis at codespeak.net Sat Jun 4 16:07:59 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 16:07:59 +0200 (CEST) Subject: [pypy-svn] r13057 - pypy/dist/pypy/translator/goal Message-ID: <20050604140759.0492F27B4C@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 16:07:58 2005 New Revision: 13057 Modified: pypy/dist/pypy/translator/goal/query.py Log: another query about callables encountered and gathered info Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Sat Jun 4 16:07:58 2005 @@ -197,6 +197,60 @@ accum.append("(%s)" % ', '.join(arg)) return ' '.join(accum) +def pbccallsanity(translator): + callb = translator.annotator.getpbccallables() + bk = translator.annotator.bookkeeper + typs = [x for x in callb if isinstance(x, (type, types.ClassType))] + for t in typs: + assert len(callb[t]) == 1 + assert callb[t] == {(None,t): True} + print len(typs), "of ",prettycallable(callablereps([(None, Exception), (None, object)])) + ubm = [x for x in callb if isinstance(x, types.MethodType) and x.im_self is None] + assert len(ubm) == 0 + bm = [x for x in callb if isinstance(x, types.MethodType) and x.im_self is not None] + frompbc = 0 + notfrompbc = [] + for b in bm: + assert len(callb[b]) == 1 + assert callb[b] == {(None,b): True} + if b.im_class in bk.pbctypes or (b.im_class is None and b.im_self in bk.pbccache): + frompbc += 1 + else: + notfrompbc.append(b) + class A: + def m(): + pass + print frompbc, "of", prettycallable(callablereps([(None, A().m)])), "from PBCs" + print len(bm)-frompbc, "of", prettycallable(callablereps([(None, A().m)])), "not from PBCs" + if len(notfrompbc) < 40: + for b in notfrompbc: + print " "*4, prettycallable((None, b)) + fs = [x for x in callb if isinstance(x, types.FunctionType)] + assert len(fs) + len(typs) + frompbc + len(notfrompbc) == len(callb) + plain = [] + r = [] + for x in fs: + if len(callb[x]) == 1 and callb[x].keys()[0][0] == None: + r.extend(callb[x].keys()) + plain.append(x) + print len(plain), "of", prettycallable(callablereps(r)) + r = [] + for x in fs: + if x not in plain and len(callb[x]) == 1: + r.extend(callb[x].keys()) + print len(r), "of", prettycallable(callablereps(r)) + r = [] + b_nb = [] + for x in fs: + if len(callb[x]) == 2 and [1 for clsdef, f in callb[x].keys() if clsdef is None]: + r.extend(callb[x].keys()) + b_nb.append(x) + print len(r), "of", prettycallable(callablereps(r)) + print "- other -" + for x in fs: + if len(callb[x]) >= 2 and x not in b_nb: + print ' '.join([prettycallable((classdef and classdef.cls, func)) for (classdef,func) in callb[x].keys()]) + def pbccall(translator): fams = translator.annotator.getpbccallfamilies().root_info.itervalues() From pedronis at codespeak.net Sat Jun 4 18:28:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 18:28:53 +0200 (CEST) Subject: [pypy-svn] r13058 - in pypy/dist/pypy: annotation translator translator/test Message-ID: <20050604162853.DB14A27B4C@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 18:28:53 2005 New Revision: 13058 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/test/test_annrpython.py Log: for less confusion and presision move pbc call sites info computation at fix-point. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sat Jun 4 18:28:53 2005 @@ -64,8 +64,13 @@ self.argtypes_spec_callsite_results = {} self.pbc_maximal_access_sets = UnionFind(PBCAccessSet) - self.pbc_maximal_call_families = UnionFind(PBCCallFamily) - self.pbc_callables = {} + # can be precisely computed only at fix-point, see + # compute_at_fixpoint + self.pbc_maximal_call_families = None + self.pbc_callables = None + + self.pbc_call_sites = {} + # import ordering hack global BUILTIN_ANALYZERS @@ -82,6 +87,15 @@ del TLS.bookkeeper del self.position_key + def compute_at_fixpoint(self): + self.pbc_maximal_call_families = UnionFind(PBCCallFamily) + self.pbc_callables = {} + + for (fn, block, i), shape in self.pbc_call_sites.iteritems(): + assert block.operations[i].opname in ('call_args', 'simple_call') + pbc = self.annotator.binding(block.operations[i].args[0], extquery=True) + self.consider_pbc_call(pbc, shape, position=(fn, block, i)) + def getclassdef(self, cls): """Get the ClassDef associated with the given user cls.""" if cls is object: @@ -298,38 +312,33 @@ return unionof(*actuals) - def mark_callable(self, callable): - classdef, func = callable - - if hasattr(func, 'im_func') and func.im_self is None: - # consider unbound methods and the undelying functions as the same - func = func.im_func - - self.pbc_callables.setdefault(func,{})[callable] = True + def consider_pbc_call(self, pbc, shape, position=None): # computation done at fix-point + if not isinstance(pbc, SomePBC): + return - def pbc_call(self, pbc, args): nonnullcallables = [] - patterns = {} - results = [] - # extract args shape - shape = args.rawshape() - for func, classdef in pbc.prebuiltinstances.items(): if func is None: continue - if isclassdef(classdef): - s_self = SomeInstance(classdef) - args1 = args.prepend(s_self) - else: + if not isclassdef(classdef): classdef = None - args1 = args - results.append(self.pycall(func, args1)) + + # if class => consider __init__ too + if isinstance(func, (type, ClassType)) and \ + func.__module__ != '__builtin__': + assert classdef is None + dontcare, s_init = self.get_s_init(func, position=position) + if s_init is not None: + init_shape = (shape[0]+1,) + shape[1:] + self.consider_pbc_call(s_init, init_shape) callable = (classdef, func) - self.mark_callable(callable) + if hasattr(func, 'im_func') and func.im_self is None: + # consider unbound methods and the undelying functions as the same + func = func.im_func + self.pbc_callables.setdefault(func,{})[callable] = True nonnullcallables.append(callable) - patterns[shape] = True - + if nonnullcallables: call_families = self.pbc_maximal_call_families @@ -337,46 +346,77 @@ for obj in nonnullcallables: dontcare, rep, callfamily = call_families.union(rep, obj) - callfamily.patterns.update(patterns) + callfamily.patterns.update({shape: True}) + + def pbc_call(self, pbc, args, implicit_init): + if not implicit_init: + fn, block, i = self.position_key + assert block.operations[i].opname in ('call_args', 'simple_call') + assert self.annotator.binding(block.operations[i].args[0], extquery=True) is pbc + + # extract shape from args + shape = args.rawshape() + if self.position_key in self.pbc_call_sites: + assert self.pbc_call_sites[self.position_key] == shape + else: + self.pbc_call_sites[self.position_key] = shape + + results = [] + for func, classdef in pbc.prebuiltinstances.items(): + if func is None: + continue + if isclassdef(classdef): + s_self = SomeInstance(classdef) + args1 = args.prepend(s_self) + else: + args1 = args + results.append(self.pycall(func, args1)) return unionof(*results) + def get_s_init(self, cls, position=None): + specialize = getattr(cls, "_specialize_", False) + if specialize: + if specialize == "location": + cls = self.specialize_by_key(cls, position, + name="%s__At_%s" % (cls.__name__, + position_name(position))) + else: + raise Exception, \ + "unsupported specialization type '%s'"%(specialize,) + + classdef = self.getclassdef(cls) + init = getattr(cls, '__init__', None) + if init is not None and init != object.__init__: + # don't record the access of __init__ on the classdef + # because it is not a dynamic attribute look-up, but + # merely a static function call + if hasattr(init, 'im_func'): + init = init.im_func + else: + assert isinstance(init, BuiltinMethodType) + s_init = self.immutablevalue(init) + return classdef, s_init + else: + return classdef, None + def pycall(self, func, args): if func is None: # consider None as a NULL function pointer return SomeImpossibleValue() if isinstance(func, (type, ClassType)) and \ func.__module__ != '__builtin__': - cls = func - specialize = getattr(cls, "_specialize_", False) - if specialize: - if specialize == "location": - cls = self.specialize_by_key(cls, self.position_key, - name="%s__At_%s" % (cls.__name__, - position_name(self.position_key))) - else: - raise Exception, \ - "unsupported specialization type '%s'"%(specialize,) - - classdef = self.getclassdef(cls) + classdef, s_init = self.get_s_init(func, position=self.position_key) s_instance = SomeInstance(classdef) # flow into __init__() if the class has got one - init = getattr(cls, '__init__', None) - if init is not None and init != object.__init__: - # don't record the access of __init__ on the classdef - # because it is not a dynamic attribute look-up, but - # merely a static function call - if hasattr(init, 'im_func'): - init = init.im_func - else: - assert isinstance(init, BuiltinMethodType) - s_init = self.immutablevalue(init) - s_init.call(args.prepend(s_instance)) + if s_init is not None: + s_init.call(args.prepend(s_instance), implicit_init=True) else: try: args.fixedunpack(0) except ValueError: raise Exception, "no __init__ found in %r" % (cls,) return s_instance + if hasattr(func, '__call__') and \ isinstance(func.__call__, MethodType): func = func.__call__ Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jun 4 18:28:53 2005 @@ -138,7 +138,7 @@ space = RPythonCallsSpace() return obj.call(Arguments.fromshape(space, s_shape.const, args_s)) - def call(obj, args): + def call(obj, args, implicit_init=False): #raise Exception, "cannot follow call_args%r" % ((obj, args),) getbookkeeper().warning("cannot follow call(%r, %r)" % (obj, args)) return SomeObject() @@ -367,7 +367,7 @@ else: return bltn.analyser(*args) - def call(bltn, args): + def call(bltn, args, implicit_init=False): args, kw = args.unpack() assert not kw, "don't call builtins with keywords arguments" if bltn.s_self is not None: @@ -385,9 +385,9 @@ def setattr(pbc, s_attr, s_value): getbookkeeper().warning("setattr not wanted on %r" % (pbc,)) - def call(pbc, args): + def call(pbc, args, implicit_init=False): bookkeeper = getbookkeeper() - return bookkeeper.pbc_call(pbc, args) + return bookkeeper.pbc_call(pbc, args, implicit_init=implicit_init) #bookkeeper = getbookkeeper() #results = [] Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sat Jun 4 18:28:53 2005 @@ -169,6 +169,7 @@ print "++-" * 20 raise AnnotatorError('%d blocks are still blocked' % self.annotated.values().count(False)) + self.bookkeeper.compute_at_fixpoint() def binding(self, arg, extquery=False): "Gives the SomeValue corresponding to the given Variable or Constant." Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Sat Jun 4 18:28:53 2005 @@ -859,6 +859,8 @@ def n(self): pass class C(A): + def __init__(self): + pass def m(self): pass def f(x): @@ -882,11 +884,12 @@ fc = lambda x: {(None, x): True} mc = lambda x: {(clsdef(x.im_class), x.im_func): True} - assert len(callables) == 5 - assert callables == { B: fc(B), C: fc(C), - A.m.im_func: mc(A.m), - C.m.im_func: mc(C.m), - B.n.im_func: mc(B.n) } + assert len(callables) == 6 + assert callables == { B: fc(B), C: fc(C), + C.__init__.im_func: fc(C.__init__.im_func), + A.m.im_func: mc(A.m), + C.m.im_func: mc(C.m), + B.n.im_func: mc(B.n) } ign, repA_m, famA_m = call_families.find((clsdef(A), A.m.im_func)) ign, repC_m, famC_m = call_families.find((clsdef(C), C.m.im_func)) @@ -900,6 +903,9 @@ assert famB_n.patterns == {(0, (), False, False): True } assert famA_m.patterns == {(0, (), False, False): True } + + ign, repCinit, famCinit = call_families.find((None, C.__init__.im_func)) + assert famCinit.patterns == {(1, (), False, False): True } def test_isinstance_usigned(self): def f(x): From pedronis at codespeak.net Sat Jun 4 19:44:34 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 19:44:34 +0200 (CEST) Subject: [pypy-svn] r13059 - in pypy/dist/pypy: annotation tool Message-ID: <20050604174434.7F17427C3E@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 19:44:33 2005 New Revision: 13059 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/tool/ansi_print.py Log: move method demotion check to a more natural position (repeated warnings are avoided) Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Sat Jun 4 19:44:33 2005 @@ -93,8 +93,25 @@ value.class_ = cls # remember that this is really a method self.add_source_for_attribute(name, sources.get(name, cls), self) + def attr_mutated(self, homedef, attrdef): # reflow from attr read positions + s_newvalue = attrdef.getvalue() + # check for method demotion + if isinstance(s_newvalue, SomePBC): + attr = attrdef.name + meth = False + for func, classdef in s_newvalue.prebuiltinstances.items(): + if isclassdef(classdef): + meth = True + break + if meth and getattr(homedef.cls, attr, None) is None: + self.bookkeeper.warning("demoting method %s to base class %s" % (attrdef.name, homedef)) + + for position in attrdef.read_locations: + self.bookkeeper.annotator.reflowfromposition(position) + def add_source_for_attribute(self, attr, source, clsdef=None): - attrdef = self.find_attribute(attr) + homedef = self.locate_attribute(attr) + attrdef = homedef.attrs[attr] attrdef.sources[source] = clsdef if attrdef.read_locations: # we should reflow from all the reader's position, @@ -103,8 +120,7 @@ s_prev_value = attrdef.s_value s_next_value = attrdef.getvalue() if s_prev_value != s_next_value: - for position in attrdef.read_locations: - self.bookkeeper.annotator.reflowfromposition(position) + self.attr_mutated(homedef, attrdef) def locate_attribute(self, attr): for cdef in self.getmro(): @@ -176,9 +192,8 @@ newattr.merge(subattr) self.attrs[attr] = newattr - # reflow from all factories - for position in newattr.read_locations: - self.bookkeeper.annotator.reflowfromposition(position) + # reflow from all read positions + self.attr_mutated(self, newattr) def generalize_attr(self, attr, s_value=None): # if the attribute exists in a superclass, generalize there. @@ -224,8 +239,7 @@ if uplookup is not None: d[upfunc] = uplookup elif meth: - if not self.check_missing_attribute_update(name): - self.bookkeeper.warning("demoting method %s to base class %s" % (name,self)) + self.check_missing_attribute_update(name) if d: return SomePBC(d) else: Modified: pypy/dist/pypy/tool/ansi_print.py ============================================================================== --- pypy/dist/pypy/tool/ansi_print.py (original) +++ pypy/dist/pypy/tool/ansi_print.py Sat Jun 4 19:44:33 2005 @@ -4,9 +4,20 @@ import sys +f = None +n = 0 + def ansi_print(text, esc, file=None): if file is None: file = sys.stderr text = text.rstrip() + global f,n + if not text.startswith('faking') and esc == "31": + if not f: + f = open("warnings.log",'w') + n += 1 + f.write("<<< %03d\n" % n) + f.write(text+'\n') + f.flush() if sys.platform != "win32" and file.isatty(): text = ('\x1b[%sm' % esc + text + From pedronis at codespeak.net Sat Jun 4 19:47:16 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 19:47:16 +0200 (CEST) Subject: [pypy-svn] r13060 - pypy/dist/pypy/tool Message-ID: <20050604174716.643D927C99@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 19:47:16 2005 New Revision: 13060 Removed: pypy/dist/pypy/tool/ansi_print.py Log: removing to undo spurious check-in Deleted: /pypy/dist/pypy/tool/ansi_print.py ============================================================================== --- /pypy/dist/pypy/tool/ansi_print.py Sat Jun 4 19:47:16 2005 +++ (empty file) @@ -1,25 +0,0 @@ -""" -A color print. -""" - -import sys - -f = None -n = 0 - -def ansi_print(text, esc, file=None): - if file is None: file = sys.stderr - text = text.rstrip() - global f,n - if not text.startswith('faking') and esc == "31": - if not f: - f = open("warnings.log",'w') - n += 1 - f.write("<<< %03d\n" % n) - f.write(text+'\n') - f.flush() - if sys.platform != "win32" and file.isatty(): - text = ('\x1b[%sm' % esc + - text + - '\x1b[0m') # ANSI color code "reset" - file.write(text + '\n') From pedronis at codespeak.net Sat Jun 4 19:47:44 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 19:47:44 +0200 (CEST) Subject: [pypy-svn] r13061 - pypy/dist/pypy/tool Message-ID: <20050604174744.B1B3D27C98@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 19:47:44 2005 New Revision: 13061 Added: pypy/dist/pypy/tool/ansi_print.py - copied unchanged from r13058, pypy/dist/pypy/tool/ansi_print.py Log: reverted From pedronis at codespeak.net Sat Jun 4 20:35:37 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 20:35:37 +0200 (CEST) Subject: [pypy-svn] r13062 - pypy/dist/pypy/annotation Message-ID: <20050604183537.1B21527C98@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 20:35:36 2005 New Revision: 13062 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: check that invocations of specialized callables are monomorphic Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sat Jun 4 20:35:36 2005 @@ -361,23 +361,25 @@ else: self.pbc_call_sites[self.position_key] = shape - results = [] - for func, classdef in pbc.prebuiltinstances.items(): - if func is None: - continue + results = [] + nonnullcallables = [(func, classdef) for func, classdef in pbc.prebuiltinstances.items()] + mono = len(nonnullcallables) == 1 + + for func, classdef in nonnullcallables: if isclassdef(classdef): s_self = SomeInstance(classdef) args1 = args.prepend(s_self) else: args1 = args - results.append(self.pycall(func, args1)) + results.append(self.pycall(func, args1, mono)) return unionof(*results) - def get_s_init(self, cls, position=None): + def get_s_init(self, cls, position=None, mono=True): specialize = getattr(cls, "_specialize_", False) if specialize: if specialize == "location": + assert mono, "not-static construction of specialized class %s" % cls cls = self.specialize_by_key(cls, position, name="%s__At_%s" % (cls.__name__, position_name(position))) @@ -400,12 +402,12 @@ else: return classdef, None - def pycall(self, func, args): + def pycall(self, func, args, mono): if func is None: # consider None as a NULL function pointer return SomeImpossibleValue() if isinstance(func, (type, ClassType)) and \ func.__module__ != '__builtin__': - classdef, s_init = self.get_s_init(func, position=self.position_key) + classdef, s_init = self.get_s_init(func, position=self.position_key, mono=mono) s_instance = SomeInstance(classdef) # flow into __init__() if the class has got one if s_init is not None: @@ -437,6 +439,7 @@ specialize = getattr(func, '_specialize_', False) if specialize: + assert mono, "not-static call to specialized %s" % func base_func = func if specialize == 'argtypes': key = short_type_name(args) @@ -462,6 +465,7 @@ elif func.func_code.co_flags & CO_VARARGS: # calls to *arg functions: create one version per number of args + assert mono, "not-static call to *arg function %s" % func assert not args.has_keywords(), ( "keyword forbidden in calls to *arg functions") nbargs = len(args.arguments_w) From pedronis at codespeak.net Sat Jun 4 22:09:13 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 4 Jun 2005 22:09:13 +0200 (CEST) Subject: [pypy-svn] r13063 - in pypy/dist/pypy: annotation translator Message-ID: <20050604200913.1CA1A27B46@code1.codespeak.net> Author: pedronis Date: Sat Jun 4 22:09:12 2005 New Revision: 13063 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/translator/annrpython.py Log: reviewed knonwtypedata interface, now it is a mapping (exitcase, variable) -> ovverriding s_annotation, this should allow to force annotations on the False paths too. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sat Jun 4 22:09:12 2005 @@ -10,6 +10,7 @@ from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator from pypy.annotation.model import SomePBC, SomeSlice, SomeFloat from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS +from pypy.annotation.model import add_knowntypedata, merge_knowntypedata from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation.classdef import isclassdef from pypy.objspace.flow.model import Constant @@ -135,9 +136,6 @@ return SomeInteger() def is_((obj1, obj2)): - # XXX assumption: for "X is Y" we for simplification - # assume that X is possibly variable and Y constant - # (and not the other way round) r = SomeBool() if obj2.is_constant(): if obj1.is_constant(): @@ -152,16 +150,23 @@ # XXX HACK HACK HACK bk = getbookkeeper() if bk is not None: # for testing - if hasattr(obj1,'is_type_of') and obj2.is_constant(): - r.knowntypedata = (obj1.is_type_of, bk.valueoftype(obj2.const)) - return r - fn, block, i = bk.position_key - annotator = bk.annotator - op = block.operations[i] - assert op.opname == "is_" - assert len(op.args) == 2 - assert annotator.binding(op.args[0]) == obj1 - r.knowntypedata = ([op.args[0]], obj2) + knowntypedata = r.knowntypedata = {} + def bind(src_obj, tgt_obj, tgt_arg): + if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant(): + add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of, + bk.valueoftype(src_obj.const)) + + fn, block, i = bk.position_key + annotator = bk.annotator + op = block.operations[i] + assert op.opname == "is_" + assert len(op.args) == 2 + assert annotator.binding(op.args[tgt_arg]) == tgt_obj + add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]], src_obj) + + bind(obj2, obj1, 0) + bind(obj1, obj2, 1) + return r def divmod((obj1, obj2)): @@ -229,11 +234,10 @@ if getattr(boo1, 'const', -1) == getattr(boo2, 'const', -2): s.const = boo1.const if hasattr(boo1, 'knowntypedata') and \ - hasattr(boo2, 'knowntypedata') and \ - boo1.knowntypedata[0] == boo2.knowntypedata[0]: - s.knowntypedata = ( - boo1.knowntypedata[0], - unionof(boo1.knowntypedata[1], boo2.knowntypedata[1])) + hasattr(boo2, 'knowntypedata'): + ktd = merge_knowntypedata(boo1.knowntypedata, boo2.knowntypedata) + if ktd: + s.knowntypedata = ktd return s class __extend__(pairtype(SomeString, SomeString)): Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat Jun 4 22:09:12 2005 @@ -10,6 +10,7 @@ from pypy.annotation.model import SomeUnicodeCodePoint from pypy.annotation.model import SomeFloat, unionof from pypy.annotation.model import annotation_to_lltype +from pypy.annotation.model import add_knowntypedata from pypy.annotation.bookkeeper import getbookkeeper from pypy.objspace.flow.model import Constant import pypy.rpython.rarithmetic @@ -134,7 +135,8 @@ variables = [op.args[1]] for variable in variables: assert bk.annotator.binding(variable) == s_obj - r.knowntypedata = (variables, bk.valueoftype(typ)) + r.knowntypedata = {} + add_knowntypedata(r.knowntypedata, True, variables, bk.valueoftype(typ)) return r def builtin_hasattr(s_obj, s_attr): Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sat Jun 4 22:09:12 2005 @@ -383,7 +383,18 @@ s1.origin = ctxt+(0,) return s1 - +# make knowntypedata dictionary + +def add_knowntypedata(ktd, truth, vars, s_obj): + for v in vars: + ktd[(truth, v)] = s_obj + +def merge_knowntypedata(ktd1, ktd2): + r = {} + for truth_v in ktd1: + if truth_v in ktd2: + r[truth_v] = unionof(ktd1[truth_v], ktd2[truth_v]) + return r # ____________________________________________________________ # internal Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sat Jun 4 22:09:12 2005 @@ -409,8 +409,11 @@ if s_exitswitch.is_constant(): exits = [link for link in exits if link.exitcase == s_exitswitch.const] - knownvars, knownvarvalue = getattr(self.bindings.get(block.exitswitch), - "knowntypedata", (None, None)) + + # mapping (exitcase, variable) -> s_annotation + # that can be attached to booleans, exitswitches + knowntypedata = getattr(self.bindings.get(block.exitswitch), + "knowntypedata", {}) # filter out those exceptions which cannot # occour for this specific, typed operation. @@ -485,10 +488,12 @@ last_exc_value_vars.append(v) else: cell = self.binding(a) - if link.exitcase is True and knownvars is not None and a in knownvars \ - and not knownvarvalue.contains(cell): - if cell.contains(knownvarvalue): # sanity check + if (link.exitcase, a) in knowntypedata: + knownvarvalue = knowntypedata[(link.exitcase, a)] + if not knownvarvalue.contains(cell) and \ + cell.contains(knownvarvalue): # sanity check cell = knownvarvalue + if hasattr(cell,'is_type_of'): renamed_is_type_of = [] for v in cell.is_type_of: From pedronis at codespeak.net Sun Jun 5 00:30:27 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Jun 2005 00:30:27 +0200 (CEST) Subject: [pypy-svn] r13064 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050604223027.912C627B46@code1.codespeak.net> Author: pedronis Date: Sun Jun 5 00:30:27 2005 New Revision: 13064 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/translator/test/test_annrpython.py Log: more fine tuning, see the new test for the point Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sun Jun 5 00:30:27 2005 @@ -140,10 +140,10 @@ if obj2.is_constant(): if obj1.is_constant(): r.const = obj1.const is obj2.const - if obj2.const is None and not getattr(obj1, 'can_be_None', True): + if obj2.const is None and not obj1.can_be_none(): r.const = False elif obj1.is_constant(): - if obj1.const is None and not getattr(obj2, 'can_be_None', True): + if obj1.const is None and not obj2.can_be_none(): r.const = False # XXX HACK HACK HACK # XXX HACK HACK HACK @@ -151,19 +151,27 @@ bk = getbookkeeper() if bk is not None: # for testing knowntypedata = r.knowntypedata = {} + fn, block, i = bk.position_key + + annotator = bk.annotator + op = block.operations[i] + assert op.opname == "is_" + assert len(op.args) == 2 + def bind(src_obj, tgt_obj, tgt_arg): if hasattr(tgt_obj, 'is_type_of') and src_obj.is_constant(): add_knowntypedata(knowntypedata, True, tgt_obj.is_type_of, bk.valueoftype(src_obj.const)) - fn, block, i = bk.position_key - annotator = bk.annotator - op = block.operations[i] - assert op.opname == "is_" - assert len(op.args) == 2 assert annotator.binding(op.args[tgt_arg]) == tgt_obj add_knowntypedata(knowntypedata, True, [op.args[tgt_arg]], src_obj) + nonnone_obj = tgt_obj + if src_obj.is_constant() and src_obj.const is None and tgt_obj.can_be_none(): + nonnone_obj = tgt_obj.nonnoneify() + + add_knowntypedata(knowntypedata, False, [op.args[tgt_arg]], nonnone_obj) + bind(obj2, obj1, 0) bind(obj1, obj2, 1) Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sun Jun 5 00:30:27 2005 @@ -146,12 +146,19 @@ def __setattr__(self, key, value): object.__setattr__(self, key, value) + def can_be_none(self): + return True + + def nonnoneify(self): + return self class SomeFloat(SomeObject): "Stands for a float or an integer." knowntype = float # if we don't know if it's a float or an int, # pretend it's a float. + def can_be_none(self): + return False class SomeInteger(SomeFloat): "Stands for an object which is known to be an integer." @@ -169,13 +176,17 @@ def __init__(self): pass - class SomeString(SomeObject): "Stands for an object which is known to be a string." knowntype = str def __init__(self, can_be_None=False): self.can_be_None = can_be_None + def can_be_none(self): + return self.can_be_None + + def nonnoneify(self): + return SomeString(can_be_None=False) class SomeChar(SomeString): "Stands for an object known to be a string of length 1." @@ -184,6 +195,9 @@ knowntype = unicode "Stands for an object known to be a unicode codepoint." + def can_be_none(self): + return False + class SomeList(SomeObject): "Stands for a homogenous list of any length." knowntype = list @@ -193,6 +207,8 @@ return (self.__class__ is other.__class__ and self.listdef.same_as(other.listdef)) + def can_be_none(self): + return False class SomeSlice(SomeObject): knowntype = slice @@ -201,6 +217,8 @@ self.stop = stop self.step = step + def can_be_none(self): + return False class SomeTuple(SomeObject): "Stands for a tuple of known length." @@ -213,6 +231,8 @@ else: self.const = tuple([i.const for i in items]) + def can_be_none(self): + return False class SomeDict(SomeObject): "Stands for a dict." @@ -223,6 +243,8 @@ return (self.__class__ is other.__class__ and self.dictdef.same_as(other.dictdef)) + def can_be_none(self): + return False class SomeIterator(SomeObject): "Stands for an iterator returning objects from a given container." @@ -230,6 +252,8 @@ def __init__(self, s_container): self.s_container = s_container + def can_be_none(self): + return False class SomeInstance(SomeObject): "Stands for an instance of a (user-defined) class." @@ -242,6 +266,13 @@ def fmt_classdef(self, cd): return cd.cls.__name__ + def can_be_none(self): + return self.can_be_None + + def nonnoneify(self): + return SomeInstance(self.classdef, can_be_None=False) + + def new_or_old_class(c): if hasattr(c, '__class__'): return c.__class__ @@ -289,6 +320,17 @@ def isNone(self): return self.prebuiltinstances == {None:True} + def can_be_none(self): + return None in self.prebuiltinstances + + def nonnoneify(self): + prebuiltinstances = self.prebuiltinstances.copy() + del prebuiltinstances[None] + if not prebuiltinstances: + return SomeImpossibleValue() + else: + return SomePBC(prebuiltinstances) + def fmt_prebuiltinstances(self, pbis): if hasattr(self, 'const'): return None @@ -310,11 +352,16 @@ self.s_self = s_self self.methodname = methodname + def can_be_none(self): + return False class SomeImpossibleValue(SomeObject): """The empty set. Instances are placeholders for objects that will never show up at run-time, e.g. elements of an empty list.""" + def can_be_none(self): + return False + #____________________________________________________________ # annotation of low-level types @@ -322,6 +369,8 @@ def __init__(self, ll_ptrtype): self.ll_ptrtype = ll_ptrtype + def can_be_none(self): + return False from pypy.rpython import lltype Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Sun Jun 5 00:30:27 2005 @@ -1188,6 +1188,24 @@ s = a.build_types(f, [int]) assert s == a.bookkeeper.immutablevalue(None) + def test_non_None_path(self): + class C: + pass + def g(c): + if c is None: + return C() + return c + def f(x): + if x: + c = None + else: + c = C() + return g(c) + a = self.RPythonAnnotator() + s = a.build_types(f, [bool]) + assert s.can_be_none() == False + + def g(n): return [0,1,2,n] From pedronis at codespeak.net Sun Jun 5 00:55:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Jun 2005 00:55:28 +0200 (CEST) Subject: [pypy-svn] r13065 - pypy/dist/pypy/annotation Message-ID: <20050604225528.C9D8B27B46@code1.codespeak.net> Author: pedronis Date: Sun Jun 5 00:55:28 2005 New Revision: 13065 Modified: pypy/dist/pypy/annotation/model.py Log: lists can be mixed with None, see binaryop Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sun Jun 5 00:55:28 2005 @@ -208,7 +208,7 @@ self.listdef.same_as(other.listdef)) def can_be_none(self): - return False + return True class SomeSlice(SomeObject): knowntype = slice From pedronis at codespeak.net Sun Jun 5 00:56:19 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Jun 2005 00:56:19 +0200 (CEST) Subject: [pypy-svn] r13066 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050604225619.1DB4E27B46@code1.codespeak.net> Author: pedronis Date: Sun Jun 5 00:56:18 2005 New Revision: 13066 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/translator/test/test_annrpython.py Log: isinstance cannot return a sure True if the object can possibly be None Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sun Jun 5 00:56:18 2005 @@ -118,7 +118,7 @@ "for integers only isinstance(.,int|r_uint) are supported") if s_obj.is_constant(): r.const = isinstance(s_obj.const, typ) - elif our_issubclass(s_obj.knowntype, typ): + elif our_issubclass(s_obj.knowntype, typ) and not s_obj.can_be_none(): r.const = True elif not our_issubclass(typ, s_obj.knowntype): r.const = False Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Sun Jun 5 00:56:18 2005 @@ -1204,6 +1204,20 @@ a = self.RPythonAnnotator() s = a.build_types(f, [bool]) assert s.can_be_none() == False + + def test_can_be_None_path(self): + class C: + pass + def f(x): + if x: + c = None + else: + c = C() + return isinstance(c, C) + a = self.RPythonAnnotator() + s = a.build_types(f, [bool]) + assert not s.is_constant() + def g(n): From tismer at codespeak.net Sun Jun 5 03:47:22 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 03:47:22 +0200 (CEST) Subject: [pypy-svn] r13067 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050605014722.BA80327B46@code1.codespeak.net> Author: tismer Date: Sun Jun 5 03:47:22 2005 New Revision: 13067 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/multimethod.py Log: some things turn out to be NOT_RPYTHON Modified: pypy/branch/pypy-translation-snapshot/objspace/std/multimethod.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/multimethod.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/multimethod.py Sun Jun 5 03:47:22 2005 @@ -93,6 +93,8 @@ # ____________________________________________________________ class Installer: + """NOT_RPYTHON""" + mmfunccache = {} prefix_memo = {} From pedronis at codespeak.net Sun Jun 5 03:57:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 5 Jun 2005 03:57:28 +0200 (CEST) Subject: [pypy-svn] r13068 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050605015728.6413227B46@code1.codespeak.net> Author: pedronis Date: Sun Jun 5 03:57:28 2005 New Revision: 13068 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/test/test_annrpython.py Log: don't support __call__ anymore, not used by PyPy itself (some planning comment about an intf for later phases to query about specialization) Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sun Jun 5 03:57:28 2005 @@ -375,6 +375,10 @@ return unionof(*results) + # decide_callable(position, func, args, mono) -> callb, key + # query_spaceop_callable(spaceop) -> pbc + # get_s_init(decided_cls) -> classdef, s_undecided_init + def get_s_init(self, cls, position=None, mono=True): specialize = getattr(cls, "_specialize_", False) if specialize: @@ -419,9 +423,6 @@ raise Exception, "no __init__ found in %r" % (cls,) return s_instance - if hasattr(func, '__call__') and \ - isinstance(func.__call__, MethodType): - func = func.__call__ if hasattr(func, 'im_func'): if func.im_self is not None: s_self = self.immutablevalue(func.im_self) Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Sun Jun 5 03:57:28 2005 @@ -293,11 +293,6 @@ a.simplify() #a.translator.view() - def test_call_pbc(self): - a = self.RPythonAnnotator() - s = a.build_types(snippet.call_cpbc, []) - assert s == a.bookkeeper.immutablevalue(42) - def test_flow_type_info(self): a = self.RPythonAnnotator() s = a.build_types(snippet.flow_type_info, [object]) From tismer at codespeak.net Sun Jun 5 04:08:31 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 04:08:31 +0200 (CEST) Subject: [pypy-svn] r13069 - pypy/dist/pypy/objspace/flow Message-ID: <20050605020831.AFAE927B42@code1.codespeak.net> Author: tismer Date: Sun Jun 5 04:08:31 2005 New Revision: 13069 Modified: pypy/dist/pypy/objspace/flow/model.py Log: moved the Slotted class into translator/pickle Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Sun Jun 5 04:08:31 2005 @@ -6,6 +6,8 @@ from __future__ import generators from pypy.tool.uid import Hashable +from pypy.translator.pickle.slotted import Slotted + """ memory size before and after introduction of __slots__ using targetpypymain with -no-c @@ -30,21 +32,6 @@ __metaclass__ = type -class Missing: - pass - -class Slotted: - __slots__ = [] - from copy_reg import _slotnames - _slotnames = classmethod(_slotnames) - def __getstate__(self): - names = self._slotnames() - return tuple([getattr(self, name, Missing) for name in names]) - def __setstate__(self, args): - names = self._slotnames() - [setattr(self, name, value) for name, value in zip(names, args) - if value is not Missing] - class FunctionGraph(Slotted): __slots__ = """func source name startblock returnblock exceptblock""".split() From tismer at codespeak.net Sun Jun 5 04:09:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 04:09:16 +0200 (CEST) Subject: [pypy-svn] r13070 - pypy/dist/pypy/objspace/std Message-ID: <20050605020916.B698A27B42@code1.codespeak.net> Author: tismer Date: Sun Jun 5 04:09:15 2005 New Revision: 13070 Modified: pypy/dist/pypy/objspace/std/multimethod.py Log: some more stuff is not rpythonic Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Sun Jun 5 04:09:15 2005 @@ -93,6 +93,8 @@ # ____________________________________________________________ class Installer: + """NOT_RPYTHON" + mmfunccache = {} prefix_memo = {} From tismer at codespeak.net Sun Jun 5 04:12:40 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 04:12:40 +0200 (CEST) Subject: [pypy-svn] r13071 - pypy/dist/pypy/translator Message-ID: <20050605021240.3797E27B46@code1.codespeak.net> Author: tismer Date: Sun Jun 5 04:12:39 2005 New Revision: 13071 Modified: pypy/dist/pypy/translator/annrpython.py Log: added explicit support for pickling. corrected ordering of code in __init__ according to comments. Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sun Jun 5 04:12:39 2005 @@ -39,11 +39,21 @@ # bindingshistory self.reflowcounter = {} self.return_bindings = {} # map return Variables to functions - # user-supplied annotation logic for functions we don't want to flow into - self.overrides = overrides # --- end of debugging information --- self.bookkeeper = Bookkeeper(self) + # user-supplied annotation logic for functions we don't want to flow into + self.overrides = overrides + def __getstate__(self): + attrs = """translator pendingblocks bindings annotated links_followed + notify bookkeeper overrides""".split() + ret = self.__dict__.copy() + for key, value in ret.items(): + if key not in attrs: + assert type(value) is dict, ("please update %s.__getstate__" % + self.__class__.__name__) + ret[key] = {} + return ret def _register_returnvar(self, flowgraph, func): if annmodel.DEBUG: From tismer at codespeak.net Sun Jun 5 04:13:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 04:13:11 +0200 (CEST) Subject: [pypy-svn] r13072 - pypy/dist/pypy/translator/pickle Message-ID: <20050605021311.0E74827B46@code1.codespeak.net> Author: tismer Date: Sun Jun 5 04:13:10 2005 New Revision: 13072 Added: pypy/dist/pypy/translator/pickle/slotted.py (contents, props changed) Log: made slotted an external module Added: pypy/dist/pypy/translator/pickle/slotted.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/pickle/slotted.py Sun Jun 5 04:13:10 2005 @@ -0,0 +1,22 @@ +class Missing: + pass + +from copy_reg import _slotnames + +# we don't turn _slotnames into a class method, because it +# is also needed externally. + +class Slotted(object): + __slots__ = [] + def __getstate__(self): + names = _slotnames(self.__class__) + return tuple([getattr(self, name, Missing) for name in names]) + def __setstate__(self, args): + names = _slotnames(self.__class__) + [setattr(self, name, value) for name, value in zip(names, args) + if value is not Missing] + +# support classes which cannot inherit from Slotted + +__getstate__ = Slotted.__getstate__.im_func +__setstate__ = Slotted.__setstate__.im_func From hpk at codespeak.net Sun Jun 5 08:29:37 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 5 Jun 2005 08:29:37 +0200 (CEST) Subject: [pypy-svn] r13073 - pypy/dist/pypy/objspace/std Message-ID: <20050605062937.5C1AA27B46@code1.codespeak.net> Author: hpk Date: Sun Jun 5 08:29:36 2005 New Revision: 13073 Modified: pypy/dist/pypy/objspace/std/multimethod.py Log: fixed syntax error ... Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Sun Jun 5 08:29:36 2005 @@ -93,7 +93,7 @@ # ____________________________________________________________ class Installer: - """NOT_RPYTHON" + """NOT_RPYTHON""" mmfunccache = {} From arigo at codespeak.net Sun Jun 5 21:26:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 5 Jun 2005 21:26:32 +0200 (CEST) Subject: [pypy-svn] r13081 - pypy/dist/pypy/rpython Message-ID: <20050605192632.D12C727B51@code1.codespeak.net> Author: arigo Date: Sun Jun 5 21:26:28 2005 New Revision: 13081 Modified: pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py Log: convert_const() methods on the Repr subclass, to convert a constant Python object (e.g. "hello") to the corresponding low-level constant (e.g. prebuilt array of 5 characters). The goal is that all Constants in the flow graph after typing have low-level values. It's most fun for class pointers and prebuilt instances. intmask() support. Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Sun Jun 5 21:26:28 2005 @@ -15,6 +15,11 @@ class __extend__(BoolRepr): + def convert_const(self, value): + if not isinstance(value, bool): + raise TyperError("not a bool: %r" % (value,)) + return value + def rtype_is_true(_, hop): vlist = hop.inputargs(Bool) return vlist[0] Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sun Jun 5 21:26:28 2005 @@ -1,6 +1,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import malloc, typeOf, nullptr, nullgcptr +from pypy.rpython import lltype +from pypy.rpython import rarithmetic from pypy.rpython.lltype import Void, Signed from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range @@ -84,6 +85,10 @@ #def rtype_builtin_range(hop): see rrange.py +def rtype_intmask(hop): + vlist = hop.inputargs(Signed) + return vlist[0] + # collect all functions import __builtin__ @@ -110,7 +115,8 @@ return hop.inputconst(Void, hop.s_result.const) -BUILTIN_TYPER[malloc] = rtype_malloc -BUILTIN_TYPER[typeOf] = rtype_const_result -BUILTIN_TYPER[nullptr] = rtype_const_result -BUILTIN_TYPER[nullgcptr] = rtype_const_result +BUILTIN_TYPER[lltype.malloc] = rtype_malloc +BUILTIN_TYPER[lltype.typeOf] = rtype_const_result +BUILTIN_TYPER[lltype.nullptr] = rtype_const_result +BUILTIN_TYPER[lltype.nullgcptr] = rtype_const_result +BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sun Jun 5 21:26:28 2005 @@ -1,3 +1,4 @@ +import types from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.lltype import * @@ -38,54 +39,89 @@ def getclassrepr(rtyper, classdef): - if classdef is None: - return root_class_repr try: result = rtyper.class_reprs[classdef] except KeyError: result = rtyper.class_reprs[classdef] = ClassRepr(rtyper, classdef) + result.setup() return result def getinstancerepr(rtyper, classdef): - if classdef is None: - return root_instance_repr try: result = rtyper.instance_reprs[classdef] except KeyError: result = rtyper.instance_reprs[classdef] = InstanceRepr(rtyper,classdef) + result.setup() return result class MissingRTypeAttribute(TyperError): pass +def cast_vtable_to_typeptr(vtable): + while typeOf(vtable).TO != OBJECT_VTABLE: + vtable = vtable.super + if typeOf(vtable) != TYPEPTR: + vtable = cast_flags(TYPEPTR, vtable) + return vtable + + class ClassRepr(Repr): + initialized = False def __init__(self, rtyper, classdef): + self.rtyper = rtyper self.classdef = classdef + self.vtable_type = ForwardReference() + self.lowleveltype = NonGcPtr(self.vtable_type) + + def __repr__(self): + if self.classdef is None: + cls = object + else: + cls = self.classdef.cls + return '' % (cls.__module__, cls.__name__) + + def setup(self): + if self.initialized: + return # already initialized self.clsfields = {} - if classdef is None: + if self.classdef is None: # 'object' root type - self.vtable_type = OBJECT_VTABLE - self.typeptr = nullptr(OBJECT_VTABLE) + self.vtable_type.become(OBJECT_VTABLE) else: - # instance attributes + # class attributes llfields = [] - attrs = classdef.attrs.items() + attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if attrdef.readonly: - r = rtyper.getrepr(attrdef.s_value) - mangled_name = name + '_C' + r = self.rtyper.getrepr(attrdef.s_value) + mangled_name = 'cls_' + name self.clsfields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # - self.rbase = getclassrepr(rtyper, classdef.basedef) - self.vtable_type = Struct('%s_vtable' % classdef.cls.__name__, - ('super', self.rbase.vtable_type), - *llfields) - self.lowleveltype = NonGcPtr(self.vtable_type) + self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) + vtable_type = Struct('%s_vtable' % self.classdef.cls.__name__, + ('super', self.rbase.vtable_type), + *llfields) + self.vtable_type.become(vtable_type) self.vtable = None + self.initialized = True + + def convert_const(self, value): + if not isinstance(value, (type, types.ClassType)): + raise TyperError("not a class: %r" % (value,)) + try: + subclassdef = self.rtyper.annotator.getuserclasses()[value] + except KeyError: + raise TyperError("no classdef: %r" % (value,)) + if self.classdef is not None: + if self.classdef.commonbase(subclassdef) != self.classdef: + raise TyperError("not a subclass of %r: %r" % ( + self.classdef.cls, value)) + # + return getclassrepr(self.rtyper, subclassdef).getvtable() def getvtable(self, cast_to_typeptr=True): """Return a ptr to the vtable of this type.""" @@ -96,10 +132,7 @@ # vtable = self.vtable if cast_to_typeptr: - r = self - while r is not root_class_repr: - r = r.rbase - vtable = cast_flags(r.lowleveltype, vtable.super) + vtable = cast_vtable_to_typeptr(vtable) return vtable def setup_vtable(self, vtable, rsubcls): @@ -163,8 +196,8 @@ self.rbase.setclsfield(vcls, attr, vvalue, llops) -root_class_repr = ClassRepr(None, None) -type_repr = root_class_repr +def get_type_repr(rtyper): + return getclassrepr(rtyper, None) # ____________________________________________________________ @@ -175,34 +208,72 @@ class InstanceRepr(Repr): + initialized = False def __init__(self, rtyper, classdef): + self.rtyper = rtyper self.classdef = classdef - self.rclass = getclassrepr(rtyper, classdef) + self.object_type = GcForwardReference() + self.lowleveltype = GcPtr(self.object_type) + + def __repr__(self): + if self.classdef is None: + cls = object + else: + cls = self.classdef.cls + return '' % (cls.__module__, cls.__name__) + + def setup(self): + if self.initialized: + return # already initialized + self.rclass = getclassrepr(self.rtyper, self.classdef) self.fields = {} self.allinstancefields = {} if self.classdef is None: self.fields['__class__'] = 'typeptr', TYPEPTR - self.object_type = OBJECT + self.object_type.become(OBJECT) else: # instance attributes llfields = [] - attrs = classdef.attrs.items() + attrs = self.classdef.attrs.items() attrs.sort() for name, attrdef in attrs: if not attrdef.readonly: - r = rtyper.getrepr(attrdef.s_value) - mangled_name = name + '_' + r = self.rtyper.getrepr(attrdef.s_value) + mangled_name = 'inst_' + name self.fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # - self.rbase = getinstancerepr(rtyper, classdef.basedef) - self.object_type = GcStruct(classdef.cls.__name__, - ('super', self.rbase.object_type), - *llfields) + self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) + object_type = GcStruct(self.classdef.cls.__name__, + ('super', self.rbase.object_type), + *llfields) + self.object_type.become(object_type) self.allinstancefields.update(self.rbase.allinstancefields) - self.lowleveltype = GcPtr(self.object_type) self.allinstancefields.update(self.fields) + self.initialized = True + + def convert_const(self, value, targetptr=None, vtable=None): + if value is None: + return nullgcptr(self.object_type) + # we will need the vtable pointer, so ask it first, to let + # ClassRepr.convert_const() perform all the necessary checks on 'value' + if vtable is None: + vtable = self.rclass.convert_const(value.__class__) + if targetptr is None: + targetptr = malloc(self.object_type) + # + if self.classdef is None: + # instantiate 'object': should be disallowed, but it's convenient + # to write convert_const() this way and use itself recursively + targetptr.typeptr = cast_vtable_to_typeptr(vtable) + else: + # build the parent part of the instance + self.rbase.convert_const(value, + targetptr = targetptr.super, + vtable = vtable) + # XXX add instance attributes from this level + return targetptr def parentpart(self, vinst, llops): """Return the pointer 'vinst' cast to the parent type.""" @@ -274,8 +345,6 @@ self.setfield(vinst, attr, vvalue, hop.llops) -root_instance_repr = InstanceRepr(None, None) - # ____________________________________________________________ def rtype_new_instance(cls, hop): Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sun Jun 5 21:26:28 2005 @@ -86,6 +86,11 @@ class __extend__(FloatRepr): + def convert_const(self, value): + if not isinstance(value, (int, float)): # can be bool too + raise TyperError("not a float: %r" % (value,)) + return float(value) + def rtype_is_true(_, hop): vlist = hop.inputargs(Float) return hop.genop('float_is_true', vlist, resulttype=Bool) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Sun Jun 5 21:26:28 2005 @@ -161,6 +161,11 @@ class __extend__(IntegerRepr): + def convert_const(self, value): + if not isinstance(value, int): # can be bool + raise TyperError("not an integer: %r" % (value,)) + return int(value) + def rtype_float(_, hop): vlist = hop.inputargs(Float) return vlist[0] Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sun Jun 5 21:26:28 2005 @@ -2,6 +2,7 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import Void, Bool, Float, Signed, Char +from pypy.rpython.lltype import typeOf, LowLevelType class Repr: @@ -20,6 +21,18 @@ def setup(self): "For recursive data structure, which must be initialized in two steps." + def convert_const(self, value): + "Convert the given constant value to the low-level repr of 'self'." + if self.lowleveltype != Void: + try: + realtype = typeOf(value) + except (AssertionError, AttributeError): + realtype = '???' + if realtype != self.lowleveltype: + raise TyperError("convert_const(self = %r, value = %r)" % ( + self, value)) + return value + # default implementation of some operations def rtype_getattr(self, hop): @@ -126,12 +139,22 @@ which can be a Repr instance or a low-level type. """ if isinstance(reqtype, Repr): - reqtype = reqtype.lowleveltype + value = reqtype.convert_const(value) + lltype = reqtype.lowleveltype + elif isinstance(reqtype, LowLevelType): + lltype = reqtype + else: + raise TypeError(repr(reqtype)) # Void Constants can hold any value; # non-Void Constants must hold a correctly ll-typed value - # XXX ---- not enforced yet ---- - #if reqtype is not Void: - # assert typeOf(value) == reqtype + if lltype != Void: + try: + realtype = typeOf(value) + except (AssertionError, AttributeError): + realtype = '???' + if realtype != lltype: + raise TyperError("inputconst(reqtype = %s, value = %s)" % ( + reqtype, value)) c = Constant(value) - c.concretetype = reqtype + c.concretetype = lltype return c Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Sun Jun 5 21:26:28 2005 @@ -10,7 +10,7 @@ if self.is_constant(): return constpyobj_repr if self.knowntype is type: - return rclass.type_repr + return rclass.get_type_repr(rtyper) else: return pyobj_repr Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 5 21:26:28 2005 @@ -1,8 +1,10 @@ +from weakref import WeakValueDictionary from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython.rmodel import StringRepr, CharRepr +from pypy.rpython.rarithmetic import intmask # ____________________________________________________________ # @@ -28,9 +30,26 @@ return char_repr +CONST_STR_CACHE = WeakValueDictionary() + class __extend__(StringRepr): lowleveltype = GcPtr(STR) + def convert_const(self, value): + if value is None: + return nullgcptr(STR) + if not isinstance(value, str): + raise TyperError("not a str: %r" % (value,)) + try: + return CONST_STR_CACHE[value] + except KeyError: + p = malloc(STR, len(value)) + for i in range(len(value)): + p.chars[i].ch = value[i] + ll_strhash(p) # precompute the hash + CONST_STR_CACHE[value] = p + return p + def rtype_len(_, hop): v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strlen, v_str) @@ -131,5 +150,5 @@ x ^= length if x == 0: x = -1 - s.hash = x + s.hash = intmask(x) return x Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun Jun 5 21:26:28 2005 @@ -277,6 +277,8 @@ 'converted_to' should be a Repr instance or a Primitive low-level type. """ + if not isinstance(converted_to, Repr): + converted_to = self.rtyper.primitive_to_repr[converted_to] v = self.spaceop.args[self.nb_popped + arg] if isinstance(v, Constant): return inputconst(converted_to, v.value) @@ -286,8 +288,6 @@ if s_binding.is_constant(): return inputconst(converted_to, s_binding.const) - if not isinstance(converted_to, Repr): - converted_to = self.rtyper.primitive_to_repr[converted_to] r_binding = self.args_r[arg] return self.llops.convertvar(v, r_binding, converted_to) From ale at codespeak.net Sun Jun 5 22:59:25 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sun, 5 Jun 2005 22:59:25 +0200 (CEST) Subject: [pypy-svn] r13082 - in pypy/dist/pypy/lib: . test2 Message-ID: <20050605205925.498D027B51@code1.codespeak.net> Author: ale Date: Sun Jun 5 22:59:23 2005 New Revision: 13082 Removed: pypy/dist/pypy/lib/test2/test_codeccallbacks.py Modified: pypy/dist/pypy/lib/inprogress__codecs.py pypy/dist/pypy/lib/unicodecodec.py Log: test_unicode.py passes now. No known failures Modified: pypy/dist/pypy/lib/inprogress__codecs.py ============================================================================== --- pypy/dist/pypy/lib/inprogress__codecs.py (original) +++ pypy/dist/pypy/lib/inprogress__codecs.py Sun Jun 5 22:59:23 2005 @@ -114,7 +114,7 @@ if isinstance(encoding,str): decoder = lookup(encoding)[1] if decoder and isinstance(errors,str): - res = decoder(v,errors) + res = decoder(obj,errors) if not isinstance(res,tuple) or len(res) != 2: raise TypeError("encoder must return a tuple (object,integer)") return res[0] @@ -227,7 +227,8 @@ res = ''.join(p) return res, len(res) else: - return ''.join(PyUnicode_FromUnicode(obj,size),size) + res = "You can do better than this" # XXX make this right + return res,len(res) def unicode_internal_decode( unistr,errors='strict'): """None @@ -241,7 +242,7 @@ t = 0 for j in range(unicode_bytes): t += ord(unistr[i+j])<<(j*8) - i += j+1 + i += unicode_bytes p += unichr(t) res = u''.join(p) return res, len(res) @@ -283,11 +284,12 @@ def mbcs_encode( obj,errors='strict'): """None """ - return (PyUnicode_EncodeMBCS( - PyUnicode_AS_UNICODE(obj), - PyUnicode_GET_SIZE(obj), - errors), - PyUnicode_GET_SIZE(obj)); + pass +## return (PyUnicode_EncodeMBCS( +## (obj), +## len(obj), +## errors), +## len(obj)) def ascii_encode( obj,errors='strict'): Deleted: /pypy/dist/pypy/lib/test2/test_codeccallbacks.py ============================================================================== --- /pypy/dist/pypy/lib/test2/test_codeccallbacks.py Sun Jun 5 22:59:23 2005 +++ (empty file) @@ -1,724 +0,0 @@ -import py -py.test.skip("this test module doesn't belong here") -import autopath -import test.test_support, unittest -import sys, htmlentitydefs, unicodedata -sys.path.insert(1,r'd:\projects\pypy_co\pypy\lib') -from pypy.lib import codecs -sys.modules['codecs'] = codecs -from pypy.lib import encodings -reload(encodings) -reload(codecs) -assert codecs == encodings.codecs -sys.modules['encodings'] = encodings - -class PosReturn: - # this can be used for configurable callbacks - - def __init__(self): - self.pos = 0 - - def handle(self, exc): - oldpos = self.pos - realpos = oldpos - if realpos<0: - realpos = len(exc.object) + realpos - # if we don't advance this time, terminate on the next call - # otherwise we'd get an endless loop - if realpos <= exc.start: - self.pos = len(exc.object) - return (u"", oldpos) - -class CodecCallbackTest(unittest.TestCase): - - def test_xmlcharrefreplace(self): - # replace unencodable characters which numeric character entities. - # For ascii, latin-1 and charmaps this is completely implemented - # in C and should be reasonably fast. - s = u"\u30b9\u30d1\u30e2 \xe4nd eggs" - self.assertEqual( - s.encode("ascii", "xmlcharrefreplace"), - "スパモ änd eggs" - ) - self.assertEqual( - s.encode("latin-1", "xmlcharrefreplace"), - "スパモ \xe4nd eggs" - ) - - def test_xmlcharnamereplace(self): - # This time use a named character entity for unencodable - # characters, if one is available. - - def xmlcharnamereplace(exc): - if not isinstance(exc, UnicodeEncodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [] - for c in exc.object[exc.start:exc.end]: - try: - l.append(u"&%s;" % htmlentitydefs.codepoint2name[ord(c)]) - except KeyError: - l.append(u"&#%d;" % ord(c)) - return (u"".join(l), exc.end) - - codecs.register_error( - "test.xmlcharnamereplace", xmlcharnamereplace) - - sin = u"\xab\u211c\xbb = \u2329\u1234\u20ac\u232a" - sout = "«ℜ» = ⟨ሴ€⟩" - self.assertEqual(codecs.encode(sin,"ascii", "test.xmlcharnamereplace"), sout) - sout = "\xabℜ\xbb = ⟨ሴ€⟩" - self.assertEqual(codecs.encode(sin,"latin-1", "test.xmlcharnamereplace"), sout) - sout = "\xabℜ\xbb = ⟨ሴ\xa4⟩" - self.assertEqual(codecs.encode(sin,"iso-8859-15", "test.xmlcharnamereplace"), sout) - - def test_uninamereplace(self): - # We're using the names from the unicode database this time, - # and we're doing "syntax highlighting" here, i.e. we include - # the replaced text in ANSI escape sequences. For this it is - # useful that the error handler is not called for every single - # unencodable character, but for a complete sequence of - # unencodable characters, otherwise we would output many - # unneccessary escape sequences. - - def uninamereplace(exc): - if not isinstance(exc, UnicodeEncodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [] - for c in exc.object[exc.start:exc.end]: - l.append(unicodedata.name(c, u"0x%x" % ord(c))) - return (u"\033[1m%s\033[0m" % u", ".join(l), exc.end) - - codecs.register_error( - "test.uninamereplace", uninamereplace) - - sin = u"\xac\u1234\u20ac\u8000" - sout = "\033[1mNOT SIGN, ETHIOPIC SYLLABLE SEE, EURO SIGN, CJK UNIFIED IDEOGRAPH-8000\033[0m" - self.assertEqual(codecs.encode(sin,"ascii", "test.uninamereplace"), sout) - - sout = "\xac\033[1mETHIOPIC SYLLABLE SEE, EURO SIGN, CJK UNIFIED IDEOGRAPH-8000\033[0m" - tout = codecs.encode(sin,"latin-1", "test.uninamereplace") - self.assertEqual(tout, sout) - sout = "\xac\033[1mETHIOPIC SYLLABLE SEE\033[0m\xa4\033[1mCJK UNIFIED IDEOGRAPH-8000\033[0m" - self.assertEqual(codecs.encode(sin,"iso-8859-15", "test.uninamereplace"), sout) - - def test_backslashescape(self): - # Does the same as the "unicode-escape" encoding, but with different - # base encodings. - sin = u"a\xac\u1234\u20ac\u8000" - if sys.maxunicode > 0xffff: - sin += unichr(sys.maxunicode) - sout = "a\\xac\\u1234\\u20ac\\u8000" - if sys.maxunicode > 0xffff: - sout += "\\U%08x" % sys.maxunicode - self.assertEqual(codecs.encode(sin,"ascii", "backslashreplace"), sout) - - sout = "a\xac\\u1234\\u20ac\\u8000" - if sys.maxunicode > 0xffff: - sout += "\\U%08x" % sys.maxunicode - self.assertEqual(codecs.encode(sin,"latin-1", "backslashreplace"), sout) - - sout = "a\xac\\u1234\xa4\\u8000" - if sys.maxunicode > 0xffff: - sout += "\\U%08x" % sys.maxunicode - self.assertEqual(codecs.encode(sin,"iso-8859-15", "backslashreplace"), sout) - - def test_relaxedutf8(self): - # This is the test for a decoding callback handler, - # that relaxes the UTF-8 minimal encoding restriction. - # A null byte that is encoded as "\xc0\x80" will be - # decoded as a null byte. All other illegal sequences - # will be handled strictly. - def relaxedutf8(exc): - if not isinstance(exc, UnicodeDecodeError): - raise TypeError("don't know how to handle %r" % exc) - if exc.object[exc.start:exc.end].startswith("\xc0\x80"): - return (u"\x00", exc.start+2) # retry after two bytes - else: - raise exc - - codecs.register_error( - "test.relaxedutf8", relaxedutf8) - - sin = "a\x00b\xc0\x80c\xc3\xbc\xc0\x80\xc0\x80" - sout = u"a\x00b\x00c\xfc\x00\x00" - self.assertEqual(codecs.decode(sin,"utf-8", "test.relaxedutf8"), sout) - sin = "\xc0\x80\xc0\x81" - self.assertRaises(UnicodeError, codecs.decode,sin, "utf-8", "test.relaxedutf8") - - def test_charmapencode(self): - # For charmap encodings the replacement string will be - # mapped through the encoding again. This means, that - # to be able to use e.g. the "replace" handler, the - # charmap has to have a mapping for "?". - charmap = dict([ (ord(c), 2*c.upper()) for c in "abcdefgh"]) - sin = u"abc" - sout = "AABBCC" - self.assertEquals(codecs.charmap_encode(sin, "strict", charmap)[0], sout) - - sin = u"abcA" - self.assertRaises(UnicodeError, codecs.charmap_encode, sin, "strict", charmap) - - charmap[ord("?")] = "XYZ" - sin = u"abcDEF" - sout = "AABBCCXYZXYZXYZ" - self.assertEquals(codecs.charmap_encode(sin, "replace", charmap)[0], sout) - - charmap[ord("?")] = u"XYZ" - self.assertRaises(TypeError, codecs.charmap_encode, sin, "replace", charmap) - - charmap[ord("?")] = u"XYZ" - self.assertRaises(TypeError, codecs.charmap_encode, sin, "replace", charmap) - - def test_callbacks(self): - def handler1(exc): - if not isinstance(exc, UnicodeEncodeError) \ - and not isinstance(exc, UnicodeDecodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [u"<%d>" % ord(exc.object[pos]) for pos in xrange(exc.start, exc.end)] - return (u"[%s]" % u"".join(l), exc.end) - - codecs.register_error("test.handler1", handler1) - - def handler2(exc): - if not isinstance(exc, UnicodeDecodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [u"<%d>" % ord(exc.object[pos]) for pos in xrange(exc.start, exc.end)] - return (u"[%s]" % u"".join(l), exc.end+1) # skip one character - - codecs.register_error("test.handler2", handler2) - - s = "\x00\x81\x7f\x80\xff" - - self.assertEqual( - codecs.decode(s,"ascii", "test.handler1"), - u"\x00[<129>]\x7f[<128>][<255>]" - ) - self.assertEqual( - codecs.decode(s,"ascii", "test.handler2"), - u"\x00[<129>][<128>]" - ) - - self.assertEqual( - codecs.decode("\\u3042\u3xxx","unicode-escape", "test.handler1"), - u"\u3042[<92><117><51><120>]xx" - ) - - self.assertEqual( - codecs.decode("\\u3042\u3xx","unicode-escape", "test.handler1"), - u"\u3042[<92><117><51><120><120>]" - ) - - self.assertEqual( - codecs.charmap_decode("abc", "test.handler1", {ord("a"): u"z"})[0], - u"z[<98>][<99>]" - ) - - self.assertEqual( - codecs.encode(u"g\xfc\xdfrk","ascii", "test.handler1"), - u"g[<252><223>]rk" - ) - - self.assertEqual( - codecs.encode(u"g\xfc\xdf","ascii", "test.handler1"), - u"g[<252><223>]" - ) - - def test_longstrings(self): - # test long strings to check for memory overflow problems - errors = [ "strict", "ignore", "replace", "xmlcharrefreplace", "backslashreplace"] - # register the handlers under different names, - # to prevent the codec from recognizing the name - for err in errors: - codecs.register_error("test." + err, codecs.lookup_error(err)) - l = 1000 - errors += [ "test." + err for err in errors ] - for uni in [ s*l for s in (u"x", u"\u3042", u"a\xe4") ]: - for enc in ("ascii", "latin-1", "iso-8859-1", "iso-8859-15", "utf-8", "utf-7", "utf-16"): - for err in errors: - try: - codecs.encode(uni,enc, err) - except UnicodeError: - pass - - def check_exceptionobjectargs(self, exctype, args, msg): - # Test UnicodeError subclasses: construction, attribute assignment and __str__ conversion - # check with one missing argument - self.assertRaises(TypeError, exctype, *args[:-1]) - # check with one argument too much - self.assertRaises(TypeError, exctype, *(args + ["too much"])) - # check with one argument of the wrong type - wrongargs = [ "spam", u"eggs", 42, 1.0, None ] - for i in xrange(len(args)): - for wrongarg in wrongargs: - if type(wrongarg) is type(args[i]): - continue - # build argument array - callargs = [] - for j in xrange(len(args)): - if i==j: - callargs.append(wrongarg) - else: - callargs.append(args[i]) - self.assertRaises(TypeError, exctype, *callargs) - - # check with the correct number and type of arguments - exc = exctype(*args) - self.assertEquals(str(exc), msg) - -## def test_unicodeencodeerror(self): -## self.check_exceptionobjectargs( -## UnicodeEncodeError, -## ["ascii", u"g\xfcrk", 1, 2, "ouch"], -## "'ascii' codec can't encode character u'\\xfc' in position 1: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeEncodeError, -## ["ascii", u"g\xfcrk", 1, 4, "ouch"], -## "'ascii' codec can't encode characters in position 1-3: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeEncodeError, -## ["ascii", u"\xfcx", 0, 1, "ouch"], -## "'ascii' codec can't encode character u'\\xfc' in position 0: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeEncodeError, -## ["ascii", u"\u0100x", 0, 1, "ouch"], -## "'ascii' codec can't encode character u'\\u0100' in position 0: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeEncodeError, -## ["ascii", u"\uffffx", 0, 1, "ouch"], -## "'ascii' codec can't encode character u'\\uffff' in position 0: ouch" -## ) -## if sys.maxunicode > 0xffff: -## self.check_exceptionobjectargs( -## UnicodeEncodeError, -## ["ascii", u"\U00010000x", 0, 1, "ouch"], -## "'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" -## ) -## -## def test_unicodedecodeerror(self): -## self.check_exceptionobjectargs( -## UnicodeDecodeError, -## ["ascii", "g\xfcrk", 1, 2, "ouch"], -## "'ascii' codec can't decode byte 0xfc in position 1: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeDecodeError, -## ["ascii", "g\xfcrk", 1, 3, "ouch"], -## "'ascii' codec can't decode bytes in position 1-2: ouch" -## ) -## -## def test_unicodetranslateerror(self): -## self.check_exceptionobjectargs( -## UnicodeTranslateError, -## [u"g\xfcrk", 1, 2, "ouch"], -## "can't translate character u'\\xfc' in position 1: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeTranslateError, -## [u"g\u0100rk", 1, 2, "ouch"], -## "can't translate character u'\\u0100' in position 1: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeTranslateError, -## [u"g\uffffrk", 1, 2, "ouch"], -## "can't translate character u'\\uffff' in position 1: ouch" -## ) -## if sys.maxunicode > 0xffff: -## self.check_exceptionobjectargs( -## UnicodeTranslateError, -## [u"g\U00010000rk", 1, 2, "ouch"], -## "can't translate character u'\\U00010000' in position 1: ouch" -## ) -## self.check_exceptionobjectargs( -## UnicodeTranslateError, -## [u"g\xfcrk", 1, 3, "ouch"], -## "can't translate characters in position 1-2: ouch" -## ) - - def test_badandgoodstrictexceptions(self): - # "strict" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.strict_errors, - 42 - ) - # "strict" complains about the wrong exception type - self.assertRaises( - Exception, - codecs.strict_errors, - Exception("ouch") - ) - - # If the correct exception is passed in, "strict" raises it - self.assertRaises( - UnicodeEncodeError, - codecs.strict_errors, - UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch") - ) - - def test_badandgoodignoreexceptions(self): - # "ignore" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.ignore_errors, - 42 - ) - # "ignore" complains about the wrong exception type - self.assertRaises( - TypeError, - codecs.ignore_errors, - UnicodeError("ouch") - ) - # If the correct exception is passed in, "ignore" returns an empty replacement - self.assertEquals( - codecs.ignore_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"", 1) - ) - self.assertEquals( - codecs.ignore_errors(UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch")), - (u"", 1) - ) - self.assertEquals( - codecs.ignore_errors(UnicodeTranslateError(u"\u3042", 0, 1, "ouch")), - (u"", 1) - ) - - def test_badandgoodreplaceexceptions(self): - # "replace" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.replace_errors, - 42 - ) - # "replace" complains about the wrong exception type - self.assertRaises( - TypeError, - codecs.replace_errors, - UnicodeError("ouch") - ) - # With the correct exception, "ignore" returns an empty replacement - self.assertEquals( - codecs.replace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"?", 1) - ) - self.assertEquals( - codecs.replace_errors(UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch")), - (u"\ufffd", 1) - ) - self.assertEquals( - codecs.replace_errors(UnicodeTranslateError(u"\u3042", 0, 1, "ouch")), - (u"\ufffd", 1) - ) - - def test_badandgoodxmlcharrefreplaceexceptions(self): - # "xmlcharrefreplace" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - 42 - ) - # "xmlcharrefreplace" complains about the wrong exception types - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - UnicodeError("ouch") - ) - # "xmlcharrefreplace" can only be used for encoding - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch") - ) - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - UnicodeTranslateError(u"\u3042", 0, 1, "ouch") - ) - # Use the correct exception - self.assertEquals( - codecs.xmlcharrefreplace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"&#%d;" % 0x3042, 1) - ) - - def test_badandgoodbackslashreplaceexceptions(self): - # "backslashreplace" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - 42 - ) - # "backslashreplace" complains about the wrong exception types - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - UnicodeError("ouch") - ) - # "backslashreplace" can only be used for encoding - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch") - ) - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - UnicodeTranslateError(u"\u3042", 0, 1, "ouch") - ) - # Use the correct exception - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"\\u3042", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\x00", 0, 1, "ouch")), - (u"\\x00", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\xff", 0, 1, "ouch")), - (u"\\xff", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\u0100", 0, 1, "ouch")), - (u"\\u0100", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\uffff", 0, 1, "ouch")), - (u"\\uffff", 1) - ) - if sys.maxunicode>0xffff: - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\U00010000", 0, 1, "ouch")), - (u"\\U00010000", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\U0010ffff", 0, 1, "ouch")), - (u"\\U0010ffff", 1) - ) - - def test_badhandlerresults(self): - results = ( 42, u"foo", (1,2,3), (u"foo", 1, 3), (u"foo", None), (u"foo",), ("foo", 1, 3), ("foo", None), ("foo",) ) - encs = ("ascii", "latin-1", "iso-8859-1", "iso-8859-15") - - for res in results: - codecs.register_error("test.badhandler", lambda: res) - for enc in encs: - self.assertRaises( - TypeError, - codecs.encode, - u"\u3042", - enc, - "test.badhandler" - ) - for (enc, bytes) in ( - ("ascii", "\xff"), - ("utf-8", "\xff"), - ("utf-7", "+x-") - ): - self.assertRaises( - TypeError, - codecs.decode, - bytes, - enc, - "test.badhandler" - ) - - def test_lookup(self): - self.assertEquals(codecs.strict_errors, codecs.lookup_error("strict")) - self.assertEquals(codecs.ignore_errors, codecs.lookup_error("ignore")) - self.assertEquals(codecs.strict_errors, codecs.lookup_error("strict")) - self.assertEquals( - codecs.xmlcharrefreplace_errors, - codecs.lookup_error("xmlcharrefreplace") - ) - self.assertEquals( - codecs.backslashreplace_errors, - codecs.lookup_error("backslashreplace") - ) - - def test_unencodablereplacement(self): - def unencrepl(exc): - if isinstance(exc, UnicodeEncodeError): - return (u"\u4242", exc.end) - else: - raise TypeError("don't know how to handle %r" % exc) - codecs.register_error("test.unencreplhandler", unencrepl) - for enc in ("ascii", "iso-8859-1", "iso-8859-15"): - self.assertRaises( - UnicodeEncodeError, - codecs.encode, - u"\u4242", - enc, - "test.unencreplhandler" - ) - - def test_badregistercall(self): - # enhance coverage of: - # Modules/_codecsmodule.c::register_error() - # Python/codecs.c::PyCodec_RegisterError() - self.assertRaises(TypeError, codecs.register_error, 42) - self.assertRaises(TypeError, codecs.register_error, "test.dummy", 42) - - def test_unknownhandler(self): - # enhance coverage of: - # Modules/_codecsmodule.c::lookup_error() - self.assertRaises(LookupError, codecs.lookup_error, "test.unknown") - - def test_xmlcharrefvalues(self): - # enhance coverage of: - # Python/codecs.c::PyCodec_XMLCharRefReplaceErrors() - # and inline implementations - v = (1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 50000) - if sys.maxunicode>=100000: - v += (100000, 500000, 1000000) - s = u"".join([unichr(x) for x in v]) - codecs.register_error("test.xmlcharrefreplace", codecs.xmlcharrefreplace_errors) - for enc in ("ascii", "iso-8859-15"): - for err in ("xmlcharrefreplace", "test.xmlcharrefreplace"): - codecs.encode(s,enc, err) - - def test_decodehelper(self): - # enhance coverage of: - # Objects/unicodeobject.c::unicode_decode_call_errorhandler() - # and callers - self.assertRaises(LookupError, codecs.decode,"\xff", "ascii", "test.unknown") - - def baddecodereturn1(exc): - return 42 - codecs.register_error("test.baddecodereturn1", baddecodereturn1) - self.assertRaises(TypeError, codecs.decode, "\xff", "ascii", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\x0", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\x0y", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\Uffffeeee", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\uyyyy", "raw-unicode-escape", "test.baddecodereturn1") - - def baddecodereturn2(exc): - return (u"?", None) - codecs.register_error("test.baddecodereturn2", baddecodereturn2) - self.assertRaises(TypeError, codecs.decode, "\xff", "ascii", "test.baddecodereturn2") - - handler = PosReturn() - codecs.register_error("test.posreturn", handler.handle) - - # Valid negative position - handler.pos = -1 - self.assertEquals(codecs.decode( "\xff0","ascii", "test.posreturn"), u"0") - - # Valid negative position - handler.pos = -2 - self.assertEquals(codecs.decode("\xff0","ascii", "test.posreturn"), u"") - - # Negative position out of bounds - handler.pos = -3 - self.assertRaises(IndexError, codecs.decode,"\xff0", "ascii", "test.posreturn") - - # Valid positive position - handler.pos = 1 - self.assertEquals(codecs.decode("\xff0","ascii", "test.posreturn"), u"0") - - # Largest valid positive position (one beyond end of input - handler.pos = 2 - self.assertEquals(codecs.decode("\xff0","ascii", "test.posreturn"), u"") - - # Invalid positive position - handler.pos = 3 - self.assertRaises(IndexError, codecs.decode,"\xff0", "ascii", "test.posreturn") - - # Restart at the "0" - handler.pos = 6 - self.assertEquals(codecs.decode("\\uyyyy0","raw-unicode-escape", "test.posreturn"), u"0") - - class D(dict): - def __getitem__(self, key): - raise ValueError - self.assertRaises(UnicodeError, codecs.charmap_decode, "\xff", "strict", {0xff: None}) - self.assertRaises(ValueError, codecs.charmap_decode, "\xff", "strict", D()) - self.assertRaises(TypeError, codecs.charmap_decode, "\xff", "strict", {0xff: sys.maxunicode+1}) - - def test_encodehelper(self): - # enhance coverage of: - # Objects/unicodeobject.c::unicode_encode_call_errorhandler() - # and callers - - self.assertRaises(LookupError, codecs.decode,u"\xff", "ascii", "test.unknown") - - def badencodereturn1(exc): - return 42 - codecs.register_error("test.badencodereturn1", badencodereturn1) - self.assertRaises(TypeError, codecs.decode, u"\xff", "ascii", "test.badencodereturn1") - - def badencodereturn2(exc): - return (u"?", None) - codecs.register_error("test.badencodereturn2", badencodereturn2) - self.assertRaises(TypeError, codecs.decode,u"\xff", "ascii", "test.badencodereturn2") - - handler = PosReturn() - codecs.register_error("test.posreturn", handler.handle) - - # Valid negative position - handler.pos = -1 - self.assertEquals(u"\xff0".encode("ascii", "test.posreturn"), "0") - - # Valid negative position - handler.pos = -2 - self.assertEquals(u"\xff0".encode("ascii", "test.posreturn"), "") - - # Negative position out of bounds - handler.pos = -3 - self.assertRaises(IndexError, u"\xff0".encode, "ascii", "test.posreturn") - - # Valid positive position - handler.pos = 1 - self.assertEquals(u"\xff0".encode("ascii", "test.posreturn"), "0") - - # Largest valid positive position (one beyond end of input - handler.pos = 2 - self.assertEquals(u"\xff0".encode("ascii", "test.posreturn"), "") - - # Invalid positive position - handler.pos = 3 - self.assertRaises(IndexError, u"\xff0".encode, "ascii", "test.posreturn") - - handler.pos = 0 - - class D(dict): - def __getitem__(self, key): - raise ValueError - for err in ("strict", "replace", "xmlcharrefreplace", "backslashreplace", "test.posreturn"): - self.assertRaises(UnicodeError, codecs.charmap_encode, u"\xff", err, {0xff: None}) - self.assertRaises(ValueError, codecs.charmap_encode, u"\xff", err, D()) - self.assertRaises(TypeError, codecs.charmap_encode, u"\xff", err, {0xff: 300}) - - def test_translatehelper(self): - # enhance coverage of: - # Objects/unicodeobject.c::unicode_encode_call_errorhandler() - # and callers - # (Unfortunately the errors argument is not directly accessible - # from Python, so we can't test that much) - class D(dict): - def __getitem__(self, key): - raise ValueError - self.assertRaises(ValueError, u"\xff".translate, D()) - self.assertRaises(TypeError, u"\xff".translate, {0xff: sys.maxunicode+1}) - self.assertRaises(TypeError, u"\xff".translate, {0xff: ()}) - - def test_bug828737(self): - charmap = { - ord("&"): u"&", - ord("<"): u"<", - ord(">"): u">", - ord('"'): u""", - } - - for n in (1, 10, 100, 1000): - text = u'abcghi'*n - text.translate(charmap) - -def test_main(): - test.test_support.run_unittest(CodecCallbackTest) - -if __name__ == "__main__": - test_main() Modified: pypy/dist/pypy/lib/unicodecodec.py ============================================================================== --- pypy/dist/pypy/lib/unicodecodec.py (original) +++ pypy/dist/pypy/lib/unicodecodec.py Sun Jun 5 22:59:23 2005 @@ -83,7 +83,7 @@ ## charvalue += ord(c) while (bits >= 6): out += B64(ch >> (bits-6)) - bits -= 6; + bits -= 6 return out,bits @@ -250,21 +250,21 @@ unicode_empty=u'' -def PyUnicode_Decode(s,size,encoding,errors): - - if (encoding == None): - encoding = PyUnicode_GetDefaultEncoding() - -## /* Shortcuts for common default encodings */ - decoder = encodings.get(encoding,None) - if decoder: - return decoder(s,encoding,errors) -## /* Decode via the codec registry */ - buf = buffer(s) - result = PyCodec_Decode(buf, encoding, errors); - if (not isinstance(result,unicode)): - raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result) - return result +##def PyUnicode_Decode(s,size,encoding,errors): +## +## if (encoding == None): +## encoding = PyUnicode_GetDefaultEncoding() +## +#### /* Shortcuts for common default encodings */ +## decoder = encodings.get(encoding,None) +## if decoder: +## return decoder(s,encoding,errors) +#### /* Decode via the codec registry */ +## buf = buffer(s) +## result = PyCodec_Decode(buf, encoding, errors) +## if (not isinstance(result,unicode)): +## raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result) +## return result def unicodeescape_string(s, size, quotes): @@ -336,7 +336,7 @@ p += '%02x'%ord(ch) #/* Copy everything else as-is */ else: - p += ch + p += chr(ord(ch)) pos += 1 if (quotes): p += p[1] @@ -439,7 +439,7 @@ if (len(s)-q<2): if (consumed): break - errmsg = "truncated data"; + errmsg = "truncated data" startinpos = q endinpos = len(s) unicode_call_errorhandler() @@ -455,7 +455,7 @@ #/* UTF-16 code pair: */ if (q >= len(s)): - errmsg = "unexpected end of data"; + errmsg = "unexpected end of data" startinpos = q-2 endinpos = len(s) unicode_call_errorhandler @@ -474,12 +474,12 @@ continue else: - errmsg = "illegal UTF-16 surrogate"; + errmsg = "illegal UTF-16 surrogate" startinpos = q-4 endinpos = startinpos+2 unicode_call_errorhandler - errmsg = "illegal encoding"; + errmsg = "illegal encoding" startinpos = q-2 endinpos = startinpos+2 unicode_call_errorhandler @@ -570,7 +570,7 @@ def PyUnicode_DecodeUTF8(s, size, errors): - return PyUnicode_DecodeUTF8Stateful(s, size, errors, None); + return PyUnicode_DecodeUTF8Stateful(s, size, errors, None) ## /* Map UTF-8 encoded prefix byte to sequence length. zero means ## illegal prefix. see RFC 2279 for details */ @@ -732,7 +732,7 @@ else: ## /* compute and append the two surrogates: */ ## /* translate from 10000..10FFFF to 0..FFFF */ - c -= 0x10000; + c -= 0x10000 #/* high surrogate = top 10 bits added to D800 */ p += unichr(0xD800 + (c >> 10)) #/* low surrogate = bottom 10 bits added to DC00 */ @@ -741,7 +741,7 @@ else: ## default: ## /* Other sizes are only needed for UCS-4 */ - errmsg = "unsupported Unicode code range"; + errmsg = "unsupported Unicode code range" startinpos = pos endinpos = startinpos+n res = unicode_call_errorhandler( @@ -910,7 +910,7 @@ errmessage = "\\ at end of string" unicode_call_errorhandler(errors,"unicodeescape",errmessage,s,pos-1,size) ch = s[pos] - + pos += 1 ## /* \x escapes */ #if ch == '\n': break; if ch == '\\': p += '\\' @@ -920,50 +920,52 @@ elif ch == 'f': p += '\014' #/* FF */ elif ch == 't': p += '\t' elif ch == 'n': p += '\n' - elif ch == 'r': p += '\r' + elif ch == 'r': + p += '\r' + elif ch == 'v': p += '\013' #break; /* VT */ elif ch == 'a': p += '\007' # break; /* BEL, not classic C */ ## /* \OOO (octal) escapes */ elif ch in [ '0','1', '2', '3','4', '5', '6','7']: x = ord(ch) - ord('0') - ch = s[pos+1] + ch = s[pos] if ('0' <= ch and ch <= '7'): x = (x<<3) + ord(ch) - ord('0') - ch = s[pos+2] + ch = s[pos+1] if ('0' <= ch and ch <= '7'): x = (x<<3) + ord(ch) - ord('0') - pos += 3 + pos += 2 p += unichr(x) ## /* hex escapes */ ## /* \xXX */ elif ch == 'x': - digits = 2; - message = "truncated \\xXX escape"; - x = hexescape(s,pos+1,digits,message,errors) + digits = 2 + message = "truncated \\xXX escape" + x = hexescape(s,pos,digits,message,errors) p += x[0] pos = x[1] # /* \uXXXX */ elif ch == 'u': - digits = 4; - message = "truncated \\uXXXX escape"; - x = hexescape(s,pos+1,digits,message,errors) + digits = 4 + message = "truncated \\uXXXX escape" + x = hexescape(s,pos,digits,message,errors) p += x[0] pos = x[1] # /* \UXXXXXXXX */ elif ch == 'U': digits = 8 - message = "truncated \\UXXXXXXXX escape"; - x = hexescape(s,pos+1,digits,message,errors) + message = "truncated \\UXXXXXXXX escape" + x = hexescape(s,pos,digits,message,errors) p += x[0] pos = x[1] ## /* \N{name} */ elif ch == 'N': message = "malformed \\N character escape" - pos += 1 + #pos += 1 try: import unicodedata except ImportError: @@ -1138,7 +1140,7 @@ bs = pos while pos < size: if (s[pos] != '\\'): - break; + break p += unichr(ord(s[pos])) pos += 1 From ale at codespeak.net Sun Jun 5 23:01:37 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sun, 5 Jun 2005 23:01:37 +0200 (CEST) Subject: [pypy-svn] r13083 - pypy/dist/pypy/module/_codecs Message-ID: <20050605210137.C48A627B51@code1.codespeak.net> Author: ale Date: Sun Jun 5 23:01:35 2005 New Revision: 13083 Added: pypy/dist/pypy/module/_codecs/ pypy/dist/pypy/module/_codecs/__init__.py - copied, changed from r13051, pypy/dist/pypy/module/unicodedata/__init__.py pypy/dist/pypy/module/_codecs/app_codecs.py - copied, changed from r13073, pypy/dist/pypy/lib/inprogress__codecs.py Log: The beginings of making _codecs a builtin module. Seems to work (but it is marked NOT_RPYTHON so it is kind of fake) Copied: pypy/dist/pypy/module/_codecs/__init__.py (from r13051, pypy/dist/pypy/module/unicodedata/__init__.py) ============================================================================== --- pypy/dist/pypy/module/unicodedata/__init__.py (original) +++ pypy/dist/pypy/module/_codecs/__init__.py Sun Jun 5 23:01:35 2005 @@ -2,19 +2,41 @@ class Module(MixedModule): appleveldefs = { + '__doc__' : 'app_codecs.__doc__', + '__name__' : 'app_codecs.__name__', + 'ascii_decode' : 'app_codecs.ascii_decode', + 'ascii_encode' : 'app_codecs.ascii_encode', + 'charbuffer_encode' : 'app_codecs.charbuffer_encode', + 'charmap_decode' : 'app_codecs.charmap_decode', + 'charmap_encode' : 'app_codecs.charmap_encode', + 'escape_decode' : 'app_codecs.escape_decode', + 'escape_encode' : 'app_codecs.escape_encode', + 'latin_1_decode' : 'app_codecs.latin_1_decode', + 'latin_1_encode' : 'app_codecs.latin_1_encode', + 'lookup' : 'app_codecs.lookup', + 'lookup_error' : 'app_codecs.lookup_error', + 'mbcs_decode' : 'app_codecs.mbcs_decode', + 'mbcs_encode' : 'app_codecs.mbcs_encode', + 'raw_unicode_escape_decode' : 'app_codecs.raw_unicode_escape_decode', + 'raw_unicode_escape_encode' : 'app_codecs.raw_unicode_escape_encode', + 'readbuffer_encode' : 'app_codecs.readbuffer_encode', + 'register' : 'app_codecs.register', + 'register_error' : 'app_codecs.register_error', + 'unicode_escape_decode' : 'app_codecs.unicode_escape_decode', + 'unicode_escape_encode' : 'app_codecs.unicode_escape_encode', + 'unicode_internal_decode' : 'app_codecs.unicode_internal_decode', + 'unicode_internal_encode' : 'app_codecs.unicode_internal_encode', + 'utf_16_be_decode' : 'app_codecs.utf_16_be_decode', + 'utf_16_be_encode' : 'app_codecs.utf_16_be_encode', + 'utf_16_decode' : 'app_codecs.utf_16_decode', + 'utf_16_encode' : 'app_codecs.utf_16_encode', + 'utf_16_ex_decode' : 'app_codecs.utf_16_ex_decode', + 'utf_16_le_decode' : 'app_codecs.utf_16_le_decode', + 'utf_16_le_encode' : 'app_codecs.utf_16_le_encode', + 'utf_7_decode' : 'app_codecs.utf_7_decode', + 'utf_7_encode' : 'app_codecs.utf_7_encode', + 'utf_8_decode' : 'app_codecs.utf_8_decode', + 'utf_8_encode' : 'app_codecs.utf_8_encode', } interpleveldefs = { - 'lookup' : 'function.lookup', - 'name' : 'function.name', - 'decimal' : 'function.decimal', - 'digit' : 'function.digit', - 'numeric' : 'function.numeric', - 'category' : 'function.category', - 'bidirectional' : 'function.bidirectional', - 'combining' : 'function.combining', - 'mirrored' : 'function.mirrored', - 'decomposition' : 'function.decomposition', - 'normalize' : 'function.normalize', - 'unidata_version' : 'space.wrap(unicodedb.version)', - '__doc__' : "space.wrap('unicode character database')", } Copied: pypy/dist/pypy/module/_codecs/app_codecs.py (from r13073, pypy/dist/pypy/lib/inprogress__codecs.py) ============================================================================== --- pypy/dist/pypy/lib/inprogress__codecs.py (original) +++ pypy/dist/pypy/module/_codecs/app_codecs.py Sun Jun 5 23:01:35 2005 @@ -1,3 +1,4 @@ +"NOT_RPYTHON" """ _codecs -- Provides access to the codec registry and the builtin @@ -34,10 +35,12 @@ Copyright (c) Corporation for National Research Initiatives. """ -from unicodecodec import * +#from unicodecodec import * +import sys #/* --- Registry ----------------------------------------------------------- */ codec_search_path = [] codec_search_cache = {} +codec_error_registry = {} def codec_register( search_function ): """register(search_function) @@ -114,7 +117,7 @@ if isinstance(encoding,str): decoder = lookup(encoding)[1] if decoder and isinstance(errors,str): - res = decoder(v,errors) + res = decoder(obj,errors) if not isinstance(res,tuple) or len(res) != 2: raise TypeError("encoder must return a tuple (object,integer)") return res[0] @@ -227,7 +230,8 @@ res = ''.join(p) return res, len(res) else: - return ''.join(PyUnicode_FromUnicode(obj,size),size) + res = "You can do better than this" # XXX make this right + return res,len(res) def unicode_internal_decode( unistr,errors='strict'): """None @@ -241,7 +245,7 @@ t = 0 for j in range(unicode_bytes): t += ord(unistr[i+j])<<(j*8) - i += j+1 + i += unicode_bytes p += unichr(t) res = u''.join(p) return res, len(res) @@ -283,11 +287,12 @@ def mbcs_encode( obj,errors='strict'): """None """ - return (PyUnicode_EncodeMBCS( - PyUnicode_AS_UNICODE(obj), - PyUnicode_GET_SIZE(obj), - errors), - PyUnicode_GET_SIZE(obj)); + pass +## return (PyUnicode_EncodeMBCS( +## (obj), +## len(obj), +## errors), +## len(obj)) def ascii_encode( obj,errors='strict'): @@ -398,8 +403,1208 @@ else: raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) + +# ---------------------------------------------------------------------- + +##import sys +##""" Python implementation of CPythons builtin unicode codecs. +## +## Generally the functions in this module take a list of characters an returns +## a list of characters. +## +## For use in the PyPy project""" + + +## indicate whether a UTF-7 character is special i.e. cannot be directly +## encoded: +## 0 - not special +## 1 - special +## 2 - whitespace (optional) +## 3 - RFC2152 Set O (optional) + +utf7_special = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, +] +unicode_latin1=[None]*256 + + +def lookup_error(errors): + """lookup_error(errors) -> handler + + Return the error handler for the specified error handling name + or raise a LookupError, if no handler exists under this name. + """ + + try: + err_handler = codec_error_registry[errors] + except KeyError: + raise LookupError("unknown error handler name %s"%errors) + return err_handler + +def register_error(errors, handler): + """register_error(errors, handler) + + Register the specified error handler under the name + errors. handler must be a callable object, that + will be called with an exception instance containing + information about the location of the encoding/decoding + error and must return a (replacement, new position) tuple. + """ + if callable(handler): + codec_error_registry[errors] = handler + else: + raise TypeError("handler must be callable") + register_error("strict",strict_errors) register_error("ignore",ignore_errors) register_error("replace",replace_errors) register_error("xmlcharrefreplace",xmlcharrefreplace_errors) -register_error("backslashreplace",backslashreplace_errors) \ No newline at end of file +register_error("backslashreplace",backslashreplace_errors) + +def SPECIAL(c, encodeO, encodeWS): + c = ord(c) + return (c>127 or utf7_special[c] == 1) or \ + (encodeWS and (utf7_special[(c)] == 2)) or \ + (encodeO and (utf7_special[(c)] == 3)) +def B64(n): + return ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f]) +def B64CHAR(c): + return (c.isalnum() or (c) == '+' or (c) == '/') +def UB64(c): + if (c) == '+' : + return 62 + elif (c) == '/': + return 63 + elif (c) >= 'a': + return ord(c) - 71 + elif (c) >= 'A': + return ord(c) - 65 + else: + return ord(c) + 4 + +def ENCODE( ch, bits) : + charvalue = 0 + out = [] +## for c in ch: +## charvalue <<= 16 +## charvalue += ord(c) + while (bits >= 6): + out += B64(ch >> (bits-6)) + bits -= 6 + return out,bits + + +def PyUnicode_DecodeUTF7(s, size, errors): + + starts = s + errmsg = "" + inShift = 0 + bitsleft = 0 + charsleft = 0 + surrogate = 0 + p = [] + errorHandler = None + exc = None + + if (size == 0): + return unicode('') + i = 0 + while i < size: + + ch = s[i] + if (inShift): + if ((ch == '-') or not B64CHAR(ch)): + inShift = 0 + i += 1 + + while (bitsleft >= 16): + outCh = ((charsleft) >> (bitsleft-16)) & 0xffff + bitsleft -= 16 + + if (surrogate): + ## We have already generated an error for the high surrogate + ## so let's not bother seeing if the low surrogate is correct or not + surrogate = 0 + elif (0xDC00 <= (outCh) and (outCh) <= 0xDFFF): + ## This is a surrogate pair. Unfortunately we can't represent + ## it in a 16-bit character + surrogate = 1 + msg = "code pairs are not supported" + out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i) + p += out + bitsleft = 0 + break + else: + p += unichr(outCh ) + #p += out + if (bitsleft >= 6): +## /* The shift sequence has a partial character in it. If +## bitsleft < 6 then we could just classify it as padding +## but that is not the case here */ + msg = "partial character in shift sequence" + out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i) + +## /* According to RFC2152 the remaining bits should be zero. We +## choose to signal an error/insert a replacement character +## here so indicate the potential of a misencoded character. */ + +## /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */ +## if (bitsleft and (charsleft << (sizeof(charsleft) * 8 - bitsleft))): +## raise UnicodeDecodeError, "non-zero padding bits in shift sequence" + if (ch == '-') : + if ((i < size) and (s[i] == '-')) : + p += '-' + inShift = 1 + + elif SPECIAL(ch,0,0) : + raise UnicodeDecodeError,"unexpected special character" + + else: + p += ch + else: + charsleft = (charsleft << 6) | UB64(ch) + bitsleft += 6 + i+=1 +## /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate); + elif ( ch == '+' ): + startinpos = i + i+=1 + if (i 0 + else: + out += chr(ord(ch)) + else: + if (not SPECIAL(ch, encodeSetO, encodeWhiteSpace)): + out += B64((charsleft) << (6-bitsleft)) + charsleft = 0 + bitsleft = 0 +## /* Characters not in the BASE64 set implicitly unshift the sequence +## so no '-' is required, except if the character is itself a '-' */ + if (B64CHAR(ch) or ch == '-'): + out += '-' + inShift = False + out += chr(ord(ch)) + else: + bitsleft += 16 + charsleft = (((charsleft) << 16) | ord(ch)) + p, bitsleft = ENCODE(charsleft, bitsleft) + out += p +## /* If the next character is special then we dont' need to terminate +## the shift sequence. If the next character is not a BASE64 character +## or '-' then the shift sequence will be terminated implicitly and we +## don't have to insert a '-'. */ + + if (bitsleft == 0): + if (i + 1 < size): + ch2 = s[i+1] + + if (SPECIAL(ch2, encodeSetO, encodeWhiteSpace)): + pass + elif (B64CHAR(ch2) or ch2 == '-'): + out += '-' + inShift = False + else: + inShift = False + else: + out += '-' + inShift = False + i+=1 + + if (bitsleft): + out += B64(charsleft << (6-bitsleft) ) + out += '-' + + return out + +unicode_empty=u'' + +##def PyUnicode_Decode(s,size,encoding,errors): +## +## if (encoding == None): +## encoding = PyUnicode_GetDefaultEncoding() +## +#### /* Shortcuts for common default encodings */ +## decoder = encodings.get(encoding,None) +## if decoder: +## return decoder(s,encoding,errors) +#### /* Decode via the codec registry */ +## buf = buffer(s) +## result = PyCodec_Decode(buf, encoding, errors) +## if (not isinstance(result,unicode)): +## raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result) +## return result + +def unicodeescape_string(s, size, quotes): + + p = [] + if (quotes) : + p += 'u' + if (s.find('\'')!=-1 and s.find('"')==-1): + p += '"' + else: + p += '\'' + pos = 0 + while (pos < size): + ch = s[pos] + #/* Escape quotes */ + if (quotes and (ch == p[1] or ch == '\\')): + p += '\\' + p += ch + pos += 1 + continue + +#ifdef Py_UNICODE_WIDE + #/* Map 21-bit characters to '\U00xxxxxx' */ + elif (ord(ch) >= 0x10000): + p += '\\' + p += 'U' + p += '%08x'%ord(ch) + pos += 1 + continue +#endif + #/* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */ + elif (ord(ch) >= 0xD800 and ord(ch) < 0xDC00): + pos += 1 + ch2 = s[pos] + + if (ord(ch2) >= 0xDC00 and ord(ch2) <= 0xDFFF): + ucs = (((ord(ch) & 0x03FF) << 10) | (ord(ch2) & 0x03FF)) + 0x00010000 + p += '\\' + p += 'U' + p += '%08x'%ucs + pos += 1 + continue + + #/* Fall through: isolated surrogates are copied as-is */ + pos -= 1 + + #/* Map 16-bit characters to '\uxxxx' */ + if (ord(ch) >= 256): + p += '\\' + p += 'u' + p += '%04x'%ord(ch) + + #/* Map special whitespace to '\t', \n', '\r' */ + elif (ch == '\t'): + p += '\\' + p += 't' + + elif (ch == '\n'): + p += '\\' + p += 'n' + + elif (ch == '\r'): + p += '\\' + p += 'r' + + #/* Map non-printable US ASCII to '\xhh' */ + elif (ch < ' ' or ch >= 0x7F) : + p += '\\' + p += 'x' + p += '%02x'%ord(ch) + #/* Copy everything else as-is */ + else: + p += chr(ord(ch)) + pos += 1 + if (quotes): + p += p[1] + return p + +def PyUnicode_DecodeASCII(s, size, errors): + +# /* ASCII is equivalent to the first 128 ordinals in Unicode. */ + if (size == 1 and ord(s) < 128) : + return [unichr(ord(s))] + if (size == 0): + return [u''] #unicode('') + p = [] + pos = 0 + while pos < len(s): + c = s[pos] + if ord(c) < 128: + p += unichr(ord(c)) + pos += 1 + else: + + res = unicode_call_errorhandler( + errors, "ascii", "ordinal not in range(128)", + s, pos, pos+1) + p += [unichr(ord(x)) for x in res[0]] + pos = res[1] + return p + +def PyUnicode_EncodeASCII(p,size,errors): + + return unicode_encode_ucs1(p, size, errors, 128) + +def PyUnicode_AsASCIIString(unistr): + + if not type(unistr) == unicode: + raise TypeError + return PyUnicode_EncodeASCII(unicode(unistr), + len(unicode), + None) + +def PyUnicode_DecodeUTF16Stateful(s,size,errors,byteorder='native',consumed=None): + + bo = 0 #/* assume native ordering by default */ + errmsg = "" + + if sys.byteorder == 'little': + ihi = 1 + ilo = 0 + else: + ihi = 0 + ilo = 1 + + if (size == 0): + return [u''] + + #/* Unpack UTF-16 encoded data */ + +## /* Check for BOM marks (U+FEFF) in the input and adjust current +## byte order setting accordingly. In native mode, the leading BOM +## mark is skipped, in all other modes, it is copied to the output +## stream as-is (giving a ZWNBSP character). */ + q = 0 + p = [] + if byteorder == 'native': + if (size >= 2): + bom = (ord(s[ihi]) << 8) | ord(s[ilo]) +#ifdef BYTEORDER_IS_LITTLE_ENDIAN + if sys.byteorder == 'little': + if (bom == 0xFEFF): + q += 2 + bo = -1 + elif bom == 0xFFFE: + q += 2 + bo = 1 + else: + if bom == 0xFEFF: + q += 2 + bo = 1 + elif bom == 0xFFFE: + q += 2 + bo = -1 + elif byteorder == 'little': + bo = -1 + else: + bo = 1 + + if (bo == -1): + #/* force LE */ + ihi = 1 + ilo = 0 + + elif (bo == 1): + #/* force BE */ + ihi = 0 + ilo = 1 + + while (q < len(s)): + + #/* remaining bytes at the end? (size should be even) */ + if (len(s)-q<2): + if (consumed): + break + errmsg = "truncated data" + startinpos = q + endinpos = len(s) + unicode_call_errorhandler() +## /* The remaining input chars are ignored if the callback +## chooses to skip the input */ + + ch = (ord(s[q+ihi]) << 8) | ord(s[q+ilo]) + q += 2 + + if (ch < 0xD800 or ch > 0xDFFF): + p += unichr(ch) + continue + + #/* UTF-16 code pair: */ + if (q >= len(s)): + errmsg = "unexpected end of data" + startinpos = q-2 + endinpos = len(s) + unicode_call_errorhandler + + if (0xD800 <= ch and ch <= 0xDBFF): + ch2 = (ord(s[q+ihi]) << 8) | ord(s[q+ilo]) + q += 2 + if (0xDC00 <= ch2 and ch2 <= 0xDFFF): + #ifndef Py_UNICODE_WIDE + if sys.maxunicode < 65536: + p += unichr(ch) + p += unichr(ch2) + else: + p += unichr((((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000) + #endif + continue + + else: + errmsg = "illegal UTF-16 surrogate" + startinpos = q-4 + endinpos = startinpos+2 + unicode_call_errorhandler + + errmsg = "illegal encoding" + startinpos = q-2 + endinpos = startinpos+2 + unicode_call_errorhandler + + return p + +def PyUnicode_EncodeUTF16(s,size,errors,byteorder='little'): + +# /* Offsets from p for storing byte pairs in the right order. */ + + def STORECHAR(CH,byteorder): + hi = chr(((CH) >> 8) & 0xff) + lo = chr((CH) & 0xff) + if byteorder == 'little': + return [lo,hi] + else: + return [hi,lo] + + p = [] + bom = sys.byteorder + if (byteorder == 'native'): + + bom = sys.byteorder + p += STORECHAR(0xFEFF,bom) + + if (size == 0): + return "" + + if (byteorder == 'little' ): + bom = 'little' + elif (byteorder == 'big'): + bom = 'big' + + + for c in s: + ch = ord(c) + ch2 = 0 + if (ch >= 0x10000) : + ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF) + ch = 0xD800 | ((ch-0x10000) >> 10) + + p += STORECHAR(ch,bom) + if (ch2): + p +=STORECHAR(ch2,bom) + + return p + + +def PyUnicode_DecodeMBCS(s, size, errors): + pass + +def PyUnicode_EncodeMBCS(p, size, errors): + pass +#### /* If there are no characters, bail now! */ +## if (size==0) +## return "" +## from ctypes import * +## WideCharToMultiByte = windll.kernel32.WideCharToMultiByte +#### /* First get the size of the result */ +## mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, s, 0, None, None); +## if (mbcssize==0) +## raise UnicodeEncodeError, "Windows cannot decode the string %s" %p +### More error handling required (check windows errors and such) +## +### /* Do the conversion */ +#### s = ' '*mbcssize +#### if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)): +#### raise UnicodeEncodeError, "Windows cannot decode the string %s" %p +## return s +def unicode_call_errorhandler(errors, encoding, + reason, input, startinpos, endinpos,decode=True): + + errorHandler = lookup_error(errors) + if decode: + exceptionObject = UnicodeDecodeError(encoding, input, startinpos, endinpos, reason) + else: + exceptionObject = UnicodeEncodeError(encoding, input, startinpos, endinpos, reason) + res = errorHandler(exceptionObject) + if isinstance(res,tuple) and isinstance(res[0],unicode) and isinstance(res[1],int): + newpos = res[1] + if (newpos<0): + newpos = len(input)+newpos + if newpos<0 or newpos>len(input): + raise IndexError( "position %d from error handler out of bounds" % newpos) + return res[0],newpos + else: + raise TypeError("encoding error handler must return (unicode, int) tuple") + +def PyUnicode_DecodeUTF8(s, size, errors): + + return PyUnicode_DecodeUTF8Stateful(s, size, errors, None) + +## /* Map UTF-8 encoded prefix byte to sequence length. zero means +## illegal prefix. see RFC 2279 for details */ +utf8_code_length = [ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 +] + +def PyUnicode_DecodeUTF8Stateful(s,size,errors,consumed): + + if (size == 0): + if (consumed): + consumed = 0 + return u'' + + p = [] + pos = 0 + while pos < size: + ch = s[pos] + if ord(ch) < 0x80: + p += ch + pos += 1 + continue + + n = utf8_code_length[ord(ch)] + startinpos = pos + if (startinpos + n > size): + if (consumed): + break + else: + errmsg = "unexpected end of data" + endinpos = size + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + if n == 0: + errmsg = "unexpected code byte" + endinpos = startinpos+1 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + elif n == 1: + errmsg = "internal error" + endinpos = startinpos+1 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + elif n == 2: + if ((ord(s[pos+1]) & 0xc0) != 0x80): + errmsg = "invalid data" + endinpos = startinpos+2 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + else: + c = ((ord(s[pos]) & 0x1f) << 6) + (ord(s[pos+1]) & 0x3f) + if c<0x80: + errmsg = "illegal encoding" + endinpos = startinpos+2 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + else: + p += unichr(c) + pos += n + #break + elif n == 3: + if ((ord(s[pos+1]) & 0xc0) != 0x80 or + (ord(s[pos+2]) & 0xc0) != 0x80): + errmsg = "invalid data" + endinpos = startinpos+3 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + else: + c = ((ord(s[pos]) & 0x0f) << 12) + \ + ((ord(s[pos+1]) & 0x3f) << 6) +\ + (ord(s[pos+2]) & 0x3f) + +## /* Note: UTF-8 encodings of surrogates are considered +## legal UTF-8 sequences; +## +## XXX For wide builds (UCS-4) we should probably try +## to recombine the surrogates into a single code +## unit. +## */ + if c < 0x0800: + errmsg = "illegal encoding" + endinpos = startinpos+3 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + else: + p += unichr(c) + pos += n + elif n == 4: +## case 4: + if ((ord(s[pos+1]) & 0xc0) != 0x80 or + (ord(s[pos+2]) & 0xc0) != 0x80 or + (ord(s[pos+3]) & 0xc0) != 0x80): + + errmsg = "invalid data" + startinpos = pos + endinpos = startinpos+4 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + else: + c = ((ord(s[pos+0]) & 0x7) << 18) + ((ord(s[pos+1]) & 0x3f) << 12) +\ + ((ord(s[pos+2]) & 0x3f) << 6) + (ord(s[pos+3]) & 0x3f) + #/* validate and convert to UTF-16 */ + if ((c < 0x10000) or (c > 0x10ffff)): + #/* minimum value allowed for 4 byte encoding */ + #/* maximum value allowed for UTF-16 */ + + errmsg = "illegal encoding" + startinpos = pos + endinpos = startinpos+4 + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + else: +#ifdef Py_UNICODE_WIDE + if c> 10)) + #/* low surrogate = bottom 10 bits added to DC00 */ + p += unichr(0xDC00 + (c & 0x03FF)) + pos += n + else: +## default: +## /* Other sizes are only needed for UCS-4 */ + errmsg = "unsupported Unicode code range" + startinpos = pos + endinpos = startinpos+n + res = unicode_call_errorhandler( + errors, "utf8", errmsg, + s, startinpos, endinpos) + p += res[0] + pos = res[1] + + #continue + + if (consumed): + consumed = pos + return p + +def PyUnicode_EncodeUTF8(s,size,errors): + + #assert(s != None) + assert(size >= 0) + p = [] + i = 0 + while i> 6))) + p += chr((0x80 | (ord(ch) & 0x3f))) + else: +## /* Encode UCS2 Unicode ordinals */ + if (ord(ch) < 0x10000): +## /* Special case: check for high surrogate */ + if (0xD800 <=ord(ch) and ord(ch) <= 0xDBFF and i != size) : + ch2 = s[i] +## /* Check for low surrogate and combine the two to +## form a UCS4 value */ + if (0xDC00 <= ord(ch2) and ord(ch2) <= 0xDFFF) : + ch3 = ((ord(ch) - 0xD800) << 10 | (ord(ch2) - 0xDC00)) + 0x10000 + i+=1 + p.extend(encodeUCS4(ch3)) + continue +## /* Fall through: handles isolated high surrogates */ + p += (chr((0xe0 | (ord(ch) >> 12)))) + p += (chr((0x80 | ((ord(ch) >> 6) & 0x3f)))) + p += (chr((0x80 | (ord(ch) & 0x3f)))) + continue + return p + +def encodeUCS4(ch): +## /* Encode UCS4 Unicode ordinals */ + p=[] + p += (chr((0xf0 | (ch >> 18)))) + p += (chr((0x80 | ((ch >> 12) & 0x3f)))) + p += (chr((0x80 | ((ch >> 6) & 0x3f)))) + p += (chr((0x80 | (ch & 0x3f)))) + return p + +#/* --- Latin-1 Codec ------------------------------------------------------ */ + +def PyUnicode_DecodeLatin1(s, size, errors): + #/* Latin-1 is equivalent to the first 256 ordinals in Unicode. */ +## if (size == 1): +## return [PyUnicode_FromUnicode(s, 1)] + pos = 0 + p = [] + while (pos < size): + p += unichr(ord(s[pos])) + pos += 1 + return p + +def unicode_encode_ucs1(p,size,errors,limit): + + if limit == 256: + reason = "ordinal not in range(256)" + encoding = "latin-1" + else: + reason = "ordinal not in range(128)" + encoding = "ascii" + + if (size == 0): + return [''] + res = [] + pos=0 + while pos < len(p): + #for ch in p: + ch = p[pos] + + if ord(ch) < limit: + res += chr(ord(ch)) + pos += 1 + else: + #/* startpos for collecting unencodable chars */ + collstart = pos + collend = pos+1 + while collend < len(p) and ord(p[collend]) >= limit: + collend += 1 + x = unicode_call_errorhandler(errors,encoding,reason,p,collstart,collend,False) + res += str(x[0]) + pos = x[1] + + return res + +def PyUnicode_EncodeLatin1(p,size,errors): + res=unicode_encode_ucs1(p, size, errors, 256) + return res + +hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10,16)] +def hexescape(s,pos,digits,message,errors): + chr = 0 + p = [] + if (pos+digits>len(s)): + message = "end of string in escape sequence" + x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2,len(s)) + p += x[0] + pos = x[1] + else: + try: + chr = int(s[pos:pos+digits],16) + except ValueError: + endinpos = pos + while s[endinpos] in hexdigits: + endinpos +=1 + x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2, + endinpos+1) + p += x[0] + pos = x[1] + #/* when we get here, chr is a 32-bit unicode character */ + else: + if chr <= sys.maxunicode: + p += [unichr(chr)] + pos += digits + + elif (chr <= 0x10ffff): + chr -= 0x10000L + p += unichr(0xD800 + (chr >> 10)) + p += unichr(0xDC00 + (chr & 0x03FF)) + pos += digits + else: + message = "illegal Unicode character" + x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2, + pos+1) + p += x[0] + pos = x[1] + res = p + return res,pos + +def PyUnicode_DecodeUnicodeEscape(s, size, errors): + + if (size == 0): + return u'' + + p = [] + pos = 0 + while (pos < size): +## /* Non-escape characters are interpreted as Unicode ordinals */ + if (s[pos] != '\\') : + p += s[pos] + pos += 1 + continue +## /* \ - Escapes */ + else: + pos +=1 + if pos>=len(s): + errmessage = "\\ at end of string" + unicode_call_errorhandler(errors,"unicodeescape",errmessage,s,pos-1,size) + ch = s[pos] + pos += 1 + ## /* \x escapes */ + #if ch == '\n': break; + if ch == '\\': p += '\\' + elif ch == '\'': p += '\'' + elif ch == '\"': p += '\"' + elif ch == 'b': p += '\b' + elif ch == 'f': p += '\014' #/* FF */ + elif ch == 't': p += '\t' + elif ch == 'n': p += '\n' + elif ch == 'r': + p += '\r' + + elif ch == 'v': p += '\013' #break; /* VT */ + elif ch == 'a': p += '\007' # break; /* BEL, not classic C */ + + ## /* \OOO (octal) escapes */ + elif ch in [ '0','1', '2', '3','4', '5', '6','7']: + x = ord(ch) - ord('0') + ch = s[pos] + if ('0' <= ch and ch <= '7'): + x = (x<<3) + ord(ch) - ord('0') + ch = s[pos+1] + if ('0' <= ch and ch <= '7'): + x = (x<<3) + ord(ch) - ord('0') + pos += 2 + + p += unichr(x) + ## /* hex escapes */ + ## /* \xXX */ + elif ch == 'x': + digits = 2 + message = "truncated \\xXX escape" + x = hexescape(s,pos,digits,message,errors) + p += x[0] + pos = x[1] + + # /* \uXXXX */ + elif ch == 'u': + digits = 4 + message = "truncated \\uXXXX escape" + x = hexescape(s,pos,digits,message,errors) + p += x[0] + pos = x[1] + + # /* \UXXXXXXXX */ + elif ch == 'U': + digits = 8 + message = "truncated \\UXXXXXXXX escape" + x = hexescape(s,pos,digits,message,errors) + p += x[0] + pos = x[1] +## /* \N{name} */ + elif ch == 'N': + message = "malformed \\N character escape" + #pos += 1 + try: + import unicodedata + except ImportError: + message = "\\N escapes not supported (can't load unicodedata module)" + unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,size) + if (s[pos] == '{'): + look = pos+1 + #/* look for the closing brace */ + while (s[look] != '}' and look < size): + look += 1 + if (look > pos+1 and look < size and s[look] == '}'): + #/* found a name. look it up in the unicode database */ + message = "unknown Unicode character name" + look += 1 + try: + chr = unicodedata.lookup(s[pos:look]) + #x = hexescape(chr,pos+1,8,message,errors) + except KeyError: + x=unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,look) + else: + x = hexescape(s,pos+1,look-pos,message,errors) + p += x[0] + pos = x[1] + else: + if (pos > size): + message = "\\ at end of string" + handler = lookup_error(errors) + x = handler(UnicodeDecodeError("unicodeescape",s,pos, + size,message)) + p += x[0] + pos = x[1] + else: + p += '\\' + p += s[pos] + return p + +def PyUnicode_EncodeRawUnicodeEscape(s,size): + + if (size == 0): + return '' + + p = [] + for ch in s: +# /* Map 32-bit characters to '\Uxxxxxxxx' */ + if (ord(ch) >= 0x10000): + p += '\\' + p += 'U' + p += '%08x'%(ord(ch)) + elif (ord(ch) >= 256) : +# /* Map 16-bit characters to '\uxxxx' */ + p += '\\' + p += 'u' + p += '%04x'%(ord(ch)) +# /* Copy everything else as-is */ + else: + p += chr(ord(ch)) + + #p += '\0' + return p + +def charmapencode_output(c,mapping): + + + rep = mapping[c] + if isinstance(rep,(int,long)): + if rep<256: + return chr(rep) + else: + raise TypeError("character mapping must be in range(256)") + elif isinstance(rep,str): + return rep + elif rep == None: + raise KeyError("character maps to ") + else: + raise TypeError("character mapping must return integer, None or str") + +def PyUnicode_EncodeCharmap(p,size,mapping='latin-1',errors='strict'): + +## /* the following variable is used for caching string comparisons +## * -1=not initialized, 0=unknown, 1=strict, 2=replace, +## * 3=ignore, 4=xmlcharrefreplace */ + +# /* Default to Latin-1 */ + if mapping == 'latin-1': + return PyUnicode_EncodeLatin1(p, size, errors) + if (size == 0): + return '' + inpos = 0 + res = [] + while (inpos",p,inpos,inpos+1,False) + try: + res += [charmapencode_output(ord(y),mapping) for y in x[0]] + except KeyError: + raise UnicodeEncodeError("charmap",p,inpos,inpos+1, + "character maps to ") +## except TypeError,err: +## x = unicode_call_errorhandler(errors,"charmap", +## err,p,inpos,inpos+1,False) +## try: +## res += [charmapencode_output(ord(y),mapping) for y in x[0]] +## except KeyError: +## raise UnicodeEncodeError("charmap",p,inpos,inpos+1, +## "character maps to ") +## + #/* done with this character => adjust input position */ + inpos+=1 + return res + +def PyUnicode_DecodeCharmap(s, size, mapping, errors): + +## /* Default to Latin-1 */ + if (mapping == None): + return PyUnicode_DecodeLatin1(s, size, errors) + + if (size == 0): + return u'' + p = [] + inpos = 0 + while (inpos< len(s)): + + #/* Get mapping (char ordinal -> integer, Unicode char or None) */ + ch = s[inpos] + try: + x = mapping[ord(ch)] + if isinstance(x,int): + if x<65536: + p += unichr(x) + else: + raise TypeError("character mapping must be in range(65536)") + elif isinstance(x,unicode): + p += x + elif not x: + raise KeyError + else: + raise TypeError + except KeyError: + x = unicode_call_errorhandler(errors,"charmap", + "character maps to ",s,inpos,inpos+1) + p += x[0] +## except TypeError: +## x = unicode_call_errorhandler(errors,"charmap", +## "character mapping must return integer, None or unicode", +## s,inpos,inpos+1) +## p += x[0] + inpos +=1 + return p + +def PyUnicode_DecodeRawUnicodeEscape(s, size,errors): + + if (size == 0): + return u'' + pos = 0 + p = [] + while (pos < len(s)): + ch = s[pos] + #/* Non-escape characters are interpreted as Unicode ordinals */ + if (ch != '\\'): + p += unichr(ord(ch)) + pos += 1 + continue + startinpos = pos + #pos += 1 +## /* \u-escapes are only interpreted iff the number of leading +## backslashes is odd */ + bs = pos + while pos < size: + if (s[pos] != '\\'): + break + p += unichr(ord(s[pos])) + pos += 1 + + if (((pos - bs) & 1) == 0 or + pos >= size or + (s[pos] != 'u' and s[pos] != 'U')) : + p += s[pos] + pos += 1 + continue + + p.pop(-1) + if s[pos] == 'u': + count = 4 + else: + count = 8 + pos += 1 + + #/* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */ + + i = 0 + x = 0 + try: + x = int(s[pos:pos+count],16) + except ValueError: + res = unicode_call_errorhandler( + errors, "rawunicodeescape", "truncated \\uXXXX", + s, size, pos, pos+count) + p += res[0] + pos = res[1] + else: + #ifndef Py_UNICODE_WIDE + if sys.maxunicode > 0xffff: + if (x > 0x10000): + res = unicode_call_errorhandler( + errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", + s, size, pos, pos+1) + pos = i = res[1] + p += res[0] + i += 1 + else: + if (x > 0x10000): + res = unicode_call_errorhandler( + errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", + s, size, pos, pos+1) + pos = i = res[1] + p += res[0] + + #endif + else: + p += unichr(x) + pos += count + + return p \ No newline at end of file From tismer at codespeak.net Sun Jun 5 23:13:07 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 23:13:07 +0200 (CEST) Subject: [pypy-svn] r13084 - pypy/dist/pypy/translator Message-ID: <20050605211307.85EE727B51@code1.codespeak.net> Author: tismer Date: Sun Jun 5 23:13:06 2005 New Revision: 13084 Modified: pypy/dist/pypy/translator/annrpython.py Log: avoid complicated imports of parts of the application by cleaning the values of overrides beforepickling. Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sun Jun 5 23:13:06 2005 @@ -53,6 +53,10 @@ assert type(value) is dict, ("please update %s.__getstate__" % self.__class__.__name__) ret[key] = {} + # special case: clean up the overrides which would trigger bad imports + overrides = ret['overrides'] = {} + for key in self.overrides: + overrides[key] = None return ret def _register_returnvar(self, flowgraph, func): From tismer at codespeak.net Sun Jun 5 23:24:38 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 23:24:38 +0200 (CEST) Subject: [pypy-svn] r13085 - pypy/dist/pypy/translator/pickle Message-ID: <20050605212438.3DD1D27B51@code1.codespeak.net> Author: tismer Date: Sun Jun 5 23:24:36 2005 New Revision: 13085 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: lots, lots, lots of changes. added domains list to distinguish between application domain and globally known objects. used inlining to most of constants, to avoid a huge amount of needless global names. The generated code is still too huge for the Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Sun Jun 5 23:24:36 2005 @@ -4,16 +4,22 @@ to restart code generation after flowing and maybe annotation. """ +from __future__ import generators, division, nested_scopes +import __future__ +all_feature_names = __future__.all_feature_names import os, sys, new, __builtin__ -from pypy.translator.gensupp import uniquemodulename, NameManager, UniqueList +from pypy.translator.gensupp import uniquemodulename, NameManager from pypy.translator.gensupp import builtin_base from pypy.rpython.rarithmetic import r_int, r_uint from pypy.objspace.flow.model import Variable, Constant, SpaceOperation from pypy.objspace.flow.model import FunctionGraph, Block, Link from pypy.interpreter.baseobjspace import ObjSpace +from pypy.translator.pickle import slotted from pickle import whichmodule, PicklingError +from copy_reg import _reduce_ex, _reconstructor + import pickle from types import * @@ -24,22 +30,42 @@ class GenPickle: - def __init__(self, translator): + def __init__(self, translator, outfile = None): self.translator = translator - self.initcode = UniqueList([ + self.initcode = [ + 'from __future__ import %s\n' % ', '.join(all_feature_names) + 'import new, types, sys', - ]) + ] self.latercode = [] # list of generators generating extra lines self.debugstack = () # linked list of nested nameof() - self.initcode = UniqueList(self.initcode) self.picklenames = {Constant(None): 'None', Constant(False): 'False', Constant(True): 'True', + # hack: overflowed float + Constant(float("1e10000000000000000000000000000000")): + 'float("1e10000000000000000000000000000000")', } + for name in all_feature_names + "new types sys".split(): + self.picklenames[Constant(globals()[name])] = name self.namespace = NameManager() self.namespace.make_reserved_names('None False True') + self.namespace.make_reserved_names('new types sys') + self.namespace.make_reserved_names(' '.join(all_feature_names)) + self.inline_consts = True # save lots of space + self._nesting = 0 # for formatting nested tuples etc. + # we distinguish between the "user program" and other stuff. + # "user program" will never use save_global. + self.domains = ( + 'pypy.objspace.std.', + 'pypy._cache.', + 'pypy.interpreter.', + 'pypy.module.', + '__main__', + ) + self.outfile = outfile + self._partition = 1234 def nameof(self, obj, debug=None, namehint=None): key = Constant(obj) @@ -58,7 +84,9 @@ else: for cls in type(obj).__mro__: meth = getattr(self, - 'nameof_' + cls.__name__.replace(' ', ''), + 'nameof_' + ''.join( [ + c for c in cls.__name__ + if c.isalpha() or c == '_'] ), None) if meth: break @@ -72,12 +100,27 @@ name = meth(obj) self.debugstack, x = self.debugstack assert x is stackentry - self.picklenames[key] = name + if name[0].isalpha(): + # avoid to store things which are used just once + self.picklenames[key] = name return name def nameofargs(self, tup): """ a string with the nameofs, concatenated """ - return ', '.join([self.nameof(arg) for arg in tup]) + if len(tup) < 5: + # see if there is nesting to be expected + for each in tup: + if type(each) is tuple: + break + else: + return ', '.join([self.nameof(arg) for arg in tup]) + # we always wrap into multi-lines, this is simple and readable + self._nesting += 1 + space = ' ' * self._nesting + ret = '\n' + space + (',\n' + space).join( + [self.nameof(arg) for arg in tup]) + ',\n' + space + self._nesting -= 1 + return ret def uniquename(self, basename): return self.namespace.uniquename(basename) @@ -96,8 +139,22 @@ def nameof_module(self, value): # all allowed here, we reproduce ourselves - name = self.uniquename('mod%s'%value.__name__) - self.initcode_python(name, "__import__(%r)" % (value.__name__,)) + if self.is_app_domain(value.__name__): + name = self.uniquename('gmod_%s' % value.__name__) + self.initcode.append('%s = new.module(%r)\n' + 'sys.modules[%r] = %s'% ( + name, value.__name__, value.__name__, name) ) + def initmodule(): + for k, v in value.__dict__.items(): + try: + nv = self.nameof(v) + yield '%s.%s = %s' % (name, k, nv) + except PicklingError: + pass + self.later(initmodule()) + else: + name = self.uniquename(value.__name__) + self.initcode_python(name, "__import__(%r)" % (value.__name__,)) return name def nameof_int(self, value): @@ -109,11 +166,15 @@ nameof_long = nameof_float = nameof_bool = nameof_NoneType = nameof_int def nameof_str(self, value): + if self.inline_consts: + return repr(value) name = self.uniquename('gstr_' + value[:32]) self.initcode_python(name, repr(value)) return name def nameof_unicode(self, value): + if self.inline_consts: + return repr(value) name = self.uniquename('guni_' + str(value[:32])) self.initcode_python(name, repr(value)) return name @@ -121,18 +182,9 @@ def skipped_function(self, func): # debugging only! Generates a placeholder for missing functions # that raises an exception when called. - if self.translator.frozen: - warning = 'NOT GENERATING' - else: - warning = 'skipped' - printable_name = '(%s:%d) %s' % ( - func.func_globals.get('__name__', '?'), - func.func_code.co_firstlineno, - func.__name__) - print warning, printable_name name = self.uniquename('gskippedfunc_' + func.__name__) - self.initcode.append('def %s(*a,**k):' % name) - self.initcode.append(' raise NotImplementedError') + self.initcode.append('def %s(*a,**k):\n' + ' raise NotImplementedError' % name) return name def nameof_staticmethod(self, sm): @@ -156,20 +208,6 @@ func, ob, typ)) return name - # old version: - def should_translate_attr(self, pbc, attr): - ann = self.translator.annotator - if ann is None or isinstance(pbc, ObjSpace): - ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', []) - if attr in ignore: - return False - else: - return "probably" # True - classdef = ann.getuserclasses().get(pbc.__class__) - if classdef and classdef.about_attribute(attr) is not None: - return True - return False - # new version: save if we don't know def should_translate_attr(self, pbc, attr): ann = self.translator.annotator @@ -210,7 +248,7 @@ def nameof_classobj(self, cls): if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'): - raise Exception, "%r should never be reached" % (cls,) + raise PicklingError, "%r should never be reached" % (cls,) try: return self.save_global(cls) @@ -240,34 +278,45 @@ content = cls.__dict__.items() content.sort() ignore = getattr(cls, 'NOT_RPYTHON_ATTRIBUTES', []) + isapp = self.is_app_domain(cls.__module__) for key, value in content: if key.startswith('__'): - if key in ['__module__', '__doc__', '__dict__', + if key in ['__module__', '__doc__', '__dict__', '__slots__', '__weakref__', '__repr__', '__metaclass__']: continue # XXX some __NAMES__ are important... nicer solution sought #raise Exception, "unexpected name %r in class %s"%(key, cls) - if isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen: - print value - continue - if isinstance(value, classmethod): - doc = value.__get__(cls).__doc__ - if doc and doc.lstrip().startswith("NOT_RPYTHON"): + if isapp: + if (isinstance(value, staticmethod) and value.__get__(1) not in + self.translator.flowgraphs and self.translator.frozen): + print value + continue + if isinstance(value, classmethod): + doc = value.__get__(cls).__doc__ + if doc and doc.lstrip().startswith("NOT_RPYTHON"): + continue + if (isinstance(value, FunctionType) and value not in + self.translator.flowgraphs and self.translator.frozen): + print value continue - if isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen: - print value - continue if key in ignore: continue - + if type(value) in self.descriptor_filter: + continue # this gets computed + yield '%s.%s = %s' % (name, key, self.nameof(value)) baseargs = ", ".join(basenames) if baseargs: baseargs = '(%s)' % baseargs - self.initcode.append('class %s%s:' % (name, baseargs)) - self.initcode.append(' __metaclass__ = %s' % metaclass) - self.later(initclassobj()) + ini = 'class %s%s:\n __metaclass__ = %s' % (name, baseargs, metaclass) + if '__slots__' in cls.__dict__: + ini += '\n __slots__ = %r' % cls.__slots__ + self.initcode.append(ini) + # squeeze it out, now# self.later(initclassobj()) + self.picklenames[Constant(cls)] = name + for line in initclassobj(): + self.initcode.append(line) return name nameof_class = nameof_classobj # for Python 2.2 @@ -285,7 +334,7 @@ # type 'builtin_function_or_method': type(len): 'type(len)', # type 'method_descriptor': - type(list.append): 'type(list.append)', + type(type.__reduce__): 'type(type.__reduce__)', # type 'wrapper_descriptor': type(type(None).__repr__): 'type(type(None).__repr__)', # type 'getset_descriptor': @@ -295,7 +344,12 @@ # type 'instancemethod': type(Exception().__init__): 'type(Exception().__init__)', } - + descriptor_filter = {} + for _key in typename_mapping.keys(): + if _key.__name__.endswith('descriptor'): + descriptor_filter[_key] = True + del _key + def nameof_type(self, cls): if cls.__module__ != '__builtin__': return self.nameof_classobj(cls) # user-defined type @@ -315,6 +369,14 @@ return name def nameof_tuple(self, tup): + # instead of defining myriads of tuples, it seems to + # be cheaper to create them inline, although they don't + # get constant folded like strings and numbers. + if self.inline_consts: + argstr = self.nameofargs(tup) + if len(tup) == 1 and not argstr.rstrip().endswith(','): + argstr += ',' + return '(%s)' % argstr name = self.uniquename('g%dtuple' % len(tup)) args = [self.nameof(x) for x in tup] args = ', '.join(args) @@ -326,15 +388,21 @@ def nameof_list(self, lis): name = self.uniquename('g%dlist' % len(lis)) def initlist(): - extname = self.nameof(extendlist) - for i in range(0, len(lis), 5): - items = lis[i:i+5] + chunk = 20 + for i in range(0, len(lis), chunk): + items = lis[i:i+chunk] itemstr = self.nameofargs(items) - yield '%s(%s, %s)' % (extname, name, itemstr) + yield '%s.extend([%s])' % (name, itemstr) self.initcode_python(name, '[]') self.later(initlist()) return name + def is_app_domain(self, modname): + for domain in self.domains: + if modname.startswith(domain): + return True + return False + def nameof_dict(self, dic): if '__name__' in dic: module = dic['__name__'] @@ -344,7 +412,7 @@ except (ImportError, KeyError, TypeError): pass else: - if dic is mod.__dict__: + if dic is mod.__dict__ and not self.is_app_domain(module): dictname = module.split('.')[-1] + '__dict__' dictname = self.uniquename(dictname) self.initcode.append('from %s import __dict__ as %s' % ( @@ -354,11 +422,14 @@ name = self.uniquename('g%ddict' % len(dic)) def initdict(): for k in dic: - if type(k) is str: - yield '%s[%r] = %s' % (name, k, self.nameof(dic[k])) - else: - yield '%s[%s] = %s' % (name, self.nameof(k), - self.nameof(dic[k])) + try: + if type(k) is str: + yield '%s[%r] = %s' % (name, k, self.nameof(dic[k])) + else: + yield '%s[%s] = %s' % (name, self.nameof(k), + self.nameof(dic[k])) + except PicklingError: + pass self.initcode_python(name, '{}') self.later(initdict()) return name @@ -388,14 +459,11 @@ def initinstance(): if hasattr(instance, '__setstate__'): # the instance knows what to do - if type(restorestate) is tuple: - # be a little shorter - setstatename = self.nameof(setstate) - argstr = self.nameofargs(restorestate) - yield '%s(%s, %s)' % (setstatename, name, argstr) - else: - args = self.nameof(restorestate) - yield '%s.__setstate__(%s)' % (name, args) + args = self.nameof(restorestate) + yield '%s.__setstate__(%s)' % (name, args) + return + elif type(restorestate) is tuple: + slotted.__setstate__(instance, restorestate) return assert type(restorestate) is dict, ( "%s has no dict and no __setstate__" % name) @@ -403,23 +471,44 @@ content.sort() for key, value in content: if self.should_translate_attr(instance, key): + if hasattr(value, '__doc__'): + doc = value.__doc__ + if type(doc) is str and doc.lstrip().startswith('NOT_RPYTHON'): + continue line = '%s.%s = %s' % (name, key, self.nameof(value)) yield line if hasattr(instance, '__reduce_ex__'): - reduced = instance.__reduce_ex__() - restorer = reduced[0] - restorename = self.nameof(restorer) - restoreargs = reduced[1] - if len(reduced) > 2: - restorestate = reduced[2] + try: + reduced = instance.__reduce_ex__() + except TypeError: + # oops! slots and no __getstate__? + if not (hasattr(instance, '__slots__') + and not hasattr(instance, '__getstate__') ): + print "PROBLEM:", instance + raise + assert not hasattr(instance, '__dict__'), ('wrong assumptions' + ' about __slots__ in %s instance without __setstate__,' + ' please update %s' % (cls.__name__, __name__) ) + restorestate = slotted.__getstate__(instance) + restorer = _reconstructor + restoreargs = klass, object, None else: - restorestate = None + restorer = reduced[0] + restoreargs = reduced[1] + if len(reduced) > 2: + restorestate = reduced[2] + else: + restorestate = None + restorename = self.nameof(restorer) # ignore possible dict, handled later by initinstance filtering # in other cases, we expect that the class knows what to pickle. else: restoreargs = (base, cls) restorename = '%s.__new__' % base - restorestate = instance.__dict__ + if hasattr(instance, '__getstate__'): + restorestate = instance.__getstate__() + else: + restorestate = instance.__dict__ restoreargstr = self.nameofargs(restoreargs) if isinstance(klass, type): self.initcode.append('%s = %s(%s)' % (name, restorename, @@ -438,7 +527,10 @@ module = getattr(obj, "__module__", None) if module is None: module = whichmodule(obj, name) - + if self.is_app_domain(module): + # not allowed to import this + raise PicklingError('%s belongs to the user program' % + name) try: __import__(module) mod = sys.modules[module] @@ -467,7 +559,10 @@ # look for skipped functions if self.translator.frozen: if func not in self.translator.flowgraphs: - return self.skipped_function(func) + # see if this is in translator's domain + module = whichmodule(func, func.__name__) + if self.is_app_domain(module): + return self.skipped_function(func) else: if (func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON')): @@ -479,11 +574,17 @@ args = (func.func_code, func.func_globals, func.func_name, func.func_defaults, func.func_closure) pyfuncobj = self.uniquename('gfunc_' + func.__name__) + # touch code,to avoid extra indentation + self.nameof(func.func_code) self.initcode.append('%s = new.function(%s)' % (pyfuncobj, self.nameofargs(args)) ) if func.__dict__: - self.initcode.append('%s.__dict__.update(%s)' % ( - pyfuncobj, self.nameof(func.__dict__)) ) + for k, v in func.__dict__.items(): + try: + self.initcode.append('%s.%s = %s' % ( + pyfuncobj, k, self.nameof(v)) ) + except PicklingError: + pass return pyfuncobj def nameof_cell(self, cel): @@ -493,25 +594,32 @@ self.nameof(obj)) ) return pycell + def nameof_property(self, prop): + pyprop = self.uniquename('gprop_') + self.initcode.append('%s = property(%s)' % (pyprop, self.nameofargs( + (prop.fget, prop.fset, prop.fdel, prop.__doc__))) ) + return pyprop + def nameof_code(self, code): args = (code.co_argcount, code.co_nlocals, code.co_stacksize, code.co_flags, code.co_code, code.co_consts, code.co_names, code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno, code.co_lnotab, code.co_freevars, code.co_cellvars) - # make the code, filename and lnotab strings nicer - codestr = code.co_code - codestrname = self.uniquename('gcodestr_' + code.co_name) - self.picklenames[Constant(codestr)] = codestrname - self.initcode.append('%s = %r' % (codestrname, codestr)) - fnstr = code.co_filename - fnstrname = self.uniquename('gfname_' + code.co_name) - self.picklenames[Constant(fnstr)] = fnstrname - self.initcode.append('%s = %r' % (fnstrname, fnstr)) - lnostr = code.co_lnotab - lnostrname = self.uniquename('glnotab_' + code.co_name) - self.picklenames[Constant(lnostr)] = lnostrname - self.initcode.append('%s = %r' % (lnostrname, lnostr)) + if not self.inline_consts: + # make the code, filename and lnotab strings nicer + codestr = code.co_code + codestrname = self.uniquename('gcodestr_' + code.co_name) + self.picklenames[Constant(codestr)] = codestrname + self.initcode.append('%s = %r' % (codestrname, codestr)) + fnstr = code.co_filename + fnstrname = self.uniquename('gfname_' + code.co_name) + self.picklenames[Constant(fnstr)] = fnstrname + self.initcode.append('%s = %r' % (fnstrname, fnstr)) + lnostr = code.co_lnotab + lnostrname = self.uniquename('glnotab_' + code.co_name) + self.picklenames[Constant(lnostr)] = lnostrname + self.initcode.append('%s = %r' % (lnostrname, lnostr)) argstr = self.nameofargs(args) codeobj = self.uniquename('gcode_' + code.co_name) self.initcode.append('%s = new.code(%s)' % (codeobj, argstr)) @@ -523,9 +631,36 @@ if fil is sys.stderr: return "sys.stderr" raise Exception, 'Cannot translate an already-open file: %r' % (fil,) + def nameof_methodwrapper(self, wp): + # this object should be enhanced in CPython! + reprwp = repr(wp) + name = wp.__name__ + def dummy_methodwrapper(): + return reprwp + (': method %s of unknown object ' + 'cannot be reconstructed, sorry!' % name ) + return self.nameof(dummy_methodwrapper) + def later(self, gen): self.latercode.append((gen, self.debugstack)) + def spill_source(self, final): + def write_block(lines): + if not lines: + return + txt = '\n'.join(lines) + print >> self.outfile, txt + print >> self.outfile, '## SECTION ##' + + if not self.outfile: + return + chunk = self._partition + while len(self.initcode) >= chunk: + write_block(self.initcode[:chunk]) + del self.initcode[:chunk] + if final and self.initcode: + write_block(self.initcode) + del self.initcode[:] + def collect_initcode(self): while self.latercode: gen, self.debugstack = self.latercode.pop() @@ -533,6 +668,9 @@ for line in gen: self.initcode.append(line) self.debugstack = () + if len(self.initcode) >= self._partition: + self.spill_source(False) + self.spill_source(True) def getfrozenbytecode(self): self.initcode.append('') @@ -563,11 +701,3 @@ func.func_defaults, (cel,)) func = new.function(*args) return func() - -# save creation of many tuples - -def setstate(obj, *args): - obj.__setstate__(args) - -def extendlist(obj, *args): - obj.extend(args) From tismer at codespeak.net Sun Jun 5 23:49:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 5 Jun 2005 23:49:20 +0200 (CEST) Subject: [pypy-svn] r13086 - pypy/dist/pypy/translator/pickle Message-ID: <20050605214920.6A82427B51@code1.codespeak.net> Author: tismer Date: Sun Jun 5 23:49:19 2005 New Revision: 13086 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: provide the original class name, thanks to samuele Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Sun Jun 5 23:49:19 2005 @@ -313,6 +313,7 @@ if '__slots__' in cls.__dict__: ini += '\n __slots__ = %r' % cls.__slots__ self.initcode.append(ini) + self.initcode.append('%s.name = %r' % (name, cls.__name__)) # squeeze it out, now# self.later(initclassobj()) self.picklenames[Constant(cls)] = name for line in initclassobj(): From pedronis at codespeak.net Mon Jun 6 04:28:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 6 Jun 2005 04:28:08 +0200 (CEST) Subject: [pypy-svn] r13087 - pypy/dist/pypy/translator/pickle Message-ID: <20050606022808.D7B2727B51@code1.codespeak.net> Author: pedronis Date: Mon Jun 6 04:28:07 2005 New Revision: 13087 Modified: pypy/dist/pypy/translator/pickle/ (props changed) Log: set svn:ignore From pedronis at codespeak.net Mon Jun 6 05:09:00 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 6 Jun 2005 05:09:00 +0200 (CEST) Subject: [pypy-svn] r13088 - in pypy/dist/pypy: annotation interpreter module/sys objspace/std tool translator translator/goal translator/test Message-ID: <20050606030900.D2BCF27B51@code1.codespeak.net> Author: pedronis Date: Mon Jun 6 05:08:52 2005 New Revision: 13088 Added: pypy/dist/pypy/annotation/policy.py (contents, props changed) pypy/dist/pypy/annotation/specialize.py (contents, props changed) Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/interpreter/compiler.py pypy/dist/pypy/interpreter/error.py pypy/dist/pypy/interpreter/miscutils.py pypy/dist/pypy/interpreter/pyframe.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/sys/state.py pypy/dist/pypy/objspace/std/fake.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/tool/cache.py pypy/dist/pypy/translator/ann_override.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/test/snippet.py pypy/dist/pypy/translator/test/test_annrpython.py pypy/dist/pypy/translator/translator.py Log: Revised specialization, see annotation/specialize.py and changes in bookkeeper; now annotator can receive a policy object to specify both overrides and specializations through the methods specialize and override a base class version is defined in annotation/policy.py, it will use methods of the form specialize__xxx or override__xxx chosen by attaching to the callable in user-code the attribute _annspecialcase_ with values: "specialize:xxx" "override:xxx" respectively. ann_override now defines such a policy class which is used by translate_pypy, (Notice: if a policy is not passed to the annotator an even more basic policy without any overrides nor specializations is used.) - 'override' methods take the policy and inputcells - 'specialize' methods take the policy and a bookkeeper, the involved spaceop, the involved callable func, an Arguments object with SomeObjects and a mono flag whether just one statically known callable is involved; they should normally return a _tuple_ key to identify the specialized version (which if absent will be created), or None meaning no specialization the policy can define a default_specialize that is always invoked, the version in the base class does the specializion for *arg functions There's no general 'location' specialization anymore, for classes there's "specialize:ctr_location" which is implemented in specialize.py and exposed by the base policy class. Now phases successive to annotation can query whether a call space op involves specialized callables: bookkeeper.query_spaceop_callable(spaceop) can be called with a call spaceop that has the called obj annotated as some PBC it will return possibly a new PBC with the specialized version effectively considered by the annotator for the callable (it also returns a flag which is normally false unless, in the only case (for now), the callable involved was marked "specialize:memo") the call site families and tables now refer to specialized versions of callables, not the original ones. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Mon Jun 6 05:08:52 2005 @@ -11,14 +11,12 @@ from pypy.annotation.classdef import ClassDef, isclassdef from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF -from pypy.tool.sourcetools import func_with_new_name, valid_identifier -from pypy.interpreter.pycode import CO_VARARGS from pypy.interpreter.pycode import cpython_code_signature -from pypy.interpreter.argument import ArgErr +from pypy.interpreter.argument import Arguments, ArgErr from pypy.rpython.rarithmetic import r_uint from pypy.tool.unionfind import UnionFind -import inspect, new +from pypy.annotation.specialize import decide_callable class PBCAccessSet: def __init__(self, obj): @@ -59,9 +57,8 @@ self.listdefs = {} # map position_keys to ListDefs self.dictdefs = {} # map position_keys to DictDefs - # mapping position -> most general result, for call sites calling - # argtypes specialized functions - self.argtypes_spec_callsite_results = {} + # mapping position -> key, prev_result for specializations + self.spec_callsite_keys_results = {} self.pbc_maximal_access_sets = UnionFind(PBCAccessSet) # can be precisely computed only at fix-point, see @@ -92,9 +89,10 @@ self.pbc_callables = {} for (fn, block, i), shape in self.pbc_call_sites.iteritems(): - assert block.operations[i].opname in ('call_args', 'simple_call') - pbc = self.annotator.binding(block.operations[i].args[0], extquery=True) - self.consider_pbc_call(pbc, shape, position=(fn, block, i)) + spaceop = block.operations[i] + assert spaceop.opname in ('call_args', 'simple_call') + pbc = self.annotator.binding(spaceop.args[0], extquery=True) + self.consider_pbc_call(pbc, shape, spaceop) def getclassdef(self, cls): """Get the ClassDef associated with the given user cls.""" @@ -312,9 +310,18 @@ return unionof(*actuals) - def consider_pbc_call(self, pbc, shape, position=None): # computation done at fix-point + def consider_pbc_call(self, pbc, shape, spaceop=None, implicit_init=None): # computation done at fix-point if not isinstance(pbc, SomePBC): return + + if implicit_init: + implicit_init = pbc, implicit_init + shape = (shape[0]+1,) + shape[1:] + else: + implicit_init = None + + pbc, dontcarememo = self.query_spaceop_callable(spaceop, + implicit_init=implicit_init) nonnullcallables = [] for func, classdef in pbc.prebuiltinstances.items(): @@ -327,10 +334,9 @@ if isinstance(func, (type, ClassType)) and \ func.__module__ != '__builtin__': assert classdef is None - dontcare, s_init = self.get_s_init(func, position=position) + init_classdef, s_init = self.get_s_init(func) if s_init is not None: - init_shape = (shape[0]+1,) + shape[1:] - self.consider_pbc_call(s_init, init_shape) + self.consider_pbc_call(s_init, shape, spaceop, implicit_init=init_classdef) callable = (classdef, func) if hasattr(func, 'im_func') and func.im_self is None: @@ -376,21 +382,52 @@ return unionof(*results) # decide_callable(position, func, args, mono) -> callb, key - # query_spaceop_callable(spaceop) -> pbc + # query_spaceop_callable(spaceop) -> pbc, memo # get_s_init(decided_cls) -> classdef, s_undecided_init - def get_s_init(self, cls, position=None, mono=True): - specialize = getattr(cls, "_specialize_", False) - if specialize: - if specialize == "location": - assert mono, "not-static construction of specialized class %s" % cls - cls = self.specialize_by_key(cls, position, - name="%s__At_%s" % (cls.__name__, - position_name(position))) + def query_spaceop_callable(self, spaceop, implicit_init=None): # -> s_pbc, memo + self.enter(None) + try: + if implicit_init is None: + assert spaceop.opname in ("simple_call", "call_args") + obj = spaceop.args[0] + s_obj = self.annotator.binding(obj, extquery=True) + init_classdef = None else: - raise Exception, \ - "unsupported specialization type '%s'"%(specialize,) + s_obj, init_classdef = implicit_init + + assert isinstance(s_obj, SomePBC) + if len(s_obj.prebuiltinstances) > 1: # no specialization expected + return s_obj, False + + argsvars = spaceop.args[1:] + args_s = [self.annotator.binding(v) for v in argsvars] + args = self.build_args(spaceop.opname, args_s) + if init_classdef: + args = args.prepend(SomeInstance(init_classdef)) + + func, classdef = s_obj.prebuiltinstances.items()[0] + func, key = decide_callable(self, spaceop, func, args, mono=True) + + if key is None: + return s_obj, False + + if func is None: # specialisation computes annotation direclty + return s_obj, True + + return SomePBC({func: classdef}), False + finally: + self.leave() + + def build_args(self, op, args_s): + space = RPythonCallsSpace() + if op == "simple_call": + return Arguments(space, args_s) + elif op == "call_args": + return Arguments.fromshape(space, args_s[0].const, # shape + args_s[1:]) + def get_s_init(self, cls): classdef = self.getclassdef(cls) init = getattr(cls, '__init__', None) if init is not None and init != object.__init__: @@ -409,9 +446,20 @@ def pycall(self, func, args, mono): if func is None: # consider None as a NULL function pointer return SomeImpossibleValue() + + # decide and pick if necessary a specialized version + base_func = func + func, key = decide_callable(self, self.position_key, func, args, mono, unpacked=True) + + if func is None: + assert isinstance(key, SomeObject) + return key + + func, args = func # method unpacking done by decide_callable + if isinstance(func, (type, ClassType)) and \ func.__module__ != '__builtin__': - classdef, s_init = self.get_s_init(func, position=self.position_key, mono=mono) + classdef, s_init = self.get_s_init(func) s_instance = SomeInstance(classdef) # flow into __init__() if the class has got one if s_init is not None: @@ -423,60 +471,7 @@ raise Exception, "no __init__ found in %r" % (cls,) return s_instance - if hasattr(func, 'im_func'): - if func.im_self is not None: - s_self = self.immutablevalue(func.im_self) - args = args.prepend(s_self) - # for debugging only, but useful to keep anyway: - try: - func.im_func.class_ = func.im_class - except AttributeError: - # probably a builtin function, we don't care to preserve - # class information then - pass - func = func.im_func assert isinstance(func, FunctionType), "[%s] expected function, got %r" % (self.whereami(), func) - # do we need to specialize this function in several versions? - specialize = getattr(func, '_specialize_', False) - - if specialize: - assert mono, "not-static call to specialized %s" % func - base_func = func - if specialize == 'argtypes': - key = short_type_name(args) - func = self.specialize_by_key(func, key, - func.__name__+'__'+key) - elif specialize == "location": - # fully specialize: create one version per call position - func = self.specialize_by_key(func, self.position_key, - name="%s__At_%s" % (func.__name__, - position_name(self.position_key))) - elif specialize == "memo": - # call the function now, and collect possible results - arglist_s, kwds_s = args.unpack() - assert not kwds_s, ("no ** args in call to function " - "marked specialize='concrete'") - possible_results = [] - for arglist in possible_arguments(arglist_s): - result = func(*arglist) - possible_results.append(self.immutablevalue(result)) - return unionof(*possible_results) - else: - raise Exception, "unsupported specialization type '%s'"%(specialize,) - - elif func.func_code.co_flags & CO_VARARGS: - # calls to *arg functions: create one version per number of args - assert mono, "not-static call to *arg function %s" % func - assert not args.has_keywords(), ( - "keyword forbidden in calls to *arg functions") - nbargs = len(args.arguments_w) - if args.w_stararg is not None: - s_len = args.w_stararg.len() - assert s_len.is_constant(), "calls require known number of args" - nbargs += s_len.const - func = self.specialize_by_key(func, nbargs, - name='%s__%d' % (func.func_name, - nbargs)) # parse the arguments according to the function we are calling signature = cpython_code_signature(func.func_code) @@ -492,19 +487,21 @@ r = self.annotator.recursivecall(func, self.position_key, inputcells) - # in the case of argtypes specialisation we may have been calling a - # different function for the site which could also be just partially analysed, - # we need to force unifying all past and present results for the site - # in order to guarantee the more general results invariant. - if specialize == 'argtypes': - key = (base_func, self.position_key) - prev_r = self.argtypes_spec_callsite_results.get(key) - if prev_r is not None: - r = unionof(prev_r, r) - self.argtypes_spec_callsite_results[key] = r + # if we got different specializations keys for a same site, mix previous results for stability + if key is not None: + occurence = (base_func, self.position_key) + try: + prev_key, prev_r = self.spec_callsite_keys_results[occurence] + except KeyError: + self.spec_callsite_keys_results[occurence] = key, r + else: + if prev_key != key: + r = unionof(r, prev_r) + prev_key = None + self.spec_callsite_keys_results[occurence] = prev_key, r + return r - def whereami(self): return self.annotator.whereami(self.position_key) @@ -516,48 +513,39 @@ pos = '?' ansi_print("*** WARNING: [%s] %s" % (pos, msg), esc="31") # RED - def specialize_by_key(self, thing, key, name=None): - key = thing, key - try: - thing = self.cachespecializations[key] - except KeyError: - if isinstance(thing, FunctionType): - # XXX XXX XXX HAAAAAAAAAAAACK - # xxx we need a way to let know subsequent phases (the - # generator) about the specialized function. - # The caller flowgraph, as it is, doesn't know. - # This line just avoids that the flowgraph of the original - # function (which is what will be considered and compiled for - # now) will be computed during generation itself. - self.annotator.translator.getflowgraph(thing) - # - thing = func_with_new_name(thing, name or thing.func_name) - elif isinstance(thing, (type, ClassType)): - superclasses = iter(inspect.getmro(thing)) - superclasses.next() # skip thing itself - for cls in superclasses: - assert not hasattr(cls, "_specialize_"), "for now specialization only for leaf classes" - - newdict = {} - for attrname,val in thing.__dict__.iteritems(): - if attrname == '_specialize_': # don't copy the marker - continue - if isinstance(val, FunctionType): - fname = val.func_name - if name: - fname = "%s_for_%s" % (fname, name) - newval = func_with_new_name(val, fname) - # xxx more special cases - else: - newval = val - newdict[attrname] = newval - thing = type(thing)(name or thing.__name__, (thing,), newdict) - else: - raise Exception, "specializing %r?? why??"%thing - self.cachespecializations[key] = thing - return thing +def ishashable(x): + try: + hash(x) + except TypeError: + return False + else: + return True + +# for parsing call arguments +class RPythonCallsSpace: + """Pseudo Object Space providing almost no real operation. + For the Arguments class: if it really needs other operations, it means + that the call pattern is too complex for R-Python. + """ + def newtuple(self, items_s): + return SomeTuple(items_s) + + def newdict(self, stuff): + raise CallPatternTooComplex, "'**' argument" + + def unpackiterable(self, s_obj, expected_length=None): + if isinstance(s_obj, SomeTuple): + if (expected_length is not None and + expected_length != len(s_obj.items)): + raise ValueError + return s_obj.items + raise CallPatternTooComplex, "'*' argument must be SomeTuple" +class CallPatternTooComplex(Exception): + pass + +# get current bookkeeper def getbookkeeper(): """Get the current Bookkeeper. @@ -566,50 +554,3 @@ return TLS.bookkeeper except AttributeError: return None - -def ishashable(x): - try: - hash(x) - except TypeError: - return False - else: - return True - -def short_type_name(args): - l = [] - shape, args_w = args.flatten() - for x in args_w: - if isinstance(x, SomeInstance) and hasattr(x, 'knowntype'): - name = "SI_" + x.knowntype.__name__ - else: - name = x.__class__.__name__ - l.append(name) - return "__".join(l) - -def position_name((fn, block, i)): - mod = valid_identifier(getattr(fn, '__module__', 'SYNTH')) - name = valid_identifier(getattr(fn, '__name__', 'UNKNOWN')) - return "%s_%s_Giving_%s" % (mod, name, block.operations[i].result) - -def possible_arguments(args): - # enumerate all tuples (x1,..xn) of concrete values that are contained - # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either - # a constant or SomePBC. - if not args: - yield () - return - s = args[0] - if s.is_constant(): - possible_values = [s.const] - elif isinstance(s, SomePBC): - for value in s.prebuiltinstances.values(): - assert value is True, ("concrete call with a method bound " - "on a non-constant instance") - possible_values = s.prebuiltinstances.keys() - elif isinstance(s, SomeBool): - possible_values = [False, True] - else: - raise AssertionError, "concrete call with a non-constant arg %r" % (s,) - for tuple_tail in possible_arguments(args[1:]): - for value in possible_values: - yield (value,) + tuple_tail Added: pypy/dist/pypy/annotation/policy.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/annotation/policy.py Mon Jun 6 05:08:52 2005 @@ -0,0 +1,46 @@ +# base annotation policy for overrides and specialization +from pypy.annotation.specialize import memo, ctr_location, default_specialize as default + +class AnnotatorPolicy: + """ + Possibly subclass and pass an instance to the annotator to control special casing during annotation + """ + + def getspecialcase(pol, kind, obj): + if hasattr(obj, '_annspecialcase_'): + sc = obj._annspecialcase_.split(':') + assert len(sc) ==2, "_annspecialcase_ should have the form kind:tag" + if sc[0] == kind: + return sc[1] + assert sc[0] in ('override', 'specialize'), "_annspecialcase_ kinds are only 'override', 'specialize'" + return None + + def override(pol, func, inputcells): + tag = pol.getspecialcase('override', func) + if tag is None: + return None + try: + override = getattr(pol, 'override__%s' % tag) + except AttributeError: + raise AttributeError, "%s override tag found in user program but not defined in annotation policy %s" % (tag, pol) + + return override(*inputcells) + + def specialize(pol, bookkeeper, spaceop, func, args, mono): + tag = pol.getspecialcase('specialize', func) + if tag is None: + return pol.default_specialize(bookkeeper, spaceop, func, args, mono) + + try: + specialize = getattr(pol, 'specialize__%s' % tag) + except AttributeError: + raise AttributeError, "%s specialize tag found in user program but not defined in annotation policy %s" % (tag, pol) + + return specialize(bookkeeper, spaceop, func, args, mono) + + + # common specializations + + default_specialize = staticmethod(default) + specialize__memo = staticmethod(memo) + specialize__ctr_location = staticmethod(ctr_location) Added: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/annotation/specialize.py Mon Jun 6 05:08:52 2005 @@ -0,0 +1,199 @@ +# specialization support +import types, inspect, new + +from pypy.tool.sourcetools import valid_identifier, func_with_new_name + +def decide_callable(bookkeeper, position, func, args, mono=True, unpacked=False): + from pypy.objspace.flow.model import SpaceOperation + from pypy.annotation.model import SomeObject + + key = None + ismeth, im_class, im_self, func, args = unpack_method(bookkeeper, func, args) + + + if position is None or isinstance(position, SpaceOperation): + spaceop = position + else: + fn, block, i = position + spaceop = block.operations[i] + + key = bookkeeper.annotator.policy.specialize(bookkeeper, spaceop, func, args, mono) + if key is not None: + assert mono, "not-static call to specialized %s" % func + if isinstance(key, SomeObject): + # direct computation + return None, key + if isinstance(key, tuple): + # cache specialization + try: + func = bookkeeper.cachespecializations[key] + except KeyError: + postfix = key + if postfix[0] is func: + postfix = postfix[1:] + func = bookkeeper.cachespecializations[key] = clone(func, postfix) + elif isinstance(key, str): + # specialization explicit in operation annotation + postfix = key + func = clone(func, postfix) + else: + # specialization already retrieved + func = key + + if unpacked: + func = func, args + else: + func = repack_method(ismeth, im_class, im_self, func) + + return func, key + +def default_specialize(bookkeeper, spaceop, func, args, mono): + from pypy.interpreter.pycode import CO_VARARGS + if isinstance(func, types.FunctionType) and func.func_code.co_flags & CO_VARARGS: + # calls to *arg functions: create one version per number of args + assert mono, "not-static call to *arg function %s" % func + assert not args.has_keywords(), ( + "keyword forbidden in calls to *arg functions") + nbargs = len(args.arguments_w) + if args.w_stararg is not None: + s_len = args.w_stararg.len() + assert s_len.is_constant(), "calls require known number of args" + nbargs += s_len.const + return (func, nbargs) + return None # no specialization + +# helpers + +def unpack_method(bookkeeper, func, args): + if not hasattr(func, 'im_func'): + return False, None, None, func, args + if func.im_self is not None: + s_self = bookkeeper.immutablevalue(func.im_self) + args = args.prepend(s_self) + # for debugging only, but useful to keep anyway: + try: + func.im_func.class_ = func.im_class + except AttributeError: + # probably a builtin function, we don't care to preserve + # class information then + pass + return True, func.im_class, func.im_self, func.im_func, args + +def repack_method(ismeth, im_class, im_self, func): + if not ismeth: + return func + return new.instancemethod(func, im_self, im_class) + + +def clone(callb, postfix): + if not isinstance(postfix, str): + postfix = '_'.join([getattr(comp, '__name__', str(comp)) for comp in postfix]) + + name = valid_identifier(callb.__name__ + "__" + postfix) + + if isinstance(callb, types.FunctionType): + newcallb = func_with_new_name(callb, name) + elif isinstance(callb, (type, types.ClassType)): + superclasses = iter(inspect.getmro(callb)) + superclasses.next() # skip callb itself + for cls in superclasses: + assert not hasattr(cls, "_annspecialcase_"), "for now specialization only for leaf classes" + + newdict = {} + for attrname,val in callb.__dict__.iteritems(): + if attrname == '_annspecialcase_': # don't copy the marker + continue + if isinstance(val, types.FunctionType): + fname = val.func_name + fname = "%s_for_%s" % (fname, name) + newval = func_with_new_name(val, fname) + # xxx more special cases + else: + newval = val + newdict[attrname] = newval + + newcallb = type(callb)(name or callb.__name__, (callb,), newdict) + else: + raise Exception, "specializing %r?? why??" % callb + + return newcallb + +# ____________________________________________________________________________ +# specializations + +def memo(bookkeeper, spaceop, func, args, mono): + """NOT_RPYTHON""" + from pypy.annotation.model import unionof + # call the function now, and collect possible results + arglist_s, kwds_s = args.unpack() + assert not kwds_s, ("no ** args in call to function " + "marked specialize='concrete'") + possible_results = [] + for arglist in possible_arguments(arglist_s): + result = func(*arglist) + possible_results.append(bookkeeper.immutablevalue(result)) + return unionof(*possible_results) + +def possible_arguments(args): + from pypy.annotation.model import SomeBool, SomePBC + # enumerate all tuples (x1,..xn) of concrete values that are contained + # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either + # a constant or SomePBC. + if not args: + yield () + return + s = args[0] + if s.is_constant(): + possible_values = [s.const] + elif isinstance(s, SomePBC): + for value in s.prebuiltinstances.values(): + assert value is True, ("concrete call with a method bound " + "on a non-constant instance") + possible_values = s.prebuiltinstances.keys() + elif isinstance(s, SomeBool): + possible_values = [False, True] + else: + raise AssertionError, "concrete call with a non-constant arg %r" % (s,) + for tuple_tail in possible_arguments(args[1:]): + for value in possible_values: + yield (value,) + tuple_tail + +#def argtypes(bookkeeper, spaceop, func, args, mono): +# """NOT_RPYTHON""" +# from pypy.annotation.model import SomeInstance +# l = [] +# shape, args_w = args.flatten() +# for x in args_w: +# if isinstance(x, SomeInstance) and hasattr(x, 'knowntype'): +# name = "SI_" + x.knowntype.__name__ +# else: +# name = x.__class__.__name__ +# l.append(name) +# return func, "__".join(l) + +def ctr_location(bookkeeper, spaceop, orig_cls, args, mono): + """NOT_RPYTHON""" + from pypy.annotation.model import SomeInstance + v = spaceop.result + s_ins = bookkeeper.annotator.binding(v, extquery=True) + if s_ins is None: + return "Giving_"+v.name + else: + assert isinstance(s_ins, SomeInstance) + cls = s_ins.classdef.cls + assert issubclass(cls, orig_cls) + return cls + +def argvalue(i): + def specialize_argvalue(bookkeeper, spaceop, func, args, mono): + """NOT_RPYTHON""" + ignore, args_w = args.flatten() + return func, args_w[i].const + return specialize_argvalue + +def argtype(i): + def specialize_argtype(bookkeeper, spaceop, func, args, mono): + """NOT_RPYTHON""" + ignore, args_w = args.flatten() + return func, args_w[i].knowntype + return specialize_argtype Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Mon Jun 6 05:08:52 2005 @@ -12,7 +12,7 @@ from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeFloat from pypy.annotation.model import SomeIterator, SomePBC, new_or_old_class from pypy.annotation.model import unionof, set, setunion, missing_operation -from pypy.annotation.bookkeeper import getbookkeeper +from pypy.annotation.bookkeeper import getbookkeeper, RPythonCallsSpace from pypy.annotation.classdef import isclassdef from pypy.annotation import builtin @@ -131,12 +131,10 @@ return obj # default unbound __get__ implementation def simple_call(obj, *args_s): - space = RPythonCallsSpace() - return obj.call(Arguments(space, args_s)) + return obj.call(getbookkeeper().build_args("simple_call", args_s)) - def call_args(obj, s_shape, *args_s): - space = RPythonCallsSpace() - return obj.call(Arguments.fromshape(space, s_shape.const, args_s)) + def call_args(obj, *args_s): + return obj.call(getbookkeeper().build_args("call_args", args_s)) def call(obj, args, implicit_init=False): #raise Exception, "cannot follow call_args%r" % ((obj, args),) @@ -428,28 +426,6 @@ return immutablevalue(outcome) -class RPythonCallsSpace: - """Pseudo Object Space providing almost no real operation. - For the Arguments class: if it really needs other operations, it means - that the call pattern is too complex for R-Python. - """ - def newtuple(self, items_s): - return SomeTuple(items_s) - - def newdict(self, stuff): - raise CallPatternTooComplex, "'**' argument" - - def unpackiterable(self, s_obj, expected_length=None): - if isinstance(s_obj, SomeTuple): - if (expected_length is not None and - expected_length != len(s_obj.items)): - raise ValueError - return s_obj.items - raise CallPatternTooComplex, "'*' argument must be SomeTuple" - -class CallPatternTooComplex(Exception): - pass - # annotation of low-level types from pypy.annotation.model import SomePtr, ll_to_annotation, annotation_to_lltype class __extend__(SomePtr): Modified: pypy/dist/pypy/interpreter/compiler.py ============================================================================== --- pypy/dist/pypy/interpreter/compiler.py (original) +++ pypy/dist/pypy/interpreter/compiler.py Mon Jun 6 05:08:52 2005 @@ -112,6 +112,7 @@ raise OperationError(space.w_TypeError,space.wrap(str(e))) from pypy.interpreter.pycode import PyCode return space.wrap(PyCode(space)._from_code(c)) + compile._annspecialcase_ = "override:cpy_compile" def getcodeflags(self, code): from pypy.interpreter.pycode import PyCode Modified: pypy/dist/pypy/interpreter/error.py ============================================================================== --- pypy/dist/pypy/interpreter/error.py (original) +++ pypy/dist/pypy/interpreter/error.py Mon Jun 6 05:08:52 2005 @@ -70,6 +70,7 @@ application.""" if RECORD_INTERPLEVEL_TRACEBACK: self.debug_excs.append(sys.exc_info()) + record_interpreter_traceback._annspecialcase_ = "override:ignore" def print_application_traceback(self, space, file=None): "NOT_RPYTHON: Dump a standard application-level traceback." Modified: pypy/dist/pypy/interpreter/miscutils.py ============================================================================== --- pypy/dist/pypy/interpreter/miscutils.py (original) +++ pypy/dist/pypy/interpreter/miscutils.py Mon Jun 6 05:08:52 2005 @@ -8,7 +8,7 @@ class Stack: """Utility class implementing a stack.""" - _specialize_ = 'location' # polymorphic + _annspecialcase_ = "specialize:ctr_location" # polymorphic def __init__(self): self.items = [] Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Mon Jun 6 05:08:52 2005 @@ -19,6 +19,7 @@ """NOT_RPYTHON""" import sys return sys.exc_info()[2] +cpython_tb._annspecialcase_ = "override:ignore" class PyFrame(eval.Frame): """Represents a frame for a regular Python function Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon Jun 6 05:08:52 2005 @@ -33,7 +33,7 @@ subcls = _buildusercls(cls, hasdict, wants_slots) subclass_cache[key] = subcls return subcls -get_unique_interplevel_subclass._specialize_ = "memo" +get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" def _buildusercls(cls, hasdict, wants_slots): "NOT_RPYTHON: initialization-time only" @@ -109,6 +109,7 @@ return object.__new__(cls) else: return new.instance(cls) +instantiate._annspecialcase_ = "override:instantiate" def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): if func is None: Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Mon Jun 6 05:08:52 2005 @@ -80,6 +80,7 @@ """NOT_RPYTHON""" from pypy.tool.udir import udir return space.wrap(str(udir)) +pypy_getudir._annspecialcase_ = "override:ignore" def getdefaultencoding(space): return space.wrap(sys.getdefaultencoding()) Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Mon Jun 6 05:08:52 2005 @@ -17,7 +17,7 @@ return space.gettypeobject(ft.typedef) ft = fake_type(type(x)) return ft(space, x) - +fake_object._annspecialcase_ = "override:fake_object" import sys @@ -43,6 +43,7 @@ w_exc = space.wrap(exc) w_value = space.wrap(value) raise OperationError, OperationError(w_exc, w_value), tb +wrap_exception._annspecialcase_ = "override:ignore" def fake_type(cpy_type): assert type(cpy_type) is type Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Mon Jun 6 05:08:52 2005 @@ -238,7 +238,7 @@ from fake import fake_object return fake_object(self, x) - wrap._specialize_ = "argtypes" + wrap._annspecialcase_ = "specialize:argtype1" def wrap_exception_cls(self, x): """NOT_RPYTHON""" @@ -246,6 +246,7 @@ w_result = getattr(self, 'w_' + x.__name__) return w_result return None + wrap_exception_cls._annspecialcase_ = "override:wrap_exception_cls" def unwrap(self, w_obj): if isinstance(w_obj, BaseWrappable): @@ -324,8 +325,7 @@ instance.user_setup(self, w_subtype, w_subtype.nslots) assert isinstance(instance, cls) return instance - allocate_instance._specialize_ = "location" - + allocate_instance._annspecialcase_ = "specialize:arg1" def unpacktuple(self, w_tuple, expected_length=-1): assert isinstance(w_tuple, W_TupleObject) Modified: pypy/dist/pypy/tool/cache.py ============================================================================== --- pypy/dist/pypy/tool/cache.py (original) +++ pypy/dist/pypy/tool/cache.py Mon Jun 6 05:08:52 2005 @@ -37,7 +37,7 @@ result = self._build(key) self.content[key] = result return result - getorbuild._specialize_ = "memo" + getorbuild._annspecialcase_ = "specialize:memo" def _freeze_(self): # needs to be SomePBC, but otherwise we can't really freeze the Modified: pypy/dist/pypy/translator/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/ann_override.py (original) +++ pypy/dist/pypy/translator/ann_override.py Mon Jun 6 05:08:52 2005 @@ -1,55 +1,39 @@ # overrides for annotation specific to PyPy codebase +from pypy.annotation.policy import AnnotatorPolicy from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation import model as annmodel +from pypy.annotation import specialize -from pypy.interpreter import error -from pypy.interpreter import pyframe -from pypy.objspace.std import fake -from pypy.module.sys import state as sys_state -import pypy.interpreter.typedef as itypedef -import pypy.interpreter.pycode as pycode -import pypy.interpreter.compiler as icompiler -from pypy.objspace.std.objspace import StdObjSpace - -def ignore(*args): - bk = getbookkeeper() - return bk.immutablevalue(None) - -def instantiate(clspbc): - assert isinstance(clspbc, annmodel.SomePBC) - clsdef = None - for cls, v in clspbc.prebuiltinstances.items(): - if not clsdef: - clsdef = getbookkeeper().getclassdef(cls) - else: - clsdef = clsdef.commonbase(getbookkeeper().getclassdef(cls)) - return annmodel.SomeInstance(clsdef) - -def wrap_exception_cls(space, x): - import pypy.objspace.std.typeobject as typeobject - clsdef = getbookkeeper().getclassdef(typeobject.W_TypeObject) - return annmodel.SomeInstance(clsdef, can_be_None=True) - -def fake_object(space, x): - clsdef = getbookkeeper().getclassdef(itypedef.W_Root) - return annmodel.SomeInstance(clsdef) - -def cpy_compile(self, source, filename, mode, flags): - clsdef = getbookkeeper().getclassdef(pycode.PyCode) - return annmodel.SomeInstance(clsdef) - -pypy_overrides = {} - -def install(tgt, override): - if hasattr(tgt, 'im_func'): - tgt = tgt.im_func - pypy_overrides[tgt] = override - -install(pyframe.cpython_tb, ignore) -install(error.OperationError.record_interpreter_traceback, ignore) -install(sys_state.pypy_getudir, ignore) -install(fake.wrap_exception, ignore) -install(fake.fake_object, fake_object) -install(itypedef.instantiate, instantiate) -install(StdObjSpace.wrap_exception_cls, wrap_exception_cls) -install(icompiler.CPythonCompiler.compile, cpy_compile) +class PyPyAnnotatorPolicy(AnnotatorPolicy): + + def override__ignore(pol, *args): + bk = getbookkeeper() + return bk.immutablevalue(None) + + def override__instantiate(pol, clspbc): + assert isinstance(clspbc, annmodel.SomePBC) + clsdef = None + for cls, v in clspbc.prebuiltinstances.items(): + if not clsdef: + clsdef = getbookkeeper().getclassdef(cls) + else: + clsdef = clsdef.commonbase(getbookkeeper().getclassdef(cls)) + return annmodel.SomeInstance(clsdef) + + def override__wrap_exception_cls(pol, space, x): + import pypy.objspace.std.typeobject as typeobject + clsdef = getbookkeeper().getclassdef(typeobject.W_TypeObject) + return annmodel.SomeInstance(clsdef, can_be_None=True) + + def override__fake_object(pol, space, x): + from pypy.interpreter import typedef + clsdef = getbookkeeper().getclassdef(typedef.W_Root) + return annmodel.SomeInstance(clsdef) + + def override__cpy_compile(pol, self, source, filename, mode, flags): + from pypy.interpreter import pycode + clsdef = getbookkeeper().getclassdef(pycode.PyCode) + return annmodel.SomeInstance(clsdef) + + specialize__arg1 = staticmethod(specialize.argvalue(1)) + specialize__argtype1 = staticmethod(specialize.argtype(1)) Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Mon Jun 6 05:08:52 2005 @@ -12,12 +12,18 @@ class AnnotatorError(Exception): pass +class NullAnnotatorPolicy: + def override(pol, func, inputcells): + return None + + def specialize(pol, bookkeeper, spaceop, func, args, mono): + return None class RPythonAnnotator: """Block annotator for RPython. See description in doc/translation/annotation.txt.""" - def __init__(self, translator=None, overrides={}): + def __init__(self, translator=None, policy = None): self.translator = translator self.pendingblocks = {} # map {block: function} self.bindings = {} # map Variables to SomeValues @@ -42,21 +48,20 @@ # --- end of debugging information --- self.bookkeeper = Bookkeeper(self) # user-supplied annotation logic for functions we don't want to flow into - self.overrides = overrides + if policy is None: + self.policy = NullAnnotatorPolicy() + else: + self.policy = policy def __getstate__(self): attrs = """translator pendingblocks bindings annotated links_followed - notify bookkeeper overrides""".split() + notify bookkeeper policy""".split() ret = self.__dict__.copy() for key, value in ret.items(): if key not in attrs: assert type(value) is dict, ("please update %s.__getstate__" % self.__class__.__name__) ret[key] = {} - # special case: clean up the overrides which would trigger bad imports - overrides = ret['overrides'] = {} - for key in self.overrides: - overrides[key] = None return ret def _register_returnvar(self, flowgraph, func): @@ -232,9 +237,9 @@ #___ interface for annotator.bookkeeper _______ def recursivecall(self, func, position_key, inputcells): - override = self.overrides.get(func, None) - if override is not None: - return override(*inputcells) + overriden = self.policy.override(func, inputcells) + if overriden is not None: + return overriden parent_fn, parent_block, parent_index = position_key graph = self.getflowgraph(func, parent_fn, position_key) # self.notify[graph.returnblock] is a dictionary of call Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Mon Jun 6 05:08:52 2005 @@ -59,7 +59,7 @@ import threading, pdb from pypy.translator.translator import Translator -from pypy.translator.ann_override import pypy_overrides +from pypy.translator.ann_override import PyPyAnnotatorPolicy from pypy.annotation import model as annmodel from pypy.tool.cache import Cache from pypy.annotation.model import SomeObject @@ -85,7 +85,7 @@ if listen_port: run_async_server() if not options['-no-a']: - a = t.annotate(inputtypes, overrides=pypy_overrides) + a = t.annotate(inputtypes, policy=PyPyAnnotatorPolicy()) sanity_check_exceptblocks(t) worstblocks_topten(a) if not options['-no-s']: Modified: pypy/dist/pypy/translator/test/snippet.py ============================================================================== --- pypy/dist/pypy/translator/test/snippet.py (original) +++ pypy/dist/pypy/translator/test/snippet.py Mon Jun 6 05:08:52 2005 @@ -1136,7 +1136,7 @@ # class specialization class PolyStk: - _specialize_ = 'location' + _annspecialcase_ = "specialize:ctr_location" def __init__(self): self.itms = [] Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Mon Jun 6 05:08:52 2005 @@ -5,6 +5,8 @@ from pypy.translator.annrpython import annmodel from pypy.translator.translator import Translator +from pypy.annotation import policy +from pypy.annotation import specialize from pypy.annotation.listdef import ListDef from pypy.annotation.dictdef import DictDef from pypy.objspace.flow.model import * @@ -589,7 +591,7 @@ assert s == a.bookkeeper.immutablevalue(42) def test_class_spec(self): - a = self.RPythonAnnotator() + a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy()) s = a.build_types(snippet.class_spec, []) assert s.items[0].knowntype == int assert s.items[1].knowntype == str @@ -668,6 +670,7 @@ def record_exc(e): """NOT_RPYTHON""" excs.append(sys.exc_info) + record_exc._annspecialcase_ = "override:record_exc" def g(): pass def f(): @@ -675,9 +678,12 @@ g() except Exception, e: record_exc(e) - def ann_record_exc(s_e): - return a.bookkeeper.immutablevalue(None) - a = self.RPythonAnnotator(overrides={record_exc: ann_record_exc}) + class MyAnnotatorPolicy(policy.AnnotatorPolicy): + + def override__record_exc(pol, s_e): + return a.bookkeeper.immutablevalue(None) + + a = self.RPythonAnnotator(policy=MyAnnotatorPolicy()) s = a.build_types(f, []) assert s.const is None @@ -925,17 +931,37 @@ i = inst(cls) assert isinstance(i, cls) return i - alloc._specialize_ = "location" + alloc._annspecialcase_ = "specialize:arg0" def f(): c1 = alloc(C1) c2 = alloc(C2) return c1,c2 - a = self.RPythonAnnotator() + + class MyAnnotatorPolicy(policy.AnnotatorPolicy): + + specialize__arg0 = staticmethod(specialize.argvalue(0)) + + a = self.RPythonAnnotator(policy=MyAnnotatorPolicy()) s = a.build_types(f, []) assert s.items[0].knowntype == C1 assert s.items[1].knowntype == C2 + callb = a.getpbccallables() + assert alloc not in callb + def visit(block): + if isinstance(block, Block): + for spaceop in block.operations: + if spaceop.opname == "simple_call" and spaceop.args[0] == Constant(alloc): + spec_alloc, memo = a.bookkeeper.query_spaceop_callable(spaceop) + assert not memo + spec_alloc = spec_alloc.const + assert spec_alloc in callb + assert callb[spec_alloc] == {(None, spec_alloc): True} + assert (a.binding(a.translator.getflowgraph(spec_alloc).getreturnvar()).knowntype + == spaceop.args[1].value) + traverse(visit, a.translator.getflowgraph(f)) + def test_assert_list_doesnt_lose_info(self): class T(object): pass Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Mon Jun 6 05:08:52 2005 @@ -114,14 +114,14 @@ graph = self.getflowgraph(func) simplify_graph(graph, passes) - def annotate(self, input_args_types, func=None, overrides={}): + def annotate(self, input_args_types, func=None, policy=None): """annotate(self, input_arg_types[, func]) -> Annotator Provides type information of arguments. Returns annotator. """ func = func or self.entrypoint if self.annotator is None: - self.annotator = RPythonAnnotator(self, overrides=overrides) + self.annotator = RPythonAnnotator(self, policy=policy) graph = self.getflowgraph(func) self.annotator.build_types(graph, input_args_types, func) return self.annotator From pedronis at codespeak.net Mon Jun 6 05:30:18 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 6 Jun 2005 05:30:18 +0200 (CEST) Subject: [pypy-svn] r13089 - in pypy/branch/pypy-translation-snapshot: interpreter module/sys objspace/std Message-ID: <20050606033018.7280B27B53@code1.codespeak.net> Author: pedronis Date: Mon Jun 6 05:30:14 2005 New Revision: 13089 Modified: pypy/branch/pypy-translation-snapshot/interpreter/compiler.py pypy/branch/pypy-translation-snapshot/interpreter/error.py pypy/branch/pypy-translation-snapshot/interpreter/miscutils.py pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py pypy/branch/pypy-translation-snapshot/interpreter/typedef.py pypy/branch/pypy-translation-snapshot/module/sys/state.py pypy/branch/pypy-translation-snapshot/objspace/std/fake.py pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Log: merging new override/specialization markup from trunk Modified: pypy/branch/pypy-translation-snapshot/interpreter/compiler.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/compiler.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/compiler.py Mon Jun 6 05:30:14 2005 @@ -112,6 +112,7 @@ raise OperationError(space.w_TypeError,space.wrap(str(e))) from pypy.interpreter.pycode import PyCode return space.wrap(PyCode(space)._from_code(c)) + compile._annspecialcase_ = "override:cpy_compile" def getcodeflags(self, code): from pypy.interpreter.pycode import PyCode Modified: pypy/branch/pypy-translation-snapshot/interpreter/error.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/error.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/error.py Mon Jun 6 05:30:14 2005 @@ -70,6 +70,7 @@ application.""" if RECORD_INTERPLEVEL_TRACEBACK: self.debug_excs.append(sys.exc_info()) + record_interpreter_traceback._annspecialcase_ = "override:ignore" def print_application_traceback(self, space, file=None): "NOT_RPYTHON: Dump a standard application-level traceback." Modified: pypy/branch/pypy-translation-snapshot/interpreter/miscutils.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/miscutils.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/miscutils.py Mon Jun 6 05:30:14 2005 @@ -8,7 +8,7 @@ class Stack: """Utility class implementing a stack.""" - _specialize_ = 'location' # polymorphic + _annspecialcase_ = "specialize:ctr_location" # polymorphic def __init__(self): self.items = [] Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyframe.py Mon Jun 6 05:30:14 2005 @@ -19,6 +19,7 @@ """NOT_RPYTHON""" import sys return sys.exc_info()[2] +cpython_tb._annspecialcase_ = "override:ignore" class PyFrame(eval.Frame): """Represents a frame for a regular Python function Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/typedef.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Mon Jun 6 05:30:14 2005 @@ -33,7 +33,7 @@ subcls = _buildusercls(cls, hasdict, wants_slots) subclass_cache[key] = subcls return subcls -get_unique_interplevel_subclass._specialize_ = "memo" +get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" def _buildusercls(cls, hasdict, wants_slots): "NOT_RPYTHON: initialization-time only" @@ -109,6 +109,7 @@ return object.__new__(cls) else: return new.instance(cls) +instantiate._annspecialcase_ = "override:instantiate" def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): if func is None: Modified: pypy/branch/pypy-translation-snapshot/module/sys/state.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/sys/state.py (original) +++ pypy/branch/pypy-translation-snapshot/module/sys/state.py Mon Jun 6 05:30:14 2005 @@ -80,6 +80,7 @@ """NOT_RPYTHON""" from pypy.tool.udir import udir return space.wrap(str(udir)) +pypy_getudir._annspecialcase_ = "override:ignore" def getdefaultencoding(space): return space.wrap(sys.getdefaultencoding()) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/fake.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/fake.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/fake.py Mon Jun 6 05:30:14 2005 @@ -17,7 +17,7 @@ return space.gettypeobject(ft.typedef) ft = fake_type(type(x)) return ft(space, x) - +fake_object._annspecialcase_ = "override:fake_object" import sys @@ -43,6 +43,7 @@ w_exc = space.wrap(exc) w_value = space.wrap(value) raise OperationError, OperationError(w_exc, w_value), tb +wrap_exception._annspecialcase_ = "override:ignore" def fake_type(cpy_type): assert type(cpy_type) is type Modified: pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Mon Jun 6 05:30:14 2005 @@ -234,7 +234,7 @@ from fake import fake_object return fake_object(self, x) - wrap._specialize_ = "argtypes" + wrap._annspecialcase_ = "specialize:argtype1" def wrap_exception_cls(self, x): """NOT_RPYTHON""" @@ -242,6 +242,7 @@ w_result = getattr(self, 'w_' + x.__name__) return w_result return None + wrap_exception_cls._annspecialcase_ = "override:wrap_exception_cls" def unwrap(self, w_obj): if isinstance(w_obj, BaseWrappable): @@ -320,8 +321,7 @@ instance.user_setup(self, w_subtype, w_subtype.nslots) assert isinstance(instance, cls) return instance - allocate_instance._specialize_ = "location" - + allocate_instance._annspecialcase_ = "specialize:arg1" def unpacktuple(self, w_tuple, expected_length=-1): assert isinstance(w_tuple, W_TupleObject) From tismer at codespeak.net Mon Jun 6 05:38:02 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 6 Jun 2005 05:38:02 +0200 (CEST) Subject: [pypy-svn] r13090 - in pypy/dist/pypy: interpreter objspace/flow translator/pickle Message-ID: <20050606033802.9731C27B51@code1.codespeak.net> Author: tismer Date: Mon Jun 6 05:38:00 2005 New Revision: 13090 Modified: pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/pickle/genpickle.py Log: a few small optimizations get the size of the pickle from 68 MB down to 46 MB Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Mon Jun 6 05:38:00 2005 @@ -493,7 +493,8 @@ # class ApplevelClass: - """A container for app-level source code that should be executed + """NOT_RPYTHON + A container for app-level source code that should be executed as a module in the object space; interphook() builds a static interp-level function that invokes the callable with the given name at app-level.""" @@ -548,7 +549,8 @@ class ApplevelCache(SpaceCache): - """The cache mapping each applevel instance to its lazily built w_dict""" + """NOT_RPYTHON + The cache mapping each applevel instance to its lazily built w_dict""" def build(self, app): "NOT_RPYTHON. Called indirectly by Applevel.getwdict()." @@ -577,6 +579,7 @@ # __________ geninterplevel version __________ class PyPyCacheDir: + "NOT_RPYTHON" # similar to applevel, but using translation to interp-level. # This version maintains a cache folder with single files. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Mon Jun 6 05:38:00 2005 @@ -6,8 +6,6 @@ from __future__ import generators from pypy.tool.uid import Hashable -from pypy.translator.pickle.slotted import Slotted - """ memory size before and after introduction of __slots__ using targetpypymain with -no-c @@ -32,7 +30,7 @@ __metaclass__ = type -class FunctionGraph(Slotted): +class FunctionGraph(object): __slots__ = """func source name startblock returnblock exceptblock""".split() def __init__(self, name, startblock, return_var=None): @@ -75,7 +73,7 @@ from pypy.translator.tool.graphpage import SingleGraphPage SingleGraphPage(self).display() -class Link(Slotted): +class Link(object): __slots__ = """args target exitcase prevblock last_exception last_exc_value""".split() @@ -116,7 +114,7 @@ def __repr__(self): return "link from %s to %s" % (str(self.prevblock), str(self.target)) -class Block(Slotted): +class Block(object): __slots__ = """isstartblock inputargs operations exitswitch exits exc_handler""".split() @@ -186,7 +184,7 @@ self.exits = exits -class Variable(Slotted): +class Variable(object): __slots__ = ["_name", "concretetype"] countall = 0 @@ -236,12 +234,41 @@ name = '_' + name self._name = name + '_' + self.name[1:] + def __reduce_ex__(self, *args): + if hasattr(self, 'concretetype'): + return _buildvar, (self._name, self.concretetype) + else: + return _buildvar, (self._name,) + __reduce__ = __reduce_ex__ + +def _buildvar(_name, concretetype=None): + v = Variable.__new__(Variable, object) + v._name = _name + if concretetype is not None: + v.concretetype = concretetype + if type(_name) is int: + if _name > Variable.countall: + Variable.countall = _name + if COUNTOBJECTS: + Variable.countcurr += 1 + Variable.countmax = max(Variable.countmax, Variable.countcurr) + return v -class Constant(Hashable, Slotted): +class Constant(Hashable): __slots__ = ["concretetype"] + def __init__(self, value, concretetype = None): + Hashable.__init__(self, value) + if concretetype is not None: + self.concretetype = concretetype + def __reduce_ex__(self, *args): + if hasattr(self, 'concretetype'): + return Constant, (self.value, self.concretetype) + else: + return Constant, (self.value,) + __reduce__ = __reduce_ex__ -class SpaceOperation(Slotted): +class SpaceOperation(object): __slots__ = "opname args result offset".split() def __init__(self, opname, args, result, offset=-1): @@ -265,6 +292,9 @@ def __repr__(self): return "%r = %s(%s)" % (self.result, self.opname, ", ".join(map(repr, self.args))) + def __reduce_ex__(self, *args): + return SpaceOperation, (self.opname, self.args, self.result, self.offset) + class Atom: def __init__(self, name): self.name = name Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Mon Jun 6 05:38:00 2005 @@ -14,6 +14,7 @@ from pypy.rpython.rarithmetic import r_int, r_uint from pypy.objspace.flow.model import Variable, Constant, SpaceOperation from pypy.objspace.flow.model import FunctionGraph, Block, Link +from pypy.objspace.flow.flowcontext import SpamBlock, EggBlock from pypy.interpreter.baseobjspace import ObjSpace from pypy.translator.pickle import slotted @@ -64,6 +65,16 @@ 'pypy.module.', '__main__', ) + self.shortnames = { + SpaceOperation: 'S', + Variable: 'V', + Constant: 'C', + Block: 'B', + SpamBlock: 'SB', + EggBlock: 'EB', + Link: 'L', + FunctionGraph: 'F', + } self.outfile = outfile self._partition = 1234 @@ -387,13 +398,14 @@ return name def nameof_list(self, lis): - name = self.uniquename('g%dlist' % len(lis)) + name = self.uniquename('L%d' % len(lis)) + extend = self.nameof(_ex) def initlist(): chunk = 20 for i in range(0, len(lis), chunk): items = lis[i:i+chunk] itemstr = self.nameofargs(items) - yield '%s.extend([%s])' % (name, itemstr) + yield '%s(%s, %s)' % (extend, name, itemstr) self.initcode_python(name, '[]') self.later(initlist()) return name @@ -420,7 +432,7 @@ module, dictname) ) self.picklenames[Constant(dic)] = dictname return dictname - name = self.uniquename('g%ddict' % len(dic)) + name = self.uniquename('D%d' % len(dic)) def initdict(): for k in dic: try: @@ -449,7 +461,10 @@ def nameof_instance(self, instance): klass = instance.__class__ - name = self.uniquename('ginst_' + klass.__name__) + if klass in self.shortnames: + name = self.uniquename(self.shortnames[klass]) + else: + name = self.uniquename('ginst_' + klass.__name__) cls = self.nameof(klass) if hasattr(klass, '__base__'): base_class = builtin_base(instance) @@ -464,7 +479,9 @@ yield '%s.__setstate__(%s)' % (name, args) return elif type(restorestate) is tuple: - slotted.__setstate__(instance, restorestate) + setstate = self.nameof(slotted.__setstate__) + args = self.nameof(restorestate) + yield '%s(%s, %s)' % (setstate, name, args) return assert type(restorestate) is dict, ( "%s has no dict and no __setstate__" % name) @@ -491,10 +508,12 @@ ' about __slots__ in %s instance without __setstate__,' ' please update %s' % (cls.__name__, __name__) ) restorestate = slotted.__getstate__(instance) - restorer = _reconstructor + restorer = _rec restoreargs = klass, object, None else: restorer = reduced[0] + if restorer is _reconstructor: + restorer = _rec restoreargs = reduced[1] if len(reduced) > 2: restorestate = reduced[2] @@ -702,3 +721,11 @@ func.func_defaults, (cel,)) func = new.function(*args) return func() + +# some shortcuts, to make the pickle smaller + +def _ex(lis, *args): + lis.extend(args) + +def _rec(*args): + return _reconstructor(*args) From tismer at codespeak.net Mon Jun 6 05:53:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 6 Jun 2005 05:53:26 +0200 (CEST) Subject: [pypy-svn] r13091 - in pypy/dist/pypy: objspace/flow translator/pickle Message-ID: <20050606035326.EEBF627B51@code1.codespeak.net> Author: tismer Date: Mon Jun 6 05:53:24 2005 New Revision: 13091 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/pickle/genpickle.py Log: some more cheapoptimizations get us below 45 MB Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Mon Jun 6 05:53:24 2005 @@ -236,12 +236,12 @@ def __reduce_ex__(self, *args): if hasattr(self, 'concretetype'): - return _buildvar, (self._name, self.concretetype) + return _bv, (self._name, self.concretetype) else: - return _buildvar, (self._name,) + return _bv, (self._name,) __reduce__ = __reduce_ex__ -def _buildvar(_name, concretetype=None): +def _bv(_name, concretetype=None): v = Variable.__new__(Variable, object) v._name = _name if concretetype is not None: Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Mon Jun 6 05:53:24 2005 @@ -15,6 +15,8 @@ from pypy.objspace.flow.model import Variable, Constant, SpaceOperation from pypy.objspace.flow.model import FunctionGraph, Block, Link from pypy.objspace.flow.flowcontext import SpamBlock, EggBlock +from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool +from pypy.annotation.model import SomeList, SomeString, SomeTuple from pypy.interpreter.baseobjspace import ObjSpace from pypy.translator.pickle import slotted @@ -74,6 +76,13 @@ EggBlock: 'EB', Link: 'L', FunctionGraph: 'F', + SomeInteger: 'SI', + SomeObject: 'SO', + SomeChar: 'SC', + SomeBool: 'SB', + SomeList: 'SL', + SomeString: 'SS', + SomeTuple: 'ST', } self.outfile = outfile self._partition = 1234 From arigo at codespeak.net Mon Jun 6 11:33:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 11:33:13 +0200 (CEST) Subject: [pypy-svn] r13092 - in pypy/dist/pypy/rpython: . test Message-ID: <20050606093313.97F3627B57@code1.codespeak.net> Author: arigo Date: Mon Jun 6 11:33:11 2005 New Revision: 13092 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Class attributes used as defaults for instance attributes. Reorganized test_rclass a bit. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jun 6 11:33:11 2005 @@ -322,7 +322,18 @@ resulttype = GcPtr(self.object_type)) ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable()) self.setfield(vptr, '__class__', ctypeptr, llops) - # XXX instance attributes + # initialize instance attributes from their defaults from the class + flds = self.allinstancefields.keys() + flds.sort() + mro = list(self.classdef.getmro()) + mro.reverse() + for clsdef in mro: + for fldname in flds: + if fldname in clsdef.cls.__dict__: + mangled_name, r = self.allinstancefields[fldname] + value = clsdef.cls.__dict__[fldname] + cvalue = inputconst(r, value) + self.setfield(vptr, fldname, cvalue, llops) return vptr def rtype_type(self, hop): Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Mon Jun 6 11:33:11 2005 @@ -3,6 +3,15 @@ from pypy.rpython.rtyper import RPythonTyper +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() + return t + class EmptyBase(object): pass @@ -12,13 +21,7 @@ def dummyfn(): x = EmptyBase() return x - - t = Translator(dummyfn) - t.annotate([]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + rtype(dummyfn) def test_instanceattr(): def dummyfn(): @@ -26,13 +29,7 @@ x.a = 5 x.a += 1 return x.a - - t = Translator(dummyfn) - t.annotate([]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + rtype(dummyfn) class Random: @@ -43,10 +40,11 @@ def dummyfn(): x = Random() return x.xyzzy + rtype(dummyfn) - t = Translator(dummyfn) - t.annotate([]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() +def test_classattr_as_defaults(): + def dummyfn(): + x = Random() + x.xyzzy += 1 + return x.xyzzy + rtype(dummyfn).view() From adim at codespeak.net Mon Jun 6 12:51:44 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 6 Jun 2005 12:51:44 +0200 (CEST) Subject: [pypy-svn] r13094 - pypy/branch/pycompiler/module/recparser/data Message-ID: <20050606105144.165FF27B53@code1.codespeak.net> Author: adim Date: Mon Jun 6 12:51:42 2005 New Revision: 13094 Modified: pypy/branch/pycompiler/module/recparser/data/Grammar2.4 Log: modified python2.4's grammar file for arglist (like it was done for the python2.3's grammar a few weeks ago because function calls like f(a,) raised a SyntaxError) Now each test in test_samples.py should pass with both 2.3 and 2.4 Modified: pypy/branch/pycompiler/module/recparser/data/Grammar2.4 ============================================================================== --- pypy/branch/pycompiler/module/recparser/data/Grammar2.4 (original) +++ pypy/branch/pycompiler/module/recparser/data/Grammar2.4 Mon Jun 6 12:51:42 2005 @@ -90,7 +90,8 @@ listmaker: test ( list_for | (',' test)* [','] ) testlist_gexp: test ( gen_for | (',' test)* [','] ) lambdef: 'lambda' [varargslist] ':' test -trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | [test] ':' [test] [sliceop] | test sliceop: ':' [test] @@ -101,7 +102,8 @@ classdef: 'class' NAME ['(' testlist ')'] ':' suite -arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +# arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) +arglist: (argument ',')* ( '*' test [',' '**' test] | '**' test | argument | [argument ','] ) argument: [test '='] test [gen_for] # Really [keyword '='] test list_iter: list_for | list_if From arigo at codespeak.net Mon Jun 6 13:01:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 13:01:11 +0200 (CEST) Subject: [pypy-svn] r13095 - in pypy/dist/pypy/rpython: . test Message-ID: <20050606110111.C442027B53@code1.codespeak.net> Author: arigo Date: Mon Jun 6 13:01:08 2005 New Revision: 13095 Added: pypy/dist/pypy/rpython/test/test_rpbc.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Some work on rpbc: variables pointing to multiple functions. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jun 6 13:01:08 2005 @@ -1,6 +1,7 @@ import types from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel +from pypy.annotation.classdef import isclassdef from pypy.rpython.lltype import typeOf, Void from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass @@ -8,41 +9,153 @@ class __extend__(annmodel.SomePBC): def rtyper_makerepr(self, rtyper): - return PBCRepr(self.prebuiltinstances) + # for now, we require that the PBC fits neatly into one of the Repr + # categories below, and doesn't for example mix functions, classes + # and methods. + callb = rtyper.annotator.getpbccallables() + choices = {} + for x, classdef in self.prebuiltinstances.items(): + cdefflag = isclassdef(classdef) + + # consider unbound methods as plain functions + if isinstance(x, types.MethodType) and x.im_self is None: + x = x.im_func + + # callable or frozen object? + if x in callb: + # what type of callable? + if isinstance(x, types.FunctionType): + if cdefflag: + choice = MethodsPBCRepr + cdefflag = False + else: + choice = FunctionsPBCRepr + elif isinstance(x, (type, types.ClassType)): + choice = ClassesPBCRepr + #elif isinstance(x, types.MethodType): + # choice = ConstMethodsPBCRepr + else: + raise TyperError("don't know about callable %r" % (x,)) + else: + # frozen object + choice = FrozenPBCRepr + if cdefflag: + raise TyperError("unexpected classdef in PBC set %r" % ( + self.prebuiltinstances,)) + choices[choice] = True -class PBCRepr(Repr): + if len(choices) > 1: + raise TyperError("mixed kinds of PBC in the set %r" % ( + self.prebuiltinstances,)) + reprcls, = choices + return reprcls(rtyper, self) - def __init__(self, prebuiltinstances): - self.prebuiltinstances = prebuiltinstances - assert len(prebuiltinstances) == 1, "Not Implemented: multiPBCs" - self.lowleveltype = Void + +# ____________________________________________________________ + + +class FrozenPBCRepr(Repr): + """Representation selected for a single non-callable pre-built constant.""" + lowleveltype = Void + + def __init__(self, rtyper, s_pbc): + assert len(s_pbc.prebuiltinstances) == 1 # XXX not implemented def rtype_getattr(_, hop): - if hop.s_result.is_constant(): - return hop.inputconst(hop.r_result, hop.s_result.const) + if not hop.s_result.is_constant(): + raise TyperError("getattr on a constant PBC returns a non-constant") + return hop.inputconst(hop.r_result, hop.s_result.const) + + +# ____________________________________________________________ + + +def getsignature(rtyper, func): + f = rtyper.getfunctionptr(func) + graph = f._obj.graph + FUNCPTR = typeOf(f) + rinputs = [rtyper.bindingrepr(v) for v in graph.getargs()] + if graph.getreturnvar() in rtyper.annotator.bindings: + rresult = rtyper.bindingrepr(graph.getreturnvar()) + else: + rresult = Void + return f, rinputs, rresult + + +class FunctionsPBCRepr(Repr): + """Representation selected for a PBC of function(s).""" + + def __init__(self, rtyper, s_pbc): + self.rtyper = rtyper + self.s_pbc = s_pbc + self.function_signatures = {} + for func in s_pbc.prebuiltinstances: + self.function_signatures[func] = getsignature(rtyper, func) + + if len(self.function_signatures) == 1: + # a single function + self.lowleveltype = Void else: - NotImplementedYet - - def rtype_simple_call(_, hop): - r_func, s_func = hop.r_s_popfirstarg() - if not s_func.is_constant(): - NotImplementedYet - func = s_func.const - if isinstance(func, types.FunctionType): - # XXX hackish - f = hop.rtyper.getfunctionptr(func) - graph = f._obj.graph - FUNCPTR = typeOf(f) - rinputs = [hop.rtyper.bindingrepr(v) for v in graph.getargs()] - if FUNCPTR.TO.RESULT == Void: - rresult = Void - else: - rresult = hop.rtyper.bindingrepr(graph.getreturnvar()) - args_v = hop.inputargs(*rinputs) - c = hop.inputconst(FUNCPTR, f) - return hop.genop('direct_call', [c] + args_v, - resulttype = rresult) - elif isinstance(func, (types.ClassType, type)): - return rclass.rtype_new_instance(s_func.const, hop) - # XXX call __init__ somewhere + signatures = self.function_signatures.values() + sig0 = signatures[0] + for sig1 in signatures[1:]: + assert typeOf(sig0[0]) == typeOf(sig1[0]) # XXX not implemented + assert sig0[1:] == sig1[1:] # XXX not implemented + self.lowleveltype = typeOf(sig0[0]) + +## callfamilies = rtyper.annotator.getpbccallfamilies() +## try: +## _, _, callfamily = callfamilies[None, functions[0]] +## except KeyError: +## self.lowleveltype = Void # no call family found +## else: +## shapes = callfamily.patterns +## assert len(shapes) == 1, "XXX not implemented" +## shape, = shapes +## shape_cnt, shape_keys, shape_star, shape_stst = shape +## assert not shape_keys, "XXX not implemented" +## assert not shape_star, "XXX not implemented" +## assert not shape_stst, "XXX not implemented" + + def convert_const(self, value): + if value not in self.function_signatures: + raise TyperError("%r not in %r" % (value, + self.s_pbc.prebuiltinstances)) + f, rinputs, rresult = self.function_signatures[value] + return f + + def rtype_simple_call(self, hop): + f, rinputs, rresult = self.function_signatures.itervalues().next() + vlist = hop.inputargs(self, *rinputs) + if self.lowleveltype == Void: + assert len(self.function_signatures) == 1 + vlist[0] = hop.inputconst(typeOf(f), f) + return hop.genop('direct_call', vlist, resulttype = rresult) + + +# ____________________________________________________________ + + +class ClassesPBCRepr(Repr): + """Representation selected for a PBC of class(es).""" + + def __init__(self, rtyper, s_pbc): + self.rtyper = rtyper + self.s_pbc = s_pbc + assert s_pbc.is_constant() # XXX not implemented + self.lowleveltype = Void +## self.classdefs = {} +## for cls in s_pbc.prebuiltinstances: +## self.classdefs[cls] = rtyper.annotator.getuserclasses()[cls] +## classdefslist = self.classdefs.values() +## commonbase = classdefslist[0] +## for cdef in classdefslist[1:]: +## commonbase = cdef.commonbase(commonbase) +## if commonbase is None: +## raise TyperError("no common base class in PBC set %r" % ( +## s_pbc.prebuiltinstances,)) + + def rtype_simple_call(self, hop): + return rclass.rtype_new_instance(self.s_pbc.const, hop) + # XXX call __init__ somewhere Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Mon Jun 6 13:01:08 2005 @@ -12,7 +12,7 @@ debug = False -crash_on_first_typeerror = False +crash_on_first_typeerror = True # XXX copied from pypy.translator.typer and modified. # We'll remove pypy.translator.typer at some point. Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Mon Jun 6 13:01:08 2005 @@ -47,4 +47,4 @@ x = Random() x.xyzzy += 1 return x.xyzzy - rtype(dummyfn).view() + rtype(dummyfn) Added: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Mon Jun 6 13:01:08 2005 @@ -0,0 +1,34 @@ +from pypy.translator.translator import Translator +from pypy.rpython.lltype import * +from pypy.rpython.rtyper import RPythonTyper + + +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() + return t + + +def test_easy_call(): + def f(x): + return x+1 + def g(y): + return f(y+2) + rtype(g, [int]) + +def test_multiple_call(): + def f1(x): + return x+1 + def f2(x): + return x+2 + def g(y): + if y < 0: + f = f1 + else: + f = f2 + return f(y+3) + rtype(g, [int]) From adim at codespeak.net Mon Jun 6 13:14:08 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 6 Jun 2005 13:14:08 +0200 (CEST) Subject: [pypy-svn] r13096 - pypy/branch/pycompiler/module/recparser/test Message-ID: <20050606111408.B0DE227B53@code1.codespeak.net> Author: adim Date: Mon Jun 6 13:14:07 2005 New Revision: 13096 Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py Log: fixed tests to match the new lexer API Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py Mon Jun 6 13:14:07 2005 @@ -1,14 +1,16 @@ from pypy.module.recparser.pythonlexer import PythonSource, py_number, \ g_symdef, g_string, py_name, py_punct +from pypy.module.recparser.grammar import Token def parse_source(source): """returns list of parsed tokens""" lexer = PythonSource(source) tokens = [] - last_token = '' - while last_token != 'ENDMARKER': - last_token, value = lexer.next() - tokens.append((last_token, value)) + last_token = Token(None, None) + while last_token.name != 'ENDMARKER': + last_token = lexer.next() + # tokens.append((last_token, value)) + tokens.append(last_token) return tokens ## class TestSuite: @@ -53,27 +55,30 @@ s = """['a' ]""" tokens = parse_source(s) - assert tokens == [('[', None), ('STRING', "'a'"), (']', None), - ('NEWLINE', ''), ('ENDMARKER', None)] + assert tokens == [Token('[', None), Token('STRING', "'a'"), + Token(']', None), Token('NEWLINE', ''), + Token('ENDMARKER', None)] def test_numbers(): """make sure all kind of numbers are correctly parsed""" for number in NUMBERS: - assert parse_source(number)[0] == ('NUMBER', number) + assert parse_source(number)[0] == Token('NUMBER', number) neg = '-%s' % number - assert parse_source(neg)[:2] == [('-', None), ('NUMBER', number)] + assert parse_source(neg)[:2] == [Token('-', None), + Token('NUMBER', number)] for number in BAD_NUMBERS: - assert parse_source(number)[0] != ('NUMBER', number) + assert parse_source(number)[0] != Token('NUMBER', number) def test_hex_number(): """basic pasrse""" tokens = parse_source("a = 0x12L") - assert tokens == [('NAME', 'a'), ('=', None), ('NUMBER', '0x12L'), - ('NEWLINE', ''), ('ENDMARKER', None)] + assert tokens == [Token('NAME', 'a'), Token('=', None), + Token('NUMBER', '0x12L'), Token('NEWLINE', ''), + Token('ENDMARKER', None)] def test_punct(): """make sure each punctuation is correctly parsed""" for pstr in PUNCTS: tokens = parse_source(pstr) - assert tokens[0][0] == pstr + assert tokens[0].name == pstr From arigo at codespeak.net Mon Jun 6 14:20:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 14:20:27 +0200 (CEST) Subject: [pypy-svn] r13099 - in pypy/dist/pypy/rpython: . test Message-ID: <20050606122027.9E2AC27B50@code1.codespeak.net> Author: arigo Date: Mon Jun 6 14:20:24 2005 New Revision: 13099 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rrange.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rrange.py Log: Fixed list iterators and copied them to make range iterators. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon Jun 6 14:20:24 2005 @@ -140,8 +140,8 @@ citerptr = hop.inputconst(Void, self.lowleveltype) return hop.gendirectcall(ll_listiter, citerptr, v_lst) - def next(self, hop): - v_iter = hop.inputargs(self) + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) return hop.gendirectcall(ll_listnext, v_iter) def ll_listiter(ITERPTR, lst): @@ -156,4 +156,4 @@ if index >= len(l.items): raise StopIteration iter.index = index + 1 - return l.items[index] + return l.items[index].item Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Mon Jun 6 14:20:24 2005 @@ -13,10 +13,11 @@ # } RANGE = GcStruct("range", ("start", Signed), ("stop", Signed)) +RANGEITER = GcStruct("range", ("next", Signed), ("stop", Signed)) class RangeRepr(Repr): - lowlevelrepr = GcPtr(RANGE) + lowleveltype = GcPtr(RANGE) def __init__(self, step): self.step = step @@ -27,7 +28,7 @@ return hop.gendirectcall(ll_rangelen, v_rng, cstep) def make_iterator_repr(self): - return riter.RangeIteratorRepr(self) + return RangeIteratorRepr(self) class __extend__(pairtype(RangeRepr, IntegerRepr)): @@ -95,3 +96,47 @@ raise TyperError("range() result used as a normal list: " "XXX not implemented") #return hop.gendirectcall(ll_range2list, vstart, vstop, vstep) + +# ____________________________________________________________ +# +# Iteration. + +class RangeIteratorRepr(Repr): + lowleveltype = GcPtr(RANGEITER) + + def __init__(self, r_rng): + self.r_rng = r_rng + + def newiter(self, hop): + v_rng, = hop.inputargs(self.r_rng) + citerptr = hop.inputconst(Void, self.lowleveltype) + return hop.gendirectcall(ll_rangeiter, citerptr, v_rng) + + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) + cstep = hop.inputconst(Signed, self.r_rng.step) + if self.r_rng.step > 0: + llfn = ll_rangenext_up + else: + llfn = ll_rangenext_down + return hop.gendirectcall(llfn, v_iter, cstep) + +def ll_rangeiter(ITERPTR, rng): + iter = malloc(ITERPTR.TO) + iter.next = rng.start + iter.stop = rng.stop + return iter + +def ll_rangenext_up(iter, step): + next = iter.next + if next >= iter.stop: + raise StopIteration + iter.next = next + step + return next + +def ll_rangenext_down(iter, step): + next = iter.next + if next <= iter.stop: + raise StopIteration + iter.next = next + step + return next Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Mon Jun 6 14:20:24 2005 @@ -21,57 +21,41 @@ # ____________________________________________________________ -def test_simple(): - def dummyfn(): - l = [10,20,30] - return l[2] - - t = Translator(dummyfn) - t.annotate([]) +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) typer = RPythonTyper(t.annotator) typer.specialize() #t.view() t.checkgraphs() + return t +def test_simple(): + def dummyfn(): + l = [10,20,30] + return l[2] + rtype(dummyfn) + def test_append(): def dummyfn(): l = [] l.append(5) l.append(6) return l[0] - - t = Translator(dummyfn) - t.annotate([]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - + rtype(dummyfn) def test_len(): def dummyfn(): l = [5,10] return len(l) + rtype(dummyfn) - t = Translator(dummyfn) - t.annotate([]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - - -def DONT_YET_test_range(): - def dummyfn(N): +def test_iterate(): + def dummyfn(): total = 0 - for i in range(N): - total += i + for x in [1,3,5,7,9]: + total += x return total + rtype(dummyfn) - t = Translator(dummyfn) - t.annotate([]) - typer = RPythonTyper(t.annotator) - typer.specialize() - t.view() - t.checkgraphs() Modified: pypy/dist/pypy/rpython/test/test_rrange.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rrange.py (original) +++ pypy/dist/pypy/rpython/test/test_rrange.py Mon Jun 6 14:20:24 2005 @@ -1,3 +1,5 @@ +from pypy.translator.translator import Translator +from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rrange import * def test_rlist_range(): @@ -17,3 +19,23 @@ for stop in (-8, 0, 4, 8, 25): for step in (1, 2, 3, -1, -2): test1(start, stop, step) + +# ____________________________________________________________ + +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() + return t + + +def test_range(): + def dummyfn(N): + total = 0 + for i in range(N): + total += i + return total + rtype(dummyfn, [int]) From arigo at codespeak.net Mon Jun 6 14:27:07 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 14:27:07 +0200 (CEST) Subject: [pypy-svn] r13100 - pypy/dist/pypy/translator Message-ID: <20050606122707.55FF827B3E@code1.codespeak.net> Author: arigo Date: Mon Jun 6 14:27:05 2005 New Revision: 13100 Modified: pypy/dist/pypy/translator/transform.py Log: Forgot to check this in. Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Mon Jun 6 14:27:05 2005 @@ -317,6 +317,8 @@ s_value = annmodel.SomeInstance(self.bookkeeper.getclassdef(Exception)) self.setbinding(etype, s_type) self.setbinding(evalue, s_value) + # make sure the bookkeeper knows about AssertionError + self.bookkeeper.getclassdef(AssertionError) def transform_graph(ann): From arigo at codespeak.net Mon Jun 6 14:28:17 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 14:28:17 +0200 (CEST) Subject: [pypy-svn] r13101 - in pypy/dist/pypy/rpython: . test Message-ID: <20050606122817.8D58027B3E@code1.codespeak.net> Author: arigo Date: Mon Jun 6 14:28:15 2005 New Revision: 13101 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: Bug in rlist related to listdefs that compare != but are the same in the sense of "same_as()". Discovered by testing recursive lists. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon Jun 6 14:28:15 2005 @@ -25,15 +25,17 @@ else: # cannot do the rtyper.getrepr() call immediately, for the case # of recursive structures -- i.e. if the listdef contains itself - return ListRepr(lambda: rtyper.getrepr(listitem.s_value)) + return ListRepr(lambda: rtyper.getrepr(listitem.s_value), + self.listdef) class ListRepr(Repr): - def __init__(self, item_repr): + def __init__(self, item_repr, listdef=None): self.LIST = GcForwardReference() self.lowleveltype = GcPtr(self.LIST) self.item_repr = item_repr # possibly uncomputed at this point! + self.listdef = listdef # setup() needs to be called to finish this initialization def setup(self): @@ -66,6 +68,15 @@ llfn = ll_getitem return hop.gendirectcall(llfn, v_lst, v_index) + +class __extend__(pairtype(ListRepr, ListRepr)): + def convert_from_to((r_lst1, r_lst2), v, llops): + if r_lst1.listdef is None or r_lst2.listdef is None: + return NotImplemented + if not r_lst1.listdef.same_as(r_lst2.listdef): + return NotImplemented + return v + # ____________________________________________________________ # # Low-level methods. These can be run for testing, but are meant to Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Mon Jun 6 14:28:15 2005 @@ -59,3 +59,11 @@ return total rtype(dummyfn) +def test_recursive(): + def dummyfn(N): + l = [] + while N > 0: + l = [l] + N -= 1 + return len(l) + rtype(dummyfn, [int]).view() From adim at codespeak.net Mon Jun 6 15:25:13 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 6 Jun 2005 15:25:13 +0200 (CEST) Subject: [pypy-svn] r13103 - pypy/branch/pycompiler/module/recparser Message-ID: <20050606132513.B6F3B27B4C@code1.codespeak.net> Author: adim Date: Mon Jun 6 15:25:12 2005 New Revision: 13103 Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py pypy/branch/pycompiler/module/recparser/grammar.py Log: Don't use *varargs construction where not needed Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/ebnfparse.py (original) +++ pypy/branch/pycompiler/module/recparser/ebnfparse.py Mon Jun 6 15:25:12 2005 @@ -125,7 +125,7 @@ items+= node.nodes[1].visit(self) if len(items)==1 and items[0].name.startswith(':'): return items[0] - alt = Alternative( self.new_name(), *items ) + alt = Alternative( self.new_name(), items ) return self.new_item( alt ) def visit_sequence( self, node ): @@ -136,7 +136,7 @@ if len(items)==1: return items[0] elif len(items)>1: - return self.new_item( Sequence( self.new_name(), *items) ) + return self.new_item( Sequence( self.new_name(), items) ) raise SyntaxError("Found empty sequence") def visit_sequence_cont( self, node ): @@ -217,34 +217,34 @@ """ global rules # star: '*' | '+' - star = Alternative( "star", Token('*'), Token('+') ) + star = Alternative( "star", [Token('*'), Token('+')] ) star_opt = KleenStar ( "star_opt", 0, 1, rule=star ) # rule: SYMBOL ':' alternative - symbol = Sequence( "symbol", Token('SYMBOL'), star_opt ) + symbol = Sequence( "symbol", [Token('SYMBOL'), star_opt] ) symboldef = Token( "SYMDEF" ) - alternative = Sequence( "alternative" ) - rule = Sequence( "rule", symboldef, alternative ) + alternative = Sequence( "alternative", []) + rule = Sequence( "rule", [symboldef, alternative] ) # grammar: rule+ grammar = KleenStar( "grammar", _min=1, rule=rule ) # alternative: sequence ( '|' sequence )* sequence = KleenStar( "sequence", 1 ) - seq_cont_list = Sequence( "seq_cont_list", Token('|'), sequence ) + seq_cont_list = Sequence( "seq_cont_list", [Token('|'), sequence] ) sequence_cont = KleenStar( "sequence_cont",0, rule=seq_cont_list ) alternative.args = [ sequence, sequence_cont ] # option: '[' alternative ']' - option = Sequence( "option", Token('['), alternative, Token(']') ) + option = Sequence( "option", [Token('['), alternative, Token(']')] ) # group: '(' alternative ')' - group = Sequence( "group", Token('('), alternative, Token(')'), star_opt ) + group = Sequence( "group", [Token('('), alternative, Token(')'), star_opt] ) # sequence: (SYMBOL | STRING | option | group )+ string = Token('STRING') - alt = Alternative( "sequence_alt", symbol, string, option, group ) + alt = Alternative( "sequence_alt", [symbol, string, option, group] ) sequence.args = [ alt ] Modified: pypy/branch/pycompiler/module/recparser/grammar.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/grammar.py (original) +++ pypy/branch/pycompiler/module/recparser/grammar.py Mon Jun 6 15:25:12 2005 @@ -269,9 +269,9 @@ class Alternative(GrammarElement): """Represents an alternative in a grammar rule (as in S -> A | B | C)""" - def __init__(self, name, *args): + def __init__(self, name, args): GrammarElement.__init__(self, name ) - self.args = list(args) + self.args = args self._reordered = False for i in self.args: assert isinstance( i, GrammarElement ) @@ -352,9 +352,9 @@ class Sequence(GrammarElement): """Reprensents a Sequence in a grammar rule (as in S -> A B C)""" - def __init__(self, name, *args): + def __init__(self, name, args): GrammarElement.__init__(self, name ) - self.args = list(args) + self.args = args for i in self.args: assert isinstance( i, GrammarElement ) From adim at codespeak.net Mon Jun 6 15:35:58 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 6 Jun 2005 15:35:58 +0200 (CEST) Subject: [pypy-svn] r13105 - pypy/branch/pycompiler/module/recparser Message-ID: <20050606133558.5193E27B51@code1.codespeak.net> Author: adim Date: Mon Jun 6 15:35:55 2005 New Revision: 13105 Modified: pypy/branch/pycompiler/module/recparser/grammar.py pypy/branch/pycompiler/module/recparser/syntaxtree.py Log: removed other pointless *varargs constructions Modified: pypy/branch/pycompiler/module/recparser/grammar.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/grammar.py (original) +++ pypy/branch/pycompiler/module/recparser/grammar.py Mon Jun 6 15:35:55 2005 @@ -94,7 +94,7 @@ # Do nothing, keep rule on top of the stack if rule.is_root(): elems = self.stack[-1].expand() - self.stack[-1] = SyntaxNode(rule.name, source, *elems) + self.stack[-1] = SyntaxNode(rule.name, source, elems) if self.debug: self.stack[-1].dumpstr() return True @@ -110,11 +110,11 @@ node_type = TempSyntaxNode # replace N elements with 1 element regrouping them if elts_number >= 1: - elem = node_type(rule.name, source, *items) + elem = node_type(rule.name, source, items) del self.stack[-elts_number:] self.stack.append(elem) elif elts_number == 0: - self.stack.append(node_type(rule.name, source)) + self.stack.append(node_type(rule.name, source, [])) if self.debug: self.stack[-1].dumpstr() return True Modified: pypy/branch/pycompiler/module/recparser/syntaxtree.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/syntaxtree.py (original) +++ pypy/branch/pycompiler/module/recparser/syntaxtree.py Mon Jun 6 15:35:55 2005 @@ -71,9 +71,9 @@ class SyntaxNode(object): """A syntax node""" - def __init__(self, name, source, *args): + def __init__(self, name, source, args): self.name = name - self.nodes = list(args) + self.nodes = args self.lineno = source.current_line() def dumptree(self, treenodes, indent): @@ -128,7 +128,7 @@ class TokenNode(SyntaxNode): """A token node""" def __init__(self, name, source, value): - SyntaxNode.__init__(self, name, source) + SyntaxNode.__init__(self, name, source, []) self.value = value def dumptree(self, treenodes, indent): From arigo at codespeak.net Mon Jun 6 15:42:56 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 15:42:56 +0200 (CEST) Subject: [pypy-svn] r13106 - pypy/dist/pypy/rpython/test Message-ID: <20050606134256.E1BB427B51@code1.codespeak.net> Author: arigo Date: Mon Jun 6 15:42:55 2005 New Revision: 13106 Modified: pypy/dist/pypy/rpython/test/test_rlist.py Log: Of course Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Mon Jun 6 15:42:55 2005 @@ -66,4 +66,4 @@ l = [l] N -= 1 return len(l) - rtype(dummyfn, [int]).view() + rtype(dummyfn, [int]) #.view() From pedronis at codespeak.net Mon Jun 6 17:00:27 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 6 Jun 2005 17:00:27 +0200 (CEST) Subject: [pypy-svn] r13112 - pypy/dist/pypy/translator/goal Message-ID: <20050606150027.9B3D627B4C@code1.codespeak.net> Author: pedronis Date: Mon Jun 6 17:00:26 2005 New Revision: 13112 Modified: pypy/dist/pypy/translator/goal/query.py Log: in the output of pbccall distinguish more clearly the three major kind of cases one/many callables -> one pattern one callable -> many patterns many callables -> many patterns Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Mon Jun 6 17:00:26 2005 @@ -300,11 +300,15 @@ for (kinds, patt), (nfam, nels) in items: print pretty_nfam(nfam), "with", pretty_nels(kinds, nels, nfam), "with one call-pattern:", prettypatt([patt]) - print "- * -" + print "- many patterns -" + manycallb = False rest.sort(lambda a,b: cmp((a[0],a[2]), (b[0],b[2]))) for n, objs, patts in rest: + if len(objs) > 1 and not manycallb: + manycallb = True + print " - many callables, many patterns -" print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) # debug helper From arigo at codespeak.net Mon Jun 6 17:33:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 17:33:25 +0200 (CEST) Subject: [pypy-svn] r13114 - in pypy/dist/pypy/rpython: . test Message-ID: <20050606153325.44EB527B51@code1.codespeak.net> Author: arigo Date: Mon Jun 6 17:33:21 2005 New Revision: 13114 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Calling setup() needs to be more subtle. This version calls it only when an undefined attribute is read from the Repr instance, hoping that it means that setup() will compute and set this attribute. The previous version wasn't lazy enough and created big trouble. Implemented simple method calls. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jun 6 17:33:21 2005 @@ -1,6 +1,7 @@ import types from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel +from pypy.annotation.classdef import isclassdef from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, inputconst @@ -43,7 +44,6 @@ result = rtyper.class_reprs[classdef] except KeyError: result = rtyper.class_reprs[classdef] = ClassRepr(rtyper, classdef) - result.setup() return result def getinstancerepr(rtyper, classdef): @@ -51,7 +51,6 @@ result = rtyper.instance_reprs[classdef] except KeyError: result = rtyper.instance_reprs[classdef] = InstanceRepr(rtyper,classdef) - result.setup() return result class MissingRTypeAttribute(TyperError): @@ -84,8 +83,15 @@ def setup(self): if self.initialized: - return # already initialized - self.clsfields = {} + assert self.initialized == True + return + self.initialized = "in progress" + # NOTE: don't store mutable objects like the dicts below on 'self' + # before they are fully built, to avoid strange bugs in case + # of recursion where other code would uses these + # partially-initialized dicts. + clsfields = {} + allmethods = {} if self.classdef is None: # 'object' root type self.vtable_type.become(OBJECT_VTABLE) @@ -96,19 +102,48 @@ attrs.sort() for name, attrdef in attrs: if attrdef.readonly: - r = self.rtyper.getrepr(attrdef.s_value) + s_value = attrdef.s_value + s_value = self.prepare_method(name, s_value, allmethods) + r = self.rtyper.getrepr(s_value) mangled_name = 'cls_' + name - self.clsfields[name] = mangled_name, r + clsfields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) + self.rbase.setup() vtable_type = Struct('%s_vtable' % self.classdef.cls.__name__, ('super', self.rbase.vtable_type), *llfields) self.vtable_type.become(vtable_type) + allmethods.update(self.rbase.allmethods) + self.clsfields = clsfields + self.allmethods = allmethods self.vtable = None self.initialized = True + def prepare_method(self, name, s_value, allmethods): + # special-casing for methods + if isinstance(s_value, annmodel.SomePBC): + debound = {} + count = 0 + for x, classdef in s_value.prebuiltinstances.items(): + if isclassdef(classdef): + if classdef.commonbase(self.classdef) != self.classdef: + raise TyperError("methods from PBC set %r don't belong " + "in %r" % (s_value.prebuiltinstances, + self.classdef.cls)) + count += 1 + classdef = True + debound[x] = classdef + if count > 0: + if count != len(s_value.prebuiltinstances): + raise TyperError("mixing functions and methods " + "in PBC set %r" % ( + s_value.prebuiltinstances,)) + s_value = annmodel.SomePBC(debound) + allmethods[name] = True + return s_value + def convert_const(self, value): if not isinstance(value, (type, types.ClassType)): raise TyperError("not a class: %r" % (value,)) @@ -225,12 +260,18 @@ def setup(self): if self.initialized: - return # already initialized + assert self.initialized == True + return + self.initialized = "in progress" + # NOTE: don't store mutable objects like the dicts below on 'self' + # before they are fully built, to avoid strange bugs in case + # of recursion where other code would uses these + # partially-initialized dicts. self.rclass = getclassrepr(self.rtyper, self.classdef) - self.fields = {} - self.allinstancefields = {} + fields = {} + allinstancefields = {} if self.classdef is None: - self.fields['__class__'] = 'typeptr', TYPEPTR + fields['__class__'] = 'typeptr', TYPEPTR self.object_type.become(OBJECT) else: # instance attributes @@ -241,16 +282,19 @@ if not attrdef.readonly: r = self.rtyper.getrepr(attrdef.s_value) mangled_name = 'inst_' + name - self.fields[name] = mangled_name, r + fields[name] = mangled_name, r llfields.append((mangled_name, r.lowleveltype)) # self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef) + self.rbase.setup() object_type = GcStruct(self.classdef.cls.__name__, ('super', self.rbase.object_type), *llfields) self.object_type.become(object_type) - self.allinstancefields.update(self.rbase.allinstancefields) - self.allinstancefields.update(self.fields) + allinstancefields.update(self.rbase.allinstancefields) + allinstancefields.update(fields) + self.fields = fields + self.allinstancefields = allinstancefields self.initialized = True def convert_const(self, value, targetptr=None, vtable=None): @@ -345,6 +389,10 @@ vinst, vattr = hop.inputargs(self, Void) if attr in self.allinstancefields: return self.getfield(vinst, attr, hop.llops) + elif attr in self.rclass.allmethods: + # special case for methods: represented as their 'self' only + # (see MethodsPBCRepr) + return vinst else: vcls = self.getfield(vinst, '__class__', hop.llops) return self.rclass.getclsfield(vcls, attr, hop.llops) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon Jun 6 17:33:21 2005 @@ -34,13 +34,17 @@ def __init__(self, item_repr, listdef=None): self.LIST = GcForwardReference() self.lowleveltype = GcPtr(self.LIST) - self.item_repr = item_repr # possibly uncomputed at this point! + if not isinstance(item_repr, Repr): # not computed yet, done by setup() + assert callable(item_repr) + self._item_repr_computer = item_repr + else: + self.item_repr = item_repr self.listdef = listdef # setup() needs to be called to finish this initialization def setup(self): - if callable(self.item_repr): - self.item_repr = self.item_repr() + if 'item_repr' not in self.__dict__: + self.item_repr = self._item_repr_computer() if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype ITEMARRAY = GcArray(("item", ITEM)) Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Mon Jun 6 17:33:21 2005 @@ -21,6 +21,16 @@ def setup(self): "For recursive data structure, which must be initialized in two steps." + def __getattr__(self, name): + # Assume that when an attribute is missing, it's because setup() needs + # to be called + self.setup() + try: + return self.__dict__[name] + except KeyError: + raise AttributeError("%s instance has no attribute %s" % ( + self.__class__.__name__, name)) + def convert_const(self, value): "Convert the given constant value to the low-level repr of 'self'." if self.lowleveltype != Void: Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jun 6 17:33:21 2005 @@ -136,6 +136,76 @@ # ____________________________________________________________ +def commonbase(classdefs): + result = classdefs[0] + for cdef in classdefs[1:]: + result = result.commonbase(cdef) + if result is None: + raise TyperError("no common base class in %r" % (classdefs,)) + return result + +def allattributenames(classdef): + for cdef1 in classdef.getmro(): + for attrname in cdef1.attrs: + yield cdef1, attrname + + +class MethodsPBCRepr(Repr): + """Representation selected for a PBC of the form {func: classdef...}. + It assumes that all the methods come from the same name in a base + classdef.""" + + def __init__(self, rtyper, s_pbc): + self.rtyper = rtyper + self.s_pbc = s_pbc + basedef = commonbase(s_pbc.prebuiltinstances.values()) + for classdef1, name in allattributenames(basedef): + # don't trust the func.func_names and see if this 'name' would be + # the one under which we can find all these methods + for func, classdef in s_pbc.prebuiltinstances.items(): + try: + if func != getattr(classdef.cls, name).im_func: + break + except AttributeError: + break + else: + # yes! + self.methodname = name + self.classdef = classdef1 # where the Attribute is defined + break + else: + raise TyperError("cannot find a unique name under which the " + "methods can be found: %r" % ( + s_pbc.prebuiltinstances,)) + # the low-level representation is just the bound 'self' argument. + self.r_instance = rclass.getinstancerepr(rtyper, self.classdef) + self.lowleveltype = self.r_instance.lowleveltype + + def rtype_simple_call(self, hop): + # XXX the graph of functions used as methods may need to be hacked + # XXX so that its 'self' argument accepts a pointer to an instance of + # XXX the common base class. This is needed to make the direct_call + # XXX below well-typed. + r_class = self.r_instance.rclass + mangled_name, r_func = r_class.clsfields[self.methodname] + assert isinstance(r_func, FunctionsPBCRepr) + # + # XXX try to unify with FunctionsPBCRepr.rtype_simple_call() + f, rinputs, rresult = r_func.function_signatures.itervalues().next() + vlist = hop.inputargs(self, *rinputs[1:]) # ignore the self from r_func + if r_func.lowleveltype == Void: + assert len(r_func.function_signatures) == 1 + vfunc = hop.inputconst(typeOf(f), f) + else: + vinst = vlist[0] + vcls = self.getfield(vinst, '__class__', hop.llops) + vfunc = r_class.getclsfield(vcls, self.methodname, hop.llops) + vlist.insert(0, vfunc) + return hop.genop('direct_call', vlist, resulttype = rresult) + + +# ____________________________________________________________ + class ClassesPBCRepr(Repr): """Representation selected for a PBC of class(es).""" Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Mon Jun 6 17:33:21 2005 @@ -24,6 +24,7 @@ self.annotator = annotator self.reprs_by_id = {} self.reprs_by_content = {} + self.reprs_must_call_setup = [] self.specialized_ll_functions = {} self.class_reprs = {} self.instance_reprs = {} @@ -55,7 +56,7 @@ "missing a GcPtr or NonGcPtr in the type specification " "of %s:\n%r" % (s_obj, result.lowleveltype)) self.reprs_by_content[key] = result - result.setup() + self.reprs_must_call_setup.append(result) self.reprs_by_id[id(s_obj)] = result, s_obj return result @@ -75,9 +76,13 @@ already_seen = {} pending = self.annotator.annotated.keys() while pending: + # specialize all blocks in the 'pending' list for block in pending: self.specialize_block(block) already_seen[block] = True + # make sure all reprs so far have had their setup() called + self.call_all_setups() + # look for newly created blocks pending = [block for block in self.annotator.annotated if block not in already_seen] if self.typererror: @@ -86,6 +91,11 @@ #self.annotator.translator.view() raise exc, value, tb + def call_all_setups(self): + # make sure all reprs so far have had their setup() called + while self.reprs_must_call_setup: + self.reprs_must_call_setup.pop().setup() + def setconcretetype(self, v): assert isinstance(v, Variable) v.concretetype = self.bindingrepr(v).lowleveltype @@ -372,6 +382,7 @@ name = '_'.join(spec_name) spec_function = func_with_new_name(ll_function, name) # flow and annotate (the copy of) the low-level function + self.rtyper.call_all_setups() # compute ForwardReferences now spec_graph = rtyper.annotator.translator.getflowgraph(spec_function) rtyper.annotator.build_types(spec_function, args_s) # cache the result Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Mon Jun 6 17:33:21 2005 @@ -32,3 +32,15 @@ f = f2 return f(y+3) rtype(g, [int]) + + +class MyBase: + def m(self, x): + return self.z + x + +def test_method_call(): + def f(a, b): + obj = MyBase() + obj.z = a + return obj.m(b) + rtype(f, [int, int]).view() From arigo at codespeak.net Mon Jun 6 17:41:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 17:41:08 +0200 (CEST) Subject: [pypy-svn] r13115 - pypy/dist/pypy/rpython/test Message-ID: <20050606154108.372F027B51@code1.codespeak.net> Author: arigo Date: Mon Jun 6 17:41:08 2005 New Revision: 13115 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: Grumble. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Mon Jun 6 17:41:08 2005 @@ -43,4 +43,4 @@ obj = MyBase() obj.z = a return obj.m(b) - rtype(f, [int, int]).view() + rtype(f, [int, int]) #.view() From arigo at codespeak.net Mon Jun 6 17:55:02 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 17:55:02 +0200 (CEST) Subject: [pypy-svn] r13116 - pypy/dist/pypy Message-ID: <20050606155502.9D86E27B51@code1.codespeak.net> Author: arigo Date: Mon Jun 6 17:55:00 2005 New Revision: 13116 Modified: pypy/dist/pypy/conftest.py Log: Print a warning when using Pygame in tests. Modified: pypy/dist/pypy/conftest.py ============================================================================== --- pypy/dist/pypy/conftest.py (original) +++ pypy/dist/pypy/conftest.py Mon Jun 6 17:55:00 2005 @@ -1,4 +1,4 @@ -import py +import py, sys from pypy.interpreter.gateway import app2interp_temp from pypy.interpreter.error import OperationError from pypy.tool.pytest import appsupport @@ -138,6 +138,8 @@ raise self.Failed(excinfo=appsupport.AppExceptionInfo(space, e)) raise +_pygame_warned = False + class IntTestFunction(PyPyTestFunction): def execute(self, target, *args): co = target.func_code @@ -147,6 +149,12 @@ target(space, *args) else: target(*args) + if 'pygame' in sys.modules: + global _pygame_warned + if not _pygame_warned: + _pygame_warned = True + py.test.skip("DO NOT FORGET to remove the Pygame invocation " + "before checking in :-)") class AppTestFunction(PyPyTestFunction): def execute(self, target, *args): From pedronis at codespeak.net Mon Jun 6 18:57:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 6 Jun 2005 18:57:55 +0200 (CEST) Subject: [pypy-svn] r13118 - in pypy/dist/pypy: annotation translator Message-ID: <20050606165755.773B827B4C@code1.codespeak.net> Author: pedronis Date: Mon Jun 6 18:57:52 2005 New Revision: 13118 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/annrpython.py Log: always normalize unbound methods to the underlying function Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Mon Jun 6 18:57:52 2005 @@ -148,6 +148,10 @@ def immutablevalue(self, x): """The most precise SomeValue instance that contains the immutable value x.""" + # convert unbound methods to the underlying function + if hasattr(x, 'im_self') and x.im_self is None: + x = x.im_func + assert not hasattr(x, 'im_self') if x is sys: # special case constant sys to someobject return SomeObject() tp = type(x) @@ -339,9 +343,7 @@ self.consider_pbc_call(s_init, shape, spaceop, implicit_init=init_classdef) callable = (classdef, func) - if hasattr(func, 'im_func') and func.im_self is None: - # consider unbound methods and the undelying functions as the same - func = func.im_func + assert not hasattr(func, 'im_func') or func.im_self is not None self.pbc_callables.setdefault(func,{})[callable] = True nonnullcallables.append(callable) @@ -434,10 +436,6 @@ # don't record the access of __init__ on the classdef # because it is not a dynamic attribute look-up, but # merely a static function call - if hasattr(init, 'im_func'): - init = init.im_func - else: - assert isinstance(init, BuiltinMethodType) s_init = self.immutablevalue(init) return classdef, s_init else: Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Mon Jun 6 18:57:52 2005 @@ -141,9 +141,8 @@ return self.bookkeeper.pbc_maximal_access_sets def getpbccallables(self): - """Return mapping callable -> {(ClassDef|None, callable'): True...}, - callable' == callable unless callable' is an unbound method then callable is callable'.im_func. - + """Return mapping callable -> {(ClassDef|None, callable): True...}, + The tuples are indices in getpbcfamilies returned mapping """ return self.bookkeeper.pbc_callables From ericvrp at codespeak.net Mon Jun 6 22:41:01 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 6 Jun 2005 22:41:01 +0200 (CEST) Subject: [pypy-svn] r13126 - pypy/dist/pypy/rpython/test Message-ID: <20050606204101.8CAD827B4C@code1.codespeak.net> Author: ericvrp Date: Mon Jun 6 22:41:00 2005 New Revision: 13126 Modified: pypy/dist/pypy/rpython/test/snippet.py Log: added main entrypoint, nothing to look at here Modified: pypy/dist/pypy/rpython/test/snippet.py ============================================================================== --- pypy/dist/pypy/rpython/test/snippet.py (original) +++ pypy/dist/pypy/rpython/test/snippet.py Mon Jun 6 22:41:00 2005 @@ -114,7 +114,7 @@ if n < 12.5: n += 666 - while n: + while n >= 0: i = i + n n = n - 1 return i @@ -128,3 +128,19 @@ n += float(6) n += float(7.8) n += float(n) + + +def main(args=[]): + b = True + i = 23 + f = 45.6 + b1 = bool1(b) + i1 = int1(i) + f1 = float1(f) + #print 'bool1(%d)' % b, b1 + #print 'int1(%d)' % i, i1 + #print 'float1(%s)' % f, f1 + + +if __name__ == '__main__': + main() From tismer at codespeak.net Mon Jun 6 23:08:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 6 Jun 2005 23:08:11 +0200 (CEST) Subject: [pypy-svn] r13127 - in pypy/dist/pypy: objspace/flow translator/pickle Message-ID: <20050606210811.B307227B4C@code1.codespeak.net> Author: tismer Date: Mon Jun 6 23:08:09 2005 New Revision: 13127 Added: pypy/dist/pypy/translator/pickle/loader.py (contents, props changed) pypy/dist/pypy/translator/pickle/main.py (contents, props changed) pypy/dist/pypy/translator/pickle/writer.py (contents, props changed) Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/pickle/genpickle.py Log: changed a few things to make the generated source smaller. It is now about 37 MB. Added writers and loaders for plain text and zipfile. todo: - write main, deciding which file format to use - integrate with translate_pypy (will use main.load and main.save) - write tests (eek, how do I test such stuff, any ideas?) Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Mon Jun 6 23:08:09 2005 @@ -293,7 +293,13 @@ return "%r = %s(%s)" % (self.result, self.opname, ", ".join(map(repr, self.args))) def __reduce_ex__(self, *args): - return SpaceOperation, (self.opname, self.args, self.result, self.offset) + # avoid lots of useless list entities + return _sop, (self.opname, self.result, self.offset) + tuple(self.args) + __reduce__ = __reduce_ex__ + +# a small and efficient restorer +def _sop(opname, result, offset, *args): + return SpaceOperation(opname, args, result, offset) class Atom: def __init__(self, name): Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Mon Jun 6 23:08:09 2005 @@ -3,6 +3,10 @@ The purpose is to create something that allows to restart code generation after flowing and maybe annotation. + +The generated source appeared to be way too large +for the CPython compiler. Therefore, we cut the +source into pieces and compile them seperately. """ from __future__ import generators, division, nested_scopes import __future__ @@ -17,11 +21,12 @@ from pypy.objspace.flow.flowcontext import SpamBlock, EggBlock from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool from pypy.annotation.model import SomeList, SomeString, SomeTuple +from pypy.annotation.unaryop import SomeInstance from pypy.interpreter.baseobjspace import ObjSpace from pypy.translator.pickle import slotted from pickle import whichmodule, PicklingError -from copy_reg import _reduce_ex, _reconstructor +from copy_reg import _reconstructor import pickle @@ -33,7 +38,7 @@ class GenPickle: - def __init__(self, translator, outfile = None): + def __init__(self, translator, writer = None): self.translator = translator self.initcode = [ 'from __future__ import %s\n' % ', '.join(all_feature_names) + @@ -56,8 +61,6 @@ self.namespace.make_reserved_names('None False True') self.namespace.make_reserved_names('new types sys') self.namespace.make_reserved_names(' '.join(all_feature_names)) - self.inline_consts = True # save lots of space - self._nesting = 0 # for formatting nested tuples etc. # we distinguish between the "user program" and other stuff. # "user program" will never use save_global. self.domains = ( @@ -68,7 +71,7 @@ '__main__', ) self.shortnames = { - SpaceOperation: 'S', + SpaceOperation: 'SOP', Variable: 'V', Constant: 'C', Block: 'B', @@ -83,9 +86,9 @@ SomeList: 'SL', SomeString: 'SS', SomeTuple: 'ST', + SomeInstance: 'SIN', } - self.outfile = outfile - self._partition = 1234 + self.writer = writer def nameof(self, obj, debug=None, namehint=None): key = Constant(obj) @@ -125,21 +128,20 @@ self.picklenames[key] = name return name - def nameofargs(self, tup): + def nameofargs(self, tup, plain_tuple = False): """ a string with the nameofs, concatenated """ - if len(tup) < 5: - # see if there is nesting to be expected - for each in tup: - if type(each) is tuple: - break - else: - return ', '.join([self.nameof(arg) for arg in tup]) - # we always wrap into multi-lines, this is simple and readable - self._nesting += 1 - space = ' ' * self._nesting - ret = '\n' + space + (',\n' + space).join( - [self.nameof(arg) for arg in tup]) + ',\n' + space - self._nesting -= 1 + # see if we can build a compact representation + for each in tup: + if type(each) is tuple and len(each) > 2: + break + else: + ret = ', '.join([self.nameof(arg) for arg in tup]) + if plain_tuple and len(tup) == 1: + ret += ',' + if len(ret) <= 90: + return ret + ret = '\n ' + (',\n ').join( + [self.nameof(arg) for arg in tup]) + ',\n ' return ret def uniquename(self, basename): @@ -184,27 +186,18 @@ # the compiler folds the consts the same way as we do. # note that true pickling is more exact, here. nameof_long = nameof_float = nameof_bool = nameof_NoneType = nameof_int - - def nameof_str(self, value): - if self.inline_consts: - return repr(value) - name = self.uniquename('gstr_' + value[:32]) - self.initcode_python(name, repr(value)) - return name - - def nameof_unicode(self, value): - if self.inline_consts: - return repr(value) - name = self.uniquename('guni_' + str(value[:32])) - self.initcode_python(name, repr(value)) - return name + nameof_str = nameof_unicode = nameof_int def skipped_function(self, func): - # debugging only! Generates a placeholder for missing functions + # Generates a placeholder for missing functions # that raises an exception when called. + # The original code object is retained in an + # attribute '_skipped_code' name = self.uniquename('gskippedfunc_' + func.__name__) + codename = self.nameof(func.func_code) self.initcode.append('def %s(*a,**k):\n' ' raise NotImplementedError' % name) + self.initcode.append('%s._skipped_code = %s' % (name, codename) ) return name def nameof_staticmethod(self, sm): @@ -390,31 +383,23 @@ return name def nameof_tuple(self, tup): - # instead of defining myriads of tuples, it seems to - # be cheaper to create them inline, although they don't - # get constant folded like strings and numbers. - if self.inline_consts: - argstr = self.nameofargs(tup) - if len(tup) == 1 and not argstr.rstrip().endswith(','): - argstr += ',' - return '(%s)' % argstr - name = self.uniquename('g%dtuple' % len(tup)) - args = [self.nameof(x) for x in tup] - args = ', '.join(args) - if args: - args += ',' - self.initcode_python(name, '(%s)' % args) + chunk = 20 + name = self.uniquename('T%d' % len(tup)) + argstr = self.nameofargs(tup[:chunk], True) + self.initcode_python(name, '(%s)' % argstr) + for i in range(chunk, len(tup), chunk): + argstr = self.nameofargs(tup[i:i+chunk], True) + self.initcode.append('%s += (%s)' % (name, argstr) ) return name def nameof_list(self, lis): + chunk = 20 name = self.uniquename('L%d' % len(lis)) - extend = self.nameof(_ex) def initlist(): chunk = 20 for i in range(0, len(lis), chunk): - items = lis[i:i+chunk] - itemstr = self.nameofargs(items) - yield '%s(%s, %s)' % (extend, name, itemstr) + argstr = self.nameofargs(lis[i:i+chunk]) + yield '%s += [%s]' % (name, argstr) self.initcode_python(name, '[]') self.later(initlist()) return name @@ -488,9 +473,9 @@ yield '%s.__setstate__(%s)' % (name, args) return elif type(restorestate) is tuple: - setstate = self.nameof(slotted.__setstate__) - args = self.nameof(restorestate) - yield '%s(%s, %s)' % (setstate, name, args) + setstate = self.nameof(_set) + argstr = self.nameofargs(restorestate) + yield '%s(%s, %s)' % (setstate, name, argstr) return assert type(restorestate) is dict, ( "%s has no dict and no __setstate__" % name) @@ -518,12 +503,14 @@ ' please update %s' % (cls.__name__, __name__) ) restorestate = slotted.__getstate__(instance) restorer = _rec - restoreargs = klass, object, None + restoreargs = klass, else: restorer = reduced[0] + restoreargs = reduced[1] if restorer is _reconstructor: restorer = _rec - restoreargs = reduced[1] + if restoreargs[1:] == (object, None): + restoreargs = restoreargs[:1] if len(reduced) > 2: restorestate = reduced[2] else: @@ -603,8 +590,6 @@ args = (func.func_code, func.func_globals, func.func_name, func.func_defaults, func.func_closure) pyfuncobj = self.uniquename('gfunc_' + func.__name__) - # touch code,to avoid extra indentation - self.nameof(func.func_code) self.initcode.append('%s = new.function(%s)' % (pyfuncobj, self.nameofargs(args)) ) if func.__dict__: @@ -635,20 +620,6 @@ code.co_varnames, code.co_filename, code.co_name, code.co_firstlineno, code.co_lnotab, code.co_freevars, code.co_cellvars) - if not self.inline_consts: - # make the code, filename and lnotab strings nicer - codestr = code.co_code - codestrname = self.uniquename('gcodestr_' + code.co_name) - self.picklenames[Constant(codestr)] = codestrname - self.initcode.append('%s = %r' % (codestrname, codestr)) - fnstr = code.co_filename - fnstrname = self.uniquename('gfname_' + code.co_name) - self.picklenames[Constant(fnstr)] = fnstrname - self.initcode.append('%s = %r' % (fnstrname, fnstr)) - lnostr = code.co_lnotab - lnostrname = self.uniquename('glnotab_' + code.co_name) - self.picklenames[Constant(lnostr)] = lnostrname - self.initcode.append('%s = %r' % (lnostrname, lnostr)) argstr = self.nameofargs(args) codeobj = self.uniquename('gcode_' + code.co_name) self.initcode.append('%s = new.code(%s)' % (codeobj, argstr)) @@ -672,34 +643,20 @@ def later(self, gen): self.latercode.append((gen, self.debugstack)) - def spill_source(self, final): - def write_block(lines): - if not lines: - return - txt = '\n'.join(lines) - print >> self.outfile, txt - print >> self.outfile, '## SECTION ##' - - if not self.outfile: - return - chunk = self._partition - while len(self.initcode) >= chunk: - write_block(self.initcode[:chunk]) - del self.initcode[:chunk] - if final and self.initcode: - write_block(self.initcode) - del self.initcode[:] - def collect_initcode(self): + writer = self.writer while self.latercode: gen, self.debugstack = self.latercode.pop() #self.initcode.extend(gen) -- eats TypeError! bad CPython! for line in gen: self.initcode.append(line) self.debugstack = () - if len(self.initcode) >= self._partition: - self.spill_source(False) - self.spill_source(True) + if writer: + for line in self.initcode: + writer.write(line) + del self.initcode[:] + if writer: + writer.close() def getfrozenbytecode(self): self.initcode.append('') @@ -733,8 +690,8 @@ # some shortcuts, to make the pickle smaller -def _ex(lis, *args): - lis.extend(args) +def _rec(klass, base=object, state=None): + return _reconstructor(klass, base, state) -def _rec(*args): - return _reconstructor(*args) +def _set(obj, *args): + slotted.__setstate__(obj, args) Added: pypy/dist/pypy/translator/pickle/loader.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/pickle/loader.py Mon Jun 6 23:08:09 2005 @@ -0,0 +1,50 @@ +import zipfile, marshal, md5 + +class Loader: + def __init__(self, fname): + self.f = self.open_file(fname) + + def open_file(self, fname): + raise SyntaxError, "implement open_file" + + def next_block(self): + raise SyntaxError, "implement next_block" + + def load(self): + dic = {} + for blk in self.next_block(): + exec blk in dic + try: + return dic['ginst_Translator'] + finally: + self.close() + + def close(self): + self.f.close() + + +class TextLoader(Loader): + + def open_file(self, fname): + return file(fname) + + def next_block(self): + data = self.f.read().split('## SECTION ##\n') + while data: + yield data.pop(0) + +class ZipLoader(Loader): + """ load compiled code from a ZIP file """ + + def open_file(self, fname): + return zipfile.ZipFile(fname, "r") + + def next_block(self): + root = self.f.read('root') + dump = self.f.read(root) + assert md5.new(dump).hexdigest() == root, "broken checksum" + blocknames = marshal.loads(dump) + for name in blocknames: + dump = self.f.read(name) + assert md5.new(dump).hexdigest() == name, "broken checksum" + yield marshal.loads(dump) Added: pypy/dist/pypy/translator/pickle/main.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/pickle/main.py Mon Jun 6 23:08:09 2005 @@ -0,0 +1,5 @@ +def load(fname): + pass + +def save(translator, fname): + pass Added: pypy/dist/pypy/translator/pickle/writer.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/pickle/writer.py Mon Jun 6 23:08:09 2005 @@ -0,0 +1,64 @@ +import zipfile, marshal, md5 + +class Writer: + def __init__(self, fname): + self.pieces = [] + self.chunksize = 100000 + self.count = 0 + self.blocknum = 0 + self.f = self.open_file(fname) + + def open_file(self, fname): + raise SyntaxError, "implement open_file" + + def write(self, text): + self.pieces.append(text) + self.count += len(text) + 1 + if self.count >= self.chunksize: + src = '\n'.join(self.pieces) + del self.pieces[:] + self.count -= self.chunksize + self.putblock(src) + self.blocknum += 1 + + def close(self): + src = '\n'.join(self.pieces) + self.putblock(src) + self.finalize() + self.f.close() + + def finalize(self): + pass + + +class TextWriter(Writer): + + def open_file(self, fname): + return file(fname, 'w') + + def putblock(self, src): + print >> self.f, src + print >> self.f, '## SECTION ##' + +class ZipWriter(Writer): + """ write compiled code to a ZIP file """ + + def __init__(self, fname): + Writer.__init__(self, fname) + self.blocknames = [] + + def open_file(self, fname): + return zipfile.ZipFile(fname, "w", zipfile.ZIP_DEFLATED) + + def putblock(self, src): + cod = compile(src, 'block_%d' % self.blocknum, 'exec') + dump = marshal.dumps(cod) + digest = md5.new(dump).hexdigest() + self.blocknames.append(digest) + self.f.writestr(digest, dump) + + def finalize(self): + dump = marshal.dumps(self.blocknames) + digest = md5.new(dump).hexdigest() + self.f.writestr(digest, dump) + self.f.writestr('root', digest) From arigo at codespeak.net Mon Jun 6 23:18:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 23:18:54 +0200 (CEST) Subject: [pypy-svn] r13128 - pypy/dist/pypy/rpython Message-ID: <20050606211854.E5F8E27B46@code1.codespeak.net> Author: arigo Date: Mon Jun 6 23:18:52 2005 New Revision: 13128 Modified: pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rstr.py Log: Be more careful in convert_from_to, because there Repr classes inherit from each other and so the __extend__(pairtype(..)) trick can catch more than you expected. Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Mon Jun 6 23:18:52 2005 @@ -37,9 +37,10 @@ class __extend__(pairtype(BoolRepr, IntegerRepr)): def convert_from_to((r_from, r_to), v, llops): - if r_to.lowleveltype == Unsigned: + if r_from.lowleveltype == Bool and r_to.lowleveltype == Unsigned: if debug: print 'explicit cast_bool_to_uint' return llops.genop('cast_bool_to_uint', [v], resulttype=Unsigned) - else: + if r_from.lowleveltype == Bool and r_to.lowleveltype == Signed: if debug: print 'explicit cast_bool_to_int' return llops.genop('cast_bool_to_int', [v], resulttype=Signed) + return NotImplemented Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Mon Jun 6 23:18:52 2005 @@ -114,14 +114,17 @@ class __extend__(pairtype(IntegerRepr, FloatRepr)): def convert_from_to((r_from, r_to), v, llops): - if r_from.lowleveltype == Unsigned: + if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Float: if debug: print 'explicit cast_uint_to_float' return llops.genop('cast_uint_to_float', [v], resulttype=Float) - else: + if r_from.lowleveltype == Signed and r_to.lowleveltype == Float: if debug: print 'explicit cast_int_to_float' return llops.genop('cast_int_to_float', [v], resulttype=Float) + return NotImplemented class __extend__(pairtype(BoolRepr, FloatRepr)): - def convert_from_to(_, v, llops): - if debug: print 'explicit cast_bool_to_float' - return llops.genop('cast_bool_to_float', [v], resulttype=Float) + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Bool and r_to.lowleveltype == Float: + if debug: print 'explicit cast_bool_to_float' + return llops.genop('cast_bool_to_float', [v], resulttype=Float) + return NotImplemented Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Mon Jun 6 23:18:52 2005 @@ -22,13 +22,12 @@ class __extend__(pairtype(IntegerRepr, IntegerRepr)): def convert_from_to((r_from, r_to), v, llops): - if r_from.lowleveltype != r_to.lowleveltype: - if r_to.lowleveltype == Unsigned: - if debug: print 'explicit cast_int_to_uint' - return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned) - else: - if debug: print 'explicit cast_uint_to_int' - return llops.genop('cast_uint_to_int', [v], resulttype=Signed) + if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed: + if debug: print 'explicit cast_int_to_uint' + return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned) + if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned: + if debug: print 'explicit cast_uint_to_int' + return llops.genop('cast_uint_to_int', [v], resulttype=Signed) return v #arithmetic @@ -237,15 +236,17 @@ if r_to.lowleveltype == Unsigned: return llops.gencapicall('PyLong_AsUnsignedLong', [v], resulttype=Unsigned) - else: + if r_to.lowleveltype == Signed: return llops.gencapicall('PyInt_AsLong', [v], resulttype=Signed) + return NotImplemented class __extend__(pairtype(IntegerRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from.lowleveltype == Unsigned: return llops.gencapicall('PyLong_FromUnsignedLong', [v], resulttype=pyobj_repr) - else: + if r_from.lowleveltype == Signed: return llops.gencapicall('PyInt_FromLong', [v], resulttype=pyobj_repr) + return NotImplemented Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Mon Jun 6 23:18:52 2005 @@ -3,7 +3,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr -from pypy.rpython.rmodel import StringRepr, CharRepr +from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst from pypy.rpython.rarithmetic import intmask # ____________________________________________________________ @@ -99,8 +99,17 @@ class __extend__(pairtype(CharRepr, StringRepr)): - def convert_from_to(_, v, llops): - return hop.gendirectcall(ll_chr2str, v) + def convert_from_to((r_from, r_to), v, llops): + if r_from == char_repr and r_to == string_repr: + return llops.gendirectcall(ll_chr2str, v) + return NotImplemented + +class __extend__(pairtype(StringRepr, CharRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from == string_repr and r_to == char_repr: + c_zero = inputconst(Signed, 0) + return llops.gendirectcall(ll_stritem_nonneg, v, c_zero) + return NotImplemented string_repr = StringRepr() From arigo at codespeak.net Mon Jun 6 23:33:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 6 Jun 2005 23:33:21 +0200 (CEST) Subject: [pypy-svn] r13129 - in pypy/dist/pypy: annotation rpython rpython/test tool translator Message-ID: <20050606213321.99D0E27B46@code1.codespeak.net> Author: arigo Date: Mon Jun 6 23:33:14 2005 New Revision: 13129 Added: pypy/dist/pypy/rpython/annlowlevel.py (contents, props changed) pypy/dist/pypy/rpython/normalizecalls.py (contents, props changed) pypy/dist/pypy/rpython/test/test_normalizecalls.py (contents, props changed) Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/tool/sourcetools.py pypy/dist/pypy/tool/unionfind.py pypy/dist/pypy/translator/annrpython.py Log: - normalizecalls: Make sure that all functions called in a group have exactly the same signature, by hacking their flow graphs if needed. Messy but quite needed. - started a LowLevelAnnotatorPolicy. - bookkeeper.compute_at_fixpoint() can now be called several times on the same annotator. - UnionFind mapping interface; has_varargs() and has_varkeywords() in sourcetools. - couple of bug fixes. (this is a catch-all intermediate check-in; the test we intended to pass -- virtual method call -- still doesn't pass) Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Mon Jun 6 23:33:14 2005 @@ -85,14 +85,17 @@ del self.position_key def compute_at_fixpoint(self): - self.pbc_maximal_call_families = UnionFind(PBCCallFamily) - self.pbc_callables = {} + if self.pbc_maximal_call_families is None: + self.pbc_maximal_call_families = UnionFind(PBCCallFamily) + if self.pbc_callables is None: + self.pbc_callables = {} for (fn, block, i), shape in self.pbc_call_sites.iteritems(): spaceop = block.operations[i] assert spaceop.opname in ('call_args', 'simple_call') pbc = self.annotator.binding(spaceop.args[0], extquery=True) self.consider_pbc_call(pbc, shape, spaceop) + self.pbc_call_sites = {} def getclassdef(self, cls): """Get the ClassDef associated with the given user cls.""" Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Mon Jun 6 23:33:14 2005 @@ -1,7 +1,8 @@ # base annotation policy for overrides and specialization from pypy.annotation.specialize import memo, ctr_location, default_specialize as default +from pypy.translator.annrpython import BasicAnnotatorPolicy -class AnnotatorPolicy: +class AnnotatorPolicy(BasicAnnotatorPolicy): """ Possibly subclass and pass an instance to the annotator to control special casing during annotation """ Added: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/annlowlevel.py Mon Jun 6 23:33:14 2005 @@ -0,0 +1,20 @@ +""" +The code needed to flow and annotate low-level helpers -- the ll_*() functions +""" + +##from pypy.translator.annrpython import BasicAnnotatorPolicy + + +##class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy): + +## def compute_at_fixpoint(self, annotator): +## pass + + +def annotate_lowlevel_helper(annotator, ll_function, args_s): +## saved = annotator.policy +## annotator.policy = LowLevelAnnotatorPolicy() +## try: + annotator.build_types(ll_function, args_s) +## finally: +## annotator.policy = saved Added: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/normalizecalls.py Mon Jun 6 23:33:14 2005 @@ -0,0 +1,100 @@ +from pypy.objspace.flow.model import Variable, Constant, Block, Link +from pypy.objspace.flow.model import SpaceOperation, checkgraph +from pypy.annotation.model import * +from pypy.tool.sourcetools import has_varargs +from pypy.rpython.rmodel import TyperError + + +def normalize_function_signatures(annotator): + # make sure that all functions called in a group have exactly + # the same signature, by hacking their flow graphs if needed + callables = annotator.getpbccallables() + call_families = annotator.getpbccallfamilies() + # for methods, we create or complete a corresponding function-only + # family with call patterns that have the extra 'self' argument + for family in call_families.infos(): + prevkey = None + for classdef, func in family.objects: + if classdef is not None: + # add (None, func) to the func_family + if prevkey is None: + prevkey = (None, func) + else: + call_families.union((None, func), prevkey) + if prevkey is not None: + # copy the patterns from family to func_family with the + # extra self argument + _, _, func_family = call_families.find(prevkey) + for pattern in family.patterns: + argcount = pattern[0] + pattern = (argcount+1,) + pattern[1:] + func_family.patterns[pattern] = True + # find the most general signature of each family + for family in call_families.infos(): + functions = [func for classdef, func in family.objects + if classdef is None] # ignore methods now + if len(functions) > 1: # otherwise, nothing to do + if len(family.patterns) > 1: + raise TyperError("don't support multiple call patterns " + "to multiple functions for now %r" % ( + functions)) + pattern, = family.patterns + shape_cnt, shape_keys, shape_star, shape_stst = pattern + assert not shape_keys, "XXX not implemented" + assert not shape_star, "XXX not implemented" + assert not shape_stst, "XXX not implemented" + # for the first 'shape_cnt' arguments we need to generalize to + # a common type + generalizedargs = [] + graph_bindings = {} + default_values = {} + for func in functions: + assert not has_varargs(func), "XXX not implemented" + graph = annotator.translator.getflowgraph(func) + graph_bindings[graph] = [annotator.binding(v) + for v in graph.getargs()] + for i in range(shape_cnt): + args_s = [] + for bindings in graph_bindings.values(): + args_s.append(bindings[i]) + s_value = unionof(*args_s) + generalizedargs.append(s_value) + for func in functions: + graph = annotator.translator.getflowgraph(func) + bindings = graph_bindings[graph] + if generalizedargs != bindings: #NB. bindings can also be longer + oldblock = graph.startblock + vlist = [] + for i in range(len(generalizedargs)): + v = Variable(graph.getargs()[i]) + annotator.setbinding(v, generalizedargs[i]) + vlist.append(v) + newblock = Block(vlist) + # add the defaults as constants + defaults = func.func_defaults or () + for i in range(len(generalizedargs), len(bindings)): + try: + default = defaults[i-len(bindings)] + except IndexError: + raise TyperError("call pattern has %d arguments, " + "but %r takes at least %d " + "arguments" % ( + len(generalizedargs), func, + len(bindings) - len(defaults))) + vlist.append(Constant(default)) + newblock.closeblock(Link(vlist, oldblock)) + oldblock.isstartblock = False + newblock.isstartblock = True + graph.startblock = newblock + # finished + checkgraph(graph) + annotator.annotated[newblock] = annotator.annotated[oldblock] + # XXX convert the return value too + + +def perform_normalizations(annotator): + annotator.frozen += 1 + try: + normalize_function_signatures(annotator) + finally: + annotator.frozen -= 1 Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jun 6 23:33:14 2005 @@ -122,7 +122,13 @@ self.initialized = True def prepare_method(self, name, s_value, allmethods): - # special-casing for methods + # special-casing for methods: + # - a class (read-only) attribute that would contain a PBC + # with {func: classdef...} is probably meant to be used as a + # method, but in corner cases it could be a constant object + # of type MethodType that just sits here in the class. But + # as MethodType has a custom __get__ too and we don't support + # it, it's a very bad idea anyway. if isinstance(s_value, annmodel.SomePBC): debound = {} count = 0 Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jun 6 23:33:14 2005 @@ -198,7 +198,7 @@ vfunc = hop.inputconst(typeOf(f), f) else: vinst = vlist[0] - vcls = self.getfield(vinst, '__class__', hop.llops) + vcls = self.r_instance.getfield(vinst, '__class__', hop.llops) vfunc = r_class.getclsfield(vcls, self.methodname, hop.llops) vlist.insert(0, vfunc) return hop.genop('direct_call', vlist, resulttype = rresult) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Mon Jun 6 23:33:14 2005 @@ -9,6 +9,8 @@ from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block from pypy.rpython.rmodel import Repr, inputconst, TyperError +from pypy.rpython.normalizecalls import perform_normalizations +from pypy.rpython.annlowlevel import annotate_lowlevel_helper debug = False @@ -71,6 +73,9 @@ def specialize(self): """Main entry point: specialize all annotated blocks of the program.""" + # first make sure that all functions called in a group have exactly + # the same signature, by hacking their flow graphs if needed + perform_normalizations(self.annotator) # new blocks can be created as a result of specialize_block(), so # we need to be careful about the loop here. already_seen = {} @@ -340,6 +345,10 @@ if v is NotImplemented: raise TyperError("don't know how to convert from %r to %r" % (r_from, r_to)) + if v.concretetype != r_to.lowleveltype: + raise TyperError("bug in convertion from %r to %r: " + "returned a %r" % (r_from, r_to, + v.concretetype)) return v def genop(self, opname, args_v, resulttype=None): @@ -383,8 +392,7 @@ spec_function = func_with_new_name(ll_function, name) # flow and annotate (the copy of) the low-level function self.rtyper.call_all_setups() # compute ForwardReferences now - spec_graph = rtyper.annotator.translator.getflowgraph(spec_function) - rtyper.annotator.build_types(spec_function, args_s) + annotate_lowlevel_helper(rtyper.annotator, spec_function, args_s) # cache the result self.rtyper.specialized_ll_functions[spec_key] = spec_function Added: pypy/dist/pypy/rpython/test/test_normalizecalls.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_normalizecalls.py Mon Jun 6 23:33:14 2005 @@ -0,0 +1,38 @@ +from pypy.annotation import model as annmodel +from pypy.translator.translator import Translator +from pypy.rpython.rtyper import RPythonTyper + + +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() + return t + +# ____________________________________________________________ + +def test_normalize_f2_as_taking_string_argument(): + def f1(l1): + pass + def f2(l2): + pass + def g(n): + if n > 0: + f1("123") + f = f1 + else: + f2("b") + f = f2 + f("a") + + translator = rtype(g, [int]) + f1graph = translator.getflowgraph(f1) + f2graph = translator.getflowgraph(f2) + s_l1 = translator.annotator.binding(f1graph.getargs()[0]) + s_l2 = translator.annotator.binding(f2graph.getargs()[0]) + assert s_l1.__class__ == annmodel.SomeString # and not SomeChar + assert s_l2.__class__ == annmodel.SomeString # and not SomeChar + #translator.view() Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Mon Jun 6 23:33:14 2005 @@ -8,7 +8,6 @@ t.annotate(argtypes) typer = RPythonTyper(t.annotator) typer.specialize() - #t.view() t.checkgraphs() return t @@ -38,9 +37,23 @@ def m(self, x): return self.z + x +class MySubclass(MyBase): + def m(self, x): + return self.z - x + def test_method_call(): def f(a, b): obj = MyBase() obj.z = a return obj.m(b) - rtype(f, [int, int]) #.view() + rtype(f, [int, int]) + +def PROGRESSING_ON_test_virtual_method_call(): + def f(a, b): + if a > 0: + obj = MyBase() + else: + obj = MySubclass() + obj.z = a + return obj.m(b) + rtype(f, [int, int]).view() Modified: pypy/dist/pypy/tool/sourcetools.py ============================================================================== --- pypy/dist/pypy/tool/sourcetools.py (original) +++ pypy/dist/pypy/tool/sourcetools.py Mon Jun 6 23:33:14 2005 @@ -235,3 +235,14 @@ if not stuff or ('0' <= stuff[0] <= '9'): stuff = '_' + stuff return stuff + +CO_VARARGS = 0x0004 +CO_VARKEYWORDS = 0x0008 + +def has_varargs(func): + func = getattr(func, 'func_code', func) + return (func.co_flags & CO_VARARGS) != 0 + +def has_varkeywords(func): + func = getattr(func, 'func_code', func) + return (func.co_flags & CO_VARKEYWORDS) != 0 Modified: pypy/dist/pypy/tool/unionfind.py ============================================================================== --- pypy/dist/pypy/tool/unionfind.py (original) +++ pypy/dist/pypy/tool/unionfind.py Mon Jun 6 23:33:14 2005 @@ -19,6 +19,18 @@ return access + def __contains__(self, obj): + return obj in self.link_to_parent + + def __iter__(self): + return iter(self.link_to_parent) + + def keys(self): + return self.link_to_parent.keys() + + def infos(self): + return self.root_info.values() + def find(self, obj): # -> new_root, obj, info if obj not in self.link_to_parent: info = self.root_info[obj] = self.info_factory(obj) Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Mon Jun 6 23:33:14 2005 @@ -12,13 +12,17 @@ class AnnotatorError(Exception): pass -class NullAnnotatorPolicy: +class BasicAnnotatorPolicy: def override(pol, func, inputcells): return None def specialize(pol, bookkeeper, spaceop, func, args, mono): return None + def compute_at_fixpoint(pol, annotator): + annotator.bookkeeper.compute_at_fixpoint() + + class RPythonAnnotator: """Block annotator for RPython. See description in doc/translation/annotation.txt.""" @@ -47,9 +51,10 @@ self.return_bindings = {} # map return Variables to functions # --- end of debugging information --- self.bookkeeper = Bookkeeper(self) + self.frozen = False # user-supplied annotation logic for functions we don't want to flow into if policy is None: - self.policy = NullAnnotatorPolicy() + self.policy = BasicAnnotatorPolicy() else: self.policy = policy @@ -156,6 +161,7 @@ def addpendingblock(self, fn, block, cells, called_from=None): """Register an entry point into block with the given input cells.""" assert self.translator is None or fn in self.translator.flowgraphs + assert not self.frozen for a in cells: assert isinstance(a, annmodel.SomeObject) if block not in self.annotated: @@ -187,7 +193,7 @@ print "++-" * 20 raise AnnotatorError('%d blocks are still blocked' % self.annotated.values().count(False)) - self.bookkeeper.compute_at_fixpoint() + self.policy.compute_at_fixpoint(self) def binding(self, arg, extquery=False): "Gives the SomeValue corresponding to the given Variable or Constant." @@ -341,6 +347,7 @@ raise def reflowpendingblock(self, fn, block): + assert not self.frozen self.pendingblocks[block] = fn assert block in self.annotated self.annotated[block] = False # must re-flow From pedronis at codespeak.net Tue Jun 7 01:30:47 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 01:30:47 +0200 (CEST) Subject: [pypy-svn] r13130 - pypy/dist/pypy/rpython Message-ID: <20050606233047.4ED7C27B51@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 01:30:46 2005 New Revision: 13130 Modified: pypy/dist/pypy/rpython/lltype.py Log: don'r access _wrparent from outsider _ptr, _struct and _array Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 01:30:46 2005 @@ -334,8 +334,8 @@ len(PTRTYPE.TO._names) == 0 or PTRTYPE.TO._flds[PTRTYPE.TO._names[0]] != CURTYPE.TO): raise InvalidCast(CURTYPE, PTRTYPE) - ptr._check() - parent = ptr._obj._wrparent() + parent = ptr._obj._parentstructure() + parent._check() PARENTTYPE = ptr._obj._wrparent_type if getattr(parent, PARENTTYPE._names[0]) is not ptr._obj: raise InvalidCast(CURTYPE, PTRTYPE) From pedronis at codespeak.net Tue Jun 7 01:45:12 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 01:45:12 +0200 (CEST) Subject: [pypy-svn] r13131 - pypy/dist/pypy/rpython Message-ID: <20050606234512.D9B5027B51@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 01:45:12 2005 New Revision: 13131 Modified: pypy/dist/pypy/rpython/lltype.py Log: some renaming Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 01:45:12 2005 @@ -336,7 +336,7 @@ raise InvalidCast(CURTYPE, PTRTYPE) parent = ptr._obj._parentstructure() parent._check() - PARENTTYPE = ptr._obj._wrparent_type + PARENTTYPE = ptr._obj._parent_type if getattr(parent, PARENTTYPE._names[0]) is not ptr._obj: raise InvalidCast(CURTYPE, PTRTYPE) return _ptr(PTRTYPE, parent) @@ -359,7 +359,7 @@ def parentlink(container): parent = container._parentstructure() if parent is not None: - return parent, container._wrparent_index + return parent, container._parent_index ## if isinstance(parent, _struct): ## for name in parent._TYPE._names: ## if getattr(parent, name) is container: @@ -422,7 +422,7 @@ self._check() setattr(self._obj, field_name, p._obj) p._obj._wrparent = weakref.ref(self._obj) - p._obj._wrparent_type = typeOf(self._obj) + p._obj._parent_type = typeOf(self._obj) return raise TypeError("%r instance has no first field" % (self._T,)) @@ -497,9 +497,9 @@ value = typ._defl() setattr(self, fld, value) if parent is not None: - self._wrparent_type = typeOf(parent) + self._parent_type = typeOf(parent) self._wrparent = weakref.ref(parent) - self._wrparent_index = parentindex + self._parent_index = parentindex def _parentstructure(self): if self._wrparent is not None: @@ -507,7 +507,7 @@ if parent is None: raise RuntimeError("accessing substructure %r,\n" "but already garbage collected parent %r" - % (self, self._wrparent_type)) + % (self, self._parent_type)) return parent return None @@ -545,9 +545,9 @@ self.items = [TYPE.OF._defl(parent=self, parentindex=j) for j in range(n)] if parent is not None: - self._wrparent_type = typeOf(parent) + self._parent_type = typeOf(parent) self._wrparent = weakref.ref(parent) - self._wrparent_index = parentindex + self._parent_index = parentindex def _parentstructure(self): if self._wrparent is not None: @@ -555,7 +555,7 @@ if parent is None: raise RuntimeError("accessing subarray %r,\n" "but already garbage collected parent %r" - % (self, self._wrparent_type)) + % (self, self._parent_type)) return parent return None From pedronis at codespeak.net Tue Jun 7 01:55:51 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 01:55:51 +0200 (CEST) Subject: [pypy-svn] r13132 - pypy/dist/pypy/rpython Message-ID: <20050606235551.1902727B51@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 01:55:50 2005 New Revision: 13132 Modified: pypy/dist/pypy/rpython/lltype.py Log: refactoring Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 01:55:50 2005 @@ -497,9 +497,12 @@ value = typ._defl() setattr(self, fld, value) if parent is not None: - self._parent_type = typeOf(parent) - self._wrparent = weakref.ref(parent) - self._parent_index = parentindex + self._setparentstructure(parent, parentindex) + + def _setparentstructure(self, parent, parentindex): + self._wrparent = weakref.ref(parent) + self._parent_type = typeOf(parent) + self._parent_index = parentindex def _parentstructure(self): if self._wrparent is not None: @@ -545,9 +548,12 @@ self.items = [TYPE.OF._defl(parent=self, parentindex=j) for j in range(n)] if parent is not None: - self._parent_type = typeOf(parent) - self._wrparent = weakref.ref(parent) - self._parent_index = parentindex + self._setparentstructure(parent, parentindex) + + def _setparentstructure(self, parent, parentindex): + self._wrparent = weakref.ref(parent) + self._parent_type = typeOf(parent) + self._parent_index = parentindex def _parentstructure(self): if self._wrparent is not None: From pedronis at codespeak.net Tue Jun 7 02:00:46 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 02:00:46 +0200 (CEST) Subject: [pypy-svn] r13133 - pypy/dist/pypy/rpython Message-ID: <20050607000046.18E3C27B51@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 02:00:45 2005 New Revision: 13133 Modified: pypy/dist/pypy/rpython/lltype.py Log: move responsability for checking _func._callable Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 02:00:45 2005 @@ -475,7 +475,10 @@ for a, ARG in zip(args, self._T.ARGS): if typeOf(a) != ARG: raise TypeError,"calling %r with wrong argument types: %r" % (self._T, args) - return self._obj._callable(*args) + callb = self._obj._callable + if callb is None: + raise RuntimeError,"calling undefined function" + return callb(*args) raise TypeError("%r instance is not a function" % (self._T,)) @@ -588,8 +591,7 @@ return None def _check(self): - if self._callable is None: - raise RuntimeError,"calling undefined function" + pass def __repr__(self): return '<%s>' % (self,) From pedronis at codespeak.net Tue Jun 7 02:03:36 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 02:03:36 +0200 (CEST) Subject: [pypy-svn] r13134 - pypy/dist/pypy/rpython Message-ID: <20050607000336.65F3327B51@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 02:03:35 2005 New Revision: 13134 Modified: pypy/dist/pypy/rpython/lltype.py Log: _check is complete parent reachability Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 02:03:35 2005 @@ -335,7 +335,6 @@ PTRTYPE.TO._flds[PTRTYPE.TO._names[0]] != CURTYPE.TO): raise InvalidCast(CURTYPE, PTRTYPE) parent = ptr._obj._parentstructure() - parent._check() PARENTTYPE = ptr._obj._parent_type if getattr(parent, PARENTTYPE._names[0]) is not ptr._obj: raise InvalidCast(CURTYPE, PTRTYPE) @@ -514,13 +513,12 @@ raise RuntimeError("accessing substructure %r,\n" "but already garbage collected parent %r" % (self, self._parent_type)) + parent._check() return parent return None def _check(self): - parent = self._parentstructure() - if parent is not None: - parent._check() + self._parentstructure() def __repr__(self): return '<%s>' % (self,) @@ -565,13 +563,12 @@ raise RuntimeError("accessing subarray %r,\n" "but already garbage collected parent %r" % (self, self._parent_type)) + parent._check() return parent return None def _check(self): - parent = self._parentstructure() - if parent is not None: - parent._check() + self._parentstructure() def __repr__(self): return '<%s>' % (self,) From pedronis at codespeak.net Tue Jun 7 02:16:05 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 02:16:05 +0200 (CEST) Subject: [pypy-svn] r13135 - pypy/dist/pypy/rpython Message-ID: <20050607001605.A3FA527B51@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 02:16:04 2005 New Revision: 13135 Modified: pypy/dist/pypy/rpython/lltype.py Log: raise a RuntimeError if trying to cast_parent a structure without a parent. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 02:16:04 2005 @@ -335,6 +335,8 @@ PTRTYPE.TO._flds[PTRTYPE.TO._names[0]] != CURTYPE.TO): raise InvalidCast(CURTYPE, PTRTYPE) parent = ptr._obj._parentstructure() + if parent is None: + raise RuntimeError("widening to trash: %r" % ptr) PARENTTYPE = ptr._obj._parent_type if getattr(parent, PARENTTYPE._names[0]) is not ptr._obj: raise InvalidCast(CURTYPE, PTRTYPE) From pedronis at codespeak.net Tue Jun 7 03:11:51 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 03:11:51 +0200 (CEST) Subject: [pypy-svn] r13136 - pypy/dist/pypy/rpython Message-ID: <20050607011151.2BAAF27B53@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 03:11:49 2005 New Revision: 13136 Modified: pypy/dist/pypy/rpython/lltype.py Log: switch _ptr._obj to a property in preparation to refactoring to have just one kind of pointers for now Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 03:11:49 2005 @@ -379,7 +379,7 @@ def __init__(self, TYPE, pointing_to): self.__dict__['_TYPE'] = TYPE self.__dict__['_T'] = TYPE.TO - self.__dict__['_obj'] = pointing_to + self.__dict__['_obj0'] = pointing_to def __eq__(self, other): if not isinstance(other, _ptr): @@ -395,15 +395,16 @@ def __nonzero__(self): return self._obj is not None - def _check(self): - if self._obj is None: - raise RuntimeError("dereferencing 'NULL' pointer to %r" % (self._T,)) - self._obj._check() + def _getobj(self): + obj = self._obj0 + if obj is not None: + obj._check() + return obj + _obj = property(_getobj) def __getattr__(self, field_name): # ! can only return basic or ptr ! if isinstance(self._T, Struct): if field_name in self._T._flds: - self._check() o = getattr(self._obj, field_name) can_have_gc = (field_name == self._T._names[0] and 'gc' in self._TYPE.flags) @@ -420,7 +421,6 @@ T2 = typeOf(p._obj) if T1 != T2: raise InvalidCast(typeOf(p), typeOf(self)) - self._check() setattr(self._obj, field_name, p._obj) p._obj._wrparent = weakref.ref(self._obj) p._obj._parent_type = typeOf(self._obj) @@ -436,7 +436,6 @@ raise TypeError("%r instance field %r:\n" "expects %r\n" " got %r" % (self._T, field_name, T1, T2)) - self._check() setattr(self._obj, field_name, val) return raise AttributeError("%r instance has no field %r" % (self._T, @@ -444,7 +443,6 @@ def __getitem__(self, i): # ! can only return basic or ptr ! if isinstance(self._T, Array): - self._check() if not (0 <= i < len(self._obj.items)): raise IndexError("array index out of bounds") o = self._obj.items[i] @@ -458,7 +456,6 @@ def __len__(self): if isinstance(self._T, Array): - self._check() return len(self._obj.items) raise TypeError("%r instance is not an array" % (self._T,)) @@ -470,7 +467,6 @@ def __call__(self, *args): if isinstance(self._T, FuncType): - self._check() if len(args) != len(self._T.ARGS): raise TypeError,"calling %r with wrong argument number: %r" % (self._T, args) for a, ARG in zip(args, self._T.ARGS): From pedronis at codespeak.net Tue Jun 7 05:04:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 05:04:08 +0200 (CEST) Subject: [pypy-svn] r13137 - pypy/branch/lltype-refactoring Message-ID: <20050607030408.3E89C27B4C@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 05:04:06 2005 New Revision: 13137 Added: pypy/branch/lltype-refactoring/ - copied from r13136, pypy/dist/pypy/ Log: creating short lived branch for progress on lltype simplication/refactoring tests pass, but the code is in flux there are open questions about: - what to do for what were NonGcPtrs to PyObjects ? * need to finish with removing GcPtr/NonGcPtr/_expose/_TmpPtr stuff and killing cast_flags * fix details, terminology From pedronis at codespeak.net Tue Jun 7 05:11:23 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 05:11:23 +0200 (CEST) Subject: [pypy-svn] r13138 - in pypy/branch/lltype-refactoring: rpython rpython/test translator/c Message-ID: <20050607031123.9D8BD27B4C@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 05:11:20 2005 New Revision: 13138 Modified: pypy/branch/lltype-refactoring/rpython/lltype.py pypy/branch/lltype-refactoring/rpython/rtyper.py pypy/branch/lltype-refactoring/rpython/test/test_llann.py pypy/branch/lltype-refactoring/rpython/test/test_lltype.py pypy/branch/lltype-refactoring/translator/c/database.py pypy/branch/lltype-refactoring/translator/c/funcgen.py pypy/branch/lltype-refactoring/translator/c/node.py pypy/branch/lltype-refactoring/translator/c/wrapper.py Log: actual refactoring changes. Still need to cleanup things Modified: pypy/branch/lltype-refactoring/rpython/lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/lltype.py Tue Jun 7 05:11:20 2005 @@ -62,10 +62,12 @@ class ContainerType(LowLevelType): + def _gcstatus(self): + return isinstance(self, GC_CONTAINER) + def _inline_is_varsize(self, last): raise TypeError, "%r cannot be inlined in structure" % self - class Struct(ContainerType): def __init__(self, name, *fields): self._name = self.__name__ = name @@ -260,7 +262,7 @@ def _example(self): o = self.TO._container_example() - return _ptr(self, o) + return _ptr(self, o, immortal=True) def withflags(self, **flags): newflags = self.flags.copy() @@ -268,9 +270,13 @@ return _PtrType(self.TO, **newflags) def GcPtr(TO, **flags): - return _PtrType(TO, gc=True, **flags) + if not TO._gcstatus(): + raise TypeError + return _PtrType(TO, **flags) def NonGcPtr(TO, **flags): + if not (isinstance(TO, FuncType) or not TO._gcstatus()): + raise TypeError return _PtrType(TO, **flags) @@ -296,7 +302,7 @@ class InvalidCast(TypeError): pass -def cast_flags(PTRTYPE, ptr): +def cast_flags(PTRTYPE, ptr): # xxx Going away if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, _PtrType): raise TypeError, "can only cast pointers to other pointers" CURTYPE = ptr._TYPE @@ -316,6 +322,8 @@ if key not in curflags or curflags[key] != newflags[key]: raise InvalidCast(CURTYPE, PTRTYPE) # end + elif len(curflags) == len(newflags): + pass # temporary hack as long as cast flags is around else: raise InvalidCast(CURTYPE, PTRTYPE) return _ptr(PTRTYPE, ptr._obj) @@ -327,6 +335,9 @@ if CURTYPE.flags != PTRTYPE.flags: raise TypeError("cast_parent() cannot change the flags (%s) to (%s)" % (CURTYPE._str_flags(), PTRTYPE._str_flags())) + if CURTYPE.TO._gcstatus() != PTRTYPE.TO._gcstatus(): + raise TypeError("cast_parent() cannot change the gc status: %s to %s" + % (CURTYPE, PTRTYPE)) # * converting from TO-structure to a parent TO-structure whose first # field is the original structure if (not isinstance(CURTYPE.TO, Struct) or @@ -344,7 +355,7 @@ def _TmpPtr(TO): - return _PtrType(TO, _tmp=True) + return _PtrType(TO) def _expose(val, can_have_gc=False): """XXX A nice docstring here""" @@ -375,11 +386,12 @@ class _ptr(object): + _weak = False - def __init__(self, TYPE, pointing_to): + def __init__(self, TYPE, pointing_to, immortal=False): self.__dict__['_TYPE'] = TYPE self.__dict__['_T'] = TYPE.TO - self.__dict__['_obj0'] = pointing_to + self._setobj(pointing_to, immortal) def __eq__(self, other): if not isinstance(other, _ptr): @@ -395,9 +407,24 @@ def __nonzero__(self): return self._obj is not None + def _setobj(self, pointing_to, immortal=False): + if pointing_to is None: + obj0 = None + elif immortal or isinstance(self._T, (GC_CONTAINER, FuncType)): + print self._T + obj0 = pointing_to + else: + self.__dict__['_weak'] = True + obj0 = weakref.ref(pointing_to) + self.__dict__['_obj0'] = obj0 + def _getobj(self): obj = self._obj0 - if obj is not None: + if obj is not None and self._weak: + obj = obj() + if obj is None: + raise RuntimeError("accessing already garbage collected %r" + % (self._T,)) obj._check() return obj _obj = property(_getobj) @@ -477,40 +504,27 @@ raise RuntimeError,"calling undefined function" return callb(*args) raise TypeError("%r instance is not a function" % (self._T,)) - -class _struct(object): - _wrparent = None - def __init__(self, TYPE, n=None, parent=None, parentindex=None): - self._TYPE = TYPE - if n is not None and TYPE._arrayfld is None: - raise TypeError("%r is not variable-sized" % (TYPE,)) - if n is None and TYPE._arrayfld is not None: - raise TypeError("%r is variable-sized" % (TYPE,)) - for fld, typ in TYPE._flds.items(): - if isinstance(typ, Struct): - value = _struct(typ, parent=self, parentindex=fld) - elif fld == TYPE._arrayfld: - value = _array(typ, n, parent=self, parentindex=fld) - else: - value = typ._defl() - setattr(self, fld, value) - if parent is not None: - self._setparentstructure(parent, parentindex) +class _parentable(object): + _wrparent = None + _kind = "?" def _setparentstructure(self, parent, parentindex): self._wrparent = weakref.ref(parent) self._parent_type = typeOf(parent) self._parent_index = parentindex + if parentindex == 0 and self._TYPE._gcstatus() == typeOf(parent)._gcstatus(): + # keep strong reference to parent, we share the same allocation + self._keepparent = parent def _parentstructure(self): if self._wrparent is not None: parent = self._wrparent() if parent is None: - raise RuntimeError("accessing substructure %r,\n" + raise RuntimeError("accessing sub%s %r,\n" "but already garbage collected parent %r" - % (self, self._parent_type)) + % (self._kind, self, self._parent_type)) parent._check() return parent return None @@ -518,6 +532,27 @@ def _check(self): self._parentstructure() + +class _struct(_parentable): + _kind = "structure" + + def __init__(self, TYPE, n=None, parent=None, parentindex=None): + self._TYPE = TYPE + if n is not None and TYPE._arrayfld is None: + raise TypeError("%r is not variable-sized" % (TYPE,)) + if n is None and TYPE._arrayfld is not None: + raise TypeError("%r is variable-sized" % (TYPE,)) + for fld, typ in TYPE._flds.items(): + if isinstance(typ, Struct): + value = _struct(typ, parent=self, parentindex=fld) + elif fld == TYPE._arrayfld: + value = _array(typ, n, parent=self, parentindex=fld) + else: + value = typ._defl() + setattr(self, fld, value) + if parent is not None: + self._setparentstructure(parent, parentindex) + def __repr__(self): return '<%s>' % (self,) @@ -535,8 +570,8 @@ def __str__(self): return 'struct %s { %s }' % (self._TYPE._name, self._str_fields()) -class _array(object): - _wrparent = None +class _array(_parentable): + _kind = "array" def __init__(self, TYPE, n, parent=None, parentindex=None): if not isinstance(n, int): @@ -549,25 +584,6 @@ if parent is not None: self._setparentstructure(parent, parentindex) - def _setparentstructure(self, parent, parentindex): - self._wrparent = weakref.ref(parent) - self._parent_type = typeOf(parent) - self._parent_index = parentindex - - def _parentstructure(self): - if self._wrparent is not None: - parent = self._wrparent() - if parent is None: - raise RuntimeError("accessing subarray %r,\n" - "but already garbage collected parent %r" - % (self, self._parent_type)) - parent._check() - return parent - return None - - def _check(self): - self._parentstructure() - def __repr__(self): return '<%s>' % (self,) @@ -621,7 +637,7 @@ T = NonGcPtr(T) else: T = GcPtr(T) - return _ptr(T, o) + return _ptr(T, o, immortal) def functionptr(TYPE, name, **attrs): if not isinstance(TYPE, FuncType): @@ -635,9 +651,11 @@ def nullgcptr(T): return _ptr(GcPtr(T), None) +# what do we want about GC/non GC pointers to PyObjects ? + def pyobjectptr(obj): o = _pyobject(obj) - return _ptr(NonGcPtr(PyObject), o) + return _ptr(GcPtr(PyObject), o) # xxx was non-gc def pyobjectgcptr(obj): o = _pyobject(obj) Modified: pypy/branch/lltype-refactoring/rpython/rtyper.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rtyper.py (original) +++ pypy/branch/lltype-refactoring/rpython/rtyper.py Tue Jun 7 05:11:20 2005 @@ -376,6 +376,7 @@ raise TyperError("non-constant variable of type Void") key = s_value.const # specialize by constant value args_s.append(s_value) + assert isinstance(s_value, annmodel.SomePBC) suffix = 'Const' else: key = v.concretetype # specialize by low-level type Modified: pypy/branch/lltype-refactoring/rpython/test/test_llann.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/test/test_llann.py (original) +++ pypy/branch/lltype-refactoring/rpython/test/test_llann.py Tue Jun 7 05:11:20 2005 @@ -35,35 +35,31 @@ s = a.build_types(llf, []) assert s.knowntype == int - def test_cast_flags(self): - S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) - NGCPS1 = NonGcPtr(S1) - def llf(): - p1 = malloc(S1) - p2 = cast_flags(NGCPS1, p1) - return p2 - a = self.RPythonAnnotator() - s = a.build_types(llf, []) - assert isinstance(s, annmodel.SomePtr) - assert s.ll_ptrtype == NGCPS1 + #def test_cast_flags(self): + # S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) + # NGCPS1 = NonGcPtr(S1) + # def llf(): + # p1 = malloc(S1) + # p2 = cast_flags(NGCPS1, p1) + # return p2 + # a = self.RPythonAnnotator() + # s = a.build_types(llf, []) + # assert isinstance(s, annmodel.SomePtr) + # assert s.ll_ptrtype == NGCPS1 def test_cast_parent(self): S2 = Struct("s2", ('a', Signed)) - S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) - GCPS1 = GcPtr(S1) + S1 = Struct("s1", ('sub1', S2), ('sub2', S2)) NGCPS1 = NonGcPtr(S1) NGCPS2 = NonGcPtr(S2) - def llf(): - p1 = malloc(S1) + def llf(p1): p2 = p1.sub1 - p3 = cast_flags(NGCPS2, p2) - p4 = cast_parent(NGCPS1, p3) - p5 = cast_flags(GCPS1, p4) - return p5 + p3 = cast_parent(NGCPS1, p2) + return p3 a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = a.build_types(llf, [annmodel.SomePtr(NGCPS1)]) assert isinstance(s, annmodel.SomePtr) - assert s.ll_ptrtype == GCPS1 + assert s.ll_ptrtype == NGCPS1 def test_cast_parent_from_gc(self): S2 = GcStruct("s2", ('a', Signed)) Modified: pypy/branch/lltype-refactoring/rpython/test/test_lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/test/test_lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/test/test_lltype.py Tue Jun 7 05:11:20 2005 @@ -1,6 +1,9 @@ from pypy.rpython.lltype import * from pypy.rpython.lltype import _TmpPtr +def isweak(p, T): + return p._weak and typeOf(p).TO == T + def test_basics(): S0 = GcStruct("s0", ('a', Signed), ('b', Signed)) assert S0.a == Signed @@ -23,7 +26,7 @@ x = malloc(Ar,3) print x assert typeOf(x) == GcPtr(Ar) - assert typeOf(x[0]) == _TmpPtr(Ar.OF) + assert isweak(x[0], Ar.OF) assert typeOf(x[0].v) == Signed assert x[0].v == 0 x[0].v = 1 @@ -93,9 +96,9 @@ py.test.raises(TypeError, "malloc(S1)") s1 = malloc(S1, 4) assert s1.a == 0 - assert typeOf(s1.rest) == _TmpPtr(S1.rest) + assert isweak(s1.rest, S1.rest) assert len(s1.rest) == 4 - assert typeOf(s1.rest[0]) == _TmpPtr(S1.rest.OF) + assert isweak(s1.rest[0], S1.rest.OF) assert typeOf(s1.rest[0].v) == Signed assert s1.rest[0].v == 0 py.test.raises(IndexError, "s1.rest[4]") @@ -116,11 +119,11 @@ S2 = Struct("s2", ('s3', S3)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1) - assert typeOf(p1.sub1) == _TmpPtr(S2) - assert typeOf(p1.sub2) == _TmpPtr(S2) - assert typeOf(p1.sub1.s3) == _TmpPtr(S3) + assert isweak(p1.sub1, S2) + assert isweak(p1.sub2, S2) + assert isweak(p1.sub1.s3, S3) p2 = cast_flags(NonGcPtr(S2), p1.sub1) - assert typeOf(p2.s3) == _TmpPtr(S3) + assert isweak(p2.s3, S3) def test_gc_substructure_ptr(): S1 = GcStruct("s2", ('a', Signed)) @@ -128,62 +131,69 @@ S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2)) p1 = malloc(S0) assert typeOf(p1.sub1) == GcPtr(S1) - assert typeOf(p1.sub2) == _TmpPtr(S2) - -def test_tagged_pointer(): - S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) - PList = [ - GcPtr(S1), - NonGcPtr(S1), - GcPtr(S1, mytag=True), - NonGcPtr(S1, mytag=True), - GcPtr(S1, myothertag=True), - ] - for P1 in PList: - for P2 in PList: - assert (P1 == P2) == (P1 is P2) - assert PList[2] == GcPtr(S1, mytag=True) + assert isweak(p1.sub2, S2) -def test_cast_flags(): - S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) - p1 = malloc(S1) - p2 = cast_flags(NonGcPtr(S1), p1) - assert typeOf(p2) == NonGcPtr(S1) - p3 = cast_flags(GcPtr(S1), p2) - assert typeOf(p3) == GcPtr(S1) - assert p1 == p3 - py.test.raises(TypeError, "p1 == p2") - py.test.raises(TypeError, "p2 == p3") - - PT = GcPtr(S1, mytag=True) - p2 = cast_flags(PT, p1) - assert typeOf(p2) == PT - p3 = cast_flags(GcPtr(S1), p2) - assert typeOf(p3) == GcPtr(S1) - assert p1 == p3 - py.test.raises(TypeError, "p1 == p2") - py.test.raises(TypeError, "p2 == p3") +#def test_tagged_pointer(): +# S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) +# PList = [ +# GcPtr(S1), +# NonGcPtr(S1), +# GcPtr(S1, mytag=True), +# NonGcPtr(S1, mytag=True), +# GcPtr(S1, myothertag=True), +# ] +# for P1 in PList: +# for P2 in PList: +# assert (P1 == P2) == (P1 is P2) +# assert PList[2] == GcPtr(S1, mytag=True) + +#def test_cast_flags(): +# S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) +# p1 = malloc(S1) +# p2 = cast_flags(NonGcPtr(S1), p1) +# assert typeOf(p2) == NonGcPtr(S1) +# p3 = cast_flags(GcPtr(S1), p2) +# assert typeOf(p3) == GcPtr(S1) +# assert p1 == p3 +# py.test.raises(TypeError, "p1 == p2") +# py.test.raises(TypeError, "p2 == p3") +# +# PT = GcPtr(S1, mytag=True) +# p2 = cast_flags(PT, p1) +# assert typeOf(p2) == PT +# p3 = cast_flags(GcPtr(S1), p2) +# assert typeOf(p3) == GcPtr(S1) +# assert p1 == p3 +# py.test.raises(TypeError, "p1 == p2") +# py.test.raises(TypeError, "p2 == p3") def test_cast_parent(): S2 = Struct("s2", ('a', Signed)) - S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2)) - p1 = malloc(S1) + S1 = Struct("s1", ('sub1', S2), ('sub2', S2)) + p1 = malloc(S1, immortal=True) p2 = p1.sub1 - assert typeOf(p2) == _TmpPtr(S2) p3 = cast_flags(NonGcPtr(S2), p2) assert typeOf(p3) == NonGcPtr(S2) p4 = cast_parent(NonGcPtr(S1), p3) assert typeOf(p4) == NonGcPtr(S1) - p5 = cast_flags(GcPtr(S1), p4) - assert typeOf(p5) == GcPtr(S1) - assert p5 == p1 - py.test.raises(TypeError, "cast_parent(GcPtr(S1), p1.sub1)") - py.test.raises(TypeError, "cast_parent(GcPtr(S1), p1.sub2)") + assert p4 == p1 + py.test.raises(TypeError, "cast_parent(NonGcPtr(S1), p1.sub2)") py.test.raises(TypeError, "cast_parent(_TmpPtr(S1), p1.sub2)") py.test.raises(TypeError, "cast_parent(NonGcPtr(S2), p3)") SUnrelated = Struct("unrelated") py.test.raises(TypeError, "cast_parent(NonGcPtr(SUnrelated), p3)") +def test_cast_parent2(): + S2 = GcStruct("s2", ('a', Signed)) + S1 = GcStruct("s1", ('sub1', S2)) + p1 = malloc(S1) + p2 = p1.sub1 + assert typeOf(p2) == GcPtr(S2) + p3 = cast_parent(GcPtr(S1), p2) + assert p3 == p1 + p2 = malloc(S2) + py.test.raises(RuntimeError, "cast_parent(GcPtr(S1), p2)") + def test_best_effort_gced_parent_detection(): S2 = Struct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) Modified: pypy/branch/lltype-refactoring/translator/c/database.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/database.py (original) +++ pypy/branch/lltype-refactoring/translator/c/database.py Tue Jun 7 05:11:20 2005 @@ -103,7 +103,7 @@ raise Exception("don't know about %r" % (obj,)) def cincrefstmt(self, expr, T): - if isinstance(T, _PtrType) and 'gc' in T.flags: + if isinstance(T, _PtrType) and T.TO._gcstatus(): if T.TO == PyObject: return 'Py_XINCREF(%s);' % expr else: @@ -113,7 +113,7 @@ return '' def cdecrefstmt(self, expr, T): - if isinstance(T, _PtrType) and 'gc' in T.flags: + if isinstance(T, _PtrType) and T.TO._gcstatus(): if T.TO == PyObject: return 'Py_XDECREF(%s);' % expr else: Modified: pypy/branch/lltype-refactoring/translator/c/funcgen.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/funcgen.py (original) +++ pypy/branch/lltype-refactoring/translator/c/funcgen.py Tue Jun 7 05:11:20 2005 @@ -8,7 +8,7 @@ PyObjGcPtr = GcPtr(PyObject) -PyObjNonGcPtr = NonGcPtr(PyObject) +#PyObjNonGcPtr = NonGcPtr(PyObject) class FunctionCodeGenerator: @@ -44,7 +44,7 @@ if isinstance(v, Variable): T = getattr(v, 'concretetype', PyObjGcPtr) else: - T = getattr(v, 'concretetype', PyObjNonGcPtr) + T = getattr(v, 'concretetype', PyObjGcPtr) # xxx was NonGcPtr, what do we want? lltypemap[v] = T return lltypemap Modified: pypy/branch/lltype-refactoring/translator/c/node.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/node.py (original) +++ pypy/branch/lltype-refactoring/translator/c/node.py Tue Jun 7 05:11:20 2005 @@ -82,7 +82,7 @@ STRUCT = self.STRUCT for name in STRUCT._names: FIELD_T = self.c_struct_field_type(name) - if isinstance(FIELD_T, _PtrType) and 'gc' in FIELD_T.flags: + if isinstance(FIELD_T, _PtrType) and FIELD_T.TO._gcstatus(): cname = self.c_struct_field_name(name) line = self.db.cdecrefstmt('%s%s' % (prefix, cname), FIELD_T) if line: Modified: pypy/branch/lltype-refactoring/translator/c/wrapper.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/wrapper.py (original) +++ pypy/branch/lltype-refactoring/translator/c/wrapper.py Tue Jun 7 05:11:20 2005 @@ -8,6 +8,8 @@ from pypy.interpreter.pycode import CO_VARARGS +Ptr = GcPtr # xxx was NonGcPtr, what do we need? + def gen_wrapper(func, rtyper): """generate a wrapper function for 'func' that can be put in a PyCFunction object. The wrapper has signature @@ -33,9 +35,9 @@ vkwds = Variable('kwds') vfname = Constant(func.func_name) # avoid incref/decref on the arguments: 'self' and 'kwds' can be NULL - vself.concretetype = NonGcPtr(PyObject) - vargs.concretetype = NonGcPtr(PyObject) - vkwds.concretetype = NonGcPtr(PyObject) + vself.concretetype = Ptr(PyObject) + vargs.concretetype = Ptr(PyObject) + vkwds.concretetype = Ptr(PyObject) varguments = [] varnames = func.func_code.co_varnames @@ -103,9 +105,9 @@ block.closeblock(Link([vresult], wgraph.returnblock)) checkgraph(wgraph) - return functionptr(FuncType([NonGcPtr(PyObject), - NonGcPtr(PyObject), - NonGcPtr(PyObject)], + return functionptr(FuncType([Ptr(PyObject), + Ptr(PyObject), + Ptr(PyObject)], GcPtr(PyObject)), wgraph.name, graph = wgraph) From pedronis at codespeak.net Tue Jun 7 14:37:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 14:37:54 +0200 (CEST) Subject: [pypy-svn] r13146 - in pypy/branch/lltype-refactoring: annotation rpython rpython/test translator/c translator/c/test Message-ID: <20050607123754.5497127B48@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 14:37:39 2005 New Revision: 13146 Modified: pypy/branch/lltype-refactoring/annotation/builtin.py pypy/branch/lltype-refactoring/rpython/lltype.py pypy/branch/lltype-refactoring/rpython/rclass.py pypy/branch/lltype-refactoring/rpython/test/test_lltype.py pypy/branch/lltype-refactoring/translator/c/database.py pypy/branch/lltype-refactoring/translator/c/funcgen.py pypy/branch/lltype-refactoring/translator/c/node.py pypy/branch/lltype-refactoring/translator/c/test/test_database.py pypy/branch/lltype-refactoring/translator/c/wrapper.py Log: - removed flags and cast_flags open issues: - added _needsgc predicate to _PtrType and _ptr (what rules do we want?) - what kind of pointers for constants? Modified: pypy/branch/lltype-refactoring/annotation/builtin.py ============================================================================== --- pypy/branch/lltype-refactoring/annotation/builtin.py (original) +++ pypy/branch/lltype-refactoring/annotation/builtin.py Tue Jun 7 14:37:39 2005 @@ -299,12 +299,6 @@ #print "MALLOC", r return r -def cast_flags(PtrT, s_p): - #print "CAST", s_p - assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p - assert PtrT.is_constant() - return SomePtr(ll_ptrtype=lltype.typeOf(lltype.cast_flags(PtrT.const, s_p.ll_ptrtype._example()))) - def cast_parent(PtrT, s_p): assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p assert PtrT.is_constant() @@ -333,7 +327,6 @@ return r BUILTIN_ANALYZERS[lltype.malloc] = malloc -BUILTIN_ANALYZERS[lltype.cast_flags] = cast_flags BUILTIN_ANALYZERS[lltype.cast_parent] = cast_parent BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.nullptr] = nullptr Modified: pypy/branch/lltype-refactoring/rpython/lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/lltype.py Tue Jun 7 14:37:39 2005 @@ -230,26 +230,20 @@ class _PtrType(LowLevelType): __name__ = property(lambda self: '%sPtr' % self.TO.__name__) - def __init__(self, TO, **flags): + def __init__(self, TO): if not isinstance(TO, ContainerType): raise TypeError, ("can only point to a Container type, " "not to %s" % (TO,)) - if 'gc' in flags: - if not isinstance(TO, GC_CONTAINER): - raise TypeError, ("GcPtr can only point to GcStruct, GcArray or" - " PyObject, not to %s" % (TO,)) self.TO = TO - self.flags = frozendict(flags) + + def _needsgc(self): + return self.TO._gcstatus() def _str_flags(self): - flags = self.flags.keys() - flags.sort() - result = [] - for flag in flags: - if self.flags[flag] is not True: - flag = '%s=%r' % (flag, self.flags[flag]) - result.append(flag) - return ', '.join(result) + if self._needsgc(): + return 'gc' + else: + return '' def _str_flavor(self): return 'ptr(%s)' % self._str_flags() @@ -264,20 +258,15 @@ o = self.TO._container_example() return _ptr(self, o, immortal=True) - def withflags(self, **flags): - newflags = self.flags.copy() - newflags.update(flags) - return _PtrType(self.TO, **newflags) - -def GcPtr(TO, **flags): +def GcPtr(TO): if not TO._gcstatus(): raise TypeError - return _PtrType(TO, **flags) + return _PtrType(TO) -def NonGcPtr(TO, **flags): +def NonGcPtr(TO): if not (isinstance(TO, FuncType) or not TO._gcstatus()): raise TypeError - return _PtrType(TO, **flags) + return _PtrType(TO) # ____________________________________________________________ @@ -302,40 +291,11 @@ class InvalidCast(TypeError): pass -def cast_flags(PTRTYPE, ptr): # xxx Going away - if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, _PtrType): - raise TypeError, "can only cast pointers to other pointers" - CURTYPE = ptr._TYPE - if CURTYPE.TO != PTRTYPE.TO: - raise TypeError, "cast_flags only between pointers to the same type" - # allowed direct casts (for others, you need several casts): - # * adding one flag - curflags = CURTYPE.flags - newflags = PTRTYPE.flags - if len(curflags) + 1 == len(newflags): - for key in curflags: - if key not in newflags or curflags[key] != newflags[key]: - raise InvalidCast(CURTYPE, PTRTYPE) - # * removing one flag - elif len(curflags) - 1 == len(newflags): - for key in newflags: - if key not in curflags or curflags[key] != newflags[key]: - raise InvalidCast(CURTYPE, PTRTYPE) - # end - elif len(curflags) == len(newflags): - pass # temporary hack as long as cast flags is around - else: - raise InvalidCast(CURTYPE, PTRTYPE) - return _ptr(PTRTYPE, ptr._obj) - def cast_parent(PTRTYPE, ptr): if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, _PtrType): raise TypeError, "can only cast pointers to other pointers" CURTYPE = ptr._TYPE - if CURTYPE.flags != PTRTYPE.flags: - raise TypeError("cast_parent() cannot change the flags (%s) to (%s)" - % (CURTYPE._str_flags(), PTRTYPE._str_flags())) - if CURTYPE.TO._gcstatus() != PTRTYPE.TO._gcstatus(): + if CURTYPE._needsgc() != PTRTYPE._needsgc(): raise TypeError("cast_parent() cannot change the gc status: %s to %s" % (CURTYPE, PTRTYPE)) # * converting from TO-structure to a parent TO-structure whose first @@ -388,6 +348,9 @@ class _ptr(object): _weak = False + def _needsgc(self): + return self._TYPE._needsgc() # xxx other rules? + def __init__(self, TYPE, pointing_to, immortal=False): self.__dict__['_TYPE'] = TYPE self.__dict__['_T'] = TYPE.TO @@ -407,7 +370,7 @@ def __nonzero__(self): return self._obj is not None - def _setobj(self, pointing_to, immortal=False): + def _setobj(self, pointing_to, immortal=False): if pointing_to is None: obj0 = None elif immortal or isinstance(self._T, (GC_CONTAINER, FuncType)): @@ -416,6 +379,7 @@ else: self.__dict__['_weak'] = True obj0 = weakref.ref(pointing_to) + self.__dict__['_immortal'] = immortal self.__dict__['_obj0'] = obj0 def _getobj(self): @@ -433,9 +397,7 @@ if isinstance(self._T, Struct): if field_name in self._T._flds: o = getattr(self._obj, field_name) - can_have_gc = (field_name == self._T._names[0] and - 'gc' in self._TYPE.flags) - return _expose(o, can_have_gc) + return _expose(o) raise AttributeError("%r instance has no field %r" % (self._T, field_name)) Modified: pypy/branch/lltype-refactoring/rpython/rclass.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rclass.py (original) +++ pypy/branch/lltype-refactoring/rpython/rclass.py Tue Jun 7 14:37:39 2005 @@ -60,8 +60,6 @@ def cast_vtable_to_typeptr(vtable): while typeOf(vtable).TO != OBJECT_VTABLE: vtable = vtable.super - if typeOf(vtable) != TYPEPTR: - vtable = cast_flags(TYPEPTR, vtable) return vtable Modified: pypy/branch/lltype-refactoring/rpython/test/test_lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/test/test_lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/test/test_lltype.py Tue Jun 7 14:37:39 2005 @@ -122,7 +122,7 @@ assert isweak(p1.sub1, S2) assert isweak(p1.sub2, S2) assert isweak(p1.sub1.s3, S3) - p2 = cast_flags(NonGcPtr(S2), p1.sub1) + p2 = p1.sub1 assert isweak(p2.s3, S3) def test_gc_substructure_ptr(): @@ -133,46 +133,12 @@ assert typeOf(p1.sub1) == GcPtr(S1) assert isweak(p1.sub2, S2) -#def test_tagged_pointer(): -# S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) -# PList = [ -# GcPtr(S1), -# NonGcPtr(S1), -# GcPtr(S1, mytag=True), -# NonGcPtr(S1, mytag=True), -# GcPtr(S1, myothertag=True), -# ] -# for P1 in PList: -# for P2 in PList: -# assert (P1 == P2) == (P1 is P2) -# assert PList[2] == GcPtr(S1, mytag=True) - -#def test_cast_flags(): -# S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) -# p1 = malloc(S1) -# p2 = cast_flags(NonGcPtr(S1), p1) -# assert typeOf(p2) == NonGcPtr(S1) -# p3 = cast_flags(GcPtr(S1), p2) -# assert typeOf(p3) == GcPtr(S1) -# assert p1 == p3 -# py.test.raises(TypeError, "p1 == p2") -# py.test.raises(TypeError, "p2 == p3") -# -# PT = GcPtr(S1, mytag=True) -# p2 = cast_flags(PT, p1) -# assert typeOf(p2) == PT -# p3 = cast_flags(GcPtr(S1), p2) -# assert typeOf(p3) == GcPtr(S1) -# assert p1 == p3 -# py.test.raises(TypeError, "p1 == p2") -# py.test.raises(TypeError, "p2 == p3") - def test_cast_parent(): S2 = Struct("s2", ('a', Signed)) S1 = Struct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1, immortal=True) p2 = p1.sub1 - p3 = cast_flags(NonGcPtr(S2), p2) + p3 = p2 assert typeOf(p3) == NonGcPtr(S2) p4 = cast_parent(NonGcPtr(S1), p3) assert typeOf(p4) == NonGcPtr(S1) Modified: pypy/branch/lltype-refactoring/translator/c/database.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/database.py (original) +++ pypy/branch/lltype-refactoring/translator/c/database.py Tue Jun 7 14:37:39 2005 @@ -103,7 +103,7 @@ raise Exception("don't know about %r" % (obj,)) def cincrefstmt(self, expr, T): - if isinstance(T, _PtrType) and T.TO._gcstatus(): + if isinstance(T, _PtrType) and T._needsgc(): if T.TO == PyObject: return 'Py_XINCREF(%s);' % expr else: @@ -113,7 +113,7 @@ return '' def cdecrefstmt(self, expr, T): - if isinstance(T, _PtrType) and T.TO._gcstatus(): + if isinstance(T, _PtrType) and T._needsgc(): if T.TO == PyObject: return 'Py_XDECREF(%s);' % expr else: Modified: pypy/branch/lltype-refactoring/translator/c/funcgen.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/funcgen.py (original) +++ pypy/branch/lltype-refactoring/translator/c/funcgen.py Tue Jun 7 14:37:39 2005 @@ -7,9 +7,7 @@ from pypy.rpython.lltype import pyobjectptr, Struct, Array -PyObjGcPtr = GcPtr(PyObject) -#PyObjNonGcPtr = NonGcPtr(PyObject) - +PyObjPtr = GcPtr(PyObject) class FunctionCodeGenerator: """ @@ -41,10 +39,8 @@ resultvar = self.graph.getreturnvar() lltypemap = {resultvar: Void} # default value, normally overridden for v in uniqueitems(result): - if isinstance(v, Variable): - T = getattr(v, 'concretetype', PyObjGcPtr) - else: - T = getattr(v, 'concretetype', PyObjGcPtr) # xxx was NonGcPtr, what do we want? + # xxx what kind of pointer for constants? + T = getattr(v, 'concretetype', PyObjPtr) lltypemap[v] = T return lltypemap Modified: pypy/branch/lltype-refactoring/translator/c/node.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/node.py (original) +++ pypy/branch/lltype-refactoring/translator/c/node.py Tue Jun 7 14:37:39 2005 @@ -82,7 +82,7 @@ STRUCT = self.STRUCT for name in STRUCT._names: FIELD_T = self.c_struct_field_type(name) - if isinstance(FIELD_T, _PtrType) and FIELD_T.TO._gcstatus(): + if isinstance(FIELD_T, _PtrType) and FIELD_T._needsgc(): cname = self.c_struct_field_name(name) line = self.db.cdecrefstmt('%s%s' % (prefix, cname), FIELD_T) if line: Modified: pypy/branch/lltype-refactoring/translator/c/test/test_database.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/test/test_database.py (original) +++ pypy/branch/lltype-refactoring/translator/c/test/test_database.py Tue Jun 7 14:37:39 2005 @@ -73,7 +73,7 @@ s.x = malloc(T) s.x.y = 42 s.u.z = -100 - s.p = cast_flags(NonGcPtr(U), s.u) + s.p = s.u db.get(s) db.complete() dump_on_stdout(db) @@ -105,8 +105,8 @@ a.y[2].i = 102 s = malloc(S) s.aptr = a - s.anitem = cast_flags(NonGcPtr(A.y.OF), a.y[1]) - s.anarray = cast_flags(NonGcPtr(A.y), a.y) + s.anitem = a.y[1] + s.anarray = a.y db.get(s) db.complete() dump_on_stdout(db) Modified: pypy/branch/lltype-refactoring/translator/c/wrapper.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/wrapper.py (original) +++ pypy/branch/lltype-refactoring/translator/c/wrapper.py Tue Jun 7 14:37:39 2005 @@ -8,7 +8,7 @@ from pypy.interpreter.pycode import CO_VARARGS -Ptr = GcPtr # xxx was NonGcPtr, what do we need? +PyObjPtr = GcPtr(PyObject) def gen_wrapper(func, rtyper): """generate a wrapper function for 'func' that can be put in a @@ -35,9 +35,9 @@ vkwds = Variable('kwds') vfname = Constant(func.func_name) # avoid incref/decref on the arguments: 'self' and 'kwds' can be NULL - vself.concretetype = Ptr(PyObject) - vargs.concretetype = Ptr(PyObject) - vkwds.concretetype = Ptr(PyObject) + vself.concretetype = PyObjPtr + vargs.concretetype = PyObjPtr + vkwds.concretetype = PyObjPtr varguments = [] varnames = func.func_code.co_varnames @@ -105,9 +105,9 @@ block.closeblock(Link([vresult], wgraph.returnblock)) checkgraph(wgraph) - return functionptr(FuncType([Ptr(PyObject), - Ptr(PyObject), - Ptr(PyObject)], - GcPtr(PyObject)), + return functionptr(FuncType([PyObjPtr, + PyObjPtr, + PyObjPtr], + PyObjPtr), wgraph.name, graph = wgraph) From pedronis at codespeak.net Tue Jun 7 15:23:43 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 15:23:43 +0200 (CEST) Subject: [pypy-svn] r13147 - in pypy/branch/lltype-refactoring: annotation annotation/test rpython rpython/test translator/c translator/c/test translator/genc/test Message-ID: <20050607132343.7433C27B48@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 15:23:27 2005 New Revision: 13147 Removed: pypy/branch/lltype-refactoring/translator/genc/test/test_lltyped.py Modified: pypy/branch/lltype-refactoring/annotation/builtin.py pypy/branch/lltype-refactoring/annotation/test/test_model.py pypy/branch/lltype-refactoring/rpython/lltype.py pypy/branch/lltype-refactoring/rpython/rbuiltin.py pypy/branch/lltype-refactoring/rpython/rclass.py pypy/branch/lltype-refactoring/rpython/rlist.py pypy/branch/lltype-refactoring/rpython/robject.py pypy/branch/lltype-refactoring/rpython/rrange.py pypy/branch/lltype-refactoring/rpython/rstr.py pypy/branch/lltype-refactoring/rpython/rtyper.py pypy/branch/lltype-refactoring/rpython/test/test_llann.py pypy/branch/lltype-refactoring/rpython/test/test_lltype.py pypy/branch/lltype-refactoring/translator/c/funcgen.py pypy/branch/lltype-refactoring/translator/c/test/test_database.py pypy/branch/lltype-refactoring/translator/c/test/test_genc.py pypy/branch/lltype-refactoring/translator/c/wrapper.py Log: - merged GcPtr and NonGcPtr -> Ptr! - doesn't make sense to keep alive the lltype support in the old gc, removed failing tests all other tests pass still open: what to do about constants and gc apart from that mergeable Modified: pypy/branch/lltype-refactoring/annotation/builtin.py ============================================================================== --- pypy/branch/lltype-refactoring/annotation/builtin.py (original) +++ pypy/branch/lltype-refactoring/annotation/builtin.py Tue Jun 7 15:23:27 2005 @@ -319,15 +319,8 @@ r.const = p return r -def nullgcptr(T): - assert T.is_constant() - p = lltype.nullgcptr(T.const) - r = SomePtr(lltype.typeOf(p)) - r.const = p - return r - BUILTIN_ANALYZERS[lltype.malloc] = malloc BUILTIN_ANALYZERS[lltype.cast_parent] = cast_parent BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.nullptr] = nullptr -BUILTIN_ANALYZERS[lltype.nullgcptr] = nullgcptr + Modified: pypy/branch/lltype-refactoring/annotation/test/test_model.py ============================================================================== --- pypy/branch/lltype-refactoring/annotation/test/test_model.py (original) +++ pypy/branch/lltype-refactoring/annotation/test/test_model.py Tue Jun 7 15:23:27 2005 @@ -115,9 +115,9 @@ S = lltype.GcStruct('s') A = lltype.GcArray() s_p = ll_to_annotation(lltype.malloc(S)) - assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltype.GcPtr(S) + assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltype.Ptr(S) s_p = ll_to_annotation(lltype.malloc(A, 0)) - assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltype.GcPtr(A) + assert isinstance(s_p, SomePtr) and s_p.ll_ptrtype == lltype.Ptr(A) def test_annotation_to_lltype(): from pypy.rpython.rarithmetic import r_uint @@ -136,17 +136,17 @@ assert annotation_to_lltype(s_u1) == lltype.Unsigned assert annotation_to_lltype(SomeBool()) == lltype.Bool assert annotation_to_lltype(SomeChar()) == lltype.Char - PS = lltype.GcPtr(lltype.GcStruct('s')) + PS = lltype.Ptr(lltype.GcStruct('s')) s_p = SomePtr(ll_ptrtype=PS) assert annotation_to_lltype(s_p) == PS py.test.raises(ValueError, "annotation_to_lltype(si0)") def test_ll_union(): - PS1 = lltype.GcPtr(lltype.GcStruct('s')) - PS2 = lltype.GcPtr(lltype.GcStruct('s')) - PS3 = lltype.GcPtr(lltype.GcStruct('s3')) - PA1 = lltype.GcPtr(lltype.GcArray()) - PA2 = lltype.GcPtr(lltype.GcArray()) + PS1 = lltype.Ptr(lltype.GcStruct('s')) + PS2 = lltype.Ptr(lltype.GcStruct('s')) + PS3 = lltype.Ptr(lltype.GcStruct('s3')) + PA1 = lltype.Ptr(lltype.GcArray()) + PA2 = lltype.Ptr(lltype.GcArray()) assert unionof(SomePtr(PS1),SomePtr(PS1)) == SomePtr(PS1) assert unionof(SomePtr(PS1),SomePtr(PS2)) == SomePtr(PS2) Modified: pypy/branch/lltype-refactoring/rpython/lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/lltype.py Tue Jun 7 15:23:27 2005 @@ -258,14 +258,7 @@ o = self.TO._container_example() return _ptr(self, o, immortal=True) -def GcPtr(TO): - if not TO._gcstatus(): - raise TypeError - return _PtrType(TO) - -def NonGcPtr(TO): - if not (isinstance(TO, FuncType) or not TO._gcstatus()): - raise TypeError +def Ptr(TO): return _PtrType(TO) @@ -313,19 +306,11 @@ raise InvalidCast(CURTYPE, PTRTYPE) return _ptr(PTRTYPE, parent) - -def _TmpPtr(TO): - return _PtrType(TO) - -def _expose(val, can_have_gc=False): +def _expose(val): """XXX A nice docstring here""" T = typeOf(val) if isinstance(T, ContainerType): - assert not isinstance(T, FuncType), "functions cannot be substructures" - if can_have_gc and isinstance(T, GcStruct): - val = _ptr(GcPtr(T), val) - else: - val = _ptr(_TmpPtr(T), val) + val = _ptr(Ptr(T), val) return val def parentlink(container): @@ -595,30 +580,18 @@ o = _array(T, n) else: raise TypeError, "malloc for Structs and Arrays only" - if immortal: - T = NonGcPtr(T) - else: - T = GcPtr(T) - return _ptr(T, o, immortal) + return _ptr(Ptr(T), o, immortal) def functionptr(TYPE, name, **attrs): if not isinstance(TYPE, FuncType): raise TypeError, "function() for FuncTypes only" o = _func(TYPE, _name=name, **attrs) - return _ptr(NonGcPtr(TYPE), o) + return _ptr(Ptr(TYPE), o) def nullptr(T): - return _ptr(NonGcPtr(T), None) - -def nullgcptr(T): - return _ptr(GcPtr(T), None) - -# what do we want about GC/non GC pointers to PyObjects ? + return _ptr(Ptr(T), None) def pyobjectptr(obj): o = _pyobject(obj) - return _ptr(GcPtr(PyObject), o) # xxx was non-gc + return _ptr(Ptr(PyObject), o) # xxx was non-gc -def pyobjectgcptr(obj): - o = _pyobject(obj) - return _ptr(GcPtr(PyObject), o) Modified: pypy/branch/lltype-refactoring/rpython/rbuiltin.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rbuiltin.py (original) +++ pypy/branch/lltype-refactoring/rpython/rbuiltin.py Tue Jun 7 15:23:27 2005 @@ -118,5 +118,4 @@ BUILTIN_TYPER[lltype.malloc] = rtype_malloc BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result -BUILTIN_TYPER[lltype.nullgcptr] = rtype_const_result BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask Modified: pypy/branch/lltype-refactoring/rpython/rclass.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rclass.py (original) +++ pypy/branch/lltype-refactoring/rpython/rclass.py Tue Jun 7 15:23:27 2005 @@ -33,7 +33,7 @@ # OBJECT_VTABLE = ForwardReference() -TYPEPTR = NonGcPtr(OBJECT_VTABLE) +TYPEPTR = Ptr(OBJECT_VTABLE) OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR))) OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) @@ -70,7 +70,7 @@ self.rtyper = rtyper self.classdef = classdef self.vtable_type = ForwardReference() - self.lowleveltype = NonGcPtr(self.vtable_type) + self.lowleveltype = Ptr(self.vtable_type) def __repr__(self): if self.classdef is None: @@ -253,7 +253,7 @@ self.rtyper = rtyper self.classdef = classdef self.object_type = GcForwardReference() - self.lowleveltype = GcPtr(self.object_type) + self.lowleveltype = Ptr(self.object_type) def __repr__(self): if self.classdef is None: @@ -303,7 +303,7 @@ def convert_const(self, value, targetptr=None, vtable=None): if value is None: - return nullgcptr(self.object_type) + return nullptr(self.object_type) # we will need the vtable pointer, so ask it first, to let # ClassRepr.convert_const() perform all the necessary checks on 'value' if vtable is None: @@ -367,7 +367,7 @@ """Build a new instance, without calling __init__.""" ctype = inputconst(Void, self.object_type) vptr = llops.genop('malloc', [ctype], - resulttype = GcPtr(self.object_type)) + resulttype = Ptr(self.object_type)) ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable()) self.setfield(vptr, '__class__', ctypeptr, llops) # initialize instance attributes from their defaults from the class Modified: pypy/branch/lltype-refactoring/rpython/rlist.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rlist.py (original) +++ pypy/branch/lltype-refactoring/rpython/rlist.py Tue Jun 7 15:23:27 2005 @@ -33,7 +33,7 @@ def __init__(self, item_repr, listdef=None): self.LIST = GcForwardReference() - self.lowleveltype = GcPtr(self.LIST) + self.lowleveltype = Ptr(self.LIST) if not isinstance(item_repr, Repr): # not computed yet, done by setup() assert callable(item_repr) self._item_repr_computer = item_repr @@ -48,7 +48,7 @@ if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype ITEMARRAY = GcArray(("item", ITEM)) - self.LIST.become(GcStruct("list", ("items", GcPtr(ITEMARRAY)))) + self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY)))) def rtype_len(self, hop): v_lst, = hop.inputargs(self) @@ -146,9 +146,9 @@ def __init__(self, r_list): self.r_list = r_list - self.lowleveltype = GcPtr(GcStruct('listiter', - ('list', r_list.lowleveltype), - ('index', Signed))) + self.lowleveltype = Ptr(GcStruct('listiter', + ('list', r_list.lowleveltype), + ('index', Signed))) def newiter(self, hop): v_lst, = hop.inputargs(self.r_list) Modified: pypy/branch/lltype-refactoring/rpython/robject.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/robject.py (original) +++ pypy/branch/lltype-refactoring/rpython/robject.py Tue Jun 7 15:23:27 2005 @@ -1,6 +1,6 @@ from pypy.annotation.pairtype import pair, pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import PyObject, GcPtr, Void, Bool +from pypy.rpython.lltype import PyObject, Ptr, Void, Bool from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass @@ -16,7 +16,7 @@ class PyObjRepr(Repr): - lowleveltype = GcPtr(PyObject) + lowleveltype = Ptr(PyObject) pyobj_repr = PyObjRepr() Modified: pypy/branch/lltype-refactoring/rpython/rrange.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rrange.py (original) +++ pypy/branch/lltype-refactoring/rpython/rrange.py Tue Jun 7 15:23:27 2005 @@ -17,7 +17,7 @@ class RangeRepr(Repr): - lowleveltype = GcPtr(RANGE) + lowleveltype = Ptr(RANGE) def __init__(self, step): self.step = step @@ -102,7 +102,7 @@ # Iteration. class RangeIteratorRepr(Repr): - lowleveltype = GcPtr(RANGEITER) + lowleveltype = Ptr(RANGEITER) def __init__(self, r_rng): self.r_rng = r_rng Modified: pypy/branch/lltype-refactoring/rpython/rstr.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rstr.py (original) +++ pypy/branch/lltype-refactoring/rpython/rstr.py Tue Jun 7 15:23:27 2005 @@ -33,11 +33,11 @@ CONST_STR_CACHE = WeakValueDictionary() class __extend__(StringRepr): - lowleveltype = GcPtr(STR) + lowleveltype = Ptr(STR) def convert_const(self, value): if value is None: - return nullgcptr(STR) + return nullptr(STR) if not isinstance(value, str): raise TyperError("not a str: %r" % (value,)) try: Modified: pypy/branch/lltype-refactoring/rpython/rtyper.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/rtyper.py (original) +++ pypy/branch/lltype-refactoring/rpython/rtyper.py Tue Jun 7 15:23:27 2005 @@ -4,7 +4,7 @@ from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void -from pypy.rpython.lltype import LowLevelType, NonGcPtr, ContainerType +from pypy.rpython.lltype import LowLevelType, Ptr, ContainerType from pypy.rpython.lltype import FuncType, functionptr, typeOf from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block @@ -55,7 +55,7 @@ # here is the code that actually builds a Repr instance result = s_obj.rtyper_makerepr(self) assert not isinstance(result.lowleveltype, ContainerType), ( - "missing a GcPtr or NonGcPtr in the type specification " + "missing a Ptr in the type specification " "of %s:\n%r" % (s_obj, result.lowleveltype)) self.reprs_by_content[key] = result self.reprs_must_call_setup.append(result) Modified: pypy/branch/lltype-refactoring/rpython/test/test_llann.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/test/test_llann.py (original) +++ pypy/branch/lltype-refactoring/rpython/test/test_llann.py Tue Jun 7 15:23:27 2005 @@ -34,46 +34,34 @@ a = self.RPythonAnnotator() s = a.build_types(llf, []) assert s.knowntype == int - - #def test_cast_flags(self): - # S1 = GcStruct("s1", ('a', Signed), ('b', Unsigned)) - # NGCPS1 = NonGcPtr(S1) - # def llf(): - # p1 = malloc(S1) - # p2 = cast_flags(NGCPS1, p1) - # return p2 - # a = self.RPythonAnnotator() - # s = a.build_types(llf, []) - # assert isinstance(s, annmodel.SomePtr) - # assert s.ll_ptrtype == NGCPS1 def test_cast_parent(self): S2 = Struct("s2", ('a', Signed)) S1 = Struct("s1", ('sub1', S2), ('sub2', S2)) - NGCPS1 = NonGcPtr(S1) - NGCPS2 = NonGcPtr(S2) + PS1 = Ptr(S1) + PS2 = Ptr(S2) def llf(p1): p2 = p1.sub1 - p3 = cast_parent(NGCPS1, p2) + p3 = cast_parent(PS1, p2) return p3 a = self.RPythonAnnotator() - s = a.build_types(llf, [annmodel.SomePtr(NGCPS1)]) + s = a.build_types(llf, [annmodel.SomePtr(PS1)]) assert isinstance(s, annmodel.SomePtr) - assert s.ll_ptrtype == NGCPS1 + assert s.ll_ptrtype == PS1 def test_cast_parent_from_gc(self): S2 = GcStruct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('x', Signed)) - GCPS1 = GcPtr(S1) + PS1 = Ptr(S1) def llf(): p1 = malloc(S1) p2 = p1.sub1 - p3 = cast_parent(GCPS1, p2) + p3 = cast_parent(PS1, p2) return p3 a = self.RPythonAnnotator() s = a.build_types(llf, []) assert isinstance(s, annmodel.SomePtr) - assert s.ll_ptrtype == GCPS1 + assert s.ll_ptrtype == PS1 def test_array_length(self): A = GcArray(('v', Signed)) @@ -86,7 +74,7 @@ def test_funcptr(self): F = FuncType((Signed,), Signed) - PF = NonGcPtr(F) + PF = Ptr(F) def llf(p): return p(0) a = self.RPythonAnnotator() Modified: pypy/branch/lltype-refactoring/rpython/test/test_lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/test/test_lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/test/test_lltype.py Tue Jun 7 15:23:27 2005 @@ -1,5 +1,4 @@ from pypy.rpython.lltype import * -from pypy.rpython.lltype import _TmpPtr def isweak(p, T): return p._weak and typeOf(p).TO == T @@ -10,7 +9,7 @@ assert S0.b == Signed s0 = malloc(S0) print s0 - assert typeOf(s0) == GcPtr(S0) + assert typeOf(s0) == Ptr(S0) assert s0.a == 0 assert s0.b == 0 assert typeOf(s0.a) == Signed @@ -25,7 +24,7 @@ assert len(x) == 0 x = malloc(Ar,3) print x - assert typeOf(x) == GcPtr(Ar) + assert typeOf(x) == Ptr(Ar) assert isweak(x[0], Ar.OF) assert typeOf(x[0].v) == Signed assert x[0].v == 0 @@ -36,7 +35,7 @@ # def define_list(T): List_typ = GcStruct("list", - ("items", GcPtr(GcArray(('item',T))))) + ("items", Ptr(GcArray(('item',T))))) def newlist(): l = malloc(List_typ) items = malloc(List_typ.items.TO, 0) @@ -61,7 +60,7 @@ List_typ, inewlist, iappend, iitem = define_list(Signed) l = inewlist() - assert typeOf(l) == GcPtr(List_typ) + assert typeOf(l) == Ptr(List_typ) iappend(l, 2) iappend(l, 3) assert len(l.items) == 2 @@ -69,10 +68,10 @@ assert iitem(l, 1) == 3 IWrap = GcStruct("iwrap", ('v', Signed)) - List_typ, iwnewlist, iwappend, iwitem = define_list(GcPtr(IWrap)) + List_typ, iwnewlist, iwappend, iwitem = define_list(Ptr(IWrap)) l = iwnewlist() - assert typeOf(l) == GcPtr(List_typ) + assert typeOf(l) == Ptr(List_typ) iw2 = malloc(IWrap) iw3 = malloc(IWrap) iw2.v = 2 @@ -130,7 +129,7 @@ S2 = Struct("s3", ('a', Signed)) S0 = GcStruct("s1", ('sub1', S1), ('sub2', S2)) p1 = malloc(S0) - assert typeOf(p1.sub1) == GcPtr(S1) + assert typeOf(p1.sub1) == Ptr(S1) assert isweak(p1.sub2, S2) def test_cast_parent(): @@ -139,26 +138,25 @@ p1 = malloc(S1, immortal=True) p2 = p1.sub1 p3 = p2 - assert typeOf(p3) == NonGcPtr(S2) - p4 = cast_parent(NonGcPtr(S1), p3) - assert typeOf(p4) == NonGcPtr(S1) + assert typeOf(p3) == Ptr(S2) + p4 = cast_parent(Ptr(S1), p3) + assert typeOf(p4) == Ptr(S1) assert p4 == p1 - py.test.raises(TypeError, "cast_parent(NonGcPtr(S1), p1.sub2)") - py.test.raises(TypeError, "cast_parent(_TmpPtr(S1), p1.sub2)") - py.test.raises(TypeError, "cast_parent(NonGcPtr(S2), p3)") + py.test.raises(TypeError, "cast_parent(Ptr(S1), p1.sub2)") + py.test.raises(TypeError, "cast_parent(Ptr(S2), p3)") SUnrelated = Struct("unrelated") - py.test.raises(TypeError, "cast_parent(NonGcPtr(SUnrelated), p3)") + py.test.raises(TypeError, "cast_parent(Ptr(SUnrelated), p3)") def test_cast_parent2(): S2 = GcStruct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2)) p1 = malloc(S1) p2 = p1.sub1 - assert typeOf(p2) == GcPtr(S2) - p3 = cast_parent(GcPtr(S1), p2) + assert typeOf(p2) == Ptr(S2) + p3 = cast_parent(Ptr(S1), p2) assert p3 == p1 p2 = malloc(S2) - py.test.raises(RuntimeError, "cast_parent(GcPtr(S1), p2)") + py.test.raises(RuntimeError, "cast_parent(Ptr(S1), p2)") def test_best_effort_gced_parent_detection(): S2 = Struct("s2", ('a', Signed)) @@ -193,9 +191,9 @@ S = GcStruct("s", ('v', Signed)) St = GcStruct("st", ('v', Signed),('trail', Array(('v', Signed)))) - PA1 = GcPtr(A1) - PS = GcPtr(S) - PSt = GcPtr(St) + PA1 = Ptr(A1) + PS = Ptr(S) + PSt = Ptr(St) ex_pa1 = PA1._example() ex_ps = PS._example() @@ -214,7 +212,7 @@ F = FuncType((Signed,), Signed) py.test.raises(TypeError, "Struct('x', ('x', F))") - PF = NonGcPtr(F) + PF = Ptr(F) pf = PF._example() assert pf(0) == 0 py.test.raises(TypeError, pf, 0, 0) @@ -223,7 +221,6 @@ def test_inconsistent_gc_containers(): A = GcArray(('y', Signed)) S = GcStruct('b', ('y', Signed)) - py.test.raises(TypeError, "GcPtr(Struct('a', ('x', Signed)))") py.test.raises(TypeError, "Struct('a', ('x', S))") py.test.raises(TypeError, "GcStruct('a', ('x', Signed), ('y', S))") py.test.raises(TypeError, "Array(('x', S))") @@ -233,9 +230,9 @@ def test_forward_reference(): F = GcForwardReference() - S = GcStruct('abc', ('x', GcPtr(F))) + S = GcStruct('abc', ('x', Ptr(F))) F.become(S) - assert S.x == GcPtr(S) + assert S.x == Ptr(S) py.test.raises(TypeError, "GcForwardReference().become(Struct('abc'))") ForwardReference().become(Struct('abc')) hash(S) Modified: pypy/branch/lltype-refactoring/translator/c/funcgen.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/funcgen.py (original) +++ pypy/branch/lltype-refactoring/translator/c/funcgen.py Tue Jun 7 15:23:27 2005 @@ -3,11 +3,11 @@ from pypy.translator.c.support import llvalue_from_constant from pypy.objspace.flow.model import Variable, Constant, Block from pypy.objspace.flow.model import traverse, uniqueitems, last_exception -from pypy.rpython.lltype import GcPtr, NonGcPtr, PyObject, Void +from pypy.rpython.lltype import Ptr, PyObject, Void from pypy.rpython.lltype import pyobjectptr, Struct, Array -PyObjPtr = GcPtr(PyObject) +PyObjPtr = Ptr(PyObject) class FunctionCodeGenerator: """ Modified: pypy/branch/lltype-refactoring/translator/c/test/test_database.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/test/test_database.py (original) +++ pypy/branch/lltype-refactoring/translator/c/test/test_database.py Tue Jun 7 15:23:27 2005 @@ -50,7 +50,7 @@ def test_complete(): db = LowLevelDatabase() T = GcStruct('subtest', ('y', Signed)) - S = GcStruct('test', ('x', GcPtr(T))) + S = GcStruct('test', ('x', Ptr(T))) s = malloc(S) s.x = malloc(T) s.x.y = 42 @@ -68,7 +68,7 @@ db = LowLevelDatabase() U = Struct('inlined', ('z', Signed)) T = GcStruct('subtest', ('y', Signed)) - S = GcStruct('test', ('x', GcPtr(T)), ('u', U), ('p', NonGcPtr(U))) + S = GcStruct('test', ('x', Ptr(T)), ('u', U), ('p', Ptr(U))) s = malloc(S) s.x = malloc(T) s.x.y = 42 @@ -81,7 +81,7 @@ def test_codegen_2(): db = LowLevelDatabase() A = GcArray(('x', Signed)) - S = GcStruct('test', ('aptr', GcPtr(A))) + S = GcStruct('test', ('aptr', Ptr(A))) a = malloc(A, 3) a[0].x = 100 a[1].x = 101 @@ -95,9 +95,9 @@ def test_codegen_3(): db = LowLevelDatabase() A = GcStruct('varsizedstuff', ('x', Signed), ('y', Array(('i', Signed)))) - S = GcStruct('test', ('aptr', GcPtr(A)), - ('anitem', NonGcPtr(A.y.OF)), - ('anarray', NonGcPtr(A.y))) + S = GcStruct('test', ('aptr', Ptr(A)), + ('anitem', Ptr(A.y.OF)), + ('anarray', Ptr(A.y))) a = malloc(A, 3) a.x = 99 a.y[0].i = 100 @@ -136,7 +136,7 @@ db.complete() dump_on_stdout(db) - S = GcStruct('testing', ('fptr', NonGcPtr(F))) + S = GcStruct('testing', ('fptr', Ptr(F))) s = malloc(S) s.fptr = f db = LowLevelDatabase() @@ -150,14 +150,14 @@ t = Translator(f) graph = t.getflowgraph() - F = FuncType([GcPtr(PyObject)], GcPtr(PyObject)) + F = FuncType([Ptr(PyObject)], Ptr(PyObject)) f = functionptr(F, "f", graph=graph) db = LowLevelDatabase() db.get(f) db.complete() dump_on_stdout(db) - S = GcStruct('testing', ('fptr', NonGcPtr(F))) + S = GcStruct('testing', ('fptr', Ptr(F))) s = malloc(S) s.fptr = f db = LowLevelDatabase() @@ -213,8 +213,8 @@ def test_multiple_malloc(): S1 = GcStruct('testing1', ('x', Signed), ('y', Signed)) - S = GcStruct('testing', ('ptr1', GcPtr(S1)), - ('ptr2', GcPtr(S1)), + S = GcStruct('testing', ('ptr1', Ptr(S1)), + ('ptr2', Ptr(S1)), ('z', Signed)) def ll_f(x): ptr1 = malloc(S1) @@ -235,9 +235,9 @@ dump_on_stdout(db) def test_nested_gcstruct(): - S1 = GcStruct('inlined', ('x', Signed), ('y', GcPtr(PyObject))) + S1 = GcStruct('inlined', ('x', Signed), ('y', Ptr(PyObject))) S = GcStruct('testing', ('head', S1), - ('ptr2', GcPtr(S1)), + ('ptr2', Ptr(S1)), ('z', Signed)) def ll_f(x): ptr2 = malloc(S1) @@ -256,7 +256,7 @@ dump_on_stdout(db) def test_array(): - A = GcArray(('obj', GcPtr(PyObject))) + A = GcArray(('obj', Ptr(PyObject))) a = malloc(A, 10) db = LowLevelDatabase() db.get(a) Modified: pypy/branch/lltype-refactoring/translator/c/test/test_genc.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/test/test_genc.py (original) +++ pypy/branch/lltype-refactoring/translator/c/test/test_genc.py Tue Jun 7 15:23:27 2005 @@ -30,8 +30,8 @@ t = Translator(f) graph = t.getflowgraph() - F = FuncType([GcPtr(PyObject)], GcPtr(PyObject)) - S = GcStruct('testing', ('fptr', NonGcPtr(F))) + F = FuncType([Ptr(PyObject)], Ptr(PyObject)) + S = GcStruct('testing', ('fptr', Ptr(F))) f = functionptr(F, "f", graph=graph) s = malloc(S) s.fptr = f @@ -93,7 +93,7 @@ S = GcStruct('testing', ('x', Signed), ('y', Signed)) def f(i): if i < 0: - p = nullgcptr(S) + p = nullptr(S) else: p = malloc(S) p.x = i*2 Modified: pypy/branch/lltype-refactoring/translator/c/wrapper.py ============================================================================== --- pypy/branch/lltype-refactoring/translator/c/wrapper.py (original) +++ pypy/branch/lltype-refactoring/translator/c/wrapper.py Tue Jun 7 15:23:27 2005 @@ -1,14 +1,14 @@ from pypy.objspace.flow.model import Variable, Constant, SpaceOperation from pypy.objspace.flow.model import Block, Link, FunctionGraph, checkgraph from pypy.annotation import model as annmodel -from pypy.rpython.lltype import GcPtr, NonGcPtr, PyObject, typeOf, Signed, Void +from pypy.rpython.lltype import Ptr, PyObject, typeOf, Signed, Void from pypy.rpython.lltype import FuncType, functionptr from pypy.rpython.rtyper import LowLevelOpList, inputconst from pypy.rpython.robject import pyobj_repr from pypy.interpreter.pycode import CO_VARARGS -PyObjPtr = GcPtr(PyObject) +PyObjPtr = Ptr(PyObject) def gen_wrapper(func, rtyper): """generate a wrapper function for 'func' that can be put in a @@ -58,7 +58,7 @@ opname = 'decode_arg_def' vlist.append(Constant(default_value)) - v = newops.genop(opname, vlist, resulttype=GcPtr(PyObject)) + v = newops.genop(opname, vlist, resulttype=Ptr(PyObject)) v._name = 'a%d' % i varguments.append(v) @@ -68,7 +68,7 @@ Constant(nb_positional_args), Constant(None), ] - vararg = newops.genop('getslice', vlist, resulttype=GcPtr(PyObject)) + vararg = newops.genop('getslice', vlist, resulttype=Ptr(PyObject)) vararg._name = 'vararg' varguments.append(vararg) else: Deleted: /pypy/branch/lltype-refactoring/translator/genc/test/test_lltyped.py ============================================================================== --- /pypy/branch/lltype-refactoring/translator/genc/test/test_lltyped.py Tue Jun 7 15:23:27 2005 +++ (empty file) @@ -1,37 +0,0 @@ -from pypy.rpython.lltype import * -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler -from pypy.translator.translator import Translator -from pypy.translator.genc.ctyper import GenCSpecializer - - -class TestLowLevelType: - objspacename = 'flow' - - def getcompiled(self, func, argstypelist=[]): - t = Translator(func, simplifying=True) - # builds starting-types from func_defs - a = t.annotate(argstypelist) - a.simplify() - GenCSpecializer(a).specialize() - t.checkgraphs() - #t.view() - return skip_missing_compiler(t.ccompile) - - def test_simple(self): - S = GcStruct("s", ('v', Signed)) - def llf(): - s = malloc(S) - return s.v - fn = self.getcompiled(llf) - assert fn() == 0 - - def test_simple2(self): - S = Struct("s", ('v', Signed)) - S2 = GcStruct("s2", ('a',S), ('b',S)) - def llf(): - s = malloc(S2) - s.a.v = 6 - s.b.v = 12 - return s.a.v+s.b.v - fn = self.getcompiled(llf) - assert fn() == 18 From pedronis at codespeak.net Tue Jun 7 15:29:27 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 15:29:27 +0200 (CEST) Subject: [pypy-svn] r13148 - pypy/branch/lltype-refactoring/rpython Message-ID: <20050607132927.85A9F27B4C@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 15:29:26 2005 New Revision: 13148 Modified: pypy/branch/lltype-refactoring/rpython/lltype.py Log: _setfirst should use _setparentstructure too Modified: pypy/branch/lltype-refactoring/rpython/lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/lltype.py Tue Jun 7 15:29:26 2005 @@ -396,8 +396,7 @@ if T1 != T2: raise InvalidCast(typeOf(p), typeOf(self)) setattr(self._obj, field_name, p._obj) - p._obj._wrparent = weakref.ref(self._obj) - p._obj._parent_type = typeOf(self._obj) + p._obj._setparentstructure(self._obj, 0) return raise TypeError("%r instance has no first field" % (self._T,)) From pedronis at codespeak.net Tue Jun 7 16:40:19 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 16:40:19 +0200 (CEST) Subject: [pypy-svn] r13149 - pypy/branch/lltype-refactoring/rpython Message-ID: <20050607144019.C38F227B49@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 16:40:18 2005 New Revision: 13149 Modified: pypy/branch/lltype-refactoring/rpython/lltype.py Log: oops, debug print Modified: pypy/branch/lltype-refactoring/rpython/lltype.py ============================================================================== --- pypy/branch/lltype-refactoring/rpython/lltype.py (original) +++ pypy/branch/lltype-refactoring/rpython/lltype.py Tue Jun 7 16:40:18 2005 @@ -359,7 +359,6 @@ if pointing_to is None: obj0 = None elif immortal or isinstance(self._T, (GC_CONTAINER, FuncType)): - print self._T obj0 = pointing_to else: self.__dict__['_weak'] = True From pedronis at codespeak.net Tue Jun 7 16:52:13 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 16:52:13 +0200 (CEST) Subject: [pypy-svn] r13150 - pypy/dist/pypy Message-ID: <20050607145213.880EC27B42@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 16:52:12 2005 New Revision: 13150 Removed: pypy/dist/pypy/ Log: removing to put lltype-refactoring in its place From pedronis at codespeak.net Tue Jun 7 16:53:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 16:53:07 +0200 (CEST) Subject: [pypy-svn] r13151 - in pypy: branch/lltype-refactoring dist/pypy Message-ID: <20050607145307.D61A627B42@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 16:53:06 2005 New Revision: 13151 Added: pypy/dist/pypy/ - copied from r13150, pypy/branch/lltype-refactoring/ Removed: pypy/branch/lltype-refactoring/ Log: making lltype-refactoring the new pypy trunk From pedronis at codespeak.net Tue Jun 7 18:21:19 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 7 Jun 2005 18:21:19 +0200 (CEST) Subject: [pypy-svn] r13153 - in pypy/dist/pypy: rpython translator/c translator/genc translator/genc/test Message-ID: <20050607162119.2218E27B3E@code1.codespeak.net> Author: pedronis Date: Tue Jun 7 18:21:14 2005 New Revision: 13153 Added: pypy/dist/pypy/translator/genc/test/test_lltyped.py - copied unchanged from r13137, pypy/dist/pypy/translator/genc/test/test_lltyped.py Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/genc/lltype.py Log: - renamed _PtrType -> Ptr - resurrected on-its-way-out genc/test/test_lltyped, I had to fix stuff in genc anyway to avoid it choking on import Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 7 18:21:14 2005 @@ -227,7 +227,7 @@ Void = Primitive("Void", None) -class _PtrType(LowLevelType): +class Ptr(LowLevelType): __name__ = property(lambda self: '%sPtr' % self.TO.__name__) def __init__(self, TO): @@ -258,9 +258,6 @@ o = self.TO._container_example() return _ptr(self, o, immortal=True) -def Ptr(TO): - return _PtrType(TO) - # ____________________________________________________________ @@ -285,7 +282,7 @@ pass def cast_parent(PTRTYPE, ptr): - if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, _PtrType): + if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, Ptr): raise TypeError, "can only cast pointers to other pointers" CURTYPE = ptr._TYPE if CURTYPE._needsgc() != PTRTYPE._needsgc(): Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Tue Jun 7 18:21:14 2005 @@ -1,6 +1,6 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import _PtrType, _ptr +from pypy.rpython.lltype import Ptr, _ptr from pypy.rpython.lltype import ContainerType, Void, Signed, Bool from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst @@ -16,7 +16,7 @@ class PtrRepr(Repr): def __init__(self, ptrtype): - assert isinstance(ptrtype, _PtrType) + assert isinstance(ptrtype, Ptr) self.lowleveltype = ptrtype def rtype_getattr(self, hop): Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Tue Jun 7 18:21:14 2005 @@ -1,4 +1,4 @@ -from pypy.rpython.lltype import Primitive, _PtrType, typeOf +from pypy.rpython.lltype import Primitive, Ptr, typeOf from pypy.rpython.lltype import Struct, Array, FuncType, PyObject, Void from pypy.rpython.lltype import ContainerType from pypy.objspace.flow.model import Constant @@ -43,7 +43,7 @@ def gettype(self, T, varlength=1, who_asks=None, argnames=[]): if isinstance(T, Primitive): return PrimitiveType[T] - elif isinstance(T, _PtrType): + elif isinstance(T, Ptr): typename = self.gettype(T.TO) # who_asks not propagated return typename.replace('@', '*@') elif isinstance(T, (Struct, Array)): @@ -85,7 +85,7 @@ T = obj.TYPE if isinstance(T, Primitive): return PrimitiveErrorValue[T] - elif isinstance(T, _PtrType): + elif isinstance(T, Ptr): return 'NULL' else: raise Exception("don't know about %r" % (T,)) @@ -93,7 +93,7 @@ T = typeOf(obj) if isinstance(T, Primitive): return PrimitiveName[T](obj) - elif isinstance(T, _PtrType): + elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL node = self.getcontainernode(obj._obj) return node.ptrname @@ -103,7 +103,7 @@ raise Exception("don't know about %r" % (obj,)) def cincrefstmt(self, expr, T): - if isinstance(T, _PtrType) and T._needsgc(): + if isinstance(T, Ptr) and T._needsgc(): if T.TO == PyObject: return 'Py_XINCREF(%s);' % expr else: @@ -113,7 +113,7 @@ return '' def cdecrefstmt(self, expr, T): - if isinstance(T, _PtrType) and T._needsgc(): + if isinstance(T, Ptr) and T._needsgc(): if T.TO == PyObject: return 'Py_XDECREF(%s);' % expr else: Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue Jun 7 18:21:14 2005 @@ -1,7 +1,7 @@ from __future__ import generators from pypy.rpython.lltype import Struct, Array, FuncType, PyObjectType, typeOf from pypy.rpython.lltype import GcStruct, GcArray, GC_CONTAINER, ContainerType -from pypy.rpython.lltype import parentlink, _PtrType +from pypy.rpython.lltype import parentlink, Ptr from pypy.translator.c.funcgen import FunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom @@ -82,7 +82,7 @@ STRUCT = self.STRUCT for name in STRUCT._names: FIELD_T = self.c_struct_field_type(name) - if isinstance(FIELD_T, _PtrType) and FIELD_T._needsgc(): + if isinstance(FIELD_T, Ptr) and FIELD_T._needsgc(): cname = self.c_struct_field_name(name) line = self.db.cdecrefstmt('%s%s' % (prefix, cname), FIELD_T) if line: Modified: pypy/dist/pypy/translator/genc/lltype.py ============================================================================== --- pypy/dist/pypy/translator/genc/lltype.py (original) +++ pypy/dist/pypy/translator/genc/lltype.py Tue Jun 7 18:21:14 2005 @@ -35,7 +35,7 @@ def needs_refcount(ct): - return isinstance(ct, CPtrType) and 'gc' in ct.lltype.flags + return isinstance(ct, CPtrType) and ct.lltype._needsgc() class CPtrType(CLLType): @@ -52,7 +52,7 @@ def init_globals(self, genc): ct = ll2concretetype(genc.translator, self.lltype.TO) yield 'typedef %s* %s;' % (ct.typename, self.typename) - if 'gc' in self.lltype.flags: + if self.lltype._needsgc(): yield '#define OP_INCREF_%s(p) if (p) REFCNT(%s, p)++;' % ( self.typename, ct.typename) yield '#define OP_DECREF_%s(p) if (p && !--REFCNT(%s, p)) %s(p);' %( @@ -206,7 +206,7 @@ lltype.GcStruct: CStructType, lltype.Array: CArrayType, lltype.GcArray: CArrayType, - lltype._PtrType: CPtrType, + lltype.Ptr: CPtrType, lltype.Primitive: get_primitive_type, } From arigo at codespeak.net Tue Jun 7 18:27:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Jun 2005 18:27:39 +0200 (CEST) Subject: [pypy-svn] r13154 - pypy/dist/pypy/documentation Message-ID: <20050607162739.7F9E927B3E@code1.codespeak.net> Author: arigo Date: Tue Jun 7 18:27:37 2005 New Revision: 13154 Modified: pypy/dist/pypy/documentation/_ref.txt pypy/dist/pypy/documentation/translation.txt Log: Some introductory documentation about the Repr classes of the RTyper. Modified: pypy/dist/pypy/documentation/_ref.txt ============================================================================== --- pypy/dist/pypy/documentation/_ref.txt (original) +++ pypy/dist/pypy/documentation/_ref.txt Tue Jun 7 18:27:37 2005 @@ -30,7 +30,9 @@ .. _`objspace/trace.py`: http://codespeak.net/svn/pypy/dist/pypy/objspace/trace.py .. _`rpython/`: http://codespeak.net/svn/pypy/dist/pypy/rpython .. _`rpython/lltype.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/lltype.py +.. _`rpython/rint.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/rint.py .. _`rpython/rlist.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/rlist.py +.. _`rpython/rmodel.py`: http://codespeak.net/svn/pypy/dist/pypy/rpython/rmodel.py .. _`pypy/test_all.py`: http://codespeak.net/svn/pypy/dist/pypy/test_all.py .. _`tool/`: http://codespeak.net/svn/pypy/dist/pypy/tool .. _`tool/pytest/`: http://codespeak.net/svn/pypy/dist/pypy/tool/pytest Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Tue Jun 7 18:27:37 2005 @@ -471,13 +471,31 @@ The process in more details --------------------------- -The RPython Typer has a structure similar to that of the Annotator_: both consider each block of the flow graphs in turn, and perform some analysis on each operation. In both cases the analysis of an operation depends on the annotations of its input arguments. This is reflected in the usage of the same ``__extend__`` syntax in the source files (compare e.g. `annotation/binaryop.py`_ and `rpython/rlist.py`_). +The RPython Typer has a structure similar to that of the Annotator_: both consider each block of the flow graphs in turn, and perform some analysis on each operation. In both cases the analysis of an operation depends on the annotations of its input arguments. This is reflected in the usage of the same ``__extend__`` syntax in the source files (compare e.g. `annotation/binaryop.py`_ and `rpython/rint.py`_). The analogy stops here, though: while it runs, the Annotator is in the middle of computing the annotations, so it might need to reflow and generalize until a fixpoint is reached. The Typer, by contrast, works on the final annotations that the Annotator computed, without changing them, assuming that they are globally consistent. There is no need to reflow: the Typer considers each block only once. And unlike the Annotator, the Typer completely modifies the flow graph, by replacing each operation with some low-level operations. -The main assumption of the RTyper, for the time being, is that each SomeXxx annotation has a canonical low-level representation. For example, all variables annotated with SomeInteger() will correspond to the ``Signed`` low-level type. The RTyper computes the canonical low-level type for each Variable based on its annotation, and stores it in the attribute ``concretetype``. It also computes a ``concretetype`` for Constants, to match the way they are used in the low-level operations (for example, ``int_add(x, 1)`` requires a ``Constant(1)`` with ``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a ``Constant(1)`` that must actually be a PyObject at run-time). +In addition to replacing operations, the RTyper creates a ``concretetype`` attribute on all Variables and Constants in the flow graphs, which tells code generators which type to use for each of them. This attribute is a `low-level type`_, as described below. +Representations +--------------- + +Representations -- the Repr classes -- are the most important internal classes used by the RTyper. (They are internal in the sense that they are an "implementation detail" and their instances just go away after the RTyper is finished; the code generators should only use the ``concretetype`` attributes, which are not Repr instances but `low-level types`_.) + +A representation contains all the logic about mapping a specific SomeXxx() annotation to a specific low-level type. For the time being, the RTyper assumes that each SomeXxx() instance needs only one "canonical" representation. For example, all variables annotated with SomeInteger() will correspond to the ``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, variables annotated SomeList() can correspond either to a structure holding an array of items of the correct type, or -- if the list in question is just a range() with a constant step -- a structure with just start and stop fields. + +This example shows that two representations may need very different low-level implementations for the same high-level operations. This is the reason for turning representations into explicit objects. + +The base Repr class is defined in `rpython/rmodel.py`_. Most of the ``rpython/r*.py`` files define one or a few subclasses of Repr. The method getrepr() of the RTyper will build and cache a single Repr instance per SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the same Repr instance. + +The key attribute of a Repr instance is called ``lowleveltype``, which is what gets copied into the attribute ``concretetype`` of the Variables that have been given this representation. The RTyper also computes a ``concretetype`` for Constants, to match the way they are used in the low-level operations (for example, ``int_add(x, 1)`` requires a ``Constant(1)`` with ``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a ``Constant(1)`` that must actually be a PyObject at run-time). + +In addition to ``lowleveltype``, each Repr subclass provides a set of methods called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` is turned into low-level operations. + + +.. _`low-level type`: + Low-Level Types --------------- From arigo at codespeak.net Tue Jun 7 18:59:42 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 7 Jun 2005 18:59:42 +0200 (CEST) Subject: [pypy-svn] r13157 - pypy/dist/pypy/documentation Message-ID: <20050607165942.095E227B43@code1.codespeak.net> Author: arigo Date: Tue Jun 7 18:59:40 2005 New Revision: 13157 Modified: pypy/dist/pypy/documentation/translation.txt Log: Removed references to GcPtr, and fixed the general wording around them to reflect the slight change in concept that follows. Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Tue Jun 7 18:59:40 2005 @@ -501,16 +501,14 @@ The RPython Typer uses a standard low-level model which we believe can correspond rather directly to various target languages from C to LLVM to Java. This model is implemented in the first part of `rpython/lltype.py`_. -The second part of `rpython/lltype.py`_ is a runnable implementation of these types, for testing purposes. It allows us to write and test plain Python code using a malloc() function to obtain and manipulate structures and arrays. This is useful for example to implement RPython types like 'list' with its operations and methods. +The second part of `rpython/lltype.py`_ is a runnable implementation of these types, for testing purposes. It allows us to write and test plain Python code using a malloc() function to obtain and manipulate structures and arrays. This is useful for example to implement and test RPython types like 'list' with its operations and methods. The basic assumption is that Variables (i.e. local variables and function arguments and return value) all contain "simple" values: basically, just integers or pointers. All the "container" data structures (struct and array) are allocated in the heap, and they are always manipulated via pointers. (There is no equivalent to the C notion of local variable of a ``struct`` type.) -Here is a quick tour:: +Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you have some older version, the ``lltype`` module might be called ``lltypes`` and you may need to add or remove a few ``Gc`` prefixes here and there):: >>> from pypy.rpython.lltype import * -(The module is called ``lltypes`` in PyPy release 0.6.) - Here are a few primitive low-level types, and the typeOf() function to figure them out:: >>> Signed @@ -528,18 +526,18 @@ >>> POINT -The structure is a ``GcStruct``, which means a structure that can be allocated in the heap and eventually freed by some garbage collector. (For platforms where we use reference counting, think about ``GcStruct`` as a struct with an additional reference counter field.) (NB. in PyPy release 0.6, GcStruct and GcArray don't exist; you must use Struct and Array instead.) +The structure is a ``GcStruct``, which means a structure that can be allocated in the heap and eventually freed by some garbage collector. (For platforms where we use reference counting, think about ``GcStruct`` as a struct with an additional reference counter field.) Giving a name ('point') to the GcStruct is only for clarity: it is used in the representation. >>> p = malloc(POINT) >>> p - <_ptrtype to struct point { x=0, y=0 }> + >>> p.x = 5 >>> p.x 5 >>> p - <_ptrtype to struct point { x=5, y=0 }> + ``malloc()`` allocates a structure from the heap, initalizes it to 0 (currently), and returns a pointer to it. The point of all this is to work with a very limited, easily controllable set of types, and define implementations of types like list in this elementary world. The ``malloc()`` function is a kind of placeholder, which must eventually be provided by the code generator for the target platform; but as we have just seen its Python implementation in `rpython/lltype.py`_ works too, which is primarily useful for testing, interactive exploring, etc. @@ -550,12 +548,12 @@ For the purpose of creating structures with pointers to other structures, we can declare pointer types explicitely:: - >>> typeOf(p) == GcPtr(POINT) + >>> typeOf(p) == Ptr(POINT) True - >>> BIZARRE = GcStruct('bizarre', ('p1', GcPtr(POINT)), ('p2', GcPtr(POINT))) + >>> BIZARRE = GcStruct('bizarre', ('p1', Ptr(POINT)), ('p2', Ptr(POINT))) >>> b = malloc(BIZARRE) >>> b.p1 - <_ptrtype to None> + >>> b.p1 = b.p2 = p >>> b.p1.y = 42 >>> b.p2.y @@ -577,7 +575,7 @@ a single character (``char``) Bool - a boolean value (could be ``char`` as well in C) + a boolean value Void a constant. Meant for variables and function arguments that should @@ -598,7 +596,7 @@ A structure can also contain an inlined array (see below), but only as its last field: in this case it is a "variable-sized" structure, whose memory layout starts with the non-variable fields and ends with a variable number of array items. This number is determined when a structure is allocated in the heap. Variable-sized structures cannot be inlined in other structures. -GcStructs have a platform-specific GC header (e.g. a reference counter); only these can be malloc()ed. Structs have no header, and are suitable for being embedded ("inlined") inside other structures. As an exception, a GcStruct can be embedded as the first field of a GcStruct: the parent structure uses the same GC header as the substructure. +GcStructs have a platform-specific GC header (e.g. a reference counter); only these can be dynamically malloc()ed. The non-GC version of Struct does not have any header, and is suitable for being embedded ("inlined") inside other structures. As an exception, a GcStruct can be embedded as the first field of a GcStruct: the parent structure uses the same GC header as the substructure. Array Types @@ -609,24 +607,23 @@ MyArrayType = Array(('field1', Type1), ('field2', Type2)...) MyArrayType = GcArray(('field1', Type1), ('field2', Type2)...) -The items of an array are always structures; the arguments to Array() give the fields of these structures (it can of course be a single field). The allowed field types follow the same rules as for Struct(), but this particular structure cannot be variable-sized. +The items of an array are always structures; the arguments to Array() give the fields of these structures (it can of course be a single field). The allowed field types follow the same rules as for Struct(), except that you cannot inline an array into the items' structure. -For now, each array stores its length explicitely in a header. An array can never be resized: it occupies a fixed amount of bytes determined when it is allocated. +GcArrays can be malloc()ed. The length must be specified when malloc() is called, and arrays cannot be resized; this length is stored explicitely in a header. -GcArrays can be malloc()ed (the length must be specified when malloc() is called, and arrays cannot be resized). Plain Arrays cannot be malloc()ed but can be used as the last field of a structure, to make a variable-sized structure. The whole structure can then be malloc()ed, and the length of the array is specified at this time. +The non-GC version of Array can be used as the last field of a structure, to make a variable-sized structure. The whole structure can then be malloc()ed, and the length of the array is specified at this time. Pointer Types +++++++++++++ -As in C, pointers provide the indirection needed to make a reference modifiable or sharable. Pointers can only point to a structure, an array, a function (see below) or a PyObject (see below). Pointers to primitive types, if needed, must be done by pointing to a structure with a single field of the required type. Pointer types are declared using one of:: +As in C, pointers provide the indirection needed to make a reference modifiable or sharable. Pointers can only point to a structure, an array, a function (see below) or a PyObject (see below). Pointers to primitive types, if needed, must be done by pointing to a structure with a single field of the required type. Pointer types are declared by:: - GcPtr(T, **flags) - NonGcPtr(T, **flags) + Ptr(TYPE) -The so-called GC pointers are the ones that hold a reference to the object they point to. Only GcStruct, GcArray and PyObject can have GcPtrs to them. Typically, the malloc() operation allocates and returns a GcPtr to a new structure or array. In a refcounting implementation, malloc() would allocate enough space for a reference counter before the actual structure, and initialize it to 1. Actually, GC pointers can only point to a malloc()ed structure or array. Non-GC pointers are used when you know that a pointer doesn't hold a (counted) reference to an object, usually because the object has no reference counter at all: for example, functions don't have one; more importantly, inlined substructures don't have one either. For them, care must be taken to ensure that the bigger structure of which they are part of isn't freed while the NonGcPtr to the substructure is still in use. +At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a reference to what they are pointing to. Pointers to non-GC structures that can go away when their container is deallocated (Struct, Array) must be handled with care: the bigger structure of which they are part of could be freed while the Ptr to the substructure is still in use. In general, it is a good idea to avoid passing around pointers to inlined substructures of malloc()ed structures. (The testing implementation of `rpython/lltype.py`_ checks to some extend that you are not trying to use a pointer to a structure after its container has been freed, using weak references. But pointers to non-GC structures are not officially meant to be weak references: using them after what they point to has been freed just crashes.) -All pointer types can also have additional flags, whose meaning is unspecified at this level (apart from the flag ``gc=True`` which GcPtrs have and NonGcPtrs miss). Types with different flags are incompatible, but the cast_flags() operation is provided to perform explicit casts. The intention is for example to represent the high-level object "the method append() of this list" as the type ``GcPtr(ListType, method='append')`` -- i.e. a pointer to the list in question with an additional flag specifying that the pointer represents the method append() of that list, as opposed to the list itself. +The malloc() operation allocates and returns a Ptr to a new GC structure or array. In a refcounting implementation, malloc() would allocate enough space for a reference counter before the actual structure, and initialize it to 1. Note that the testing implementation also allows malloc() to allocate a non-GC structure or array with a keyword argument ``immortal=True``. Its purpose is to declare and initialize prebuilt data structures which the code generators will turn into static immortal non-GC'ed data. Function Types @@ -636,21 +633,28 @@ MyFuncType = FuncType([Type1, Type2, ...], ResultType) -declares a function type taking arguments of the given types and returning a result of the given type. All these types must be primitives or pointers. The function type itself is considered to be a "container" type: if you wish, a function contains the bytes that make up its executable code. As with structures and arrays, they can only be manipulated through pointers. More precisely, the only thing you can do -- more or less -- with MyFuncType is to embbed it in a NonGcPtr. +declares a function type taking arguments of the given types and returning a result of the given type. All these types must be primitives or pointers. The function type itself is considered to be a "container" type: if you wish, a function contains the bytes that make up its executable code. As with structures and arrays, they can only be manipulated through pointers. + +The testing implementation allows you to "create" functions by calling ``functionptr(TYPE, name, **attrs)``. The extra attributes describe the function in a way that isn't fully specified now, but the following attributes *might* be present: + + :_callable: a Python callable, typically a function object. + :graph: the flow graph of the function. The PyObject Type +++++++++++++++++ -This is a special type, for compatibility with CPython: it stands for a structure compatible with PyObject. It should be manipulated via GcPtr or NonGcPtr, depending on whether the CPython reference counter should be updated or not. A typed graph can still contain generic space operations (add, getitem, etc.) provided they are applied on objects whose low-level type is a pointer to ``PyObject``. In fact, code generators that support this should consider that the default type of a variable, if none is specified, is ``GcPtr(PyObject)``. In this way, they can generate the correct code for fully-untyped flow graphs. +This is a special type, for compatibility with CPython: it stands for a structure compatible with PyObject. This is also a "container" type (thinking about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated via a Ptr. A typed graph can still contain generic space operations (add, getitem, etc.) provided they are applied on objects whose low-level type is ``Ptr(PyObject)``. In fact, code generators that support this should consider that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. In this way, they can generate the correct code for fully-untyped flow graphs. + +The testing implementation allows you to "create" PyObjects by calling ``pyobjectptr(obj)``. Implementing RPython types -------------------------- -As hinted above, the RPython types (e.g. 'list') are implemented in some "restricted-restricted Python" format by manipulating only low-level types, as provided by the "testing" concrete implementation of malloc() and friends. What occurs then is that the same (tested!) very-low-level Python code -- which looks really just like C -- is then transformed into a flow graph and integrated with the rest of the user program. In other words, we replace an operation like ``add`` between two variables annotated as SomeList, with a ``simple_call`` operation invoking this very-low-level list concatenation. +As hinted above, the RPython types (e.g. 'list') are implemented in some "restricted-restricted Python" format by manipulating only low-level types, as provided by the testing implementation of malloc() and friends. What occurs then is that the same (tested!) very-low-level Python code -- which looks really just like C -- is then transformed into a flow graph and integrated with the rest of the user program. In other words, we replace an operation like ``add`` between two variables annotated as SomeList, with a ``direct_call`` operation invoking this very-low-level list concatenation. -This list concatenation flow graph is then annotated as usual, with one difference: the annotator has to be taught about malloc() and the way the pointer thus obtained can be manipulated. This generates a flow graph which is hopefully completely annotated with the SomePtr annotation. Introduced just for this case, SomePtr maps directly to a low-level pointer type. This is the only change needed to the Annotator to allow it to perform type inferrence of our very-low-level snippets of code. +This list concatenation flow graph is then annotated as usual, with one difference: the annotator has to be taught about malloc() and the way the pointer thus obtained can be manipulated. This generates a flow graph which is hopefully completely annotated with SomePtr() annotation. Introduced just for this case, SomePtr maps directly to a low-level pointer type. This is the only change needed to the Annotator to allow it to perform type inference of our very-low-level snippets of code. See for example `rpython/rlist.py`_. From ale at codespeak.net Tue Jun 7 19:16:55 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 7 Jun 2005 19:16:55 +0200 (CEST) Subject: [pypy-svn] r13159 - pypy/dist/lib-python/modified-2.3.4/test Message-ID: <20050607171655.EB2A927B3E@code1.codespeak.net> Author: ale Date: Tue Jun 7 19:16:54 2005 New Revision: 13159 Removed: pypy/dist/lib-python/modified-2.3.4/test/test_codeccallbacks.py pypy/dist/lib-python/modified-2.3.4/test/test_codecs.py Log: not needed anymore Deleted: /pypy/dist/lib-python/modified-2.3.4/test/test_codeccallbacks.py ============================================================================== --- /pypy/dist/lib-python/modified-2.3.4/test/test_codeccallbacks.py Tue Jun 7 19:16:54 2005 +++ (empty file) @@ -1,717 +0,0 @@ - -import test.test_support, unittest -import sys, htmlentitydefs, unicodedata -import codecs -print sys.modules['codecs'],sys.modules['_codecs']#,sys.modules['encodings'] -class PosReturn: - # this can be used for configurable callbacks - - def __init__(self): - self.pos = 0 - - def handle(self, exc): - oldpos = self.pos - realpos = oldpos - if realpos<0: - realpos = len(exc.object) + realpos - # if we don't advance this time, terminate on the next call - # otherwise we'd get an endless loop - if realpos <= exc.start: - self.pos = len(exc.object) - return (u"", oldpos) - -class CodecCallbackTest(unittest.TestCase): - - def test_xmlcharrefreplace(self): - # replace unencodable characters which numeric character entities. - # For ascii, latin-1 and charmaps this is completely implemented - # in C and should be reasonably fast. - s = u"\u30b9\u30d1\u30e2 \xe4nd eggs" - self.assertEqual( - codecs.encode(s,"ascii", "xmlcharrefreplace"), - "スパモ änd eggs" - ) - self.assertEqual( - codecs.encode(s,"latin-1", "xmlcharrefreplace"), - "スパモ \xe4nd eggs" - ) - - def test_xmlcharnamereplace(self): - # This time use a named character entity for unencodable - # characters, if one is available. - - def xmlcharnamereplace(exc): - if not isinstance(exc, UnicodeEncodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [] - for c in exc.object[exc.start:exc.end]: - try: - l.append(u"&%s;" % htmlentitydefs.codepoint2name[ord(c)]) - except KeyError: - l.append(u"&#%d;" % ord(c)) - return (u"".join(l), exc.end) - - codecs.register_error( - "test.xmlcharnamereplace", xmlcharnamereplace) - - sin = u"\xab\u211c\xbb = \u2329\u1234\u20ac\u232a" - sout = "«ℜ» = ⟨ሴ€⟩" - self.assertEqual(codecs.encode(sin,"ascii", "test.xmlcharnamereplace"), sout) - sout = "\xabℜ\xbb = ⟨ሴ€⟩" - self.assertEqual(codecs.encode(sin,"latin-1", "test.xmlcharnamereplace"), sout) - sout = "\xabℜ\xbb = ⟨ሴ\xa4⟩" - self.assertEqual(codecs.encode(sin,"iso-8859-15", "test.xmlcharnamereplace"), sout) - - def test_uninamereplace(self): - # We're using the names from the unicode database this time, - # and we're doing "syntax highlighting" here, i.e. we include - # the replaced text in ANSI escape sequences. For this it is - # useful that the error handler is not called for every single - # unencodable character, but for a complete sequence of - # unencodable characters, otherwise we would output many - # unneccessary escape sequences. - - def uninamereplace(exc): - if not isinstance(exc, UnicodeEncodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [] - for c in exc.object[exc.start:exc.end]: - l.append(unicodedata.name(c, u"0x%x" % ord(c))) - return (u"\033[1m%s\033[0m" % u", ".join(l), exc.end) - - codecs.register_error( - "test.uninamereplace", uninamereplace) - - sin = u"\xac\u1234\u20ac\u8000" - sout = "\033[1mNOT SIGN, ETHIOPIC SYLLABLE SEE, EURO SIGN, CJK UNIFIED IDEOGRAPH-8000\033[0m" - self.assertEqual(codecs.encode(sin,"ascii", "test.uninamereplace"), sout) - - sout = "\xac\033[1mETHIOPIC SYLLABLE SEE, EURO SIGN, CJK UNIFIED IDEOGRAPH-8000\033[0m" - tout = codecs.encode(sin,"latin-1", "test.uninamereplace") - self.assertEqual(tout, sout) - sout = "\xac\033[1mETHIOPIC SYLLABLE SEE\033[0m\xa4\033[1mCJK UNIFIED IDEOGRAPH-8000\033[0m" - self.assertEqual(codecs.encode(sin,"iso-8859-15", "test.uninamereplace"), sout) - - def test_backslashescape(self): - # Does the same as the "unicode-escape" encoding, but with different - # base encodings. - sin = u"a\xac\u1234\u20ac\u8000" - if sys.maxunicode > 0xffff: - sin += unichr(sys.maxunicode) - sout = "a\\xac\\u1234\\u20ac\\u8000" - if sys.maxunicode > 0xffff: - sout += "\\U%08x" % sys.maxunicode - self.assertEqual(codecs.encode(sin,"ascii", "backslashreplace"), sout) - - sout = "a\xac\\u1234\\u20ac\\u8000" - if sys.maxunicode > 0xffff: - sout += "\\U%08x" % sys.maxunicode - self.assertEqual(codecs.encode(sin,"latin-1", "backslashreplace"), sout) - - sout = "a\xac\\u1234\xa4\\u8000" - if sys.maxunicode > 0xffff: - sout += "\\U%08x" % sys.maxunicode - self.assertEqual(codecs.encode(sin,"iso-8859-15", "backslashreplace"), sout) - - def test_relaxedutf8(self): - # This is the test for a decoding callback handler, - # that relaxes the UTF-8 minimal encoding restriction. - # A null byte that is encoded as "\xc0\x80" will be - # decoded as a null byte. All other illegal sequences - # will be handled strictly. - def relaxedutf8(exc): - if not isinstance(exc, UnicodeDecodeError): - raise TypeError("don't know how to handle %r" % exc) - if exc.object[exc.start:exc.end].startswith("\xc0\x80"): - return (u"\x00", exc.start+2) # retry after two bytes - else: - raise exc - - codecs.register_error( - "test.relaxedutf8", relaxedutf8) - - sin = "a\x00b\xc0\x80c\xc3\xbc\xc0\x80\xc0\x80" - sout = u"a\x00b\x00c\xfc\x00\x00" - self.assertEqual(codecs.decode(sin,"utf-8", "test.relaxedutf8"), sout) - sin = "\xc0\x80\xc0\x81" - self.assertRaises(UnicodeError, codecs.decode,sin, "utf-8", "test.relaxedutf8") - - def test_charmapencode(self): - # For charmap encodings the replacement string will be - # mapped through the encoding again. This means, that - # to be able to use e.g. the "replace" handler, the - # charmap has to have a mapping for "?". - charmap = dict([ (ord(c), 2*c.upper()) for c in "abcdefgh"]) - sin = u"abc" - sout = "AABBCC" - self.assertEquals(codecs.charmap_encode(sin, "strict", charmap)[0], sout) - - sin = u"abcA" - self.assertRaises(UnicodeError, codecs.charmap_encode, sin, "strict", charmap) - - charmap[ord("?")] = "XYZ" - sin = u"abcDEF" - sout = "AABBCCXYZXYZXYZ" - self.assertEquals(codecs.charmap_encode(sin, "replace", charmap)[0], sout) - - charmap[ord("?")] = u"XYZ" - self.assertRaises(TypeError, codecs.charmap_encode, sin, "replace", charmap) - - charmap[ord("?")] = u"XYZ" - self.assertRaises(TypeError, codecs.charmap_encode, sin, "replace", charmap) - - def test_callbacks(self): - def handler1(exc): - if not isinstance(exc, UnicodeEncodeError) \ - and not isinstance(exc, UnicodeDecodeError): - raise TypeError("don't know how to handle %r" % exc) - - l = [u"<%d>" % ord(exc.object[pos]) for pos in xrange(exc.start, exc.end)] - return (u"[%s]" % u"".join(l), exc.end) - - codecs.register_error("test.handler1", handler1) - - def handler2(exc): - if not isinstance(exc, UnicodeDecodeError): - raise TypeError("don't know how to handle %r" % exc) - l = [u"<%d>" % ord(exc.object[pos]) for pos in xrange(exc.start, exc.end)] - return (u"[%s]" % u"".join(l), exc.end+1) # skip one character - - codecs.register_error("test.handler2", handler2) - - s = "\x00\x81\x7f\x80\xff" - - self.assertEqual( - codecs.decode(s,"ascii", "test.handler1"), - u"\x00[<129>]\x7f[<128>][<255>]" - ) - self.assertEqual( - codecs.decode(s,"ascii", "test.handler2"), - u"\x00[<129>][<128>]" - ) - - self.assertEqual( - codecs.decode("\\u3042\u3xxx","unicode-escape", "test.handler1"), - u"\u3042[<92><117><51><120>]xx" - ) - - self.assertEqual( - codecs.decode("\\u3042\u3xx","unicode-escape", "test.handler1"), - u"\u3042[<92><117><51><120><120>]" - ) - - self.assertEqual( - codecs.charmap_decode("abc", "test.handler1", {ord("a"): u"z"})[0], - u"z[<98>][<99>]" - ) - - self.assertEqual( - codecs.encode(u"g\xfc\xdfrk","ascii", "test.handler1"), - u"g[<252><223>]rk" - ) - - self.assertEqual( - codecs.encode(u"g\xfc\xdf","ascii", "test.handler1"), - u"g[<252><223>]" - ) - - def test_longstrings(self): - # test long strings to check for memory overflow problems - errors = [ "strict", "ignore", "replace", "xmlcharrefreplace", "backslashreplace"] - # register the handlers under different names, - # to prevent the codec from recognizing the name - for err in errors: - codecs.register_error("test." + err, codecs.lookup_error(err)) - l = 1000 - errors += [ "test." + err for err in errors ] - for uni in [ s*l for s in (u"x", u"\u3042", u"a\xe4") ]: - for enc in ("ascii", "latin-1", "iso-8859-1", "iso-8859-15", "utf-8", "utf-7", "utf-16"): - for err in errors: - try: - print uni[0],enc,err - codecs.encode(uni,enc, err) - except UnicodeError: - pass - - def check_exceptionobjectargs(self, exctype, args, msg): - # Test UnicodeError subclasses: construction, attribute assignment and __str__ conversion - # check with one missing argument - self.assertRaises(TypeError, exctype, *args[:-1]) - # check with one argument too much - self.assertRaises(TypeError, exctype, *(args + ["too much"])) - # check with one argument of the wrong type - wrongargs = [ "spam", u"eggs", 42, 1.0, None ] - for i in xrange(len(args)): - for wrongarg in wrongargs: - if type(wrongarg) is type(args[i]): - continue - # build argument array - callargs = [] - for j in xrange(len(args)): - if i==j: - callargs.append(wrongarg) - else: - callargs.append(args[i]) - self.assertRaises(TypeError, exctype, *callargs) - - # check with the correct number and type of arguments - exc = exctype(*args) - self.assertEquals(str(exc), msg) - - def test_unicodeencodeerror(self): - self.check_exceptionobjectargs( - UnicodeEncodeError, - ["ascii", u"g\xfcrk", 1, 2, "ouch"], - "'ascii' codec can't encode character u'\\xfc' in position 1: ouch" - ) - self.check_exceptionobjectargs( - UnicodeEncodeError, - ["ascii", u"g\xfcrk", 1, 4, "ouch"], - "'ascii' codec can't encode characters in position 1-3: ouch" - ) - self.check_exceptionobjectargs( - UnicodeEncodeError, - ["ascii", u"\xfcx", 0, 1, "ouch"], - "'ascii' codec can't encode character u'\\xfc' in position 0: ouch" - ) - self.check_exceptionobjectargs( - UnicodeEncodeError, - ["ascii", u"\u0100x", 0, 1, "ouch"], - "'ascii' codec can't encode character u'\\u0100' in position 0: ouch" - ) - self.check_exceptionobjectargs( - UnicodeEncodeError, - ["ascii", u"\uffffx", 0, 1, "ouch"], - "'ascii' codec can't encode character u'\\uffff' in position 0: ouch" - ) - if sys.maxunicode > 0xffff: - self.check_exceptionobjectargs( - UnicodeEncodeError, - ["ascii", u"\U00010000x", 0, 1, "ouch"], - "'ascii' codec can't encode character u'\\U00010000' in position 0: ouch" - ) - - def test_unicodedecodeerror(self): - self.check_exceptionobjectargs( - UnicodeDecodeError, - ["ascii", "g\xfcrk", 1, 2, "ouch"], - "'ascii' codec can't decode byte 0xfc in position 1: ouch" - ) - self.check_exceptionobjectargs( - UnicodeDecodeError, - ["ascii", "g\xfcrk", 1, 3, "ouch"], - "'ascii' codec can't decode bytes in position 1-2: ouch" - ) - - def test_unicodetranslateerror(self): - self.check_exceptionobjectargs( - UnicodeTranslateError, - [u"g\xfcrk", 1, 2, "ouch"], - "can't translate character u'\\xfc' in position 1: ouch" - ) - self.check_exceptionobjectargs( - UnicodeTranslateError, - [u"g\u0100rk", 1, 2, "ouch"], - "can't translate character u'\\u0100' in position 1: ouch" - ) - self.check_exceptionobjectargs( - UnicodeTranslateError, - [u"g\uffffrk", 1, 2, "ouch"], - "can't translate character u'\\uffff' in position 1: ouch" - ) - if sys.maxunicode > 0xffff: - self.check_exceptionobjectargs( - UnicodeTranslateError, - [u"g\U00010000rk", 1, 2, "ouch"], - "can't translate character u'\\U00010000' in position 1: ouch" - ) - self.check_exceptionobjectargs( - UnicodeTranslateError, - [u"g\xfcrk", 1, 3, "ouch"], - "can't translate characters in position 1-2: ouch" - ) - - def test_badandgoodstrictexceptions(self): - # "strict" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.strict_errors, - 42 - ) - # "strict" complains about the wrong exception type - self.assertRaises( - Exception, - codecs.strict_errors, - Exception("ouch") - ) - - # If the correct exception is passed in, "strict" raises it - self.assertRaises( - UnicodeEncodeError, - codecs.strict_errors, - UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch") - ) - - def test_badandgoodignoreexceptions(self): - # "ignore" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.ignore_errors, - 42 - ) - # "ignore" complains about the wrong exception type - self.assertRaises( - TypeError, - codecs.ignore_errors, - UnicodeError("ouch") - ) - # If the correct exception is passed in, "ignore" returns an empty replacement - self.assertEquals( - codecs.ignore_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"", 1) - ) - self.assertEquals( - codecs.ignore_errors(UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch")), - (u"", 1) - ) - self.assertEquals( - codecs.ignore_errors(UnicodeTranslateError(u"\u3042", 0, 1, "ouch")), - (u"", 1) - ) - - def test_badandgoodreplaceexceptions(self): - # "replace" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.replace_errors, - 42 - ) - # "replace" complains about the wrong exception type - self.assertRaises( - TypeError, - codecs.replace_errors, - UnicodeError("ouch") - ) - # With the correct exception, "ignore" returns an empty replacement - self.assertEquals( - codecs.replace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"?", 1) - ) - self.assertEquals( - codecs.replace_errors(UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch")), - (u"\ufffd", 1) - ) - self.assertEquals( - codecs.replace_errors(UnicodeTranslateError(u"\u3042", 0, 1, "ouch")), - (u"\ufffd", 1) - ) - - def test_badandgoodxmlcharrefreplaceexceptions(self): - # "xmlcharrefreplace" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - 42 - ) - # "xmlcharrefreplace" complains about the wrong exception types - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - UnicodeError("ouch") - ) - # "xmlcharrefreplace" can only be used for encoding - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch") - ) - self.assertRaises( - TypeError, - codecs.xmlcharrefreplace_errors, - UnicodeTranslateError(u"\u3042", 0, 1, "ouch") - ) - # Use the correct exception - self.assertEquals( - codecs.xmlcharrefreplace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"&#%d;" % 0x3042, 1) - ) - - def test_badandgoodbackslashreplaceexceptions(self): - # "backslashreplace" complains about a non-exception passed in - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - 42 - ) - # "backslashreplace" complains about the wrong exception types - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - UnicodeError("ouch") - ) - # "backslashreplace" can only be used for encoding - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - UnicodeDecodeError("ascii", "\xff", 0, 1, "ouch") - ) - self.assertRaises( - TypeError, - codecs.backslashreplace_errors, - UnicodeTranslateError(u"\u3042", 0, 1, "ouch") - ) - # Use the correct exception - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\u3042", 0, 1, "ouch")), - (u"\\u3042", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\x00", 0, 1, "ouch")), - (u"\\x00", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\xff", 0, 1, "ouch")), - (u"\\xff", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\u0100", 0, 1, "ouch")), - (u"\\u0100", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\uffff", 0, 1, "ouch")), - (u"\\uffff", 1) - ) - if sys.maxunicode>0xffff: - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\U00010000", 0, 1, "ouch")), - (u"\\U00010000", 1) - ) - self.assertEquals( - codecs.backslashreplace_errors(UnicodeEncodeError("ascii", u"\U0010ffff", 0, 1, "ouch")), - (u"\\U0010ffff", 1) - ) - - def test_badhandlerresults(self): - results = ( 42, u"foo", (1,2,3), (u"foo", 1, 3), (u"foo", None), (u"foo",), ("foo", 1, 3), ("foo", None), ("foo",) ) - encs = ("ascii", "latin-1", "iso-8859-1", "iso-8859-15") - - for res in results: - codecs.register_error("test.badhandler", lambda: res) - for enc in encs: - self.assertRaises( - TypeError, - codecs.encode, - u"\u3042", - enc, - "test.badhandler" - ) - for (enc, bytes) in ( - ("ascii", "\xff"), - ("utf-8", "\xff"), - ("utf-7", "+x-") - ): - self.assertRaises( - TypeError, - codecs.decode, - bytes, - enc, - "test.badhandler" - ) - - def test_lookup(self): - self.assertEquals(codecs.strict_errors, codecs.lookup_error("strict")) - self.assertEquals(codecs.ignore_errors, codecs.lookup_error("ignore")) - self.assertEquals(codecs.strict_errors, codecs.lookup_error("strict")) - self.assertEquals( - codecs.xmlcharrefreplace_errors, - codecs.lookup_error("xmlcharrefreplace") - ) - self.assertEquals( - codecs.backslashreplace_errors, - codecs.lookup_error("backslashreplace") - ) - - def test_unencodablereplacement(self): - def unencrepl(exc): - if isinstance(exc, UnicodeEncodeError): - return (u"\u4242", exc.end) - else: - raise TypeError("don't know how to handle %r" % exc) - codecs.register_error("test.unencreplhandler", unencrepl) - for enc in ("ascii", "iso-8859-1", "iso-8859-15"): - self.assertRaises( - UnicodeEncodeError, - codecs.encode, - u"\u4242", - enc, - "test.unencreplhandler" - ) - - def test_badregistercall(self): - # enhance coverage of: - # Modules/_codecsmodule.c::register_error() - # Python/codecs.c::PyCodec_RegisterError() - self.assertRaises(TypeError, codecs.register_error, 42) - self.assertRaises(TypeError, codecs.register_error, "test.dummy", 42) - - def test_unknownhandler(self): - # enhance coverage of: - # Modules/_codecsmodule.c::lookup_error() - self.assertRaises(LookupError, codecs.lookup_error, "test.unknown") - - def test_xmlcharrefvalues(self): - # enhance coverage of: - # Python/codecs.c::PyCodec_XMLCharRefReplaceErrors() - # and inline implementations - v = (1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 50000) - if sys.maxunicode>=100000: - v += (100000, 500000, 1000000) - s = u"".join([unichr(x) for x in v]) - codecs.register_error("test.xmlcharrefreplace", codecs.xmlcharrefreplace_errors) - for enc in ("ascii", "iso-8859-15"): - for err in ("xmlcharrefreplace", "test.xmlcharrefreplace"): - codecs.encode(s,enc, err) - - def test_decodehelper(self): - # enhance coverage of: - # Objects/unicodeobject.c::unicode_decode_call_errorhandler() - # and callers - self.assertRaises(LookupError, codecs.decode,"\xff", "ascii", "test.unknown") - - def baddecodereturn1(exc): - return 42 - codecs.register_error("test.baddecodereturn1", baddecodereturn1) - self.assertRaises(TypeError, codecs.decode, "\xff", "ascii", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\x0", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\x0y", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\Uffffeeee", "unicode-escape", "test.baddecodereturn1") - self.assertRaises(TypeError, codecs.decode, "\\uyyyy", "raw-unicode-escape", "test.baddecodereturn1") - - def baddecodereturn2(exc): - return (u"?", None) - codecs.register_error("test.baddecodereturn2", baddecodereturn2) - self.assertRaises(TypeError, codecs.decode, "\xff", "ascii", "test.baddecodereturn2") - - handler = PosReturn() - codecs.register_error("test.posreturn", handler.handle) - - # Valid negative position - handler.pos = -1 - self.assertEquals(codecs.decode( "\xff0","ascii", "test.posreturn"), u"0") - - # Valid negative position - handler.pos = -2 - self.assertEquals(codecs.decode("\xff0","ascii", "test.posreturn"), u"") - - # Negative position out of bounds - handler.pos = -3 - self.assertRaises(IndexError, codecs.decode,"\xff0", "ascii", "test.posreturn") - - # Valid positive position - handler.pos = 1 - self.assertEquals(codecs.decode("\xff0","ascii", "test.posreturn"), u"0") - - # Largest valid positive position (one beyond end of input - handler.pos = 2 - self.assertEquals(codecs.decode("\xff0","ascii", "test.posreturn"), u"") - - # Invalid positive position - handler.pos = 3 - self.assertRaises(IndexError, codecs.decode,"\xff0", "ascii", "test.posreturn") - - # Restart at the "0" - handler.pos = 6 - self.assertEquals(codecs.decode("\\uyyyy0","raw-unicode-escape", "test.posreturn"), u"0") - - class D(dict): - def __getitem__(self, key): - raise ValueError - self.assertRaises(UnicodeError, codecs.charmap_decode, "\xff", "strict", {0xff: None}) - self.assertRaises(ValueError, codecs.charmap_decode, "\xff", "strict", D()) - self.assertRaises(TypeError, codecs.charmap_decode, "\xff", "strict", {0xff: sys.maxunicode+1}) - - def test_encodehelper(self): - # enhance coverage of: - # Objects/unicodeobject.c::unicode_encode_call_errorhandler() - # and callers - - self.assertRaises(LookupError, codecs.decode,u"\xff", "ascii", "test.unknown") - - def badencodereturn1(exc): - return 42 - codecs.register_error("test.badencodereturn1", badencodereturn1) - self.assertRaises(TypeError, codecs.decode, u"\xff", "ascii", "test.badencodereturn1") - - def badencodereturn2(exc): - return (u"?", None) - codecs.register_error("test.badencodereturn2", badencodereturn2) - self.assertRaises(TypeError, codecs.decode,u"\xff", "ascii", "test.badencodereturn2") - - handler = PosReturn() - codecs.register_error("test.posreturn", handler.handle) - - # Valid negative position - handler.pos = -1 - self.assertEquals(codecs.encode(u"\xff0","ascii", "test.posreturn"), "0") - - # Valid negative position - handler.pos = -2 - self.assertEquals(codecs.encode(u"\xff0","ascii", "test.posreturn"), "") - - # Negative position out of bounds - handler.pos = -3 - self.assertRaises(IndexError, codecs.encode,u"\xff0", "ascii", "test.posreturn") - - # Valid positive position - handler.pos = 1 - self.assertEquals(codecs.encode(u"\xff0","ascii", "test.posreturn"), "0") - - # Largest valid positive position (one beyond end of input - handler.pos = 2 - self.assertEquals(codecs.encode(u"\xff0","ascii", "test.posreturn"), "") - - # Invalid positive position - handler.pos = 3 - self.assertRaises(IndexError, codecs.encode,u"\xff0", "ascii", "test.posreturn") - - handler.pos = 0 - - class D(dict): - def __getitem__(self, key): - raise ValueError - for err in ("strict", "replace", "xmlcharrefreplace", "backslashreplace", "test.posreturn"): - self.assertRaises(UnicodeError, codecs.charmap_encode, u"\xff", err, {0xff: None}) - self.assertRaises(ValueError, codecs.charmap_encode, u"\xff", err, D()) - self.assertRaises(TypeError, codecs.charmap_encode, u"\xff", err, {0xff: 300}) - - def test_translatehelper(self): - # enhance coverage of: - # Objects/unicodeobject.c::unicode_encode_call_errorhandler() - # and callers - # (Unfortunately the errors argument is not directly accessible - # from Python, so we can't test that much) - class D(dict): - def __getitem__(self, key): - raise ValueError - self.assertRaises(ValueError, u"\xff".translate, D()) - self.assertRaises(TypeError, u"\xff".translate, {0xff: sys.maxunicode+1}) - self.assertRaises(TypeError, u"\xff".translate, {0xff: ()}) - - def test_bug828737(self): - charmap = { - ord("&"): u"&", - ord("<"): u"<", - ord(">"): u">", - ord('"'): u""", - } - - for n in (1, 10, 100, 1000): - text = u'abcghi'*n - text.translate(charmap) - -def test_main(): - test.test_support.run_unittest(CodecCallbackTest) - -if __name__ == "__main__": - test_main() Deleted: /pypy/dist/lib-python/modified-2.3.4/test/test_codecs.py ============================================================================== --- /pypy/dist/lib-python/modified-2.3.4/test/test_codecs.py Tue Jun 7 19:16:54 2005 +++ (empty file) @@ -1,361 +0,0 @@ -from test import test_support -import unittest -import sys -sys.path.insert(0,r'd:\projects\pypy_co') -sys.path.insert(0,r'd:\projects\pypy_co\pypy\lib') -sys.path.insert(0,r'd:\projects\pypy_co\lib-python\modified-2.3.4') -sys.path.insert(0,r'd:\projects\pypy_co\lib-python\2.3.4') -from pypy.lib import _codecs -sys.modules['_codecs'] = _codecs -from pypy.lib import encodings -sys.modules['encodings'] = encodings -from pypy.lib import codecs -sys.modules['codecs'] = codecs -reload(encodings) -reload(codecs) -assert codecs == encodings.codecs - -import codecs -import StringIO - -class UTF16Test(unittest.TestCase): - - spamle = '\xff\xfes\x00p\x00a\x00m\x00s\x00p\x00a\x00m\x00' - spambe = '\xfe\xff\x00s\x00p\x00a\x00m\x00s\x00p\x00a\x00m' - - def test_only_one_bom(self): - _,_,reader,writer = codecs.lookup("utf-16") - # encode some stream - s = StringIO.StringIO() - f = writer(s) - f.write(u"spam") - f.write(u"spam") - d = s.getvalue() - # check whether there is exactly one BOM in it - self.assert_(d == self.spamle or d == self.spambe) - # try to read it back - s = StringIO.StringIO(d) - f = reader(s) - self.assertEquals(f.read(), u"spamspam") - -class EscapeDecodeTest(unittest.TestCase): - def test_empty_escape_decode(self): - self.assertEquals(codecs.escape_decode(""), ("", 0)) - -class RecodingTest(unittest.TestCase): - def test_recoding(self): - f = StringIO.StringIO() - f2 = codecs.EncodedFile(f, "unicode_internal", "utf-8") - f2.write(u"a") - f2.close() - # Python used to crash on this at exit because of a refcount - # bug in _codecsmodule.c - -# From RFC 3492 -punycode_testcases = [ - # A Arabic (Egyptian): - (u"\u0644\u064A\u0647\u0645\u0627\u0628\u062A\u0643\u0644" - u"\u0645\u0648\u0634\u0639\u0631\u0628\u064A\u061F", - "egbpdaj6bu4bxfgehfvwxn"), - # B Chinese (simplified): - (u"\u4ED6\u4EEC\u4E3A\u4EC0\u4E48\u4E0D\u8BF4\u4E2D\u6587", - "ihqwcrb4cv8a8dqg056pqjye"), - # C Chinese (traditional): - (u"\u4ED6\u5011\u7232\u4EC0\u9EBD\u4E0D\u8AAA\u4E2D\u6587", - "ihqwctvzc91f659drss3x8bo0yb"), - # D Czech: Proprostnemluvesky - (u"\u0050\u0072\u006F\u010D\u0070\u0072\u006F\u0073\u0074" - u"\u011B\u006E\u0065\u006D\u006C\u0075\u0076\u00ED\u010D" - u"\u0065\u0073\u006B\u0079", - "Proprostnemluvesky-uyb24dma41a"), - # E Hebrew: - (u"\u05DC\u05DE\u05D4\u05D4\u05DD\u05E4\u05E9\u05D5\u05D8" - u"\u05DC\u05D0\u05DE\u05D3\u05D1\u05E8\u05D9\u05DD\u05E2" - u"\u05D1\u05E8\u05D9\u05EA", - "4dbcagdahymbxekheh6e0a7fei0b"), - # F Hindi (Devanagari): - (u"\u092F\u0939\u0932\u094B\u0917\u0939\u093F\u0928\u094D" - u"\u0926\u0940\u0915\u094D\u092F\u094B\u0902\u0928\u0939" - u"\u0940\u0902\u092C\u094B\u0932\u0938\u0915\u0924\u0947" - u"\u0939\u0948\u0902", - "i1baa7eci9glrd9b2ae1bj0hfcgg6iyaf8o0a1dig0cd"), - - #(G) Japanese (kanji and hiragana): - (u"\u306A\u305C\u307F\u3093\u306A\u65E5\u672C\u8A9E\u3092" - u"\u8A71\u3057\u3066\u304F\u308C\u306A\u3044\u306E\u304B", - "n8jok5ay5dzabd5bym9f0cm5685rrjetr6pdxa"), - - # (H) Korean (Hangul syllables): - (u"\uC138\uACC4\uC758\uBAA8\uB4E0\uC0AC\uB78C\uB4E4\uC774" - u"\uD55C\uAD6D\uC5B4\uB97C\uC774\uD574\uD55C\uB2E4\uBA74" - u"\uC5BC\uB9C8\uB098\uC88B\uC744\uAE4C", - "989aomsvi5e83db1d2a355cv1e0vak1dwrv93d5xbh15a0dt30a5j" - "psd879ccm6fea98c"), - - # (I) Russian (Cyrillic): - (u"\u043F\u043E\u0447\u0435\u043C\u0443\u0436\u0435\u043E" - u"\u043D\u0438\u043D\u0435\u0433\u043E\u0432\u043E\u0440" - u"\u044F\u0442\u043F\u043E\u0440\u0443\u0441\u0441\u043A" - u"\u0438", - "b1abfaaepdrnnbgefbaDotcwatmq2g4l"), - - # (J) Spanish: PorqunopuedensimplementehablarenEspaol - (u"\u0050\u006F\u0072\u0071\u0075\u00E9\u006E\u006F\u0070" - u"\u0075\u0065\u0064\u0065\u006E\u0073\u0069\u006D\u0070" - u"\u006C\u0065\u006D\u0065\u006E\u0074\u0065\u0068\u0061" - u"\u0062\u006C\u0061\u0072\u0065\u006E\u0045\u0073\u0070" - u"\u0061\u00F1\u006F\u006C", - "PorqunopuedensimplementehablarenEspaol-fmd56a"), - - # (K) Vietnamese: - # Tisaohkhngthch\ - # nitingVit - (u"\u0054\u1EA1\u0069\u0073\u0061\u006F\u0068\u1ECD\u006B" - u"\u0068\u00F4\u006E\u0067\u0074\u0068\u1EC3\u0063\u0068" - u"\u1EC9\u006E\u00F3\u0069\u0074\u0069\u1EBF\u006E\u0067" - u"\u0056\u0069\u1EC7\u0074", - "TisaohkhngthchnitingVit-kjcr8268qyxafd2f1b9g"), - - - #(L) 3B - (u"\u0033\u5E74\u0042\u7D44\u91D1\u516B\u5148\u751F", - "3B-ww4c5e180e575a65lsy2b"), - - # (M) -with-SUPER-MONKEYS - (u"\u5B89\u5BA4\u5948\u7F8E\u6075\u002D\u0077\u0069\u0074" - u"\u0068\u002D\u0053\u0055\u0050\u0045\u0052\u002D\u004D" - u"\u004F\u004E\u004B\u0045\u0059\u0053", - "-with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n"), - - # (N) Hello-Another-Way- - (u"\u0048\u0065\u006C\u006C\u006F\u002D\u0041\u006E\u006F" - u"\u0074\u0068\u0065\u0072\u002D\u0057\u0061\u0079\u002D" - u"\u305D\u308C\u305E\u308C\u306E\u5834\u6240", - "Hello-Another-Way--fc4qua05auwb3674vfr0b"), - - # (O) 2 - (u"\u3072\u3068\u3064\u5C4B\u6839\u306E\u4E0B\u0032", - "2-u9tlzr9756bt3uc0v"), - - # (P) MajiKoi5 - (u"\u004D\u0061\u006A\u0069\u3067\u004B\u006F\u0069\u3059" - u"\u308B\u0035\u79D2\u524D", - "MajiKoi5-783gue6qz075azm5e"), - - # (Q) de - (u"\u30D1\u30D5\u30A3\u30FC\u0064\u0065\u30EB\u30F3\u30D0", - "de-jg4avhby1noc0d"), - - # (R) - (u"\u305D\u306E\u30B9\u30D4\u30FC\u30C9\u3067", - "d9juau41awczczp"), - - # (S) -> $1.00 <- - (u"\u002D\u003E\u0020\u0024\u0031\u002E\u0030\u0030\u0020" - u"\u003C\u002D", - "-> $1.00 <--") - ] - -for i in punycode_testcases: - if len(i)!=2: - print repr(i) - -class PunycodeTest(unittest.TestCase): - def test_encode(self): - for uni, puny in punycode_testcases: - # Need to convert both strings to lower case, since - # some of the extended encodings use upper case, but our - # code produces only lower case. Converting just puny to - # lower is also insufficient, since some of the input characters - # are upper case. - self.assertEquals(uni.encode("punycode").lower(), puny.lower()) - - def test_decode(self): - for uni, puny in punycode_testcases: - self.assertEquals(uni, puny.decode("punycode")) - -# From http://www.gnu.org/software/libidn/draft-josefsson-idn-test-vectors.html -nameprep_tests = [ - # 3.1 Map to nothing. - ('foo\xc2\xad\xcd\x8f\xe1\xa0\x86\xe1\xa0\x8bbar' - '\xe2\x80\x8b\xe2\x81\xa0baz\xef\xb8\x80\xef\xb8\x88\xef' - '\xb8\x8f\xef\xbb\xbf', - 'foobarbaz'), - # 3.2 Case folding ASCII U+0043 U+0041 U+0046 U+0045. - ('CAFE', - 'cafe'), - # 3.3 Case folding 8bit U+00DF (german sharp s). - # The original test case is bogus; it says \xc3\xdf - ('\xc3\x9f', - 'ss'), - # 3.4 Case folding U+0130 (turkish capital I with dot). - ('\xc4\xb0', - 'i\xcc\x87'), - # 3.5 Case folding multibyte U+0143 U+037A. - ('\xc5\x83\xcd\xba', - '\xc5\x84 \xce\xb9'), - # 3.6 Case folding U+2121 U+33C6 U+1D7BB. - # XXX: skip this as it fails in UCS-2 mode - #('\xe2\x84\xa1\xe3\x8f\x86\xf0\x9d\x9e\xbb', - # 'telc\xe2\x88\x95kg\xcf\x83'), - (None, None), - # 3.7 Normalization of U+006a U+030c U+00A0 U+00AA. - ('j\xcc\x8c\xc2\xa0\xc2\xaa', - '\xc7\xb0 a'), - # 3.8 Case folding U+1FB7 and normalization. - ('\xe1\xbe\xb7', - '\xe1\xbe\xb6\xce\xb9'), - # 3.9 Self-reverting case folding U+01F0 and normalization. - # The original test case is bogus, it says `\xc7\xf0' - ('\xc7\xb0', - '\xc7\xb0'), - # 3.10 Self-reverting case folding U+0390 and normalization. - ('\xce\x90', - '\xce\x90'), - # 3.11 Self-reverting case folding U+03B0 and normalization. - ('\xce\xb0', - '\xce\xb0'), - # 3.12 Self-reverting case folding U+1E96 and normalization. - ('\xe1\xba\x96', - '\xe1\xba\x96'), - # 3.13 Self-reverting case folding U+1F56 and normalization. - ('\xe1\xbd\x96', - '\xe1\xbd\x96'), - # 3.14 ASCII space character U+0020. - (' ', - ' '), - # 3.15 Non-ASCII 8bit space character U+00A0. - ('\xc2\xa0', - ' '), - # 3.16 Non-ASCII multibyte space character U+1680. - ('\xe1\x9a\x80', - None), - # 3.17 Non-ASCII multibyte space character U+2000. - ('\xe2\x80\x80', - ' '), - # 3.18 Zero Width Space U+200b. - ('\xe2\x80\x8b', - ''), - # 3.19 Non-ASCII multibyte space character U+3000. - ('\xe3\x80\x80', - ' '), - # 3.20 ASCII control characters U+0010 U+007F. - ('\x10\x7f', - '\x10\x7f'), - # 3.21 Non-ASCII 8bit control character U+0085. - ('\xc2\x85', - None), - # 3.22 Non-ASCII multibyte control character U+180E. - ('\xe1\xa0\x8e', - None), - # 3.23 Zero Width No-Break Space U+FEFF. - ('\xef\xbb\xbf', - ''), - # 3.24 Non-ASCII control character U+1D175. - ('\xf0\x9d\x85\xb5', - None), - # 3.25 Plane 0 private use character U+F123. - ('\xef\x84\xa3', - None), - # 3.26 Plane 15 private use character U+F1234. - ('\xf3\xb1\x88\xb4', - None), - # 3.27 Plane 16 private use character U+10F234. - ('\xf4\x8f\x88\xb4', - None), - # 3.28 Non-character code point U+8FFFE. - ('\xf2\x8f\xbf\xbe', - None), - # 3.29 Non-character code point U+10FFFF. - ('\xf4\x8f\xbf\xbf', - None), - # 3.30 Surrogate code U+DF42. - ('\xed\xbd\x82', - None), - # 3.31 Non-plain text character U+FFFD. - ('\xef\xbf\xbd', - None), - # 3.32 Ideographic description character U+2FF5. - ('\xe2\xbf\xb5', - None), - # 3.33 Display property character U+0341. - ('\xcd\x81', - '\xcc\x81'), - # 3.34 Left-to-right mark U+200E. - ('\xe2\x80\x8e', - None), - # 3.35 Deprecated U+202A. - ('\xe2\x80\xaa', - None), - # 3.36 Language tagging character U+E0001. - ('\xf3\xa0\x80\x81', - None), - # 3.37 Language tagging character U+E0042. - ('\xf3\xa0\x81\x82', - None), - # 3.38 Bidi: RandALCat character U+05BE and LCat characters. - ('foo\xd6\xbebar', - None), - # 3.39 Bidi: RandALCat character U+FD50 and LCat characters. - ('foo\xef\xb5\x90bar', - None), - # 3.40 Bidi: RandALCat character U+FB38 and LCat characters. - ('foo\xef\xb9\xb6bar', - 'foo \xd9\x8ebar'), - # 3.41 Bidi: RandALCat without trailing RandALCat U+0627 U+0031. - ('\xd8\xa71', - None), - # 3.42 Bidi: RandALCat character U+0627 U+0031 U+0628. - ('\xd8\xa71\xd8\xa8', - '\xd8\xa71\xd8\xa8'), - # 3.43 Unassigned code point U+E0002. - # Skip this test as we allow unassigned - #('\xf3\xa0\x80\x82', - # None), - (None, None), - # 3.44 Larger test (shrinking). - # Original test case reads \xc3\xdf - ('X\xc2\xad\xc3\x9f\xc4\xb0\xe2\x84\xa1j\xcc\x8c\xc2\xa0\xc2' - '\xaa\xce\xb0\xe2\x80\x80', - 'xssi\xcc\x87tel\xc7\xb0 a\xce\xb0 '), - # 3.45 Larger test (expanding). - # Original test case reads \xc3\x9f - ('X\xc3\x9f\xe3\x8c\x96\xc4\xb0\xe2\x84\xa1\xe2\x92\x9f\xe3\x8c' - '\x80', - 'xss\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3' - '\x83\x88\xe3\x83\xabi\xcc\x87tel\x28d\x29\xe3\x82' - '\xa2\xe3\x83\x91\xe3\x83\xbc\xe3\x83\x88') - ] - - -class NameprepTest(unittest.TestCase): - def test_nameprep(self): - from encodings.idna import nameprep - for pos, (orig, prepped) in enumerate(nameprep_tests): - if orig is None: - # Skipped - continue - # The Unicode strings are given in UTF-8 - orig = unicode(orig, "utf-8") - if prepped is None: - # Input contains prohibited characters - self.assertRaises(UnicodeError, nameprep, orig) - else: - prepped = unicode(prepped, "utf-8") - try: - self.assertEquals(nameprep(orig), prepped) - except Exception,e: - raise test_support.TestFailed("Test 3.%d: %s" % (pos+1, str(e))) - -def test_main(): - test_support.run_unittest( - UTF16Test, - EscapeDecodeTest, - RecodingTest, - PunycodeTest, - NameprepTest - ) - - -if __name__ == "__main__": - test_main() From ale at codespeak.net Tue Jun 7 19:17:40 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 7 Jun 2005 19:17:40 +0200 (CEST) Subject: [pypy-svn] r13160 - pypy/dist/pypy/tool/pytest Message-ID: <20050607171740.E3DDC27B46@code1.codespeak.net> Author: ale Date: Tue Jun 7 19:17:39 2005 New Revision: 13160 Modified: pypy/dist/pypy/tool/pytest/result.py Log: typo Modified: pypy/dist/pypy/tool/pytest/result.py ============================================================================== --- pypy/dist/pypy/tool/pytest/result.py (original) +++ pypy/dist/pypy/tool/pytest/result.py Tue Jun 7 19:17:39 2005 @@ -36,7 +36,7 @@ def repr_short_error(self): if not self.isok(): if 'reportdiff' in self._blocks: - return "output comaprison failed, see reportdiff" + return "output comparison failed, see reportdiff" else: text = self.getnamedtext('stderr') lines = text.strip().split('\n') From ale at codespeak.net Tue Jun 7 21:50:04 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 7 Jun 2005 21:50:04 +0200 (CEST) Subject: [pypy-svn] r13163 - pypy/dist/pypy/interpreter Message-ID: <20050607195004.24BC327B3F@code1.codespeak.net> Author: ale Date: Tue Jun 7 21:50:02 2005 New Revision: 13163 Modified: pypy/dist/pypy/interpreter/baseobjspace.py Log: By uncommenting a line _codecs will be a builtin module Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue Jun 7 21:50:02 2005 @@ -130,7 +130,8 @@ self.setitem(w_modules, w_name, w_builtin) self.setitem(self.builtin.w_dict, self.wrap('__builtins__'), w_builtin) self.setbuiltinmodule('unicodedata') - + # Uncomment the following line to enable the builtin _codecs module + #self.setbuiltinmodule('_codecs') # XXX we need to resolve unwrapping issues to # make this the default _sre module #self.setbuiltinmodule("_sre", "_sre_pypy") From ale at codespeak.net Tue Jun 7 22:03:03 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 7 Jun 2005 22:03:03 +0200 (CEST) Subject: [pypy-svn] r13164 - pypy/dist/lib-python Message-ID: <20050607200303.3281F27B3F@code1.codespeak.net> Author: ale Date: Tue Jun 7 22:03:02 2005 New Revision: 13164 Modified: pypy/dist/lib-python/conftest.py Log: making conftest.py work on windows Modified: pypy/dist/lib-python/conftest.py ============================================================================== --- pypy/dist/lib-python/conftest.py (original) +++ pypy/dist/lib-python/conftest.py Tue Jun 7 22:03:02 2005 @@ -677,7 +677,7 @@ RegrTest('test_ucn.py', enabled=False), RegrTest('test_unary.py', enabled=True, core=True), - RegrTest('test_unicode.py', enabled=False), + RegrTest('test_unicode.py', enabled=False), #, core=True), RegrTest('test_unicode_file.py', enabled=False), RegrTest('test_unicodedata.py', enabled=False), RegrTest('test_univnewlines.py', enabled=True, core=True), @@ -863,13 +863,19 @@ try: stdout = tempdir.join(self.fspath.basename) + '.out' stderr = tempdir.join(self.fspath.basename) + '.err' - - status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr)) - if os.WIFEXITED(status): - status = os.WEXITSTATUS(status) + if sys.platform == 'win32': + status = os.system("%s >%s 2>%s" %(cmd, stdout, stderr)) + if status>=0: + status = status + else: + status = 'abnormal termination 0x%x' % status else: - status = 'abnormal termination 0x%x' % status - return status, stdout.read(), stderr.read() + status = os.system("%s >>%s 2>>%s" %(cmd, stdout, stderr)) + if os.WIFEXITED(status): + status = os.WEXITSTATUS(status) + else: + status = 'abnormal termination 0x%x' % status + return status, stdout.read(mode='rU'), stderr.read(mode='rU') finally: tempdir.remove() @@ -898,7 +904,7 @@ expectedpath = regrtest.getoutputpath() if not exit_status: if expectedpath is not None: - expected = expectedpath.read(mode='r') + expected = expectedpath.read(mode='rU') test_stdout = "%s\n%s" % (self.fspath.purebasename, test_stdout) if test_stdout != expected: exit_status = 2 From ale at codespeak.net Tue Jun 7 22:06:31 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 7 Jun 2005 22:06:31 +0200 (CEST) Subject: [pypy-svn] r13165 - pypy/dist/lib-python/modified-2.3.4 Message-ID: <20050607200631.A54B327B3F@code1.codespeak.net> Author: ale Date: Tue Jun 7 22:06:30 2005 New Revision: 13165 Removed: pypy/dist/lib-python/modified-2.3.4/DISABLED-codecs.py Log: not needed anymore Deleted: /pypy/dist/lib-python/modified-2.3.4/DISABLED-codecs.py ============================================================================== --- /pypy/dist/lib-python/modified-2.3.4/DISABLED-codecs.py Tue Jun 7 22:06:30 2005 +++ (empty file) @@ -1,750 +0,0 @@ -""" codecs -- Python Codec Registry, API and helpers. - - -Written by Marc-Andre Lemburg (mal at lemburg.com). - -(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. - -"""#" - -import __builtin__, sys - -### Registry and builtin stateless codec functions - -try: - import sys - if sys.path[0] != r'd:\projects\pypy_co': - sys.path.insert(0,r'd:\projects\pypy_co') - from pypy.lib import _codecs - reload(_codecs) - del _codecs - from pypy.lib._codecs import * -except ImportError, why: - raise SystemError,\ - 'Failed to load the builtin codecs: %s' % why - -__all__ = ["register", "lookup", "open", "EncodedFile", "BOM", "BOM_BE", - "BOM_LE", "BOM32_BE", "BOM32_LE", "BOM64_BE", "BOM64_LE", - "BOM_UTF8", "BOM_UTF16", "BOM_UTF16_LE", "BOM_UTF16_BE", - "BOM_UTF32", "BOM_UTF32_LE", "BOM_UTF32_BE", - "strict_errors", "ignore_errors", "replace_errors", - "xmlcharrefreplace_errors", - "register_error", "lookup_error"] - -### Constants - -# -# Byte Order Mark (BOM = ZERO WIDTH NO-BREAK SPACE = U+FEFF) -# and its possible byte string values -# for UTF8/UTF16/UTF32 output and little/big endian machines -# - -# UTF-8 -BOM_UTF8 = '\xef\xbb\xbf' - -# UTF-16, little endian -BOM_LE = BOM_UTF16_LE = '\xff\xfe' - -# UTF-16, big endian -BOM_BE = BOM_UTF16_BE = '\xfe\xff' - -# UTF-32, little endian -BOM_UTF32_LE = '\xff\xfe\x00\x00' - -# UTF-32, big endian -BOM_UTF32_BE = '\x00\x00\xfe\xff' - -if sys.byteorder == 'little': - - # UTF-16, native endianness - BOM = BOM_UTF16 = BOM_UTF16_LE - - # UTF-32, native endianness - BOM_UTF32 = BOM_UTF32_LE - -else: - - # UTF-16, native endianness - BOM = BOM_UTF16 = BOM_UTF16_BE - - # UTF-32, native endianness - BOM_UTF32 = BOM_UTF32_BE - -# Old broken names (don't use in new code) -BOM32_LE = BOM_UTF16_LE -BOM32_BE = BOM_UTF16_BE -BOM64_LE = BOM_UTF32_LE -BOM64_BE = BOM_UTF32_BE - - -### Codec base classes (defining the API) - -class Codec: - - """ Defines the interface for stateless encoders/decoders. - - The .encode()/.decode() methods may use different error - handling schemes by providing the errors argument. These - string values are predefined: - - 'strict' - raise a ValueError error (or a subclass) - 'ignore' - ignore the character and continue with the next - 'replace' - replace with a suitable replacement character; - Python will use the official U+FFFD REPLACEMENT - CHARACTER for the builtin Unicode codecs on - decoding and '?' on encoding. - 'xmlcharrefreplace' - Replace with the appropriate XML - character reference (only for encoding). - 'backslashreplace' - Replace with backslashed escape sequences - (only for encoding). - - The set of allowed values can be extended via register_error. - - """ - def encode(self, input, errors='strict'): - - """ Encodes the object input and returns a tuple (output - object, length consumed). - - errors defines the error handling to apply. It defaults to - 'strict' handling. - - The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. - - The encoder must be able to handle zero length input and - return an empty object of the output object type in this - situation. - - """ - raise NotImplementedError - - def decode(self, input, errors='strict'): - - """ Decodes the object input and returns a tuple (output - object, length consumed). - - input must be an object which provides the bf_getreadbuf - buffer slot. Python strings, buffer objects and memory - mapped files are examples of objects providing this slot. - - errors defines the error handling to apply. It defaults to - 'strict' handling. - - The method may not store state in the Codec instance. Use - StreamCodec for codecs which have to keep state in order to - make encoding/decoding efficient. - - The decoder must be able to handle zero length input and - return an empty object of the output object type in this - situation. - - """ - raise NotImplementedError - -# -# The StreamWriter and StreamReader class provide generic working -# interfaces which can be used to implement new encoding submodules -# very easily. See encodings/utf_8.py for an example on how this is -# done. -# - -class StreamWriter(Codec): - - def __init__(self, stream, errors='strict'): - - """ Creates a StreamWriter instance. - - stream must be a file-like object open for writing - (binary) data. - - The StreamWriter may use different error handling - schemes by providing the errors keyword argument. These - parameters are predefined: - - 'strict' - raise a ValueError (or a subclass) - 'ignore' - ignore the character and continue with the next - 'replace'- replace with a suitable replacement character - 'xmlcharrefreplace' - Replace with the appropriate XML - character reference. - 'backslashreplace' - Replace with backslashed escape - sequences (only for encoding). - - The set of allowed parameter values can be extended via - register_error. - """ - self.stream = stream - self.errors = errors - - def write(self, object): - - """ Writes the object's contents encoded to self.stream. - """ - data, consumed = self.encode(object, self.errors) - print type(data) - self.stream.write(data) - - def writelines(self, list): - - """ Writes the concatenated list of strings to the stream - using .write(). - """ - self.write(''.join(list)) - - def reset(self): - - """ Flushes and resets the codec buffers used for keeping state. - - Calling this method should ensure that the data on the - output is put into a clean state, that allows appending - of new fresh data without having to rescan the whole - stream to recover state. - - """ - pass - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - -### - -class StreamReader(Codec): - - def __init__(self, stream, errors='strict'): - - """ Creates a StreamReader instance. - - stream must be a file-like object open for reading - (binary) data. - - The StreamReader may use different error handling - schemes by providing the errors keyword argument. These - parameters are predefined: - - 'strict' - raise a ValueError (or a subclass) - 'ignore' - ignore the character and continue with the next - 'replace'- replace with a suitable replacement character; - - The set of allowed parameter values can be extended via - register_error. - """ - self.stream = stream - self.errors = errors - self.bytebuffer = "" - self.charbuffer = u"" - self.atcr = False - - def decode(self, input, errors='strict'): - raise NotImplementedError - - def read(self, size=-1, chars=-1): - - """ Decodes data from the stream self.stream and returns the - resulting object. - - chars indicates the number of characters to read from the - stream. read() will never return more than chars - characters, but it might return less, if there are not enough - characters available. - - size indicates the approximate maximum number of bytes to - read from the stream for decoding purposes. The decoder - can modify this setting as appropriate. The default value - -1 indicates to read and decode as much as possible. size - is intended to prevent having to decode huge files in one - step. - - The method should use a greedy read strategy meaning that - it should read as much data as is allowed within the - definition of the encoding and the given size, e.g. if - optional encoding endings or state markers are available - on the stream, these should be read too. - """ - # read until we get the required number of characters (if available) - while True: - # can the request can be satisfied from the character buffer? - if chars < 0: - if self.charbuffer: - break - else: - if len(self.charbuffer) >= chars: - break - # we need more data - if size < 0: - newdata = self.stream.read() - else: - newdata = self.stream.read(size) - # decode bytes (those remaining from the last call included) - data = self.bytebuffer + newdata - newchars, decodedbytes = self.decode(data, self.errors) - # keep undecoded bytes until the next call - self.bytebuffer = data[decodedbytes:] - # put new characters in the character buffer - self.charbuffer += newchars - # there was no data available - if not newdata: - break - if chars < 0: - # Return everything we've got - result = self.charbuffer - self.charbuffer = u"" - else: - # Return the first chars characters - result = self.charbuffer[:chars] - self.charbuffer = self.charbuffer[chars:] - return result - - def readline(self, size=None, keepends=True): - - """ Read one line from the input stream and return the - decoded data. - - size, if given, is passed as size argument to the - read() method. - - """ - readsize = size or 72 - line = u"" - # If size is given, we call read() only once - while True: - data = self.read(readsize) - if self.atcr and data.startswith(u"\n"): - data = data[1:] - if data: - self.atcr = data.endswith(u"\r") - line += data - lines = line.splitlines(True) - if lines: - line0withend = lines[0] - line0withoutend = lines[0].splitlines(False)[0] - if line0withend != line0withoutend: # We really have a line end - # Put the rest back together and keep it until the next call - self.charbuffer = u"".join(lines[1:]) + self.charbuffer - if keepends: - line = line0withend - else: - line = line0withoutend - break - # we didn't get anything or this was our only try - elif not data or size is not None: - if line and not keepends: - line = line.splitlines(False)[0] - break - if readsize<8000: - readsize *= 2 - return line - - def readlines(self, sizehint=None, keepends=True): - - """ Read all lines available on the input stream - and return them as list of lines. - - Line breaks are implemented using the codec's decoder - method and are included in the list entries. - - sizehint, if given, is ignored since there is no efficient - way to finding the true end-of-line. - - """ - data = self.read() - return data.splitlines(keepends) - - def reset(self): - - """ Resets the codec buffers used for keeping state. - - Note that no stream repositioning should take place. - This method is primarily intended to be able to recover - from decoding errors. - - """ - pass - - def next(self): - - """ Return the next decoded line from the input stream.""" - line = self.readline() - if line: - return line - raise StopIteration - - def __iter__(self): - return self - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - -### - -class StreamReaderWriter: - - """ StreamReaderWriter instances allow wrapping streams which - work in both read and write modes. - - The design is such that one can use the factory functions - returned by the codec.lookup() function to construct the - instance. - - """ - # Optional attributes set by the file wrappers below - encoding = 'unknown' - - def __init__(self, stream, Reader, Writer, errors='strict'): - - """ Creates a StreamReaderWriter instance. - - stream must be a Stream-like object. - - Reader, Writer must be factory functions or classes - providing the StreamReader, StreamWriter interface resp. - - Error handling is done in the same way as defined for the - StreamWriter/Readers. - - """ - self.stream = stream - self.reader = Reader(stream, errors) - self.writer = Writer(stream, errors) - self.errors = errors - - def read(self, size=-1): - - return self.reader.read(size) - - def readline(self, size=None): - - return self.reader.readline(size) - - def readlines(self, sizehint=None): - - return self.reader.readlines(sizehint) - - def next(self): - - """ Return the next decoded line from the input stream.""" - return self.reader.next() - - def __iter__(self): - return self - - def write(self, data): - - return self.writer.write(data) - - def writelines(self, list): - - return self.writer.writelines(list) - - def reset(self): - - self.reader.reset() - self.writer.reset() - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - -### - -class StreamRecoder: - - """ StreamRecoder instances provide a frontend - backend - view of encoding data. - - They use the complete set of APIs returned by the - codecs.lookup() function to implement their task. - - Data written to the stream is first decoded into an - intermediate format (which is dependent on the given codec - combination) and then written to the stream using an instance - of the provided Writer class. - - In the other direction, data is read from the stream using a - Reader instance and then return encoded data to the caller. - - """ - # Optional attributes set by the file wrappers below - data_encoding = 'unknown' - file_encoding = 'unknown' - - def __init__(self, stream, encode, decode, Reader, Writer, - errors='strict'): - - """ Creates a StreamRecoder instance which implements a two-way - conversion: encode and decode work on the frontend (the - input to .read() and output of .write()) while - Reader and Writer work on the backend (reading and - writing to the stream). - - You can use these objects to do transparent direct - recodings from e.g. latin-1 to utf-8 and back. - - stream must be a file-like object. - - encode, decode must adhere to the Codec interface, Reader, - Writer must be factory functions or classes providing the - StreamReader, StreamWriter interface resp. - - encode and decode are needed for the frontend translation, - Reader and Writer for the backend translation. Unicode is - used as intermediate encoding. - - Error handling is done in the same way as defined for the - StreamWriter/Readers. - - """ - self.stream = stream - self.encode = encode - self.decode = decode - self.reader = Reader(stream, errors) - self.writer = Writer(stream, errors) - self.errors = errors - - def read(self, size=-1): - - data = self.reader.read(size) - data, bytesencoded = self.encode(data, self.errors) - return data - - def readline(self, size=None): - - if size is None: - data = self.reader.readline() - else: - data = self.reader.readline(size) - data, bytesencoded = self.encode(data, self.errors) - return data - - def readlines(self, sizehint=None): - - data = self.reader.read() - data, bytesencoded = self.encode(data, self.errors) - return data.splitlines(1) - - def next(self): - - """ Return the next decoded line from the input stream.""" - return self.reader.next() - - def __iter__(self): - return self - - def write(self, data): - - data, bytesdecoded = self.decode(data, self.errors) - return self.writer.write(data) - - def writelines(self, list): - - data = ''.join(list) - data, bytesdecoded = self.decode(data, self.errors) - return self.writer.write(data) - - def reset(self): - - self.reader.reset() - self.writer.reset() - - def __getattr__(self, name, - getattr=getattr): - - """ Inherit all other methods from the underlying stream. - """ - return getattr(self.stream, name) - -### Shortcuts - -def open(filename, mode='rb', encoding=None, errors='strict', buffering=1): - - """ Open an encoded file using the given mode and return - a wrapped version providing transparent encoding/decoding. - - Note: The wrapped version will only accept the object format - defined by the codecs, i.e. Unicode objects for most builtin - codecs. Output is also codec dependent and will usually by - Unicode as well. - - Files are always opened in binary mode, even if no binary mode - was specified. This is done to avoid data loss due to encodings - using 8-bit values. The default file mode is 'rb' meaning to - open the file in binary read mode. - - encoding specifies the encoding which is to be used for the - file. - - errors may be given to define the error handling. It defaults - to 'strict' which causes ValueErrors to be raised in case an - encoding error occurs. - - buffering has the same meaning as for the builtin open() API. - It defaults to line buffered. - - The returned wrapped file object provides an extra attribute - .encoding which allows querying the used encoding. This - attribute is only available if an encoding was specified as - parameter. - - """ - if encoding is not None and \ - 'b' not in mode: - # Force opening of the file in binary mode - mode = mode + 'b' - file = __builtin__.open(filename, mode, buffering) - if encoding is None: - return file - (e, d, sr, sw) = lookup(encoding) - srw = StreamReaderWriter(file, sr, sw, errors) - # Add attributes to simplify introspection - srw.encoding = encoding - return srw - -def EncodedFile(file, data_encoding, file_encoding=None, errors='strict'): - - """ Return a wrapped version of file which provides transparent - encoding translation. - - Strings written to the wrapped file are interpreted according - to the given data_encoding and then written to the original - file as string using file_encoding. The intermediate encoding - will usually be Unicode but depends on the specified codecs. - - Strings are read from the file using file_encoding and then - passed back to the caller as string using data_encoding. - - If file_encoding is not given, it defaults to data_encoding. - - errors may be given to define the error handling. It defaults - to 'strict' which causes ValueErrors to be raised in case an - encoding error occurs. - - The returned wrapped file object provides two extra attributes - .data_encoding and .file_encoding which reflect the given - parameters of the same name. The attributes can be used for - introspection by Python programs. - - """ - if file_encoding is None: - file_encoding = data_encoding - encode, decode = lookup(data_encoding)[:2] - Reader, Writer = lookup(file_encoding)[2:] - sr = StreamRecoder(file, - encode, decode, Reader, Writer, - errors) - # Add attributes to simplify introspection - sr.data_encoding = data_encoding - sr.file_encoding = file_encoding - return sr - -### Helpers for codec lookup - -def getencoder(encoding): - - """ Lookup up the codec for the given encoding and return - its encoder function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding)[0] - -def getdecoder(encoding): - - """ Lookup up the codec for the given encoding and return - its decoder function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding)[1] - -def getreader(encoding): - - """ Lookup up the codec for the given encoding and return - its StreamReader class or factory function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding)[2] - -def getwriter(encoding): - - """ Lookup up the codec for the given encoding and return - its StreamWriter class or factory function. - - Raises a LookupError in case the encoding cannot be found. - - """ - return lookup(encoding)[3] - -### Helpers for charmap-based codecs - -def make_identity_dict(rng): - - """ make_identity_dict(rng) -> dict - - Return a dictionary where elements of the rng sequence are - mapped to themselves. - - """ - res = {} - for i in rng: - res[i]=i - return res - -def make_encoding_map(decoding_map): - - """ Creates an encoding map from a decoding map. - - If a target mapping in the decoding map occurs multiple - times, then that target is mapped to None (undefined mapping), - causing an exception when encountered by the charmap codec - during translation. - - One example where this happens is cp875.py which decodes - multiple character to \u001a. - - """ - m = {} - for k,v in decoding_map.items(): - if not v in m: - m[v] = k - else: - m[v] = None - return m - -### error handlers - -strict_errors = lookup_error("strict") -ignore_errors = lookup_error("ignore") -replace_errors = lookup_error("replace") -xmlcharrefreplace_errors = lookup_error("xmlcharrefreplace") -backslashreplace_errors = lookup_error("backslashreplace") - -# Tell modulefinder that using codecs probably needs the encodings -# package -_false = 1 -if _false: - import encodings - -### Tests - -if __name__ == '__main__': - - # Make stdout translate Latin-1 output into UTF-8 output - sys.stdout = EncodedFile(sys.stdout, 'latin-1', 'utf-8') - - # Have stdin translate Latin-1 input into UTF-8 input - sys.stdin = EncodedFile(sys.stdin, 'utf-8', 'latin-1') From ale at codespeak.net Tue Jun 7 22:20:02 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 7 Jun 2005 22:20:02 +0200 (CEST) Subject: [pypy-svn] r13166 - pypy/dist/pypy/objspace/std Message-ID: <20050607202002.08FE327B3F@code1.codespeak.net> Author: ale Date: Tue Jun 7 22:20:00 2005 New Revision: 13166 Modified: pypy/dist/pypy/objspace/std/unicodeobject.py Log: Added a type check to .encode. I am not quite sure if this is the right place to do the check. Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Tue Jun 7 22:20:00 2005 @@ -781,7 +781,9 @@ retval, lenght = encoder(unistr) else: retval, length = encoder(unistr, errors) - + if not isinstance(retval,str): + raise TypeError("encoder did not return an unicode object (type=%s)" % + type(retval).__name__) return retval ''') From cfbolz at codespeak.net Tue Jun 7 23:28:58 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 7 Jun 2005 23:28:58 +0200 (CEST) Subject: [pypy-svn] r13167 - pypy/dist/pypy/translator/llvm/test Message-ID: <20050607212858.EA92527B43@code1.codespeak.net> Author: cfbolz Date: Tue Jun 7 23:28:58 2005 New Revision: 13167 Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py Log: Disabling test Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_genllvm.py Tue Jun 7 23:28:58 2005 @@ -8,6 +8,7 @@ from pypy.objspace.flow.model import Constant, Variable def setup_module(mod): + py.test.skip("nothing works at the moment") mod.llvm_found = is_on_path("llvm-as") def compile_function(function, annotate): From cfbolz at codespeak.net Tue Jun 7 23:30:56 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 7 Jun 2005 23:30:56 +0200 (CEST) Subject: [pypy-svn] r13168 - pypy/dist/pypy/translator/llvm Message-ID: <20050607213056.8592627B43@code1.codespeak.net> Author: cfbolz Date: Tue Jun 7 23:30:55 2005 New Revision: 13168 Modified: pypy/dist/pypy/translator/llvm/funcrepr.py pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/llvm/lazyattribute.py pypy/dist/pypy/translator/llvm/representation.py pypy/dist/pypy/translator/llvm/reprmap.py pypy/dist/pypy/translator/llvm/typerepr.py Log: started refactoring genllvm. this is an intermediate checking. It's a big mess now, lots of debug prints and comments. I'll clean this up real soon now. Modified: pypy/dist/pypy/translator/llvm/funcrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcrepr.py (original) +++ pypy/dist/pypy/translator/llvm/funcrepr.py Tue Jun 7 23:30:55 2005 @@ -11,15 +11,18 @@ from pypy.objspace.flow.model import traverse, checkgraph from pypy.annotation import model as annmodel from pypy.annotation.builtin import BUILTIN_ANALYZERS -from pypy.translator.llvm import llvmbc -from pypy.translator.unsimplify import remove_double_links +from pypy.rpython import lltype + +from pypy.translator.unsimplify import remove_double_links +from pypy.translator.llvm import llvmbc from pypy.translator.llvm.representation import debug, LLVMRepr, CompileError from pypy.translator.llvm.representation import last_exception, last_exc_value from pypy.translator.llvm.representation import SimpleRepr from pypy.translator.llvm.typerepr import TypeRepr, PointerTypeRepr -debug = False +debug = True +lazy_debug = True INTRINSIC_OPS = ["lt", "le", "eq", "ne", "gt", "ge", "is_", "is_true", "len", "neg", "pos", "invert", "add", "sub", "mul", "truediv", @@ -74,10 +77,18 @@ l_args[1] = l_tmp lblock.call(l_target, l_args[0], l_args[1:]) + class FunctionRepr(LLVMRepr): l_functions = {} def get(obj, gen): - name = None + if isinstance(obj, lltype._func): + print "1a)" + if obj._callable not in FunctionRepr.l_functions: + print "1b)" + FunctionRepr.l_functions[obj._callable] = FunctionRepr(obj, gen) + return FunctionRepr.l_functions[obj._callable] + return None + name = None #ZZZZ this can probably be removed if (isinstance(obj, annmodel.SomePBC) and len(obj.prebuiltinstances) == 1 and isinstance(obj.prebuiltinstances.keys()[0], FunctionType)): @@ -98,38 +109,47 @@ return None get = staticmethod(get) - def __init__(self, name, function, gen): + def __init__(self, function, gen): if debug: - print "FunctionRepr: %s" % name + print "FunctionRepr: %s" % function self.gen = gen self.func = function self.translator = gen.translator - self.name = gen.get_global_tmp(name) - self.graph = self.translator.getflowgraph(self.func) + if debug: print "init 1a)" + #if debug: print 'QQQ',function.name,'QQQ' + #if debug: print "init 1b)" + print function, function.__class__ + self.name = gen.get_global_tmp(function._name) + if debug: print "init 2)" + self.graph = function.graph self.annotator = gen.translator.annotator self.blocknum = {} self.allblocks = [] self.pyrex_source = "" self.dependencies = sets.Set() - self.l_retvalue = self.gen.get_repr( - self.graph.returnblock.inputargs[0]) - self.dependencies.add(self.l_retvalue) - self.l_args = [self.gen.get_repr(ar) - for ar in self.graph.startblock.inputargs] + if debug: print "init 3)" + self.type = self.gen.get_repr(function._TYPE) + if debug: print "init 4)" + self.l_args = self.type.l_args + self.dependencies.add(self.type) self.dependencies.update(self.l_args) + if debug: print "init 8)" self.l_default_args = None remove_double_links(self.translator, self.graph) + print "init 9)" self.get_bbs() + print "init done" - lazy_attributes = ['llvm_func', 'lblocks'] + lazy_attributes = ['llvm_func', 'lblocks'] def setup(self): + print "setup" self.se = True self.lblocks = [] self.build_bbs() def get_returntype(): - return self.rettype.llvmname() + return self.type.l_returntype.typename() def get_bbs(self): def visit(node): @@ -137,7 +157,7 @@ self.allblocks.append(node) self.blocknum[node] = len(self.blocknum) traverse(visit, self.graph) - self.same_origin_block = [False] * len(self.allblocks) +# self.same_origin_block = [False] * len(self.allblocks) def build_bbs(self): for number, pyblock in enumerate(self.allblocks): @@ -159,11 +179,11 @@ self.lblocks.append(lblock) def llvmfuncdef(self): - s = "internal %s %s(" % (self.l_retvalue.llvmtype(), self.name) + s = "internal %s %s(" % (self.type.l_returntype.typename(), self.name) return s + ", ".join([a.typed_name() for a in self.l_args]) + ")" def rettype(self): - return self.l_retvalue.llvmtype() + return self.type.l_rettype.llvmname() def get_functions(self): return str(self.llvm_func) @@ -460,7 +480,9 @@ lazy_attributes = ['l_function', 'llvm_func', 'init_block', 'exceptblock'] def setup(self): - self.l_function = self.gen.get_repr(self.function) + f = self.gen.rtyper.getfunctionptr(self.function)._obj + print "EntryFunctionRepr", f + self.l_function = self.gen.get_repr(f) self.dependencies.add(self.l_function) #XXX clean this up #create entry block @@ -476,18 +498,19 @@ self.llvm_func.basic_block(self.init_block) #create the block that calls the "real" function real_entry = llvmbc.TryBasicBlock("real_entry", "retblock", "exc") - l_ret = self.gen.get_local_tmp(self.l_function.l_retvalue.type, + l_ret = self.gen.get_local_tmp(self.l_function.type.l_returntype, self) real_entry.last_op = True self.l_function.op_simple_call( - l_ret, [self.function] + self.l_function.l_args, real_entry, self) + l_ret, [self.gen.rtyper.getfunctionptr(self.function)._obj] + + self.l_function.l_args, real_entry, self) self.llvm_func.basic_block(real_entry) #create the block that catches remaining unwinds and sets #pypy____uncaught_exception to 1 self.exceptblock = llvmbc.BasicBlock("exc") ins = """store int 1, int* %%pypy__uncaught_exception \t%%dummy_ret = cast int 0 to %s -\tret %s %%dummy_ret""" % tuple([self.l_function.l_retvalue.llvmtype()] * 2) +\tret %s %%dummy_ret""" % tuple([self.l_function.type.l_returntype.typename()] * 2) self.exceptblock.instruction(ins) self.exceptblock.closed = True self.llvm_func.basic_block(self.exceptblock) @@ -503,8 +526,8 @@ rettype_c = C_SIMPLE_TYPES[a.binding(retv).__class__] self.void = False except KeyError: - l_retv = self.l_function.l_retvalue - if l_retv.llvmtype() == "%std.void*": + l_rett = self.l_function.type.l_returntype + if l_retv.llvmname() == "%std.void*": rettype_c = "void" self.void = True else: @@ -516,7 +539,7 @@ return fd def llvmfuncdef(self): - s = "%s %s(" % (self.l_function.l_retvalue.llvmtype(), self.name) + s = "%s %s(" % (self.l_function.type.l_returntype.typename(), self.name) s += ", ".join([a.typed_name() for a in self.l_function.l_args]) + ")" return s @@ -549,7 +572,7 @@ return self.pyrex_source def rettype(self): - return self.l_function.l_retvalue.llvmtype() + return self.l_function.type.l_returntype.typename() def get_functions(self): if not self.branch_added: @@ -573,6 +596,7 @@ # to the appropriate class # Should be replaced by function pointers def get(obj, gen): + return None #this function will go away, I just disable it for now if (isinstance(obj, annmodel.SomePBC) and len(obj.prebuiltinstances) > 1 and isinstance(obj.prebuiltinstances.keys()[0], FunctionType)): Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Tue Jun 7 23:30:55 2005 @@ -77,7 +77,11 @@ pbcrepr]: self.repr_classes += [getattr(mod, s) for s in dir(mod) if "Repr" in s] + #if debug: + # print 'LLVMGenerator before repr_classes=', len(self.repr_classes), self.repr_classes self.repr_classes = [c for c in self.repr_classes if hasattr(c, "get")] + #if debug: + # print 'LLVMGenerator after repr_classes=', len(self.repr_classes), self.repr_classes self.llvm_reprs = {} self.depth = 0 self.entryname = self.translator.functions[0].__name__ @@ -85,10 +89,8 @@ self.l_entrypoint = EntryFunctionRepr("%__entry__" + self.entryname, self.translator.functions[0], self) -## classrepr.create_builtin_exceptions( -## self, self.l_entrypoint.get_dependencies()) self.local_counts[self.l_entrypoint] = 0 - self.l_entrypoint.setup() + #self.l_entrypoint.setup() def compile(self, optimize=False): from pypy.tool.udir import udir @@ -136,12 +138,8 @@ print "->exists already:", self.llvm_reprs[key] return self.llvm_reprs[key] elif isinstance(obj, Variable): - try: - obj.concretetype - except AttributeError: - self.rtyper.setconcretetype(obj) result = representation.VariableRepr(obj, self) - self.llvm_reprs[result] = result + self.llvm_reprs[key] = result self.depth -= 1 return result elif isinstance(obj, lltype.Primitive): @@ -151,8 +149,8 @@ return result if isinstance(obj, Constant): try: - T = lltype.typeOf(obj) - if isinstance(T, lltype.Primitive): + concretetype = obj.concretetype + if isinstance(concretetype, lltype.Primitive): result = reprmap.PRIMITIVE_REPRS[concretetype](obj, self) self.llvm_reprs[key] = result self.depth -= 1 @@ -161,14 +159,22 @@ except AttributeError: pass for cl in self.repr_classes: + if 0: #debug: + print 'try cl.get(obj, self) where cl=', cl try: g = cl.get(obj, self) + #if debug: + # print 'A) g=', g except AttributeError: continue + #if debug: + # print 'B) g=', g if g is not None: self.llvm_reprs[key] = g self.local_counts[g] = 0 self.depth -= 1 + #if debug: + # print 'C) should return here' return g raise CompileError, "Can't get repr of %s, %s" % (obj, obj.__class__) @@ -257,11 +263,3 @@ remove_loops(l_dep, seen_repr.union(sets.Set([l_repr]))) deps.difference_update(remove) -## def f(): -## l = [10,20,30] -## return l[2] - -## t = Translator(f) -## a = t.annotate([]) - -## flg = t.getflowgraph() Modified: pypy/dist/pypy/translator/llvm/lazyattribute.py ============================================================================== --- pypy/dist/pypy/translator/llvm/lazyattribute.py (original) +++ pypy/dist/pypy/translator/llvm/lazyattribute.py Tue Jun 7 23:30:55 2005 @@ -2,6 +2,8 @@ import sets +debug = True + def create_property(cls, la, name): def get(self): self.setup() @@ -27,7 +29,7 @@ def setup(self): if self.__setup_called__: return - if getattr(cls.__module__, "lazy_debug", None): + if debug: print "calling setup of class", name self.__setup_called__ = True self.gen.lazy_objects.discard(self) Modified: pypy/dist/pypy/translator/llvm/representation.py ============================================================================== --- pypy/dist/pypy/translator/llvm/representation.py (original) +++ pypy/dist/pypy/translator/llvm/representation.py Tue Jun 7 23:30:55 2005 @@ -55,30 +55,30 @@ def setup(self): pass - def get_globals(self): + def get_globals(self): #this is called when the global definitions are collected return "" - def get_functions(self): + def get_functions(self): #this is called, when functions are collected return "" - def collect_init_code(self, lblock, l_func): - pass + def collect_init_code(self, lblock, l_func): #this collects init code + pass #it is only executed once at module import time - def llvmname(self): + def llvmname(self): #this is the name of the object in LLVM world: "5" for the int 5 return self.name - def llvmtype(self): + def llvmtype(self): #this is the name of the type of the object: "long" for and int return self.type.typename() - def llvmsize(self): + def llvmsize(self): #this is the size in bytes -- not really used yet, but will be soon raise NotImplementedError, "This object has no size!" - def op(self, opname, l_target, args, lblock, l_func): - if hasattr(self, "type") and hasattr(self.type, "t_op"): + def op(self, opname, l_target, args, lblock, l_func): #This is used when code is generated: + if hasattr(self, "type") and hasattr(self.type, "t_op"): #I'll tell you about it soon return self.type.t_op(opname, l_target, args, lblock, l_func) raise CompileError, "op '%s' not supported" % opname - def typed_name(self): + def typed_name(self): #helper function: gives "int 5" for the int 5 return self.llvmtype() + " " + self.llvmname() def get_dependencies(self): @@ -99,7 +99,7 @@ return str(self.value) def get_dependencies(self): - return [self.type] + return sets.Set([self.type]) class UnsignedRepr(LLVMRepr): def __init__(self, value, gen): @@ -113,7 +113,7 @@ return str(self.value) def get_dependencies(self): - return [self.type] + return sets.Set([self.type]) class BoolRepr(LLVMRepr): def __init__(self, value, gen): @@ -127,7 +127,21 @@ return str(self.value).lower() def get_dependencies(self): - return [self.type] + return sets.Set([self.type]) + +class FloatRepr(LLVMRepr): + def __init__(self, value, gen): + if debug: + print "FloatRepr: %f" % value + self.value = float(value) + self.gen = gen + self.type = self.gen.get_repr(lltype.Float) + + def llvmname(self): + return str(self.value).lower() + + def get_dependencies(self): + return sets.Set([self.type]) class CharRepr(LLVMRepr): def __init__(self, value, gen): @@ -146,7 +160,7 @@ return '%d' % ord(value) def get_dependencies(self): - return [self.type] + return sets.Set([self.type]) class SimpleRepr(LLVMRepr): Modified: pypy/dist/pypy/translator/llvm/reprmap.py ============================================================================== --- pypy/dist/pypy/translator/llvm/reprmap.py (original) +++ pypy/dist/pypy/translator/llvm/reprmap.py Tue Jun 7 23:30:55 2005 @@ -3,13 +3,14 @@ from pypy.rpython import lltype from pypy.translator.llvm import representation, funcrepr, typerepr, seqrepr -from pypy.translator.llvm import classrepr, pbcrepr +from pypy.translator.llvm import classrepr, pbcrepr, pointerrepr PRIMITIVE_REPRS = { lltype.Signed: representation.SignedRepr, lltype.Unsigned: representation.UnsignedRepr, lltype.Char: representation.CharRepr, - lltype.Bool: representation.BoolRepr + lltype.Bool: representation.BoolRepr, + lltype.Float: representation.FloatRepr, } PRIMITIVE_TYPES = { @@ -17,5 +18,10 @@ lltype.Unsigned: typerepr.UnsignedTypeRepr, lltype.Char: typerepr.CharTypeRepr, lltype.Bool: typerepr.BoolTypeRepr, + lltype.Float: typerepr.FloatTypeRepr, } +#def ptr_types(ptr): +# if isinstance(ptr._obj, lltype._func): +# return pointerrepr.FuncPointerRepr(ptr) + Modified: pypy/dist/pypy/translator/llvm/typerepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/typerepr.py (original) +++ pypy/dist/pypy/translator/llvm/typerepr.py Tue Jun 7 23:30:55 2005 @@ -15,13 +15,17 @@ from pypy.translator.llvm.representation import debug, LLVMRepr, CompileError from pypy.translator.llvm.representation import LLVM_SIMPLE_TYPES +from pypy.rpython import lltype import sys + if 2147483647 == sys.maxint: BYTES_IN_INT = 4 else: BYTES_IN_INT = 8 +lazy_debug = True +debug = True class TypeRepr(LLVMRepr): def get(obj, gen): @@ -137,6 +141,18 @@ def llvmsize(self): return 1 +class FloatTypeRepr(TypeRepr): + def __init__(self, gen): + if debug: + print "FloatTypeRepr" + self.gen = gen + + def typename(self): + return "double" + + def llvmsize(self): + return 8 + class CharTypeRepr(TypeRepr): def __init__(self, gen): if debug: @@ -149,6 +165,25 @@ def llvmsize(self): return 1 +class FuncTypeRepr(TypeRepr): + def get(obj, gen): + if obj.__class__ is lltype.FuncType: + return FuncTypeRepr(obj, gen) + get = staticmethod(get) + + def __init__(self, functype, gen): + if debug: + print "FuncTypeRepr: %s" % functype + self.gen = gen + self.functype = functype + self.l_returntype = self.gen.get_repr(functype.RESULT) + self.l_args = [self.gen.get_repr(arg) for arg in functype.ARGS] + self.dependencies = sets.Set(self.l_args + [self.l_returntype]) + + def typename(self): + args = ", ".join([l_arg.llvmname() for arg in self.l_args]) + return "%s (%s)" % (self.l_returntype.llvmname(), args) + class StringTypeRepr(TypeRepr): def get(obj, gen): From cfbolz at codespeak.net Wed Jun 8 09:47:19 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 8 Jun 2005 09:47:19 +0200 (CEST) Subject: [pypy-svn] r13171 - pypy/dist/pypy/translator/llvm Message-ID: <20050608074719.618F527B4A@code1.codespeak.net> Author: cfbolz Date: Wed Jun 8 09:47:18 2005 New Revision: 13171 Added: pypy/dist/pypy/translator/llvm/pointerrepr.py Log: missing from last night's commit Added: pypy/dist/pypy/translator/llvm/pointerrepr.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm/pointerrepr.py Wed Jun 8 09:47:18 2005 @@ -0,0 +1,10 @@ +import autopath +import sets + +from pypy.objspace.flow.model import Variable, Constant +from pypy.objspace.flow.model import last_exception + +from pypy.rpython import lltype + +from pypy.annotation import model as annmodel + From ericvrp at codespeak.net Wed Jun 8 11:17:16 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 11:17:16 +0200 (CEST) Subject: [pypy-svn] r13172 - pypy/dist/pypy/translator/llvm Message-ID: <20050608091716.29CD027B4A@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 11:17:15 2005 New Revision: 13172 Added: pypy/dist/pypy/translator/llvm/compyle.py (contents, props changed) Log: tool for quickly testing backend source generation, flowgraph display and backend code generation(+testing) Added: pypy/dist/pypy/translator/llvm/compyle.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm/compyle.py Wed Jun 8 11:17:15 2005 @@ -0,0 +1,162 @@ +#!/usr/bin/python + +"""PyPy compiler to be used as a wrapper around the various backend translators. + +options: + -h(elp) + -v(iew flow graph) + -b (set backend) [default=llvm] + -s(show source) + -C(ompilation disable) + -t(est compiled) + [python script] +""" + +import autopath, os, sys +from pypy.translator.translator import Translator +from pypy.rpython.rtyper import * +from pypy.rpython.rarithmetic import * + + +class Options(object): + available_backends = {'org':'Original source', 'c':'C translation', 'cl':'common lisp translation', 'llvm':'LLVM translation(default)', 'pyrex':'pyrex translation'} + backend = 'llvm' + python_script = '' + entry_function = 'main()' + view_flow_graph = False + show_source = False + compile = True + test_compiled = False + + def __init__(self,argv=[]): + if not argv: + print __doc__ + sys.exit(0) + + for arg in argv: + if arg[0] == '-': + option = arg[:2] + + if option == '-b': + new_backend = arg[2:] + if new_backend in self.available_backends: + self.backend = new_backend + else: + print 'error: unknown backend', new_backend, '. Avaialable backends are:', self.available_backends + sys.exit(0) + + elif option == '-v': + self.view_flow_graph = True + + elif option == '-s': + self.show_source = True + + elif option == '-C': + self.compile = False + + elif option == '-t': + self.test_compiled = True + + else: + print __doc__ + sys.exit(0) + + else: + if not self.python_script: + self.python_script = arg + else: + self.entry_function = arg + + +def main(argv=[]): + options = Options(argv) + + modname = options.python_script + if '/' in modname: + modname = modname.replace('/', '.') + if modname[-3:] == '.py': + modname = modname[:-3] + exec "import %(modname)s as testmodule" % locals() + + if '(' in options.entry_function: + entry_function, arguments = options.entry_function.split('(',1) + else: + entry_function, arguments = options.entry_function, ')' + + #print 'entry_functionText=',entry_function + entry_function = getattr(testmodule, entry_function) + #print 'entry_function=',entry_function + + if arguments != ')' and arguments.find(',') == -1: + arguments = arguments[:-1] + ',)' + arguments = [argument for argument in eval('('+arguments)] + #print 'arguments=',arguments + + argumentTypes = [type(arg) for arg in arguments] + #print 'argumentTypes=',argumentTypes + + t = Translator(entry_function) + t.simplify() + a = t.annotate(argumentTypes) + a.simplify() + + if options.view_flow_graph: + rtyper = RPythonTyper(t.annotator) + rtyper.specialize() + t.view() + t = Translator(entry_function) + t.simplify() + a = t.annotate(argumentTypes) + a.simplify() + + if options.show_source: + if options.backend == 'org': + print t.source() + + elif options.backend == 'c': + print t.c() + #note: this is a workaround until GenC can generate identical code multiple times + t = Translator(entry_function) + t.simplify() + a = t.annotate([type(arg), type(arg) == type(int)]) # pass the list of args types + a.simplify() + + elif options.backend == 'cl': + print t.cl() + + elif options.backend == 'llvm': + print t.llvm() + + elif options.backend == 'pyrex': + print t.pyrex() + + if options.compile: + if options.backend == 'c': + a.specialize() # use low level operations (for C only) + f = t.ccompile() + + elif options.backend == 'llvm': + f = t.llvmcompile() + + elif options.backend == 'pyrex': + f = t.pyrexcompile() + + else: + print 'warning: backend', options.backend, 'has no compile phase' + sys.exit(0) + + assert f + print 'Backend', options.backend, 'compilation successful!' + + if f and options.test_compiled: + #assert f(arg) == t.call(arg) # sanity check #XXX make args a commandline argument!!! + print 'Backend', options.backend, 'test successful! (not tested actually)' + + +if __name__ == '__main__': + if (os.getcwd() not in sys.path and + os.path.curdir not in sys.path): + sys.path.insert(0, os.getcwd()) + + sys.exit(main(sys.argv[1:])) + From ericvrp at codespeak.net Wed Jun 8 11:17:39 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 11:17:39 +0200 (CEST) Subject: [pypy-svn] r13173 - pypy/dist/pypy/rpython/test Message-ID: <20050608091739.4912027B4A@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 11:17:38 2005 New Revision: 13173 Modified: pypy/dist/pypy/rpython/test/snippet.py Log: fixed test return values Modified: pypy/dist/pypy/rpython/test/snippet.py ============================================================================== --- pypy/dist/pypy/rpython/test/snippet.py (original) +++ pypy/dist/pypy/rpython/test/snippet.py Wed Jun 8 11:17:38 2005 @@ -1,5 +1,13 @@ # generic +def simple1(): + return 1 + + +def simple2(): + return False + + def not1(n): return not n @@ -27,6 +35,7 @@ n += bool(6) n += bool(7.8) n += bool(n) + return n #ints @@ -89,6 +98,7 @@ n += int(8) n += int(5.7) n += int(n) + return n # floats @@ -128,6 +138,7 @@ n += float(6) n += float(7.8) n += float(n) + return n def main(args=[]): @@ -137,9 +148,7 @@ b1 = bool1(b) i1 = int1(i) f1 = float1(f) - #print 'bool1(%d)' % b, b1 - #print 'int1(%d)' % i, i1 - #print 'float1(%s)' % f, f1 + return 0 if __name__ == '__main__': From cfbolz at codespeak.net Wed Jun 8 11:46:32 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 8 Jun 2005 11:46:32 +0200 (CEST) Subject: [pypy-svn] r13174 - in pypy/dist/pypy/translator/llvm: . test Message-ID: <20050608094632.9B13B27B4A@code1.codespeak.net> Author: cfbolz Date: Wed Jun 8 11:46:32 2005 New Revision: 13174 Modified: pypy/dist/pypy/translator/llvm/funcrepr.py pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/llvm/test/test_genllvm.py pypy/dist/pypy/translator/llvm/typerepr.py Log: make some tests actually pass again: function calls with arguments work Modified: pypy/dist/pypy/translator/llvm/funcrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcrepr.py (original) +++ pypy/dist/pypy/translator/llvm/funcrepr.py Wed Jun 8 11:46:32 2005 @@ -130,7 +130,8 @@ if debug: print "init 3)" self.type = self.gen.get_repr(function._TYPE) if debug: print "init 4)" - self.l_args = self.type.l_args + self.l_args = [self.gen.get_repr(ar) + for ar in self.graph.startblock.inputargs] self.dependencies.add(self.type) self.dependencies.update(self.l_args) if debug: print "init 8)" @@ -539,6 +540,7 @@ return fd def llvmfuncdef(self): + print self.l_function.l_args s = "%s %s(" % (self.l_function.type.l_returntype.typename(), self.name) s += ", ".join([a.typed_name() for a in self.l_function.l_args]) + ")" return s Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Wed Jun 8 11:46:32 2005 @@ -151,7 +151,8 @@ try: concretetype = obj.concretetype if isinstance(concretetype, lltype.Primitive): - result = reprmap.PRIMITIVE_REPRS[concretetype](obj, self) + result = reprmap.PRIMITIVE_REPRS[concretetype](obj.value, + self) self.llvm_reprs[key] = result self.depth -= 1 return result Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_genllvm.py Wed Jun 8 11:46:32 2005 @@ -8,7 +8,6 @@ from pypy.objspace.flow.model import Constant, Variable def setup_module(mod): - py.test.skip("nothing works at the moment") mod.llvm_found = is_on_path("llvm-as") def compile_function(function, annotate): Modified: pypy/dist/pypy/translator/llvm/typerepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/typerepr.py (original) +++ pypy/dist/pypy/translator/llvm/typerepr.py Wed Jun 8 11:46:32 2005 @@ -177,12 +177,12 @@ self.gen = gen self.functype = functype self.l_returntype = self.gen.get_repr(functype.RESULT) - self.l_args = [self.gen.get_repr(arg) for arg in functype.ARGS] - self.dependencies = sets.Set(self.l_args + [self.l_returntype]) + self.l_argtypes = [self.gen.get_repr(arg) for arg in functype.ARGS] + self.dependencies = sets.Set(self.l_argtypes + [self.l_returntype]) def typename(self): - args = ", ".join([l_arg.llvmname() for arg in self.l_args]) - return "%s (%s)" % (self.l_returntype.llvmname(), args) + argtypes = ", ".join([l_arg.llvmname() for arg in self.l_argtypes]) + return "%s (%s)" % (self.l_returntype.llvmname(), argtypes) class StringTypeRepr(TypeRepr): From ericvrp at codespeak.net Wed Jun 8 12:33:27 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 12:33:27 +0200 (CEST) Subject: [pypy-svn] r13178 - pypy/dist/pypy/translator/llvm Message-ID: <20050608103327.1328927B4A@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 12:33:26 2005 New Revision: 13178 Modified: pypy/dist/pypy/translator/llvm/compyle.py Log: Simplyfied common-case commandline parameters. Fixed: commandline parameters now used for annotator input and for testing the compilation result. example usages: ./compyle.py test/llvmsnippet.py simple1 ./compyle.py test/llvmsnippet.py "simple5(True)" ./compyle.py test/llvmsnippet.py "simple5(False)" -s -t Modified: pypy/dist/pypy/translator/llvm/compyle.py ============================================================================== --- pypy/dist/pypy/translator/llvm/compyle.py (original) +++ pypy/dist/pypy/translator/llvm/compyle.py Wed Jun 8 12:33:26 2005 @@ -1,6 +1,6 @@ #!/usr/bin/python -"""PyPy compiler to be used as a wrapper around the various backend translators. +"""PyPy compiler to be used as a wrapper around the various backend translators. As a sideeffect the entry function of the compiled code will be run. options: -h(elp) @@ -71,11 +71,9 @@ def main(argv=[]): options = Options(argv) - modname = options.python_script - if '/' in modname: - modname = modname.replace('/', '.') - if modname[-3:] == '.py': - modname = modname[:-3] + modname = options.python_script.replace('/', '.') + if modname[-3:] == '.py': + modname = modname[:-3] exec "import %(modname)s as testmodule" % locals() if '(' in options.entry_function: @@ -147,10 +145,14 @@ assert f print 'Backend', options.backend, 'compilation successful!' + backendReturn = t.call(*arguments) - if f and options.test_compiled: - #assert f(arg) == t.call(arg) # sanity check #XXX make args a commandline argument!!! - print 'Backend', options.backend, 'test successful! (not tested actually)' + if options.test_compiled: + pythonReturn = f(*arguments) + assert backendReturn == pythonReturn + print 'Backend', options.backend, 'compiled code returns same as python script (%s)' % backendReturn + else: + print 'Backend', options.backend, 'compiled code returns (%s)' % backendReturn, '[use -t to perform a sanity check]' if __name__ == '__main__': From cfbolz at codespeak.net Wed Jun 8 14:28:31 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 8 Jun 2005 14:28:31 +0200 (CEST) Subject: [pypy-svn] r13179 - in pypy/dist/pypy/translator/llvm: . test Message-ID: <20050608122831.BEFBF27B4D@code1.codespeak.net> Author: cfbolz Date: Wed Jun 8 14:28:31 2005 New Revision: 13179 Modified: pypy/dist/pypy/translator/llvm/funcrepr.py pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/llvm/pbcrepr.py pypy/dist/pypy/translator/llvm/pointerrepr.py pypy/dist/pypy/translator/llvm/representation.py pypy/dist/pypy/translator/llvm/test/test_genllvm.py pypy/dist/pypy/translator/llvm/typerepr.py Log: more fixes. most functions with arithmetic only work again. enabled respective tests Modified: pypy/dist/pypy/translator/llvm/funcrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcrepr.py (original) +++ pypy/dist/pypy/translator/llvm/funcrepr.py Wed Jun 8 14:28:31 2005 @@ -217,6 +217,9 @@ l_func.dependencies.update(l_args) lblock.call(l_target, l_args[0], l_args[1:]) + op_direct_call = op_simple_call #XXX is simple_call still used? + + class BlockRepr(object): def __init__(self, l_func, pyblock, gen): if debug: @@ -274,6 +277,7 @@ return try: l_arg0.op(op.opname, l_target, op.args, self.lblock, self.l_func) + return except NotImplementedError: pass except CompileError: Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Wed Jun 8 14:28:31 2005 @@ -26,7 +26,7 @@ from pypy.translator.llvm.test import llvmsnippet as test2 from pypy.translator.llvm import representation, funcrepr, typerepr, seqrepr -from pypy.translator.llvm import classrepr, pbcrepr +from pypy.translator.llvm import classrepr, pbcrepr, pointerrepr from pypy.translator.llvm.representation import LLVMRepr, TmpVariableRepr from pypy.translator.llvm.representation import CompileError @@ -74,7 +74,7 @@ self.local_counts = {} self.repr_classes = [] for mod in [representation, funcrepr, typerepr, seqrepr, classrepr, - pbcrepr]: + pbcrepr, pointerrepr]: self.repr_classes += [getattr(mod, s) for s in dir(mod) if "Repr" in s] #if debug: @@ -156,6 +156,8 @@ self.llvm_reprs[key] = result self.depth -= 1 return result + if isinstance(concretetype, lltype.Ptr): + return pointerrepr.PointerRepr(obj.value, self) #XXX find the right type if it is not a Primitive except AttributeError: pass Modified: pypy/dist/pypy/translator/llvm/pbcrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/pbcrepr.py (original) +++ pypy/dist/pypy/translator/llvm/pbcrepr.py Wed Jun 8 14:28:31 2005 @@ -25,6 +25,7 @@ class PBCTypeRepr(TypeRepr): def get(obj, gen): + return None #disabling for now: this class will go away if (isinstance(obj, annmodel.SomePBC) and len(obj.prebuiltinstances) == 1 and #only one pb instance for now not isinstance(obj.prebuiltinstances.keys()[0], Modified: pypy/dist/pypy/translator/llvm/pointerrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/pointerrepr.py (original) +++ pypy/dist/pypy/translator/llvm/pointerrepr.py Wed Jun 8 14:28:31 2005 @@ -8,3 +8,52 @@ from pypy.annotation import model as annmodel +from pypy.translator.llvm import representation +from pypy.translator.llvm import typerepr + +debug = True + +class PointerRepr(representation.LLVMRepr): + def __init__(self, ptr, gen): + if debug: + print "PointerRepr(%s)" % ptr + self.ptr = ptr + self.gen = gen + self.type = gen.get_repr(ptr._TYPE) + self.l_obj = gen.get_repr(ptr._obj) + print self.l_obj, ptr._obj + self.dependencies = sets.Set([self.l_obj, self.type]) + + def llvmname(self): + return self.l_obj.llvmname() + + def __getattr__(self, name): + if debug: + print "getattr called", name, self.l_obj.llvmname() + if name.startswith("op_"): + attr = getattr(self.l_obj, name, None) + if attr is not None: + return attr + raise AttributeError, ("PointerRepr instance has no attribute %s" % + repr(name)) + + +class PointerTypeRepr(typerepr.TypeRepr): + def get(obj, gen): + if obj.__class__ is lltype.Ptr: + return PointerTypeRepr(obj, gen) + return None + get = staticmethod(get) + + def __init__(self, ptrtype, gen): + if debug: + print "PointerTypeRepr(%s)" % ptrtype + self.ptrtype = ptrtype + self.gen = gen + self.l_to = gen.get_repr(ptrtype.TO) + self.dependencies = sets.Set([self.l_to]) + + def typename(self): + return self.l_to.typename() + + \ No newline at end of file Modified: pypy/dist/pypy/translator/llvm/representation.py ============================================================================== --- pypy/dist/pypy/translator/llvm/representation.py (original) +++ pypy/dist/pypy/translator/llvm/representation.py Wed Jun 8 14:28:31 2005 @@ -94,12 +94,17 @@ self.value = value self.gen = gen self.type = self.gen.get_repr(lltype.Signed) + self.dependencies = sets.Set([self.type]) def llvmname(self): return str(self.value) - def get_dependencies(self): - return sets.Set([self.type]) + def __getattr__(self, name): + if name.startswith("op_"): + return getattr(self.type, "t_" + name, None) + else: + raise AttributeError, ("SignedRepr instance has no attribute %s" % + repr(name)) class UnsignedRepr(LLVMRepr): def __init__(self, value, gen): @@ -108,12 +113,17 @@ self.value = value self.gen = gen self.type = self.gen.get_repr(lltype.Unsigned) + self.dependencies = sets.Set([self.type]) def llvmname(self): return str(self.value) - def get_dependencies(self): - return sets.Set([self.type]) + def __getattr__(self, name): + if name.startswith("op_"): + return getattr(self.type, "t_" + name, None) + else: + raise AttributeError, ("UnsignedRepr instance has no attribute %s" + % repr(name)) class BoolRepr(LLVMRepr): def __init__(self, value, gen): @@ -122,12 +132,17 @@ self.value = bool(value) self.gen = gen self.type = self.gen.get_repr(lltype.Bool) + self.dependencies = sets.Set([self.type]) def llvmname(self): return str(self.value).lower() - - def get_dependencies(self): - return sets.Set([self.type]) + + def __getattr__(self, name): + if name.startswith("op_"): + return getattr(self.type, "t_" + name, None) + else: + raise AttributeError, ("BoolRepr instance has no attribute %s" + % repr(name)) class FloatRepr(LLVMRepr): def __init__(self, value, gen): @@ -136,12 +151,17 @@ self.value = float(value) self.gen = gen self.type = self.gen.get_repr(lltype.Float) + self.dependencies = sets.Set([self.type]) def llvmname(self): return str(self.value).lower() - - def get_dependencies(self): - return sets.Set([self.type]) + + def __getattr__(self, name): + if name.startswith("op_"): + return getattr(self.type, "t_" + name, None) + else: + raise AttributeError, ("FloatRepr instance has no attribute %s" + % repr(name)) class CharRepr(LLVMRepr): def __init__(self, value, gen): @@ -151,6 +171,7 @@ self.value = value self.gen = gen self.type = self.gen.get_repr(lltype.Char) + self.dependencies = sets.Set([self.type]) def llvmname(self): value = value @@ -158,9 +179,13 @@ return "'%s'" % (value.replace("'", r"\'"),) else: return '%d' % ord(value) - - def get_dependencies(self): - return sets.Set([self.type]) + + def __getattr__(self, name): + if name.startswith("op_"): + return getattr(self.type, "t_" + name, None) + else: + raise AttributeError, ("CharRepr instance has no attribute %s" + % repr(name)) class SimpleRepr(LLVMRepr): @@ -256,14 +281,15 @@ except AttributeError: type_ = gen.annotator.binding(var.c) self.type = gen.get_repr(type_) - print "XXXXXXXXXXXXXXXX", self.type + if debug: + print "XXXXXXXXXXXXXXXX", self.type self.dependencies = sets.Set([self.type]) def llvmname(self): return "%" + self.var.name def __getattr__(self, name): - print "$%%%%%%%%%%%%%%%%%getattr called", name, self.type.typename() + print "getattr called", name, self.type.typename() if name.startswith("op_"): return getattr(self.type, "t_" + name, None) elif name.startswith("cast_"): Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_genllvm.py Wed Jun 8 14:28:31 2005 @@ -62,7 +62,7 @@ f = compile_function(llvmsnippet.simple2, []) assert f() == 0 - def DONOTtest_simple4(self): + def test_simple4(self): f = compile_function(llvmsnippet.simple4, []) assert f() == 4 @@ -71,7 +71,7 @@ assert f(1) == 12 assert f(0) == 13 - def DONOTtest_ackermann(self): + def test_ackermann(self): f = compile_function(llvmsnippet.ackermann, [int, int]) for i in range(10): assert f(0, i) == i + 1 @@ -79,7 +79,7 @@ assert f(2, i) == 2 * i + 3 assert f(3, i) == 2 ** (i + 3) - 3 - def DONOTtest_calling(self): + def test_calling(self): f = compile_function(llvmsnippet.calling1, [int]) assert f(10) == 1 @@ -99,7 +99,6 @@ class TestFloat(object): def setup_method(self, method): - py.test.skip("nothing works for now") if not llvm_found: py.test.skip("llvm-as not found on path.") Modified: pypy/dist/pypy/translator/llvm/typerepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/typerepr.py (original) +++ pypy/dist/pypy/translator/llvm/typerepr.py Wed Jun 8 14:28:31 2005 @@ -142,6 +142,21 @@ return 1 class FloatTypeRepr(TypeRepr): + directly_supported_ops = { + "float_add": "add", + "float_sub": "sub", + "float_mul": "mul", + "float_div": "div", + "float_mod": "rem", + "float_xor": "xor", + "float_and_": "and", + "float_eq": "seteq", + "float_ne": "setne", + "float_gt": "setgt", + "float_ge": "setge", + "float_lt": "setlt", + "float_le": "setle"} + def __init__(self, gen): if debug: print "FloatTypeRepr" @@ -150,6 +165,15 @@ def typename(self): return "double" + def t_op(self, opname, l_target, args, lblock, l_func): + if opname in FloatTypeRepr.directly_supported_ops: + assert len(args) == 2 + l_args = [self.gen.get_repr(arg) for arg in args] + l_func.dependencies.update(l_args) + lblock.binary_instruction( + FloatTypeRepr.directly_supported_ops[opname], l_target, + l_args[0], l_args[1]) + def llvmsize(self): return 8 From ericvrp at codespeak.net Wed Jun 8 15:36:38 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 15:36:38 +0200 (CEST) Subject: [pypy-svn] r13180 - pypy/dist/pypy/translator/llvm Message-ID: <20050608133638.CDA2E27B4E@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 15:36:38 2005 New Revision: 13180 Modified: pypy/dist/pypy/translator/llvm/compyle.py Log: commit before move Modified: pypy/dist/pypy/translator/llvm/compyle.py ============================================================================== --- pypy/dist/pypy/translator/llvm/compyle.py (original) +++ pypy/dist/pypy/translator/llvm/compyle.py Wed Jun 8 15:36:38 2005 @@ -74,7 +74,16 @@ modname = options.python_script.replace('/', '.') if modname[-3:] == '.py': modname = modname[:-3] - exec "import %(modname)s as testmodule" % locals() + + if modname[0] == '.': #absolute path + #print imp.find_module(options.python_script) + sys.path.append('/') #XXX may not work on all platforms + #print sys.path + absmodname = modname[1:] + exec "import %(absmodname)s as testmodule" % locals() + ##print 'pop',sys.path.pop() + else: #relative path + exec "import %(modname)s as testmodule" % locals() if '(' in options.entry_function: entry_function, arguments = options.entry_function.split('(',1) From ericvrp at codespeak.net Wed Jun 8 15:37:18 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 15:37:18 +0200 (CEST) Subject: [pypy-svn] r13181 - pypy/dist/pypy/bin Message-ID: <20050608133718.E349527B53@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 15:37:18 2005 New Revision: 13181 Added: pypy/dist/pypy/bin/compyle.py - copied unchanged from r13180, pypy/dist/pypy/translator/llvm/compyle.py Log: compyle.py now lives here From ericvrp at codespeak.net Wed Jun 8 16:39:06 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 16:39:06 +0200 (CEST) Subject: [pypy-svn] r13184 - pypy/dist/pypy/bin Message-ID: <20050608143906.1E2BD27B4E@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 16:39:05 2005 New Revision: 13184 Removed: pypy/dist/pypy/bin/compyle.py Modified: pypy/dist/pypy/bin/translator.py Log: Moved functionality of compyle to translator. Fixed absolute pathnames. Deleted: /pypy/dist/pypy/bin/compyle.py ============================================================================== --- /pypy/dist/pypy/bin/compyle.py Wed Jun 8 16:39:05 2005 +++ (empty file) @@ -1,173 +0,0 @@ -#!/usr/bin/python - -"""PyPy compiler to be used as a wrapper around the various backend translators. As a sideeffect the entry function of the compiled code will be run. - -options: - -h(elp) - -v(iew flow graph) - -b (set backend) [default=llvm] - -s(show source) - -C(ompilation disable) - -t(est compiled) - [python script] -""" - -import autopath, os, sys -from pypy.translator.translator import Translator -from pypy.rpython.rtyper import * -from pypy.rpython.rarithmetic import * - - -class Options(object): - available_backends = {'org':'Original source', 'c':'C translation', 'cl':'common lisp translation', 'llvm':'LLVM translation(default)', 'pyrex':'pyrex translation'} - backend = 'llvm' - python_script = '' - entry_function = 'main()' - view_flow_graph = False - show_source = False - compile = True - test_compiled = False - - def __init__(self,argv=[]): - if not argv: - print __doc__ - sys.exit(0) - - for arg in argv: - if arg[0] == '-': - option = arg[:2] - - if option == '-b': - new_backend = arg[2:] - if new_backend in self.available_backends: - self.backend = new_backend - else: - print 'error: unknown backend', new_backend, '. Avaialable backends are:', self.available_backends - sys.exit(0) - - elif option == '-v': - self.view_flow_graph = True - - elif option == '-s': - self.show_source = True - - elif option == '-C': - self.compile = False - - elif option == '-t': - self.test_compiled = True - - else: - print __doc__ - sys.exit(0) - - else: - if not self.python_script: - self.python_script = arg - else: - self.entry_function = arg - - -def main(argv=[]): - options = Options(argv) - - modname = options.python_script.replace('/', '.') - if modname[-3:] == '.py': - modname = modname[:-3] - - if modname[0] == '.': #absolute path - #print imp.find_module(options.python_script) - sys.path.append('/') #XXX may not work on all platforms - #print sys.path - absmodname = modname[1:] - exec "import %(absmodname)s as testmodule" % locals() - ##print 'pop',sys.path.pop() - else: #relative path - exec "import %(modname)s as testmodule" % locals() - - if '(' in options.entry_function: - entry_function, arguments = options.entry_function.split('(',1) - else: - entry_function, arguments = options.entry_function, ')' - - #print 'entry_functionText=',entry_function - entry_function = getattr(testmodule, entry_function) - #print 'entry_function=',entry_function - - if arguments != ')' and arguments.find(',') == -1: - arguments = arguments[:-1] + ',)' - arguments = [argument for argument in eval('('+arguments)] - #print 'arguments=',arguments - - argumentTypes = [type(arg) for arg in arguments] - #print 'argumentTypes=',argumentTypes - - t = Translator(entry_function) - t.simplify() - a = t.annotate(argumentTypes) - a.simplify() - - if options.view_flow_graph: - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() - t.view() - t = Translator(entry_function) - t.simplify() - a = t.annotate(argumentTypes) - a.simplify() - - if options.show_source: - if options.backend == 'org': - print t.source() - - elif options.backend == 'c': - print t.c() - #note: this is a workaround until GenC can generate identical code multiple times - t = Translator(entry_function) - t.simplify() - a = t.annotate([type(arg), type(arg) == type(int)]) # pass the list of args types - a.simplify() - - elif options.backend == 'cl': - print t.cl() - - elif options.backend == 'llvm': - print t.llvm() - - elif options.backend == 'pyrex': - print t.pyrex() - - if options.compile: - if options.backend == 'c': - a.specialize() # use low level operations (for C only) - f = t.ccompile() - - elif options.backend == 'llvm': - f = t.llvmcompile() - - elif options.backend == 'pyrex': - f = t.pyrexcompile() - - else: - print 'warning: backend', options.backend, 'has no compile phase' - sys.exit(0) - - assert f - print 'Backend', options.backend, 'compilation successful!' - backendReturn = t.call(*arguments) - - if options.test_compiled: - pythonReturn = f(*arguments) - assert backendReturn == pythonReturn - print 'Backend', options.backend, 'compiled code returns same as python script (%s)' % backendReturn - else: - print 'Backend', options.backend, 'compiled code returns (%s)' % backendReturn, '[use -t to perform a sanity check]' - - -if __name__ == '__main__': - if (os.getcwd() not in sys.path and - os.path.curdir not in sys.path): - sys.path.insert(0, os.getcwd()) - - sys.exit(main(sys.argv[1:])) - Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Wed Jun 8 16:39:05 2005 @@ -1,5 +1,6 @@ #!/usr/bin/env python + """PyPy Translator Frontend Glue script putting together the various pieces of the translator. @@ -30,10 +31,178 @@ Some functions are provided for the benefit of interactive testing. Try dir(test) for list of current snippets. + +For extra features start this script with a -h option. """ + +extra_help = """Extra options enable features for testing the various backend +translators. As a sideeffect the entry function of the compiled +code will be run. + +options: + -h(elp) + -v(iew flow graph) + -b (set backend) [default=c] + -s(show source) + -C(ompilation disable) + -t(est compiled) + [python script] +""" + + import autopath, os, sys from pypy.translator.translator import Translator +from pypy.rpython.rtyper import * +from pypy.rpython.rarithmetic import * + +import py + +class Options(object): + available_backends = {'org':'Original source', 'c':'C translation (default)', 'cl':'common lisp translation', 'llvm':'LLVM translation', 'pyrex':'pyrex translation'} + backend = 'c' #ugly !?! + python_script = '' + entry_function = 'main()' + view_flow_graph = False + show_source = False + compile = True + test_compiled = False + + def __init__(self,argv=[]): + if not argv: + print extra_help + sys.exit(0) + + for arg in argv: + if arg[0] == '-': + option = arg[:2] + + if option == '-b': + new_backend = arg[2:] + if new_backend in self.available_backends: + self.backend = new_backend + else: + print 'error: unknown backend', new_backend, '. Avaialable backends are:', self.available_backends + sys.exit(0) + + elif option == '-v': + self.view_flow_graph = True + + elif option == '-s': + self.show_source = True + + elif option == '-C': + self.compile = False + + elif option == '-t': + self.test_compiled = True + + else: + print __doc__ + sys.exit(0) + + else: + if not self.python_script: + self.python_script = arg + else: + self.entry_function = arg + + +def main(argv=[]): + options = Options(argv) + + modname = options.python_script.replace('/', '.') + if modname[-3:] == '.py': + modname = modname[:-3] + + if modname[0] == '.': #absolute path #ah + path = py.path.local(options.python_script) + print path, path.get("basename"), path.get("dirname") + sys.path.append(path.get("dirname")[0]) + absmodname = path.get("purebasename")[0] + exec "import %(absmodname)s as testmodule" % locals() + sys.path.pop() + else: #relative path + exec "import %(modname)s as testmodule" % locals() + + if '(' in options.entry_function: + entry_function, arguments = options.entry_function.split('(',1) + else: + entry_function, arguments = options.entry_function, ')' + + #print 'entry_functionText=',entry_function + entry_function = getattr(testmodule, entry_function) + #print 'entry_function=',entry_function + + if arguments != ')' and arguments.find(',') == -1: + arguments = arguments[:-1] + ',)' + arguments = [argument for argument in eval('('+arguments)] + #print 'arguments=',arguments + + argumentTypes = [type(arg) for arg in arguments] + #print 'argumentTypes=',argumentTypes + + t = Translator(entry_function) + t.simplify() + a = t.annotate(argumentTypes) + a.simplify() + + if options.view_flow_graph: + rtyper = RPythonTyper(t.annotator) + rtyper.specialize() + t.view() + t = Translator(entry_function) + t.simplify() + a = t.annotate(argumentTypes) + a.simplify() + + if options.show_source: + if options.backend == 'org': + print t.source() + + elif options.backend == 'c': + print t.c() + #note: this is a workaround until GenC can generate identical code multiple times + t = Translator(entry_function) + t.simplify() + a = t.annotate(argumentTypes) + a.simplify() + + elif options.backend == 'cl': + print t.cl() + + elif options.backend == 'llvm': + print t.llvm() + + elif options.backend == 'pyrex': + print t.pyrex() + + if options.compile: + if options.backend == 'c': + a.specialize() # use low level operations (for C only) + f = t.ccompile() + + elif options.backend == 'llvm': + f = t.llvmcompile() + + elif options.backend == 'pyrex': + f = t.pyrexcompile() + + else: + print 'warning: backend', options.backend, 'has no compile phase' + sys.exit(0) + + assert f + print 'Backend', options.backend, 'compilation successful!' + backendReturn = t.call(*arguments) + + if options.test_compiled: + pythonReturn = f(*arguments) + assert backendReturn == pythonReturn + print 'Backend', options.backend, 'compiled code returns same as python script (%s)' % backendReturn + else: + print 'Backend', options.backend, 'compiled code returns (%s)' % backendReturn, '[use -t to perform a sanity check]' + if __name__ == '__main__': @@ -41,8 +210,14 @@ if (os.getcwd() not in sys.path and os.path.curdir not in sys.path): sys.path.insert(0, os.getcwd()) + + if len(sys.argv) > 1: + sys.exit(main(sys.argv[1:])) + print __doc__ # 2.3 specific -- sanxiyn import os os.putenv("PYTHONINSPECT", "1") + + From ericvrp at codespeak.net Wed Jun 8 16:46:24 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 8 Jun 2005 16:46:24 +0200 (CEST) Subject: [pypy-svn] r13185 - pypy/dist/pypy/translator/llvm Message-ID: <20050608144624.54E3827B56@code1.codespeak.net> Author: ericvrp Date: Wed Jun 8 16:46:23 2005 New Revision: 13185 Removed: pypy/dist/pypy/translator/llvm/compyle.py Log: integrated in pypy/bin/translate.py Deleted: /pypy/dist/pypy/translator/llvm/compyle.py ============================================================================== --- /pypy/dist/pypy/translator/llvm/compyle.py Wed Jun 8 16:46:23 2005 +++ (empty file) @@ -1,173 +0,0 @@ -#!/usr/bin/python - -"""PyPy compiler to be used as a wrapper around the various backend translators. As a sideeffect the entry function of the compiled code will be run. - -options: - -h(elp) - -v(iew flow graph) - -b (set backend) [default=llvm] - -s(show source) - -C(ompilation disable) - -t(est compiled) - [python script] -""" - -import autopath, os, sys -from pypy.translator.translator import Translator -from pypy.rpython.rtyper import * -from pypy.rpython.rarithmetic import * - - -class Options(object): - available_backends = {'org':'Original source', 'c':'C translation', 'cl':'common lisp translation', 'llvm':'LLVM translation(default)', 'pyrex':'pyrex translation'} - backend = 'llvm' - python_script = '' - entry_function = 'main()' - view_flow_graph = False - show_source = False - compile = True - test_compiled = False - - def __init__(self,argv=[]): - if not argv: - print __doc__ - sys.exit(0) - - for arg in argv: - if arg[0] == '-': - option = arg[:2] - - if option == '-b': - new_backend = arg[2:] - if new_backend in self.available_backends: - self.backend = new_backend - else: - print 'error: unknown backend', new_backend, '. Avaialable backends are:', self.available_backends - sys.exit(0) - - elif option == '-v': - self.view_flow_graph = True - - elif option == '-s': - self.show_source = True - - elif option == '-C': - self.compile = False - - elif option == '-t': - self.test_compiled = True - - else: - print __doc__ - sys.exit(0) - - else: - if not self.python_script: - self.python_script = arg - else: - self.entry_function = arg - - -def main(argv=[]): - options = Options(argv) - - modname = options.python_script.replace('/', '.') - if modname[-3:] == '.py': - modname = modname[:-3] - - if modname[0] == '.': #absolute path - #print imp.find_module(options.python_script) - sys.path.append('/') #XXX may not work on all platforms - #print sys.path - absmodname = modname[1:] - exec "import %(absmodname)s as testmodule" % locals() - ##print 'pop',sys.path.pop() - else: #relative path - exec "import %(modname)s as testmodule" % locals() - - if '(' in options.entry_function: - entry_function, arguments = options.entry_function.split('(',1) - else: - entry_function, arguments = options.entry_function, ')' - - #print 'entry_functionText=',entry_function - entry_function = getattr(testmodule, entry_function) - #print 'entry_function=',entry_function - - if arguments != ')' and arguments.find(',') == -1: - arguments = arguments[:-1] + ',)' - arguments = [argument for argument in eval('('+arguments)] - #print 'arguments=',arguments - - argumentTypes = [type(arg) for arg in arguments] - #print 'argumentTypes=',argumentTypes - - t = Translator(entry_function) - t.simplify() - a = t.annotate(argumentTypes) - a.simplify() - - if options.view_flow_graph: - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() - t.view() - t = Translator(entry_function) - t.simplify() - a = t.annotate(argumentTypes) - a.simplify() - - if options.show_source: - if options.backend == 'org': - print t.source() - - elif options.backend == 'c': - print t.c() - #note: this is a workaround until GenC can generate identical code multiple times - t = Translator(entry_function) - t.simplify() - a = t.annotate([type(arg), type(arg) == type(int)]) # pass the list of args types - a.simplify() - - elif options.backend == 'cl': - print t.cl() - - elif options.backend == 'llvm': - print t.llvm() - - elif options.backend == 'pyrex': - print t.pyrex() - - if options.compile: - if options.backend == 'c': - a.specialize() # use low level operations (for C only) - f = t.ccompile() - - elif options.backend == 'llvm': - f = t.llvmcompile() - - elif options.backend == 'pyrex': - f = t.pyrexcompile() - - else: - print 'warning: backend', options.backend, 'has no compile phase' - sys.exit(0) - - assert f - print 'Backend', options.backend, 'compilation successful!' - backendReturn = t.call(*arguments) - - if options.test_compiled: - pythonReturn = f(*arguments) - assert backendReturn == pythonReturn - print 'Backend', options.backend, 'compiled code returns same as python script (%s)' % backendReturn - else: - print 'Backend', options.backend, 'compiled code returns (%s)' % backendReturn, '[use -t to perform a sanity check]' - - -if __name__ == '__main__': - if (os.getcwd() not in sys.path and - os.path.curdir not in sys.path): - sys.path.insert(0, os.getcwd()) - - sys.exit(main(sys.argv[1:])) - From ac at codespeak.net Wed Jun 8 18:21:37 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 8 Jun 2005 18:21:37 +0200 (CEST) Subject: [pypy-svn] r13187 - in pypy/dist/pypy: documentation interpreter module/__builtin__ module/unicodedata objspace/std Message-ID: <20050608162137.F355E27B4B@code1.codespeak.net> Author: ac Date: Wed Jun 8 18:21:37 2005 New Revision: 13187 Modified: pypy/dist/pypy/documentation/objspace.txt pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/module/__builtin__/operation.py pypy/dist/pypy/module/unicodedata/function.py pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py pypy/dist/pypy/objspace/std/objspace.py Log: Add normalization of unicode strings. Modified: pypy/dist/pypy/documentation/objspace.txt ============================================================================== --- pypy/dist/pypy/documentation/objspace.txt (original) +++ pypy/dist/pypy/documentation/objspace.txt Wed Jun 8 18:21:37 2005 @@ -94,7 +94,7 @@ Creates a string from a list of wrapped integers. **newunicode(codelist):** - Creates a unicode string from a list of wrapped integers. + Creates a unicode string from a list of integers. Conversions from Application Level to Interpreter Level ---------------------------------------------------------- Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Wed Jun 8 18:21:37 2005 @@ -534,7 +534,7 @@ # newtuple([w_1, w_2,...]) -> w_tuple # newlist([w_1, w_2,...]) -> w_list # newstring([w_1, w_2,...]) -> w_string from ascii numbers (bytes) -# newunicode([w_1, w_2,...]) -> w_unicode from numbers +# newunicode([i1, i2,...]) -> w_unicode from integers # newdict([(w_key,w_value),...]) -> w_dict # newslice(w_start,w_stop,w_step) -> w_slice # call_args(w_obj,Arguments()) -> w_result Modified: pypy/dist/pypy/module/__builtin__/operation.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/operation.py (original) +++ pypy/dist/pypy/module/__builtin__/operation.py Wed Jun 8 18:21:37 2005 @@ -16,7 +16,7 @@ return w_character def unichr(space, w_code): - return space.newunicode([w_code]) + return space.newunicode([space.int_w(w_code)]) def len(space, w_obj): "len(object) -> integer\n\nReturn the number of items of a sequence or mapping." Modified: pypy/dist/pypy/module/unicodedata/function.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/function.py (original) +++ pypy/dist/pypy/module/unicodedata/function.py Wed Jun 8 18:21:37 2005 @@ -82,24 +82,124 @@ def decomposition(space, w_unichr): code = unichr_to_code_w(space, w_unichr) - raise OperationError(space.w_NotImplementedError, - space.wrap('Decomposition is not implemented')) + return space.wrap(unicodedb.decomposition(code)) + + +# Contants for Hangul characters +SBase = 0xAC00 +LBase = 0x1100 +VBase = 0x1161 +TBase = 0x11A7 +LCount = 19 +VCount = 21 +TCount = 28 +NCount = (VCount*TCount) +SCount = (LCount*NCount) def normalize(space, w_form, w_unistr): form = space.str_w(w_form) if not space.is_true(space.isinstance(w_unistr, space.w_unicode)): raise TypeError, 'argument 2 must be unicode' if form == 'NFC': - raise OperationError(space.w_NotImplementedError, - space.wrap('Normalization is not implemented')) - if form == 'NFD': - raise OperationError(space.w_NotImplementedError, - space.wrap('Normalization is not implemented')) - if form == 'NFKC': - raise OperationError(space.w_NotImplementedError, - space.wrap('Normalization is not implemented')) - if form == 'NFKD': - raise OperationError(space.w_NotImplementedError, - space.wrap('Normalization is not implemented')) - raise OperationError(space.w_ValueError, - space.wrap('invalid normalization form')) + composed = True + decomposition = unicodedb._canon_decomposition + elif form == 'NFD': + composed = False + decomposition = unicodedb._canon_decomposition + elif form == 'NFKC': + composed = True + decomposition = unicodedb._compat_decomposition + elif form == 'NFKD': + composed = False + decomposition = unicodedb._compat_decomposition + else: + raise OperationError(space.w_ValueError, + space.wrap('invalid normalization form')) + + strlen = space.int_w(space.len(w_unistr)) + result = [] + # Expand the character + for i in range(strlen): + ch = space.int_w(space.ord(space.getitem(w_unistr, space.wrap(i)))) + # Do Hangul decomposition + if SBase <= ch < SBase + SCount: + SIndex = ch - SBase; + L = LBase + SIndex / NCount; + V = VBase + (SIndex % NCount) / TCount; + T = TBase + SIndex % TCount; + if T == TBase: + result.extend([L, V]) + else: + result.extend([L, V, T]) + continue + + result.extend(decomposition.get(ch, [ch])) + + # Sort all combining marks + for i in range(len(result)): + ch = result[i] + comb = unicodedb.combining(ch) + if comb == 0: + continue + for j in range(i, 0, -1): + if unicodedb.combining(result[j - 1]) <= comb: + result[j] = ch + break + + result[j] = result[j - 1] + else: + result[0] = ch + + if not composed: # If decomposed normalization we are done + return space.newunicode(result) + + if len(result) <= 1: + return space.newunicode(result) + + current = result[0] + starter_pos = 0 + next_insert = 1 + prev_combining = 0 + if unicodedb.combining(current): + prev_combining = 256 + for j in range(1, len(result)): + next = result[j] + next_combining = unicodedb.combining(next) + if next_insert == starter_pos + 1 or prev_combining < next_combining: + # Combine if not blocked + if (LBase <= current < LBase + LCount and + VBase <= next < VBase + VCount): + # If L, V -> LV + current = SBase + ((current - LBase)*VCount + (next - VBase)) * TCount + continue + if (SBase <= current < SBase + SCount and + TBase <= next < TBase + TCount and + (current - SBase) % TCount == 0): + # If LV, T -> LVT + current = current + (next - TBase) + continue + try: + current = unicodedb._composition[(current, next)] + continue + except KeyError: + pass + + if next_combining == 0: + # New starter symbol + result[starter_pos] = current + starter_pos = next_insert + next_insert += 1 + prev_combining = 0 + current = next + continue + + + result[next_insert] = next + next_insert += 1 + if next_combining > prev_combining: + prev_combining = next_combining + + result[starter_pos] = current + + return space.newunicode(result[:next_insert]) + Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/generate_unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/generate_unicodedb.py Wed Jun 8 18:21:37 2005 @@ -12,9 +12,21 @@ if data[3]: self.combining = int(data[3]) self.bidirectional = data[4] - self.decomposition = None + self.raw_decomposition = '' + self.decomposition = [] + self.isCompatibility = False + self.canonical_decomp = None + self.compat_decomp = None + self.excluded = False + self.decompositionTag = '' if data[5]: - self.decomposition = data[5] + self.raw_decomposition = data[5] + if data[5][0] == '<': + self.isCompatibility = True + self.decompositionTag, decomp = data[5].split(None, 1) + else: + decomp = data[5] + self.decomposition = map(lambda x:int(x, 16), decomp.split()) self.decimal = None if data[6]: self.decimal = int(data[6]) @@ -38,12 +50,33 @@ self.title = None if data[14]: self.title = int(data[14], 16) + -def read_unicodedata(infile): +def get_compat_decomposition(table, code): + if not table[code].decomposition: + return [code] + if not table[code].compat_decomp: + result = [] + for decomp in table[code].decomposition: + result.extend(get_compat_decomposition(table, decomp)) + table[code].compat_decomp = result + return table[code].compat_decomp + +def get_canonical_decomposition(table, code): + if not table[code].decomposition or table[code].isCompatibility: + return [code] + if not table[code].canonical_decomp: + result = [] + for decomp in table[code].decomposition: + result.extend(get_canonical_decomposition(table, decomp)) + table[code].canonical_decomp = result + return table[code].canonical_decomp + +def read_unicodedata(unicodedata_file, exclusions_file): rangeFirst = {} rangeLast = {} table = [Unicodechar(['0000', None, 'Cn'] + [''] * 12)] * (sys.maxunicode + 1) - for line in infile: + for line in unicodedata_file: line = line.split('#', 1)[0].strip() if not line: continue @@ -67,6 +100,17 @@ unichar = Unicodechar(['0000', None] + data[2:]) for code in range(start, end + 1): table[code] = unichar + # Read exclusions + for line in exclusions_file: + line = line.split('#', 1)[0].strip() + if not line: + continue + table[int(line, 16)].excluded = True + + # Compute full decompositions. + for code in range(len(table)): + get_canonical_decomposition(table, code) + get_compat_decomposition(table, code) return table @@ -138,6 +182,10 @@ print >> outfile, 'version = %r' % version print >> outfile + cjk_end = 0x9FA5 + if version >= "4.1": + cjk_end = 0x9FBB + # Character names print >> outfile, '_charnames = {' for code in range(len(table)): @@ -200,7 +248,7 @@ raise KeyError code = int(cjk_code, 16) if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x9FA5 or # 9FBB in Unicode 4.1 + 0x4E00 <= code <= 0x%X or 0x9FA5 or # 9FBB in Unicode 4.1 0x20000 <= code <= 0x2A6D6): return code raise KeyError @@ -232,7 +280,7 @@ _hangul_V[v_code] + _hangul_T[t_code]) return _charnames[code] -''' +''' % cjk_end # Categories categories = {} @@ -346,19 +394,43 @@ return _tolower.get(code, code) def totitle(code): return _totitle.get(code, code) - ''' # Decomposition decomposition = {} for code in range(len(table)): - if table[code].decomposition: - decomposition[code] = table[code].decomposition - writeDict(outfile, '_decomposition', decomposition) + if table[code].raw_decomposition: + decomposition[code] = table[code].raw_decomposition + writeDict(outfile, '_raw_decomposition', decomposition) print >> outfile, ''' -def decompisition(code): - return _decomposition.get(code,'') +def decomposition(code): + return _raw_decomposition.get(code,'') ''' + # Collect the composition pairs. + compositions = {} + for code in range(len(table)): + unichar = table[code] + if (not unichar.decomposition or + unichar.isCompatibility or + unichar.excluded or + len(unichar.decomposition) != 2 or + table[unichar.decomposition[0]].combining): + continue + compositions[tuple(unichar.decomposition)] = code + writeDict(outfile, '_composition', compositions) + + decomposition = {} + for code in range(len(table)): + if table[code].canonical_decomp: + decomposition[code] = table[code].canonical_decomp + writeDict(outfile, '_canon_decomposition', decomposition) + + decomposition = {} + for code in range(len(table)): + if table[code].compat_decomp: + decomposition[code] = table[code].compat_decomp + writeDict(outfile, '_compat_decomposition', decomposition) + if __name__ == '__main__': import getopt, re @@ -378,6 +450,7 @@ infilename = args[0] infile = open(infilename, 'r') + exclusions = open(args[1]) if unidata_version is None: m = re.search(r'-([0-9]+\.)+', infilename) if m: @@ -386,7 +459,7 @@ if unidata_version is None: raise ValueError('No version specified') - table = read_unicodedata(infile) + table = read_unicodedata(infile, exclusions) print >> outfile, '# UNICODE CHARACTER DATABASE' print >> outfile, '# This file was generated with the command:' print >> outfile, '# ', ' '.join(sys.argv) Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Wed Jun 8 18:21:37 2005 @@ -19103,8 +19103,7 @@ def totitle(code): return _totitle.get(code, code) - -_decomposition = { +_raw_decomposition = { 160: ' 0020', 168: ' 0020 0308', 170: ' 0061', @@ -24251,7 +24250,8002 @@ } -def decompisition(code): - return _decomposition.get(code,'') +def decomposition(code): + return _raw_decomposition.get(code,'') + + +_composition = { +(60, 824): 8814, +(61, 824): 8800, +(62, 824): 8815, +(65, 768): 192, +(65, 769): 193, +(65, 770): 194, +(65, 771): 195, +(65, 772): 256, +(65, 774): 258, +(65, 775): 550, +(65, 776): 196, +(65, 777): 7842, +(65, 778): 197, +(65, 780): 461, +(65, 783): 512, +(65, 785): 514, +(65, 803): 7840, +(65, 805): 7680, +(65, 808): 260, +(66, 775): 7682, +(66, 803): 7684, +(66, 817): 7686, +(67, 769): 262, +(67, 770): 264, +(67, 775): 266, +(67, 780): 268, +(67, 807): 199, +(68, 775): 7690, +(68, 780): 270, +(68, 803): 7692, +(68, 807): 7696, +(68, 813): 7698, +(68, 817): 7694, +(69, 768): 200, +(69, 769): 201, +(69, 770): 202, +(69, 771): 7868, +(69, 772): 274, +(69, 774): 276, +(69, 775): 278, +(69, 776): 203, +(69, 777): 7866, +(69, 780): 282, +(69, 783): 516, +(69, 785): 518, +(69, 803): 7864, +(69, 807): 552, +(69, 808): 280, +(69, 813): 7704, +(69, 816): 7706, +(70, 775): 7710, +(71, 769): 500, +(71, 770): 284, +(71, 772): 7712, +(71, 774): 286, +(71, 775): 288, +(71, 780): 486, +(71, 807): 290, +(72, 770): 292, +(72, 775): 7714, +(72, 776): 7718, +(72, 780): 542, +(72, 803): 7716, +(72, 807): 7720, +(72, 814): 7722, +(73, 768): 204, +(73, 769): 205, +(73, 770): 206, +(73, 771): 296, +(73, 772): 298, +(73, 774): 300, +(73, 775): 304, +(73, 776): 207, +(73, 777): 7880, +(73, 780): 463, +(73, 783): 520, +(73, 785): 522, +(73, 803): 7882, +(73, 808): 302, +(73, 816): 7724, +(74, 770): 308, +(75, 769): 7728, +(75, 780): 488, +(75, 803): 7730, +(75, 807): 310, +(75, 817): 7732, +(76, 769): 313, +(76, 780): 317, +(76, 803): 7734, +(76, 807): 315, +(76, 813): 7740, +(76, 817): 7738, +(77, 769): 7742, +(77, 775): 7744, +(77, 803): 7746, +(78, 768): 504, +(78, 769): 323, +(78, 771): 209, +(78, 775): 7748, +(78, 780): 327, +(78, 803): 7750, +(78, 807): 325, +(78, 813): 7754, +(78, 817): 7752, +(79, 768): 210, +(79, 769): 211, +(79, 770): 212, +(79, 771): 213, +(79, 772): 332, +(79, 774): 334, +(79, 775): 558, +(79, 776): 214, +(79, 777): 7886, +(79, 779): 336, +(79, 780): 465, +(79, 783): 524, +(79, 785): 526, +(79, 795): 416, +(79, 803): 7884, +(79, 808): 490, +(80, 769): 7764, +(80, 775): 7766, +(82, 769): 340, +(82, 775): 7768, +(82, 780): 344, +(82, 783): 528, +(82, 785): 530, +(82, 803): 7770, +(82, 807): 342, +(82, 817): 7774, +(83, 769): 346, +(83, 770): 348, +(83, 775): 7776, +(83, 780): 352, +(83, 803): 7778, +(83, 806): 536, +(83, 807): 350, +(84, 775): 7786, +(84, 780): 356, +(84, 803): 7788, +(84, 806): 538, +(84, 807): 354, +(84, 813): 7792, +(84, 817): 7790, +(85, 768): 217, +(85, 769): 218, +(85, 770): 219, +(85, 771): 360, +(85, 772): 362, +(85, 774): 364, +(85, 776): 220, +(85, 777): 7910, +(85, 778): 366, +(85, 779): 368, +(85, 780): 467, +(85, 783): 532, +(85, 785): 534, +(85, 795): 431, +(85, 803): 7908, +(85, 804): 7794, +(85, 808): 370, +(85, 813): 7798, +(85, 816): 7796, +(86, 771): 7804, +(86, 803): 7806, +(87, 768): 7808, +(87, 769): 7810, +(87, 770): 372, +(87, 775): 7814, +(87, 776): 7812, +(87, 803): 7816, +(88, 775): 7818, +(88, 776): 7820, +(89, 768): 7922, +(89, 769): 221, +(89, 770): 374, +(89, 771): 7928, +(89, 772): 562, +(89, 775): 7822, +(89, 776): 376, +(89, 777): 7926, +(89, 803): 7924, +(90, 769): 377, +(90, 770): 7824, +(90, 775): 379, +(90, 780): 381, +(90, 803): 7826, +(90, 817): 7828, +(97, 768): 224, +(97, 769): 225, +(97, 770): 226, +(97, 771): 227, +(97, 772): 257, +(97, 774): 259, +(97, 775): 551, +(97, 776): 228, +(97, 777): 7843, +(97, 778): 229, +(97, 780): 462, +(97, 783): 513, +(97, 785): 515, +(97, 803): 7841, +(97, 805): 7681, +(97, 808): 261, +(98, 775): 7683, +(98, 803): 7685, +(98, 817): 7687, +(99, 769): 263, +(99, 770): 265, +(99, 775): 267, +(99, 780): 269, +(99, 807): 231, +(100, 775): 7691, +(100, 780): 271, +(100, 803): 7693, +(100, 807): 7697, +(100, 813): 7699, +(100, 817): 7695, +(101, 768): 232, +(101, 769): 233, +(101, 770): 234, +(101, 771): 7869, +(101, 772): 275, +(101, 774): 277, +(101, 775): 279, +(101, 776): 235, +(101, 777): 7867, +(101, 780): 283, +(101, 783): 517, +(101, 785): 519, +(101, 803): 7865, +(101, 807): 553, +(101, 808): 281, +(101, 813): 7705, +(101, 816): 7707, +(102, 775): 7711, +(103, 769): 501, +(103, 770): 285, +(103, 772): 7713, +(103, 774): 287, +(103, 775): 289, +(103, 780): 487, +(103, 807): 291, +(104, 770): 293, +(104, 775): 7715, +(104, 776): 7719, +(104, 780): 543, +(104, 803): 7717, +(104, 807): 7721, +(104, 814): 7723, +(104, 817): 7830, +(105, 768): 236, +(105, 769): 237, +(105, 770): 238, +(105, 771): 297, +(105, 772): 299, +(105, 774): 301, +(105, 776): 239, +(105, 777): 7881, +(105, 780): 464, +(105, 783): 521, +(105, 785): 523, +(105, 803): 7883, +(105, 808): 303, +(105, 816): 7725, +(106, 770): 309, +(106, 780): 496, +(107, 769): 7729, +(107, 780): 489, +(107, 803): 7731, +(107, 807): 311, +(107, 817): 7733, +(108, 769): 314, +(108, 780): 318, +(108, 803): 7735, +(108, 807): 316, +(108, 813): 7741, +(108, 817): 7739, +(109, 769): 7743, +(109, 775): 7745, +(109, 803): 7747, +(110, 768): 505, +(110, 769): 324, +(110, 771): 241, +(110, 775): 7749, +(110, 780): 328, +(110, 803): 7751, +(110, 807): 326, +(110, 813): 7755, +(110, 817): 7753, +(111, 768): 242, +(111, 769): 243, +(111, 770): 244, +(111, 771): 245, +(111, 772): 333, +(111, 774): 335, +(111, 775): 559, +(111, 776): 246, +(111, 777): 7887, +(111, 779): 337, +(111, 780): 466, +(111, 783): 525, +(111, 785): 527, +(111, 795): 417, +(111, 803): 7885, +(111, 808): 491, +(112, 769): 7765, +(112, 775): 7767, +(114, 769): 341, +(114, 775): 7769, +(114, 780): 345, +(114, 783): 529, +(114, 785): 531, +(114, 803): 7771, +(114, 807): 343, +(114, 817): 7775, +(115, 769): 347, +(115, 770): 349, +(115, 775): 7777, +(115, 780): 353, +(115, 803): 7779, +(115, 806): 537, +(115, 807): 351, +(116, 775): 7787, +(116, 776): 7831, +(116, 780): 357, +(116, 803): 7789, +(116, 806): 539, +(116, 807): 355, +(116, 813): 7793, +(116, 817): 7791, +(117, 768): 249, +(117, 769): 250, +(117, 770): 251, +(117, 771): 361, +(117, 772): 363, +(117, 774): 365, +(117, 776): 252, +(117, 777): 7911, +(117, 778): 367, +(117, 779): 369, +(117, 780): 468, +(117, 783): 533, +(117, 785): 535, +(117, 795): 432, +(117, 803): 7909, +(117, 804): 7795, +(117, 808): 371, +(117, 813): 7799, +(117, 816): 7797, +(118, 771): 7805, +(118, 803): 7807, +(119, 768): 7809, +(119, 769): 7811, +(119, 770): 373, +(119, 775): 7815, +(119, 776): 7813, +(119, 778): 7832, +(119, 803): 7817, +(120, 775): 7819, +(120, 776): 7821, +(121, 768): 7923, +(121, 769): 253, +(121, 770): 375, +(121, 771): 7929, +(121, 772): 563, +(121, 775): 7823, +(121, 776): 255, +(121, 777): 7927, +(121, 778): 7833, +(121, 803): 7925, +(122, 769): 378, +(122, 770): 7825, +(122, 775): 380, +(122, 780): 382, +(122, 803): 7827, +(122, 817): 7829, +(168, 768): 8173, +(168, 769): 901, +(168, 834): 8129, +(194, 768): 7846, +(194, 769): 7844, +(194, 771): 7850, +(194, 777): 7848, +(196, 772): 478, +(197, 769): 506, +(198, 769): 508, +(198, 772): 482, +(199, 769): 7688, +(202, 768): 7872, +(202, 769): 7870, +(202, 771): 7876, +(202, 777): 7874, +(207, 769): 7726, +(212, 768): 7890, +(212, 769): 7888, +(212, 771): 7894, +(212, 777): 7892, +(213, 769): 7756, +(213, 772): 556, +(213, 776): 7758, +(214, 772): 554, +(216, 769): 510, +(220, 768): 475, +(220, 769): 471, +(220, 772): 469, +(220, 780): 473, +(226, 768): 7847, +(226, 769): 7845, +(226, 771): 7851, +(226, 777): 7849, +(228, 772): 479, +(229, 769): 507, +(230, 769): 509, +(230, 772): 483, +(231, 769): 7689, +(234, 768): 7873, +(234, 769): 7871, +(234, 771): 7877, +(234, 777): 7875, +(239, 769): 7727, +(244, 768): 7891, +(244, 769): 7889, +(244, 771): 7895, +(244, 777): 7893, +(245, 769): 7757, +(245, 772): 557, +(245, 776): 7759, +(246, 772): 555, +(248, 769): 511, +(252, 768): 476, +(252, 769): 472, +(252, 772): 470, +(252, 780): 474, +(258, 768): 7856, +(258, 769): 7854, +(258, 771): 7860, +(258, 777): 7858, +(259, 768): 7857, +(259, 769): 7855, +(259, 771): 7861, +(259, 777): 7859, +(274, 768): 7700, +(274, 769): 7702, +(275, 768): 7701, +(275, 769): 7703, +(332, 768): 7760, +(332, 769): 7762, +(333, 768): 7761, +(333, 769): 7763, +(346, 775): 7780, +(347, 775): 7781, +(352, 775): 7782, +(353, 775): 7783, +(360, 769): 7800, +(361, 769): 7801, +(362, 776): 7802, +(363, 776): 7803, +(383, 775): 7835, +(416, 768): 7900, +(416, 769): 7898, +(416, 771): 7904, +(416, 777): 7902, +(416, 803): 7906, +(417, 768): 7901, +(417, 769): 7899, +(417, 771): 7905, +(417, 777): 7903, +(417, 803): 7907, +(431, 768): 7914, +(431, 769): 7912, +(431, 771): 7918, +(431, 777): 7916, +(431, 803): 7920, +(432, 768): 7915, +(432, 769): 7913, +(432, 771): 7919, +(432, 777): 7917, +(432, 803): 7921, +(439, 780): 494, +(490, 772): 492, +(491, 772): 493, +(550, 772): 480, +(551, 772): 481, +(552, 774): 7708, +(553, 774): 7709, +(558, 772): 560, +(559, 772): 561, +(658, 780): 495, +(913, 768): 8122, +(913, 769): 902, +(913, 772): 8121, +(913, 774): 8120, +(913, 787): 7944, +(913, 788): 7945, +(913, 837): 8124, +(917, 768): 8136, +(917, 769): 904, +(917, 787): 7960, +(917, 788): 7961, +(919, 768): 8138, +(919, 769): 905, +(919, 787): 7976, +(919, 788): 7977, +(919, 837): 8140, +(921, 768): 8154, +(921, 769): 906, +(921, 772): 8153, +(921, 774): 8152, +(921, 776): 938, +(921, 787): 7992, +(921, 788): 7993, +(927, 768): 8184, +(927, 769): 908, +(927, 787): 8008, +(927, 788): 8009, +(929, 788): 8172, +(933, 768): 8170, +(933, 769): 910, +(933, 772): 8169, +(933, 774): 8168, +(933, 776): 939, +(933, 788): 8025, +(937, 768): 8186, +(937, 769): 911, +(937, 787): 8040, +(937, 788): 8041, +(937, 837): 8188, +(940, 837): 8116, +(942, 837): 8132, +(945, 768): 8048, +(945, 769): 940, +(945, 772): 8113, +(945, 774): 8112, +(945, 787): 7936, +(945, 788): 7937, +(945, 834): 8118, +(945, 837): 8115, +(949, 768): 8050, +(949, 769): 941, +(949, 787): 7952, +(949, 788): 7953, +(951, 768): 8052, +(951, 769): 942, +(951, 787): 7968, +(951, 788): 7969, +(951, 834): 8134, +(951, 837): 8131, +(953, 768): 8054, +(953, 769): 943, +(953, 772): 8145, +(953, 774): 8144, +(953, 776): 970, +(953, 787): 7984, +(953, 788): 7985, +(953, 834): 8150, +(959, 768): 8056, +(959, 769): 972, +(959, 787): 8000, +(959, 788): 8001, +(961, 787): 8164, +(961, 788): 8165, +(965, 768): 8058, +(965, 769): 973, +(965, 772): 8161, +(965, 774): 8160, +(965, 776): 971, +(965, 787): 8016, +(965, 788): 8017, +(965, 834): 8166, +(969, 768): 8060, +(969, 769): 974, +(969, 787): 8032, +(969, 788): 8033, +(969, 834): 8182, +(969, 837): 8179, +(970, 768): 8146, +(970, 769): 912, +(970, 834): 8151, +(971, 768): 8162, +(971, 769): 944, +(971, 834): 8167, +(974, 837): 8180, +(978, 769): 979, +(978, 776): 980, +(1030, 776): 1031, +(1040, 774): 1232, +(1040, 776): 1234, +(1043, 769): 1027, +(1045, 768): 1024, +(1045, 774): 1238, +(1045, 776): 1025, +(1046, 774): 1217, +(1046, 776): 1244, +(1047, 776): 1246, +(1048, 768): 1037, +(1048, 772): 1250, +(1048, 774): 1049, +(1048, 776): 1252, +(1050, 769): 1036, +(1054, 776): 1254, +(1059, 772): 1262, +(1059, 774): 1038, +(1059, 776): 1264, +(1059, 779): 1266, +(1063, 776): 1268, +(1067, 776): 1272, +(1069, 776): 1260, +(1072, 774): 1233, +(1072, 776): 1235, +(1075, 769): 1107, +(1077, 768): 1104, +(1077, 774): 1239, +(1077, 776): 1105, +(1078, 774): 1218, +(1078, 776): 1245, +(1079, 776): 1247, +(1080, 768): 1117, +(1080, 772): 1251, +(1080, 774): 1081, +(1080, 776): 1253, +(1082, 769): 1116, +(1086, 776): 1255, +(1091, 772): 1263, +(1091, 774): 1118, +(1091, 776): 1265, +(1091, 779): 1267, +(1095, 776): 1269, +(1099, 776): 1273, +(1101, 776): 1261, +(1110, 776): 1111, +(1140, 783): 1142, +(1141, 783): 1143, +(1240, 776): 1242, +(1241, 776): 1243, +(1256, 776): 1258, +(1257, 776): 1259, +(1575, 1619): 1570, +(1575, 1620): 1571, +(1575, 1621): 1573, +(1608, 1620): 1572, +(1610, 1620): 1574, +(1729, 1620): 1730, +(1746, 1620): 1747, +(1749, 1620): 1728, +(2344, 2364): 2345, +(2352, 2364): 2353, +(2355, 2364): 2356, +(2503, 2494): 2507, +(2503, 2519): 2508, +(2887, 2878): 2891, +(2887, 2902): 2888, +(2887, 2903): 2892, +(2962, 3031): 2964, +(3014, 3006): 3018, +(3014, 3031): 3020, +(3015, 3006): 3019, +(3142, 3158): 3144, +(3263, 3285): 3264, +(3270, 3266): 3274, +(3270, 3285): 3271, +(3270, 3286): 3272, +(3274, 3285): 3275, +(3398, 3390): 3402, +(3398, 3415): 3404, +(3399, 3390): 3403, +(3545, 3530): 3546, +(3545, 3535): 3548, +(3545, 3551): 3550, +(3548, 3530): 3549, +(4133, 4142): 4134, +(7734, 772): 7736, +(7735, 772): 7737, +(7770, 772): 7772, +(7771, 772): 7773, +(7778, 775): 7784, +(7779, 775): 7785, +(7840, 770): 7852, +(7840, 774): 7862, +(7841, 770): 7853, +(7841, 774): 7863, +(7864, 770): 7878, +(7865, 770): 7879, +(7884, 770): 7896, +(7885, 770): 7897, +(7936, 768): 7938, +(7936, 769): 7940, +(7936, 834): 7942, +(7936, 837): 8064, +(7937, 768): 7939, +(7937, 769): 7941, +(7937, 834): 7943, +(7937, 837): 8065, +(7938, 837): 8066, +(7939, 837): 8067, +(7940, 837): 8068, +(7941, 837): 8069, +(7942, 837): 8070, +(7943, 837): 8071, +(7944, 768): 7946, +(7944, 769): 7948, +(7944, 834): 7950, +(7944, 837): 8072, +(7945, 768): 7947, +(7945, 769): 7949, +(7945, 834): 7951, +(7945, 837): 8073, +(7946, 837): 8074, +(7947, 837): 8075, +(7948, 837): 8076, +(7949, 837): 8077, +(7950, 837): 8078, +(7951, 837): 8079, +(7952, 768): 7954, +(7952, 769): 7956, +(7953, 768): 7955, +(7953, 769): 7957, +(7960, 768): 7962, +(7960, 769): 7964, +(7961, 768): 7963, +(7961, 769): 7965, +(7968, 768): 7970, +(7968, 769): 7972, +(7968, 834): 7974, +(7968, 837): 8080, +(7969, 768): 7971, +(7969, 769): 7973, +(7969, 834): 7975, +(7969, 837): 8081, +(7970, 837): 8082, +(7971, 837): 8083, +(7972, 837): 8084, +(7973, 837): 8085, +(7974, 837): 8086, +(7975, 837): 8087, +(7976, 768): 7978, +(7976, 769): 7980, +(7976, 834): 7982, +(7976, 837): 8088, +(7977, 768): 7979, +(7977, 769): 7981, +(7977, 834): 7983, +(7977, 837): 8089, +(7978, 837): 8090, +(7979, 837): 8091, +(7980, 837): 8092, +(7981, 837): 8093, +(7982, 837): 8094, +(7983, 837): 8095, +(7984, 768): 7986, +(7984, 769): 7988, +(7984, 834): 7990, +(7985, 768): 7987, +(7985, 769): 7989, +(7985, 834): 7991, +(7992, 768): 7994, +(7992, 769): 7996, +(7992, 834): 7998, +(7993, 768): 7995, +(7993, 769): 7997, +(7993, 834): 7999, +(8000, 768): 8002, +(8000, 769): 8004, +(8001, 768): 8003, +(8001, 769): 8005, +(8008, 768): 8010, +(8008, 769): 8012, +(8009, 768): 8011, +(8009, 769): 8013, +(8016, 768): 8018, +(8016, 769): 8020, +(8016, 834): 8022, +(8017, 768): 8019, +(8017, 769): 8021, +(8017, 834): 8023, +(8025, 768): 8027, +(8025, 769): 8029, +(8025, 834): 8031, +(8032, 768): 8034, +(8032, 769): 8036, +(8032, 834): 8038, +(8032, 837): 8096, +(8033, 768): 8035, +(8033, 769): 8037, +(8033, 834): 8039, +(8033, 837): 8097, +(8034, 837): 8098, +(8035, 837): 8099, +(8036, 837): 8100, +(8037, 837): 8101, +(8038, 837): 8102, +(8039, 837): 8103, +(8040, 768): 8042, +(8040, 769): 8044, +(8040, 834): 8046, +(8040, 837): 8104, +(8041, 768): 8043, +(8041, 769): 8045, +(8041, 834): 8047, +(8041, 837): 8105, +(8042, 837): 8106, +(8043, 837): 8107, +(8044, 837): 8108, +(8045, 837): 8109, +(8046, 837): 8110, +(8047, 837): 8111, +(8048, 837): 8114, +(8052, 837): 8130, +(8060, 837): 8178, +(8118, 837): 8119, +(8127, 768): 8141, +(8127, 769): 8142, +(8127, 834): 8143, +(8134, 837): 8135, +(8182, 837): 8183, +(8190, 768): 8157, +(8190, 769): 8158, +(8190, 834): 8159, +(8592, 824): 8602, +(8594, 824): 8603, +(8596, 824): 8622, +(8656, 824): 8653, +(8658, 824): 8655, +(8660, 824): 8654, +(8707, 824): 8708, +(8712, 824): 8713, +(8715, 824): 8716, +(8739, 824): 8740, +(8741, 824): 8742, +(8764, 824): 8769, +(8771, 824): 8772, +(8773, 824): 8775, +(8776, 824): 8777, +(8781, 824): 8813, +(8801, 824): 8802, +(8804, 824): 8816, +(8805, 824): 8817, +(8818, 824): 8820, +(8819, 824): 8821, +(8822, 824): 8824, +(8823, 824): 8825, +(8826, 824): 8832, +(8827, 824): 8833, +(8828, 824): 8928, +(8829, 824): 8929, +(8834, 824): 8836, +(8835, 824): 8837, +(8838, 824): 8840, +(8839, 824): 8841, +(8849, 824): 8930, +(8850, 824): 8931, +(8866, 824): 8876, +(8872, 824): 8877, +(8873, 824): 8878, +(8875, 824): 8879, +(8882, 824): 8938, +(8883, 824): 8939, +(8884, 824): 8940, +(8885, 824): 8941, +(12358, 12441): 12436, +(12363, 12441): 12364, +(12365, 12441): 12366, +(12367, 12441): 12368, +(12369, 12441): 12370, +(12371, 12441): 12372, +(12373, 12441): 12374, +(12375, 12441): 12376, +(12377, 12441): 12378, +(12379, 12441): 12380, +(12381, 12441): 12382, +(12383, 12441): 12384, +(12385, 12441): 12386, +(12388, 12441): 12389, +(12390, 12441): 12391, +(12392, 12441): 12393, +(12399, 12441): 12400, +(12399, 12442): 12401, +(12402, 12441): 12403, +(12402, 12442): 12404, +(12405, 12441): 12406, +(12405, 12442): 12407, +(12408, 12441): 12409, +(12408, 12442): 12410, +(12411, 12441): 12412, +(12411, 12442): 12413, +(12445, 12441): 12446, +(12454, 12441): 12532, +(12459, 12441): 12460, +(12461, 12441): 12462, +(12463, 12441): 12464, +(12465, 12441): 12466, +(12467, 12441): 12468, +(12469, 12441): 12470, +(12471, 12441): 12472, +(12473, 12441): 12474, +(12475, 12441): 12476, +(12477, 12441): 12478, +(12479, 12441): 12480, +(12481, 12441): 12482, +(12484, 12441): 12485, +(12486, 12441): 12487, +(12488, 12441): 12489, +(12495, 12441): 12496, +(12495, 12442): 12497, +(12498, 12441): 12499, +(12498, 12442): 12500, +(12501, 12441): 12502, +(12501, 12442): 12503, +(12504, 12441): 12505, +(12504, 12442): 12506, +(12507, 12441): 12508, +(12507, 12442): 12509, +(12527, 12441): 12535, +(12528, 12441): 12536, +(12529, 12441): 12537, +(12530, 12441): 12538, +(12541, 12441): 12542, +} +_canon_decomposition = { +192: [65, 768], +193: [65, 769], +194: [65, 770], +195: [65, 771], +196: [65, 776], +197: [65, 778], +199: [67, 807], +200: [69, 768], +201: [69, 769], +202: [69, 770], +203: [69, 776], +204: [73, 768], +205: [73, 769], +206: [73, 770], +207: [73, 776], +209: [78, 771], +210: [79, 768], +211: [79, 769], +212: [79, 770], +213: [79, 771], +214: [79, 776], +217: [85, 768], +218: [85, 769], +219: [85, 770], +220: [85, 776], +221: [89, 769], +224: [97, 768], +225: [97, 769], +226: [97, 770], +227: [97, 771], +228: [97, 776], +229: [97, 778], +231: [99, 807], +232: [101, 768], +233: [101, 769], +234: [101, 770], +235: [101, 776], +236: [105, 768], +237: [105, 769], +238: [105, 770], +239: [105, 776], +241: [110, 771], +242: [111, 768], +243: [111, 769], +244: [111, 770], +245: [111, 771], +246: [111, 776], +249: [117, 768], +250: [117, 769], +251: [117, 770], +252: [117, 776], +253: [121, 769], +255: [121, 776], +256: [65, 772], +257: [97, 772], +258: [65, 774], +259: [97, 774], +260: [65, 808], +261: [97, 808], +262: [67, 769], +263: [99, 769], +264: [67, 770], +265: [99, 770], +266: [67, 775], +267: [99, 775], +268: [67, 780], +269: [99, 780], +270: [68, 780], +271: [100, 780], +274: [69, 772], +275: [101, 772], +276: [69, 774], +277: [101, 774], +278: [69, 775], +279: [101, 775], +280: [69, 808], +281: [101, 808], +282: [69, 780], +283: [101, 780], +284: [71, 770], +285: [103, 770], +286: [71, 774], +287: [103, 774], +288: [71, 775], +289: [103, 775], +290: [71, 807], +291: [103, 807], +292: [72, 770], +293: [104, 770], +296: [73, 771], +297: [105, 771], +298: [73, 772], +299: [105, 772], +300: [73, 774], +301: [105, 774], +302: [73, 808], +303: [105, 808], +304: [73, 775], +308: [74, 770], +309: [106, 770], +310: [75, 807], +311: [107, 807], +313: [76, 769], +314: [108, 769], +315: [76, 807], +316: [108, 807], +317: [76, 780], +318: [108, 780], +323: [78, 769], +324: [110, 769], +325: [78, 807], +326: [110, 807], +327: [78, 780], +328: [110, 780], +332: [79, 772], +333: [111, 772], +334: [79, 774], +335: [111, 774], +336: [79, 779], +337: [111, 779], +340: [82, 769], +341: [114, 769], +342: [82, 807], +343: [114, 807], +344: [82, 780], +345: [114, 780], +346: [83, 769], +347: [115, 769], +348: [83, 770], +349: [115, 770], +350: [83, 807], +351: [115, 807], +352: [83, 780], +353: [115, 780], +354: [84, 807], +355: [116, 807], +356: [84, 780], +357: [116, 780], +360: [85, 771], +361: [117, 771], +362: [85, 772], +363: [117, 772], +364: [85, 774], +365: [117, 774], +366: [85, 778], +367: [117, 778], +368: [85, 779], +369: [117, 779], +370: [85, 808], +371: [117, 808], +372: [87, 770], +373: [119, 770], +374: [89, 770], +375: [121, 770], +376: [89, 776], +377: [90, 769], +378: [122, 769], +379: [90, 775], +380: [122, 775], +381: [90, 780], +382: [122, 780], +416: [79, 795], +417: [111, 795], +431: [85, 795], +432: [117, 795], +461: [65, 780], +462: [97, 780], +463: [73, 780], +464: [105, 780], +465: [79, 780], +466: [111, 780], +467: [85, 780], +468: [117, 780], +469: [85, 776, 772], +470: [117, 776, 772], +471: [85, 776, 769], +472: [117, 776, 769], +473: [85, 776, 780], +474: [117, 776, 780], +475: [85, 776, 768], +476: [117, 776, 768], +478: [65, 776, 772], +479: [97, 776, 772], +480: [65, 775, 772], +481: [97, 775, 772], +482: [198, 772], +483: [230, 772], +486: [71, 780], +487: [103, 780], +488: [75, 780], +489: [107, 780], +490: [79, 808], +491: [111, 808], +492: [79, 808, 772], +493: [111, 808, 772], +494: [439, 780], +495: [658, 780], +496: [106, 780], +500: [71, 769], +501: [103, 769], +504: [78, 768], +505: [110, 768], +506: [65, 778, 769], +507: [97, 778, 769], +508: [198, 769], +509: [230, 769], +510: [216, 769], +511: [248, 769], +512: [65, 783], +513: [97, 783], +514: [65, 785], +515: [97, 785], +516: [69, 783], +517: [101, 783], +518: [69, 785], +519: [101, 785], +520: [73, 783], +521: [105, 783], +522: [73, 785], +523: [105, 785], +524: [79, 783], +525: [111, 783], +526: [79, 785], +527: [111, 785], +528: [82, 783], +529: [114, 783], +530: [82, 785], +531: [114, 785], +532: [85, 783], +533: [117, 783], +534: [85, 785], +535: [117, 785], +536: [83, 806], +537: [115, 806], +538: [84, 806], +539: [116, 806], +542: [72, 780], +543: [104, 780], +550: [65, 775], +551: [97, 775], +552: [69, 807], +553: [101, 807], +554: [79, 776, 772], +555: [111, 776, 772], +556: [79, 771, 772], +557: [111, 771, 772], +558: [79, 775], +559: [111, 775], +560: [79, 775, 772], +561: [111, 775, 772], +562: [89, 772], +563: [121, 772], +832: [768], +833: [769], +835: [787], +836: [776, 769], +884: [697], +894: [59], +901: [168, 769], +902: [913, 769], +903: [183], +904: [917, 769], +905: [919, 769], +906: [921, 769], +908: [927, 769], +910: [933, 769], +911: [937, 769], +912: [953, 776, 769], +938: [921, 776], +939: [933, 776], +940: [945, 769], +941: [949, 769], +942: [951, 769], +943: [953, 769], +944: [965, 776, 769], +970: [953, 776], +971: [965, 776], +972: [959, 769], +973: [965, 769], +974: [969, 769], +979: [978, 769], +980: [978, 776], +1024: [1045, 768], +1025: [1045, 776], +1027: [1043, 769], +1031: [1030, 776], +1036: [1050, 769], +1037: [1048, 768], +1038: [1059, 774], +1049: [1048, 774], +1081: [1080, 774], +1104: [1077, 768], +1105: [1077, 776], +1107: [1075, 769], +1111: [1110, 776], +1116: [1082, 769], +1117: [1080, 768], +1118: [1091, 774], +1142: [1140, 783], +1143: [1141, 783], +1217: [1046, 774], +1218: [1078, 774], +1232: [1040, 774], +1233: [1072, 774], +1234: [1040, 776], +1235: [1072, 776], +1238: [1045, 774], +1239: [1077, 774], +1242: [1240, 776], +1243: [1241, 776], +1244: [1046, 776], +1245: [1078, 776], +1246: [1047, 776], +1247: [1079, 776], +1250: [1048, 772], +1251: [1080, 772], +1252: [1048, 776], +1253: [1080, 776], +1254: [1054, 776], +1255: [1086, 776], +1258: [1256, 776], +1259: [1257, 776], +1260: [1069, 776], +1261: [1101, 776], +1262: [1059, 772], +1263: [1091, 772], +1264: [1059, 776], +1265: [1091, 776], +1266: [1059, 779], +1267: [1091, 779], +1268: [1063, 776], +1269: [1095, 776], +1272: [1067, 776], +1273: [1099, 776], +1570: [1575, 1619], +1571: [1575, 1620], +1572: [1608, 1620], +1573: [1575, 1621], +1574: [1610, 1620], +1728: [1749, 1620], +1730: [1729, 1620], +1747: [1746, 1620], +2345: [2344, 2364], +2353: [2352, 2364], +2356: [2355, 2364], +2392: [2325, 2364], +2393: [2326, 2364], +2394: [2327, 2364], +2395: [2332, 2364], +2396: [2337, 2364], +2397: [2338, 2364], +2398: [2347, 2364], +2399: [2351, 2364], +2507: [2503, 2494], +2508: [2503, 2519], +2524: [2465, 2492], +2525: [2466, 2492], +2527: [2479, 2492], +2611: [2610, 2620], +2614: [2616, 2620], +2649: [2582, 2620], +2650: [2583, 2620], +2651: [2588, 2620], +2654: [2603, 2620], +2888: [2887, 2902], +2891: [2887, 2878], +2892: [2887, 2903], +2908: [2849, 2876], +2909: [2850, 2876], +2964: [2962, 3031], +3018: [3014, 3006], +3019: [3015, 3006], +3020: [3014, 3031], +3144: [3142, 3158], +3264: [3263, 3285], +3271: [3270, 3285], +3272: [3270, 3286], +3274: [3270, 3266], +3275: [3270, 3266, 3285], +3402: [3398, 3390], +3403: [3399, 3390], +3404: [3398, 3415], +3546: [3545, 3530], +3548: [3545, 3535], +3549: [3545, 3535, 3530], +3550: [3545, 3551], +3907: [3906, 4023], +3917: [3916, 4023], +3922: [3921, 4023], +3927: [3926, 4023], +3932: [3931, 4023], +3945: [3904, 4021], +3955: [3953, 3954], +3957: [3953, 3956], +3958: [4018, 3968], +3960: [4019, 3968], +3969: [3953, 3968], +3987: [3986, 4023], +3997: [3996, 4023], +4002: [4001, 4023], +4007: [4006, 4023], +4012: [4011, 4023], +4025: [3984, 4021], +4134: [4133, 4142], +7680: [65, 805], +7681: [97, 805], +7682: [66, 775], +7683: [98, 775], +7684: [66, 803], +7685: [98, 803], +7686: [66, 817], +7687: [98, 817], +7688: [67, 807, 769], +7689: [99, 807, 769], +7690: [68, 775], +7691: [100, 775], +7692: [68, 803], +7693: [100, 803], +7694: [68, 817], +7695: [100, 817], +7696: [68, 807], +7697: [100, 807], +7698: [68, 813], +7699: [100, 813], +7700: [69, 772, 768], +7701: [101, 772, 768], +7702: [69, 772, 769], +7703: [101, 772, 769], +7704: [69, 813], +7705: [101, 813], +7706: [69, 816], +7707: [101, 816], +7708: [69, 807, 774], +7709: [101, 807, 774], +7710: [70, 775], +7711: [102, 775], +7712: [71, 772], +7713: [103, 772], +7714: [72, 775], +7715: [104, 775], +7716: [72, 803], +7717: [104, 803], +7718: [72, 776], +7719: [104, 776], +7720: [72, 807], +7721: [104, 807], +7722: [72, 814], +7723: [104, 814], +7724: [73, 816], +7725: [105, 816], +7726: [73, 776, 769], +7727: [105, 776, 769], +7728: [75, 769], +7729: [107, 769], +7730: [75, 803], +7731: [107, 803], +7732: [75, 817], +7733: [107, 817], +7734: [76, 803], +7735: [108, 803], +7736: [76, 803, 772], +7737: [108, 803, 772], +7738: [76, 817], +7739: [108, 817], +7740: [76, 813], +7741: [108, 813], +7742: [77, 769], +7743: [109, 769], +7744: [77, 775], +7745: [109, 775], +7746: [77, 803], +7747: [109, 803], +7748: [78, 775], +7749: [110, 775], +7750: [78, 803], +7751: [110, 803], +7752: [78, 817], +7753: [110, 817], +7754: [78, 813], +7755: [110, 813], +7756: [79, 771, 769], +7757: [111, 771, 769], +7758: [79, 771, 776], +7759: [111, 771, 776], +7760: [79, 772, 768], +7761: [111, 772, 768], +7762: [79, 772, 769], +7763: [111, 772, 769], +7764: [80, 769], +7765: [112, 769], +7766: [80, 775], +7767: [112, 775], +7768: [82, 775], +7769: [114, 775], +7770: [82, 803], +7771: [114, 803], +7772: [82, 803, 772], +7773: [114, 803, 772], +7774: [82, 817], +7775: [114, 817], +7776: [83, 775], +7777: [115, 775], +7778: [83, 803], +7779: [115, 803], +7780: [83, 769, 775], +7781: [115, 769, 775], +7782: [83, 780, 775], +7783: [115, 780, 775], +7784: [83, 803, 775], +7785: [115, 803, 775], +7786: [84, 775], +7787: [116, 775], +7788: [84, 803], +7789: [116, 803], +7790: [84, 817], +7791: [116, 817], +7792: [84, 813], +7793: [116, 813], +7794: [85, 804], +7795: [117, 804], +7796: [85, 816], +7797: [117, 816], +7798: [85, 813], +7799: [117, 813], +7800: [85, 771, 769], +7801: [117, 771, 769], +7802: [85, 772, 776], +7803: [117, 772, 776], +7804: [86, 771], +7805: [118, 771], +7806: [86, 803], +7807: [118, 803], +7808: [87, 768], +7809: [119, 768], +7810: [87, 769], +7811: [119, 769], +7812: [87, 776], +7813: [119, 776], +7814: [87, 775], +7815: [119, 775], +7816: [87, 803], +7817: [119, 803], +7818: [88, 775], +7819: [120, 775], +7820: [88, 776], +7821: [120, 776], +7822: [89, 775], +7823: [121, 775], +7824: [90, 770], +7825: [122, 770], +7826: [90, 803], +7827: [122, 803], +7828: [90, 817], +7829: [122, 817], +7830: [104, 817], +7831: [116, 776], +7832: [119, 778], +7833: [121, 778], +7835: [383, 775], +7840: [65, 803], +7841: [97, 803], +7842: [65, 777], +7843: [97, 777], +7844: [65, 770, 769], +7845: [97, 770, 769], +7846: [65, 770, 768], +7847: [97, 770, 768], +7848: [65, 770, 777], +7849: [97, 770, 777], +7850: [65, 770, 771], +7851: [97, 770, 771], +7852: [65, 803, 770], +7853: [97, 803, 770], +7854: [65, 774, 769], +7855: [97, 774, 769], +7856: [65, 774, 768], +7857: [97, 774, 768], +7858: [65, 774, 777], +7859: [97, 774, 777], +7860: [65, 774, 771], +7861: [97, 774, 771], +7862: [65, 803, 774], +7863: [97, 803, 774], +7864: [69, 803], +7865: [101, 803], +7866: [69, 777], +7867: [101, 777], +7868: [69, 771], +7869: [101, 771], +7870: [69, 770, 769], +7871: [101, 770, 769], +7872: [69, 770, 768], +7873: [101, 770, 768], +7874: [69, 770, 777], +7875: [101, 770, 777], +7876: [69, 770, 771], +7877: [101, 770, 771], +7878: [69, 803, 770], +7879: [101, 803, 770], +7880: [73, 777], +7881: [105, 777], +7882: [73, 803], +7883: [105, 803], +7884: [79, 803], +7885: [111, 803], +7886: [79, 777], +7887: [111, 777], +7888: [79, 770, 769], +7889: [111, 770, 769], +7890: [79, 770, 768], +7891: [111, 770, 768], +7892: [79, 770, 777], +7893: [111, 770, 777], +7894: [79, 770, 771], +7895: [111, 770, 771], +7896: [79, 803, 770], +7897: [111, 803, 770], +7898: [79, 795, 769], +7899: [111, 795, 769], +7900: [79, 795, 768], +7901: [111, 795, 768], +7902: [79, 795, 777], +7903: [111, 795, 777], +7904: [79, 795, 771], +7905: [111, 795, 771], +7906: [79, 795, 803], +7907: [111, 795, 803], +7908: [85, 803], +7909: [117, 803], +7910: [85, 777], +7911: [117, 777], +7912: [85, 795, 769], +7913: [117, 795, 769], +7914: [85, 795, 768], +7915: [117, 795, 768], +7916: [85, 795, 777], +7917: [117, 795, 777], +7918: [85, 795, 771], +7919: [117, 795, 771], +7920: [85, 795, 803], +7921: [117, 795, 803], +7922: [89, 768], +7923: [121, 768], +7924: [89, 803], +7925: [121, 803], +7926: [89, 777], +7927: [121, 777], +7928: [89, 771], +7929: [121, 771], +7936: [945, 787], +7937: [945, 788], +7938: [945, 787, 768], +7939: [945, 788, 768], +7940: [945, 787, 769], +7941: [945, 788, 769], +7942: [945, 787, 834], +7943: [945, 788, 834], +7944: [913, 787], +7945: [913, 788], +7946: [913, 787, 768], +7947: [913, 788, 768], +7948: [913, 787, 769], +7949: [913, 788, 769], +7950: [913, 787, 834], +7951: [913, 788, 834], +7952: [949, 787], +7953: [949, 788], +7954: [949, 787, 768], +7955: [949, 788, 768], +7956: [949, 787, 769], +7957: [949, 788, 769], +7960: [917, 787], +7961: [917, 788], +7962: [917, 787, 768], +7963: [917, 788, 768], +7964: [917, 787, 769], +7965: [917, 788, 769], +7968: [951, 787], +7969: [951, 788], +7970: [951, 787, 768], +7971: [951, 788, 768], +7972: [951, 787, 769], +7973: [951, 788, 769], +7974: [951, 787, 834], +7975: [951, 788, 834], +7976: [919, 787], +7977: [919, 788], +7978: [919, 787, 768], +7979: [919, 788, 768], +7980: [919, 787, 769], +7981: [919, 788, 769], +7982: [919, 787, 834], +7983: [919, 788, 834], +7984: [953, 787], +7985: [953, 788], +7986: [953, 787, 768], +7987: [953, 788, 768], +7988: [953, 787, 769], +7989: [953, 788, 769], +7990: [953, 787, 834], +7991: [953, 788, 834], +7992: [921, 787], +7993: [921, 788], +7994: [921, 787, 768], +7995: [921, 788, 768], +7996: [921, 787, 769], +7997: [921, 788, 769], +7998: [921, 787, 834], +7999: [921, 788, 834], +8000: [959, 787], +8001: [959, 788], +8002: [959, 787, 768], +8003: [959, 788, 768], +8004: [959, 787, 769], +8005: [959, 788, 769], +8008: [927, 787], +8009: [927, 788], +8010: [927, 787, 768], +8011: [927, 788, 768], +8012: [927, 787, 769], +8013: [927, 788, 769], +8016: [965, 787], +8017: [965, 788], +8018: [965, 787, 768], +8019: [965, 788, 768], +8020: [965, 787, 769], +8021: [965, 788, 769], +8022: [965, 787, 834], +8023: [965, 788, 834], +8025: [933, 788], +8027: [933, 788, 768], +8029: [933, 788, 769], +8031: [933, 788, 834], +8032: [969, 787], +8033: [969, 788], +8034: [969, 787, 768], +8035: [969, 788, 768], +8036: [969, 787, 769], +8037: [969, 788, 769], +8038: [969, 787, 834], +8039: [969, 788, 834], +8040: [937, 787], +8041: [937, 788], +8042: [937, 787, 768], +8043: [937, 788, 768], +8044: [937, 787, 769], +8045: [937, 788, 769], +8046: [937, 787, 834], +8047: [937, 788, 834], +8048: [945, 768], +8049: [945, 769], +8050: [949, 768], +8051: [949, 769], +8052: [951, 768], +8053: [951, 769], +8054: [953, 768], +8055: [953, 769], +8056: [959, 768], +8057: [959, 769], +8058: [965, 768], +8059: [965, 769], +8060: [969, 768], +8061: [969, 769], +8064: [945, 787, 837], +8065: [945, 788, 837], +8066: [945, 787, 768, 837], +8067: [945, 788, 768, 837], +8068: [945, 787, 769, 837], +8069: [945, 788, 769, 837], +8070: [945, 787, 834, 837], +8071: [945, 788, 834, 837], +8072: [913, 787, 837], +8073: [913, 788, 837], +8074: [913, 787, 768, 837], +8075: [913, 788, 768, 837], +8076: [913, 787, 769, 837], +8077: [913, 788, 769, 837], +8078: [913, 787, 834, 837], +8079: [913, 788, 834, 837], +8080: [951, 787, 837], +8081: [951, 788, 837], +8082: [951, 787, 768, 837], +8083: [951, 788, 768, 837], +8084: [951, 787, 769, 837], +8085: [951, 788, 769, 837], +8086: [951, 787, 834, 837], +8087: [951, 788, 834, 837], +8088: [919, 787, 837], +8089: [919, 788, 837], +8090: [919, 787, 768, 837], +8091: [919, 788, 768, 837], +8092: [919, 787, 769, 837], +8093: [919, 788, 769, 837], +8094: [919, 787, 834, 837], +8095: [919, 788, 834, 837], +8096: [969, 787, 837], +8097: [969, 788, 837], +8098: [969, 787, 768, 837], +8099: [969, 788, 768, 837], +8100: [969, 787, 769, 837], +8101: [969, 788, 769, 837], +8102: [969, 787, 834, 837], +8103: [969, 788, 834, 837], +8104: [937, 787, 837], +8105: [937, 788, 837], +8106: [937, 787, 768, 837], +8107: [937, 788, 768, 837], +8108: [937, 787, 769, 837], +8109: [937, 788, 769, 837], +8110: [937, 787, 834, 837], +8111: [937, 788, 834, 837], +8112: [945, 774], +8113: [945, 772], +8114: [945, 768, 837], +8115: [945, 837], +8116: [945, 769, 837], +8118: [945, 834], +8119: [945, 834, 837], +8120: [913, 774], +8121: [913, 772], +8122: [913, 768], +8123: [913, 769], +8124: [913, 837], +8126: [953], +8129: [168, 834], +8130: [951, 768, 837], +8131: [951, 837], +8132: [951, 769, 837], +8134: [951, 834], +8135: [951, 834, 837], +8136: [917, 768], +8137: [917, 769], +8138: [919, 768], +8139: [919, 769], +8140: [919, 837], +8141: [8127, 768], +8142: [8127, 769], +8143: [8127, 834], +8144: [953, 774], +8145: [953, 772], +8146: [953, 776, 768], +8147: [953, 776, 769], +8150: [953, 834], +8151: [953, 776, 834], +8152: [921, 774], +8153: [921, 772], +8154: [921, 768], +8155: [921, 769], +8157: [8190, 768], +8158: [8190, 769], +8159: [8190, 834], +8160: [965, 774], +8161: [965, 772], +8162: [965, 776, 768], +8163: [965, 776, 769], +8164: [961, 787], +8165: [961, 788], +8166: [965, 834], +8167: [965, 776, 834], +8168: [933, 774], +8169: [933, 772], +8170: [933, 768], +8171: [933, 769], +8172: [929, 788], +8173: [168, 768], +8174: [168, 769], +8175: [96], +8178: [969, 768, 837], +8179: [969, 837], +8180: [969, 769, 837], +8182: [969, 834], +8183: [969, 834, 837], +8184: [927, 768], +8185: [927, 769], +8186: [937, 768], +8187: [937, 769], +8188: [937, 837], +8189: [180], +8192: [8194], +8193: [8195], +8486: [937], +8490: [75], +8491: [65, 778], +8602: [8592, 824], +8603: [8594, 824], +8622: [8596, 824], +8653: [8656, 824], +8654: [8660, 824], +8655: [8658, 824], +8708: [8707, 824], +8713: [8712, 824], +8716: [8715, 824], +8740: [8739, 824], +8742: [8741, 824], +8769: [8764, 824], +8772: [8771, 824], +8775: [8773, 824], +8777: [8776, 824], +8800: [61, 824], +8802: [8801, 824], +8813: [8781, 824], +8814: [60, 824], +8815: [62, 824], +8816: [8804, 824], +8817: [8805, 824], +8820: [8818, 824], +8821: [8819, 824], +8824: [8822, 824], +8825: [8823, 824], +8832: [8826, 824], +8833: [8827, 824], +8836: [8834, 824], +8837: [8835, 824], +8840: [8838, 824], +8841: [8839, 824], +8876: [8866, 824], +8877: [8872, 824], +8878: [8873, 824], +8879: [8875, 824], +8928: [8828, 824], +8929: [8829, 824], +8930: [8849, 824], +8931: [8850, 824], +8938: [8882, 824], +8939: [8883, 824], +8940: [8884, 824], +8941: [8885, 824], +9001: [12296], +9002: [12297], +10972: [10973, 824], +12364: [12363, 12441], +12366: [12365, 12441], +12368: [12367, 12441], +12370: [12369, 12441], +12372: [12371, 12441], +12374: [12373, 12441], +12376: [12375, 12441], +12378: [12377, 12441], +12380: [12379, 12441], +12382: [12381, 12441], +12384: [12383, 12441], +12386: [12385, 12441], +12389: [12388, 12441], +12391: [12390, 12441], +12393: [12392, 12441], +12400: [12399, 12441], +12401: [12399, 12442], +12403: [12402, 12441], +12404: [12402, 12442], +12406: [12405, 12441], +12407: [12405, 12442], +12409: [12408, 12441], +12410: [12408, 12442], +12412: [12411, 12441], +12413: [12411, 12442], +12436: [12358, 12441], +12446: [12445, 12441], +12460: [12459, 12441], +12462: [12461, 12441], +12464: [12463, 12441], +12466: [12465, 12441], +12468: [12467, 12441], +12470: [12469, 12441], +12472: [12471, 12441], +12474: [12473, 12441], +12476: [12475, 12441], +12478: [12477, 12441], +12480: [12479, 12441], +12482: [12481, 12441], +12485: [12484, 12441], +12487: [12486, 12441], +12489: [12488, 12441], +12496: [12495, 12441], +12497: [12495, 12442], +12499: [12498, 12441], +12500: [12498, 12442], +12502: [12501, 12441], +12503: [12501, 12442], +12505: [12504, 12441], +12506: [12504, 12442], +12508: [12507, 12441], +12509: [12507, 12442], +12532: [12454, 12441], +12535: [12527, 12441], +12536: [12528, 12441], +12537: [12529, 12441], +12538: [12530, 12441], +12542: [12541, 12441], +63744: [35912], +63745: [26356], +63746: [36554], +63747: [36040], +63748: [28369], +63749: [20018], +63750: [21477], +63751: [40860], +63752: [40860], +63753: [22865], +63754: [37329], +63755: [21895], +63756: [22856], +63757: [25078], +63758: [30313], +63759: [32645], +63760: [34367], +63761: [34746], +63762: [35064], +63763: [37007], +63764: [27138], +63765: [27931], +63766: [28889], +63767: [29662], +63768: [33853], +63769: [37226], +63770: [39409], +63771: [20098], +63772: [21365], +63773: [27396], +63774: [29211], +63775: [34349], +63776: [40478], +63777: [23888], +63778: [28651], +63779: [34253], +63780: [35172], +63781: [25289], +63782: [33240], +63783: [34847], +63784: [24266], +63785: [26391], +63786: [28010], +63787: [29436], +63788: [37070], +63789: [20358], +63790: [20919], +63791: [21214], +63792: [25796], +63793: [27347], +63794: [29200], +63795: [30439], +63796: [32769], +63797: [34310], +63798: [34396], +63799: [36335], +63800: [38706], +63801: [39791], +63802: [40442], +63803: [30860], +63804: [31103], +63805: [32160], +63806: [33737], +63807: [37636], +63808: [40575], +63809: [35542], +63810: [22751], +63811: [24324], +63812: [31840], +63813: [32894], +63814: [29282], +63815: [30922], +63816: [36034], +63817: [38647], +63818: [22744], +63819: [23650], +63820: [27155], +63821: [28122], +63822: [28431], +63823: [32047], +63824: [32311], +63825: [38475], +63826: [21202], +63827: [32907], +63828: [20956], +63829: [20940], +63830: [31260], +63831: [32190], +63832: [33777], +63833: [38517], +63834: [35712], +63835: [25295], +63836: [27138], +63837: [35582], +63838: [20025], +63839: [23527], +63840: [24594], +63841: [29575], +63842: [30064], +63843: [21271], +63844: [30971], +63845: [20415], +63846: [24489], +63847: [19981], +63848: [27852], +63849: [25976], +63850: [32034], +63851: [21443], +63852: [22622], +63853: [30465], +63854: [33865], +63855: [35498], +63856: [27578], +63857: [36784], +63858: [27784], +63859: [25342], +63860: [33509], +63861: [25504], +63862: [30053], +63863: [20142], +63864: [20841], +63865: [20937], +63866: [26753], +63867: [31975], +63868: [33391], +63869: [35538], +63870: [37327], +63871: [21237], +63872: [21570], +63873: [22899], +63874: [24300], +63875: [26053], +63876: [28670], +63877: [31018], +63878: [38317], +63879: [39530], +63880: [40599], +63881: [40654], +63882: [21147], +63883: [26310], +63884: [27511], +63885: [36706], +63886: [24180], +63887: [24976], +63888: [25088], +63889: [25754], +63890: [28451], +63891: [29001], +63892: [29833], +63893: [31178], +63894: [32244], +63895: [32879], +63896: [36646], +63897: [34030], +63898: [36899], +63899: [37706], +63900: [21015], +63901: [21155], +63902: [21693], +63903: [28872], +63904: [35010], +63905: [35498], +63906: [24265], +63907: [24565], +63908: [25467], +63909: [27566], +63910: [31806], +63911: [29557], +63912: [20196], +63913: [22265], +63914: [23527], +63915: [23994], +63916: [24604], +63917: [29618], +63918: [29801], +63919: [32666], +63920: [32838], +63921: [37428], +63922: [38646], +63923: [38728], +63924: [38936], +63925: [20363], +63926: [31150], +63927: [37300], +63928: [38584], +63929: [24801], +63930: [20102], +63931: [20698], +63932: [23534], +63933: [23615], +63934: [26009], +63935: [27138], +63936: [29134], +63937: [30274], +63938: [34044], +63939: [36988], +63940: [40845], +63941: [26248], +63942: [38446], +63943: [21129], +63944: [26491], +63945: [26611], +63946: [27969], +63947: [28316], +63948: [29705], +63949: [30041], +63950: [30827], +63951: [32016], +63952: [39006], +63953: [20845], +63954: [25134], +63955: [38520], +63956: [20523], +63957: [23833], +63958: [28138], +63959: [36650], +63960: [24459], +63961: [24900], +63962: [26647], +63963: [29575], +63964: [38534], +63965: [21033], +63966: [21519], +63967: [23653], +63968: [26131], +63969: [26446], +63970: [26792], +63971: [27877], +63972: [29702], +63973: [30178], +63974: [32633], +63975: [35023], +63976: [35041], +63977: [37324], +63978: [38626], +63979: [21311], +63980: [28346], +63981: [21533], +63982: [29136], +63983: [29848], +63984: [34298], +63985: [38563], +63986: [40023], +63987: [40607], +63988: [26519], +63989: [28107], +63990: [33256], +63991: [31435], +63992: [31520], +63993: [31890], +63994: [29376], +63995: [28825], +63996: [35672], +63997: [20160], +63998: [33590], +63999: [21050], +64000: [20999], +64001: [24230], +64002: [25299], +64003: [31958], +64004: [23429], +64005: [27934], +64006: [26292], +64007: [36667], +64008: [34892], +64009: [38477], +64010: [35211], +64011: [24275], +64012: [20800], +64013: [21952], +64016: [22618], +64018: [26228], +64021: [20958], +64022: [29482], +64023: [30410], +64024: [31036], +64025: [31070], +64026: [31077], +64027: [31119], +64028: [38742], +64029: [31934], +64030: [32701], +64032: [34322], +64034: [35576], +64037: [36920], +64038: [37117], +64042: [39151], +64043: [39164], +64044: [39208], +64045: [40372], +64048: [20398], +64049: [20711], +64050: [20813], +64051: [21193], +64052: [21220], +64053: [21329], +64054: [21917], +64055: [22022], +64056: [22120], +64057: [22592], +64058: [22696], +64059: [23652], +64060: [23662], +64061: [24724], +64062: [24936], +64063: [24974], +64064: [25074], +64065: [25935], +64066: [26082], +64067: [26257], +64068: [26757], +64069: [28023], +64070: [28186], +64071: [28450], +64072: [29038], +64073: [29227], +64074: [29730], +64075: [30865], +64076: [31038], +64077: [31049], +64078: [31048], +64079: [31056], +64080: [31062], +64081: [31069], +64082: [31117], +64083: [31118], +64084: [31296], +64085: [31361], +64086: [31680], +64087: [32244], +64088: [32265], +64089: [32321], +64090: [32626], +64091: [32773], +64092: [33261], +64093: [33401], +64094: [33401], +64095: [33879], +64096: [35088], +64097: [35222], +64098: [35585], +64099: [35641], +64100: [36051], +64101: [36104], +64102: [36790], +64103: [36920], +64104: [38627], +64105: [38911], +64106: [38971], +64285: [1497, 1460], +64287: [1522, 1463], +64298: [1513, 1473], +64299: [1513, 1474], +64300: [1513, 1468, 1473], +64301: [1513, 1468, 1474], +64302: [1488, 1463], +64303: [1488, 1464], +64304: [1488, 1468], +64305: [1489, 1468], +64306: [1490, 1468], +64307: [1491, 1468], +64308: [1492, 1468], +64309: [1493, 1468], +64310: [1494, 1468], +64312: [1496, 1468], +64313: [1497, 1468], +64314: [1498, 1468], +64315: [1499, 1468], +64316: [1500, 1468], +64318: [1502, 1468], +64320: [1504, 1468], +64321: [1505, 1468], +64323: [1507, 1468], +64324: [1508, 1468], +64326: [1510, 1468], +64327: [1511, 1468], +64328: [1512, 1468], +64329: [1513, 1468], +64330: [1514, 1468], +64331: [1493, 1465], +64332: [1489, 1471], +64333: [1499, 1471], +64334: [1508, 1471], +119134: [119127, 119141], +119135: [119128, 119141], +119136: [119128, 119141, 119150], +119137: [119128, 119141, 119151], +119138: [119128, 119141, 119152], +119139: [119128, 119141, 119153], +119140: [119128, 119141, 119154], +119227: [119225, 119141], +119228: [119226, 119141], +119229: [119225, 119141, 119150], +119230: [119226, 119141, 119150], +119231: [119225, 119141, 119151], +119232: [119226, 119141, 119151], +194560: [20029], +194561: [20024], +194562: [20033], +194563: [131362], +194564: [20320], +194565: [20398], +194566: [20411], +194567: [20482], +194568: [20602], +194569: [20633], +194570: [20711], +194571: [20687], +194572: [13470], +194573: [132666], +194574: [20813], +194575: [20820], +194576: [20836], +194577: [20855], +194578: [132380], +194579: [13497], +194580: [20839], +194581: [20877], +194582: [132427], +194583: [20887], +194584: [20900], +194585: [20172], +194586: [20908], +194587: [20917], +194588: [168415], +194589: [20981], +194590: [20995], +194591: [13535], +194592: [21051], +194593: [21062], +194594: [21106], +194595: [21111], +194596: [13589], +194597: [21191], +194598: [21193], +194599: [21220], +194600: [21242], +194601: [21253], +194602: [21254], +194603: [21271], +194604: [21321], +194605: [21329], +194606: [21338], +194607: [21363], +194608: [21373], +194609: [21375], +194610: [21375], +194611: [21375], +194612: [133676], +194613: [28784], +194614: [21450], +194615: [21471], +194616: [133987], +194617: [21483], +194618: [21489], +194619: [21510], +194620: [21662], +194621: [21560], +194622: [21576], +194623: [21608], +194624: [21666], +194625: [21750], +194626: [21776], +194627: [21843], +194628: [21859], +194629: [21892], +194630: [21892], +194631: [21913], +194632: [21931], +194633: [21939], +194634: [21954], +194635: [22294], +194636: [22022], +194637: [22295], +194638: [22097], +194639: [22132], +194640: [20999], +194641: [22766], +194642: [22478], +194643: [22516], +194644: [22541], +194645: [22411], +194646: [22578], +194647: [22577], +194648: [22700], +194649: [136420], +194650: [22770], +194651: [22775], +194652: [22790], +194653: [22810], +194654: [22818], +194655: [22882], +194656: [136872], +194657: [136938], +194658: [23020], +194659: [23067], +194660: [23079], +194661: [23000], +194662: [23142], +194663: [14062], +194664: [136042], +194665: [23304], +194666: [23358], +194667: [23358], +194668: [137672], +194669: [23491], +194670: [23512], +194671: [23527], +194672: [23539], +194673: [138008], +194674: [23551], +194675: [23558], +194676: [24371], +194677: [23586], +194678: [14209], +194679: [23648], +194680: [23662], +194681: [23744], +194682: [23693], +194683: [138724], +194684: [23875], +194685: [138726], +194686: [23918], +194687: [23915], +194688: [23932], +194689: [24033], +194690: [24034], +194691: [14383], +194692: [24061], +194693: [24104], +194694: [24125], +194695: [24169], +194696: [14434], +194697: [139651], +194698: [14460], +194699: [24240], +194700: [24243], +194701: [24246], +194702: [24266], +194703: [172946], +194704: [24318], +194705: [140081], +194706: [140081], +194707: [33281], +194708: [24354], +194709: [24354], +194710: [14535], +194711: [144056], +194712: [156122], +194713: [24418], +194714: [24427], +194715: [14563], +194716: [24474], +194717: [24525], +194718: [24535], +194719: [24569], +194720: [24705], +194721: [14650], +194722: [14620], +194723: [24724], +194724: [141012], +194725: [24775], +194726: [24904], +194727: [24908], +194728: [24910], +194729: [24908], +194730: [24954], +194731: [24974], +194732: [25010], +194733: [24996], +194734: [25007], +194735: [25054], +194736: [25074], +194737: [25078], +194738: [25104], +194739: [25115], +194740: [25181], +194741: [25265], +194742: [25300], +194743: [25424], +194744: [142092], +194745: [25405], +194746: [25340], +194747: [25448], +194748: [25475], +194749: [25572], +194750: [142321], +194751: [25634], +194752: [25541], +194753: [25513], +194754: [14894], +194755: [25705], +194756: [25726], +194757: [25757], +194758: [25719], +194759: [14956], +194760: [25935], +194761: [25964], +194762: [143370], +194763: [26083], +194764: [26360], +194765: [26185], +194766: [15129], +194767: [26257], +194768: [15112], +194769: [15076], +194770: [20882], +194771: [20885], +194772: [26368], +194773: [26268], +194774: [32941], +194775: [17369], +194776: [26391], +194777: [26395], +194778: [26401], +194779: [26462], +194780: [26451], +194781: [144323], +194782: [15177], +194783: [26618], +194784: [26501], +194785: [26706], +194786: [26757], +194787: [144493], +194788: [26766], +194789: [26655], +194790: [26900], +194791: [15261], +194792: [26946], +194793: [27043], +194794: [27114], +194795: [27304], +194796: [145059], +194797: [27355], +194798: [15384], +194799: [27425], +194800: [145575], +194801: [27476], +194802: [15438], +194803: [27506], +194804: [27551], +194805: [27578], +194806: [27579], +194807: [146061], +194808: [138507], +194809: [146170], +194810: [27726], +194811: [146620], +194812: [27839], +194813: [27853], +194814: [27751], +194815: [27926], +194816: [27966], +194817: [28023], +194818: [27969], +194819: [28009], +194820: [28024], +194821: [28037], +194822: [146718], +194823: [27956], +194824: [28207], +194825: [28270], +194826: [15667], +194827: [28363], +194828: [28359], +194829: [147153], +194830: [28153], +194831: [28526], +194832: [147294], +194833: [147342], +194834: [28614], +194835: [28729], +194836: [28702], +194837: [28699], +194838: [15766], +194839: [28746], +194840: [28797], +194841: [28791], +194842: [28845], +194843: [132389], +194844: [28997], +194845: [148067], +194846: [29084], +194847: [17323], +194848: [29224], +194849: [29237], +194850: [29264], +194851: [149000], +194852: [29312], +194853: [29333], +194854: [149301], +194855: [149524], +194856: [29562], +194857: [29579], +194858: [16044], +194859: [29605], +194860: [16056], +194861: [16056], +194862: [29767], +194863: [29788], +194864: [29809], +194865: [29829], +194866: [29898], +194867: [16155], +194868: [29988], +194869: [150582], +194870: [30014], +194871: [150674], +194872: [30064], +194873: [139679], +194874: [30224], +194875: [151457], +194876: [151480], +194877: [151620], +194878: [16380], +194879: [16392], +194880: [30452], +194881: [151795], +194882: [151794], +194883: [151833], +194884: [151859], +194885: [30494], +194886: [30495], +194887: [30495], +194888: [30538], +194889: [16441], +194890: [30603], +194891: [16454], +194892: [16534], +194893: [152605], +194894: [30798], +194895: [30860], +194896: [30924], +194897: [16611], +194898: [153126], +194899: [31062], +194900: [153242], +194901: [153285], +194902: [31119], +194903: [31211], +194904: [16687], +194905: [31296], +194906: [31306], +194907: [31311], +194908: [153980], +194909: [154279], +194910: [154279], +194911: [31406], +194912: [16898], +194913: [154539], +194914: [31686], +194915: [31689], +194916: [16935], +194917: [154752], +194918: [31954], +194919: [17056], +194920: [31976], +194921: [31971], +194922: [32000], +194923: [155526], +194924: [32099], +194925: [17153], +194926: [32199], +194927: [32258], +194928: [32325], +194929: [17204], +194930: [156200], +194931: [156231], +194932: [17241], +194933: [156377], +194934: [32634], +194935: [156478], +194936: [32661], +194937: [32762], +194938: [32773], +194939: [156890], +194940: [156963], +194941: [32864], +194942: [157096], +194943: [32880], +194944: [144223], +194945: [17365], +194946: [32946], +194947: [33027], +194948: [17419], +194949: [33086], +194950: [23221], +194951: [157607], +194952: [157621], +194953: [144275], +194954: [144284], +194955: [33281], +194956: [33284], +194957: [36766], +194958: [17515], +194959: [33425], +194960: [33419], +194961: [33437], +194962: [21171], +194963: [33457], +194964: [33459], +194965: [33469], +194966: [33510], +194967: [158524], +194968: [33509], +194969: [33565], +194970: [33635], +194971: [33709], +194972: [33571], +194973: [33725], +194974: [33767], +194975: [33879], +194976: [33619], +194977: [33738], +194978: [33740], +194979: [33756], +194980: [158774], +194981: [159083], +194982: [158933], +194983: [17707], +194984: [34033], +194985: [34035], +194986: [34070], +194987: [160714], +194988: [34148], +194989: [159532], +194990: [17757], +194991: [17761], +194992: [159665], +194993: [159954], +194994: [17771], +194995: [34384], +194996: [34396], +194997: [34407], +194998: [34409], +194999: [34473], +195000: [34440], +195001: [34574], +195002: [34530], +195003: [34681], +195004: [34600], +195005: [34667], +195006: [34694], +195007: [19799], +195008: [34785], +195009: [34817], +195010: [17913], +195011: [34912], +195012: [34915], +195013: [161383], +195014: [35031], +195015: [35038], +195016: [17973], +195017: [35066], +195018: [13499], +195019: [161966], +195020: [162150], +195021: [18110], +195022: [18119], +195023: [35488], +195024: [35565], +195025: [35722], +195026: [35925], +195027: [162984], +195028: [36011], +195029: [36033], +195030: [36123], +195031: [36215], +195032: [163631], +195033: [133124], +195034: [36299], +195035: [36284], +195036: [36336], +195037: [133342], +195038: [36564], +195039: [36664], +195040: [165330], +195041: [165357], +195042: [37012], +195043: [37105], +195044: [37137], +195045: [165678], +195046: [37147], +195047: [37432], +195048: [37591], +195049: [37592], +195050: [37500], +195051: [37881], +195052: [37909], +195053: [166906], +195054: [38283], +195055: [18837], +195056: [38327], +195057: [167287], +195058: [18918], +195059: [38595], +195060: [23986], +195061: [38691], +195062: [168261], +195063: [168474], +195064: [19054], +195065: [19062], +195066: [38880], +195067: [168970], +195068: [19122], +195069: [169110], +195070: [38923], +195071: [38923], +195072: [38953], +195073: [169398], +195074: [39138], +195075: [19251], +195076: [39209], +195077: [39335], +195078: [39362], +195079: [39422], +195080: [19406], +195081: [170800], +195082: [39698], +195083: [40000], +195084: [40189], +195085: [19662], +195086: [19693], +195087: [40295], +195088: [172238], +195089: [19704], +195090: [172293], +195091: [172558], +195092: [172689], +195093: [40635], +195094: [19798], +195095: [40697], +195096: [40702], +195097: [40709], +195098: [40719], +195099: [40726], +195100: [40763], +195101: [173568], +} + +_compat_decomposition = { +160: [32], +168: [32, 776], +170: [97], +175: [32, 772], +178: [50], +179: [51], +180: [32, 769], +181: [956], +184: [32, 807], +185: [49], +186: [111], +188: [49, 8260, 52], +189: [49, 8260, 50], +190: [51, 8260, 52], +192: [65, 768], +193: [65, 769], +194: [65, 770], +195: [65, 771], +196: [65, 776], +197: [65, 778], +199: [67, 807], +200: [69, 768], +201: [69, 769], +202: [69, 770], +203: [69, 776], +204: [73, 768], +205: [73, 769], +206: [73, 770], +207: [73, 776], +209: [78, 771], +210: [79, 768], +211: [79, 769], +212: [79, 770], +213: [79, 771], +214: [79, 776], +217: [85, 768], +218: [85, 769], +219: [85, 770], +220: [85, 776], +221: [89, 769], +224: [97, 768], +225: [97, 769], +226: [97, 770], +227: [97, 771], +228: [97, 776], +229: [97, 778], +231: [99, 807], +232: [101, 768], +233: [101, 769], +234: [101, 770], +235: [101, 776], +236: [105, 768], +237: [105, 769], +238: [105, 770], +239: [105, 776], +241: [110, 771], +242: [111, 768], +243: [111, 769], +244: [111, 770], +245: [111, 771], +246: [111, 776], +249: [117, 768], +250: [117, 769], +251: [117, 770], +252: [117, 776], +253: [121, 769], +255: [121, 776], +256: [65, 772], +257: [97, 772], +258: [65, 774], +259: [97, 774], +260: [65, 808], +261: [97, 808], +262: [67, 769], +263: [99, 769], +264: [67, 770], +265: [99, 770], +266: [67, 775], +267: [99, 775], +268: [67, 780], +269: [99, 780], +270: [68, 780], +271: [100, 780], +274: [69, 772], +275: [101, 772], +276: [69, 774], +277: [101, 774], +278: [69, 775], +279: [101, 775], +280: [69, 808], +281: [101, 808], +282: [69, 780], +283: [101, 780], +284: [71, 770], +285: [103, 770], +286: [71, 774], +287: [103, 774], +288: [71, 775], +289: [103, 775], +290: [71, 807], +291: [103, 807], +292: [72, 770], +293: [104, 770], +296: [73, 771], +297: [105, 771], +298: [73, 772], +299: [105, 772], +300: [73, 774], +301: [105, 774], +302: [73, 808], +303: [105, 808], +304: [73, 775], +306: [73, 74], +307: [105, 106], +308: [74, 770], +309: [106, 770], +310: [75, 807], +311: [107, 807], +313: [76, 769], +314: [108, 769], +315: [76, 807], +316: [108, 807], +317: [76, 780], +318: [108, 780], +319: [76, 183], +320: [108, 183], +323: [78, 769], +324: [110, 769], +325: [78, 807], +326: [110, 807], +327: [78, 780], +328: [110, 780], +329: [700, 110], +332: [79, 772], +333: [111, 772], +334: [79, 774], +335: [111, 774], +336: [79, 779], +337: [111, 779], +340: [82, 769], +341: [114, 769], +342: [82, 807], +343: [114, 807], +344: [82, 780], +345: [114, 780], +346: [83, 769], +347: [115, 769], +348: [83, 770], +349: [115, 770], +350: [83, 807], +351: [115, 807], +352: [83, 780], +353: [115, 780], +354: [84, 807], +355: [116, 807], +356: [84, 780], +357: [116, 780], +360: [85, 771], +361: [117, 771], +362: [85, 772], +363: [117, 772], +364: [85, 774], +365: [117, 774], +366: [85, 778], +367: [117, 778], +368: [85, 779], +369: [117, 779], +370: [85, 808], +371: [117, 808], +372: [87, 770], +373: [119, 770], +374: [89, 770], +375: [121, 770], +376: [89, 776], +377: [90, 769], +378: [122, 769], +379: [90, 775], +380: [122, 775], +381: [90, 780], +382: [122, 780], +383: [115], +416: [79, 795], +417: [111, 795], +431: [85, 795], +432: [117, 795], +452: [68, 90, 780], +453: [68, 122, 780], +454: [100, 122, 780], +455: [76, 74], +456: [76, 106], +457: [108, 106], +458: [78, 74], +459: [78, 106], +460: [110, 106], +461: [65, 780], +462: [97, 780], +463: [73, 780], +464: [105, 780], +465: [79, 780], +466: [111, 780], +467: [85, 780], +468: [117, 780], +469: [85, 776, 772], +470: [117, 776, 772], +471: [85, 776, 769], +472: [117, 776, 769], +473: [85, 776, 780], +474: [117, 776, 780], +475: [85, 776, 768], +476: [117, 776, 768], +478: [65, 776, 772], +479: [97, 776, 772], +480: [65, 775, 772], +481: [97, 775, 772], +482: [198, 772], +483: [230, 772], +486: [71, 780], +487: [103, 780], +488: [75, 780], +489: [107, 780], +490: [79, 808], +491: [111, 808], +492: [79, 808, 772], +493: [111, 808, 772], +494: [439, 780], +495: [658, 780], +496: [106, 780], +497: [68, 90], +498: [68, 122], +499: [100, 122], +500: [71, 769], +501: [103, 769], +504: [78, 768], +505: [110, 768], +506: [65, 778, 769], +507: [97, 778, 769], +508: [198, 769], +509: [230, 769], +510: [216, 769], +511: [248, 769], +512: [65, 783], +513: [97, 783], +514: [65, 785], +515: [97, 785], +516: [69, 783], +517: [101, 783], +518: [69, 785], +519: [101, 785], +520: [73, 783], +521: [105, 783], +522: [73, 785], +523: [105, 785], +524: [79, 783], +525: [111, 783], +526: [79, 785], +527: [111, 785], +528: [82, 783], +529: [114, 783], +530: [82, 785], +531: [114, 785], +532: [85, 783], +533: [117, 783], +534: [85, 785], +535: [117, 785], +536: [83, 806], +537: [115, 806], +538: [84, 806], +539: [116, 806], +542: [72, 780], +543: [104, 780], +550: [65, 775], +551: [97, 775], +552: [69, 807], +553: [101, 807], +554: [79, 776, 772], +555: [111, 776, 772], +556: [79, 771, 772], +557: [111, 771, 772], +558: [79, 775], +559: [111, 775], +560: [79, 775, 772], +561: [111, 775, 772], +562: [89, 772], +563: [121, 772], +688: [104], +689: [614], +690: [106], +691: [114], +692: [633], +693: [635], +694: [641], +695: [119], +696: [121], +728: [32, 774], +729: [32, 775], +730: [32, 778], +731: [32, 808], +732: [32, 771], +733: [32, 779], +736: [611], +737: [108], +738: [115], +739: [120], +740: [661], +832: [768], +833: [769], +835: [787], +836: [776, 769], +884: [697], +890: [32, 837], +894: [59], +900: [32, 769], +901: [32, 776, 769], +902: [913, 769], +903: [183], +904: [917, 769], +905: [919, 769], +906: [921, 769], +908: [927, 769], +910: [933, 769], +911: [937, 769], +912: [953, 776, 769], +938: [921, 776], +939: [933, 776], +940: [945, 769], +941: [949, 769], +942: [951, 769], +943: [953, 769], +944: [965, 776, 769], +970: [953, 776], +971: [965, 776], +972: [959, 769], +973: [965, 769], +974: [969, 769], +976: [946], +977: [952], +978: [933], +979: [933, 769], +980: [933, 776], +981: [966], +982: [960], +1008: [954], +1009: [961], +1010: [962], +1012: [920], +1013: [949], +1024: [1045, 768], +1025: [1045, 776], +1027: [1043, 769], +1031: [1030, 776], +1036: [1050, 769], +1037: [1048, 768], +1038: [1059, 774], +1049: [1048, 774], +1081: [1080, 774], +1104: [1077, 768], +1105: [1077, 776], +1107: [1075, 769], +1111: [1110, 776], +1116: [1082, 769], +1117: [1080, 768], +1118: [1091, 774], +1142: [1140, 783], +1143: [1141, 783], +1217: [1046, 774], +1218: [1078, 774], +1232: [1040, 774], +1233: [1072, 774], +1234: [1040, 776], +1235: [1072, 776], +1238: [1045, 774], +1239: [1077, 774], +1242: [1240, 776], +1243: [1241, 776], +1244: [1046, 776], +1245: [1078, 776], +1246: [1047, 776], +1247: [1079, 776], +1250: [1048, 772], +1251: [1080, 772], +1252: [1048, 776], +1253: [1080, 776], +1254: [1054, 776], +1255: [1086, 776], +1258: [1256, 776], +1259: [1257, 776], +1260: [1069, 776], +1261: [1101, 776], +1262: [1059, 772], +1263: [1091, 772], +1264: [1059, 776], +1265: [1091, 776], +1266: [1059, 779], +1267: [1091, 779], +1268: [1063, 776], +1269: [1095, 776], +1272: [1067, 776], +1273: [1099, 776], +1415: [1381, 1410], +1570: [1575, 1619], +1571: [1575, 1620], +1572: [1608, 1620], +1573: [1575, 1621], +1574: [1610, 1620], +1653: [1575, 1652], +1654: [1608, 1652], +1655: [1735, 1652], +1656: [1610, 1652], +1728: [1749, 1620], +1730: [1729, 1620], +1747: [1746, 1620], +2345: [2344, 2364], +2353: [2352, 2364], +2356: [2355, 2364], +2392: [2325, 2364], +2393: [2326, 2364], +2394: [2327, 2364], +2395: [2332, 2364], +2396: [2337, 2364], +2397: [2338, 2364], +2398: [2347, 2364], +2399: [2351, 2364], +2507: [2503, 2494], +2508: [2503, 2519], +2524: [2465, 2492], +2525: [2466, 2492], +2527: [2479, 2492], +2611: [2610, 2620], +2614: [2616, 2620], +2649: [2582, 2620], +2650: [2583, 2620], +2651: [2588, 2620], +2654: [2603, 2620], +2888: [2887, 2902], +2891: [2887, 2878], +2892: [2887, 2903], +2908: [2849, 2876], +2909: [2850, 2876], +2964: [2962, 3031], +3018: [3014, 3006], +3019: [3015, 3006], +3020: [3014, 3031], +3144: [3142, 3158], +3264: [3263, 3285], +3271: [3270, 3285], +3272: [3270, 3286], +3274: [3270, 3266], +3275: [3270, 3266, 3285], +3402: [3398, 3390], +3403: [3399, 3390], +3404: [3398, 3415], +3546: [3545, 3530], +3548: [3545, 3535], +3549: [3545, 3535, 3530], +3550: [3545, 3551], +3635: [3661, 3634], +3763: [3789, 3762], +3804: [3755, 3737], +3805: [3755, 3745], +3852: [3851], +3907: [3906, 4023], +3917: [3916, 4023], +3922: [3921, 4023], +3927: [3926, 4023], +3932: [3931, 4023], +3945: [3904, 4021], +3955: [3953, 3954], +3957: [3953, 3956], +3958: [4018, 3968], +3959: [4018, 3953, 3968], +3960: [4019, 3968], +3961: [4019, 3953, 3968], +3969: [3953, 3968], +3987: [3986, 4023], +3997: [3996, 4023], +4002: [4001, 4023], +4007: [4006, 4023], +4012: [4011, 4023], +4025: [3984, 4021], +4134: [4133, 4142], +7680: [65, 805], +7681: [97, 805], +7682: [66, 775], +7683: [98, 775], +7684: [66, 803], +7685: [98, 803], +7686: [66, 817], +7687: [98, 817], +7688: [67, 807, 769], +7689: [99, 807, 769], +7690: [68, 775], +7691: [100, 775], +7692: [68, 803], +7693: [100, 803], +7694: [68, 817], +7695: [100, 817], +7696: [68, 807], +7697: [100, 807], +7698: [68, 813], +7699: [100, 813], +7700: [69, 772, 768], +7701: [101, 772, 768], +7702: [69, 772, 769], +7703: [101, 772, 769], +7704: [69, 813], +7705: [101, 813], +7706: [69, 816], +7707: [101, 816], +7708: [69, 807, 774], +7709: [101, 807, 774], +7710: [70, 775], +7711: [102, 775], +7712: [71, 772], +7713: [103, 772], +7714: [72, 775], +7715: [104, 775], +7716: [72, 803], +7717: [104, 803], +7718: [72, 776], +7719: [104, 776], +7720: [72, 807], +7721: [104, 807], +7722: [72, 814], +7723: [104, 814], +7724: [73, 816], +7725: [105, 816], +7726: [73, 776, 769], +7727: [105, 776, 769], +7728: [75, 769], +7729: [107, 769], +7730: [75, 803], +7731: [107, 803], +7732: [75, 817], +7733: [107, 817], +7734: [76, 803], +7735: [108, 803], +7736: [76, 803, 772], +7737: [108, 803, 772], +7738: [76, 817], +7739: [108, 817], +7740: [76, 813], +7741: [108, 813], +7742: [77, 769], +7743: [109, 769], +7744: [77, 775], +7745: [109, 775], +7746: [77, 803], +7747: [109, 803], +7748: [78, 775], +7749: [110, 775], +7750: [78, 803], +7751: [110, 803], +7752: [78, 817], +7753: [110, 817], +7754: [78, 813], +7755: [110, 813], +7756: [79, 771, 769], +7757: [111, 771, 769], +7758: [79, 771, 776], +7759: [111, 771, 776], +7760: [79, 772, 768], +7761: [111, 772, 768], +7762: [79, 772, 769], +7763: [111, 772, 769], +7764: [80, 769], +7765: [112, 769], +7766: [80, 775], +7767: [112, 775], +7768: [82, 775], +7769: [114, 775], +7770: [82, 803], +7771: [114, 803], +7772: [82, 803, 772], +7773: [114, 803, 772], +7774: [82, 817], +7775: [114, 817], +7776: [83, 775], +7777: [115, 775], +7778: [83, 803], +7779: [115, 803], +7780: [83, 769, 775], +7781: [115, 769, 775], +7782: [83, 780, 775], +7783: [115, 780, 775], +7784: [83, 803, 775], +7785: [115, 803, 775], +7786: [84, 775], +7787: [116, 775], +7788: [84, 803], +7789: [116, 803], +7790: [84, 817], +7791: [116, 817], +7792: [84, 813], +7793: [116, 813], +7794: [85, 804], +7795: [117, 804], +7796: [85, 816], +7797: [117, 816], +7798: [85, 813], +7799: [117, 813], +7800: [85, 771, 769], +7801: [117, 771, 769], +7802: [85, 772, 776], +7803: [117, 772, 776], +7804: [86, 771], +7805: [118, 771], +7806: [86, 803], +7807: [118, 803], +7808: [87, 768], +7809: [119, 768], +7810: [87, 769], +7811: [119, 769], +7812: [87, 776], +7813: [119, 776], +7814: [87, 775], +7815: [119, 775], +7816: [87, 803], +7817: [119, 803], +7818: [88, 775], +7819: [120, 775], +7820: [88, 776], +7821: [120, 776], +7822: [89, 775], +7823: [121, 775], +7824: [90, 770], +7825: [122, 770], +7826: [90, 803], +7827: [122, 803], +7828: [90, 817], +7829: [122, 817], +7830: [104, 817], +7831: [116, 776], +7832: [119, 778], +7833: [121, 778], +7834: [97, 702], +7835: [115, 775], +7840: [65, 803], +7841: [97, 803], +7842: [65, 777], +7843: [97, 777], +7844: [65, 770, 769], +7845: [97, 770, 769], +7846: [65, 770, 768], +7847: [97, 770, 768], +7848: [65, 770, 777], +7849: [97, 770, 777], +7850: [65, 770, 771], +7851: [97, 770, 771], +7852: [65, 803, 770], +7853: [97, 803, 770], +7854: [65, 774, 769], +7855: [97, 774, 769], +7856: [65, 774, 768], +7857: [97, 774, 768], +7858: [65, 774, 777], +7859: [97, 774, 777], +7860: [65, 774, 771], +7861: [97, 774, 771], +7862: [65, 803, 774], +7863: [97, 803, 774], +7864: [69, 803], +7865: [101, 803], +7866: [69, 777], +7867: [101, 777], +7868: [69, 771], +7869: [101, 771], +7870: [69, 770, 769], +7871: [101, 770, 769], +7872: [69, 770, 768], +7873: [101, 770, 768], +7874: [69, 770, 777], +7875: [101, 770, 777], +7876: [69, 770, 771], +7877: [101, 770, 771], +7878: [69, 803, 770], +7879: [101, 803, 770], +7880: [73, 777], +7881: [105, 777], +7882: [73, 803], +7883: [105, 803], +7884: [79, 803], +7885: [111, 803], +7886: [79, 777], +7887: [111, 777], +7888: [79, 770, 769], +7889: [111, 770, 769], +7890: [79, 770, 768], +7891: [111, 770, 768], +7892: [79, 770, 777], +7893: [111, 770, 777], +7894: [79, 770, 771], +7895: [111, 770, 771], +7896: [79, 803, 770], +7897: [111, 803, 770], +7898: [79, 795, 769], +7899: [111, 795, 769], +7900: [79, 795, 768], +7901: [111, 795, 768], +7902: [79, 795, 777], +7903: [111, 795, 777], +7904: [79, 795, 771], +7905: [111, 795, 771], +7906: [79, 795, 803], +7907: [111, 795, 803], +7908: [85, 803], +7909: [117, 803], +7910: [85, 777], +7911: [117, 777], +7912: [85, 795, 769], +7913: [117, 795, 769], +7914: [85, 795, 768], +7915: [117, 795, 768], +7916: [85, 795, 777], +7917: [117, 795, 777], +7918: [85, 795, 771], +7919: [117, 795, 771], +7920: [85, 795, 803], +7921: [117, 795, 803], +7922: [89, 768], +7923: [121, 768], +7924: [89, 803], +7925: [121, 803], +7926: [89, 777], +7927: [121, 777], +7928: [89, 771], +7929: [121, 771], +7936: [945, 787], +7937: [945, 788], +7938: [945, 787, 768], +7939: [945, 788, 768], +7940: [945, 787, 769], +7941: [945, 788, 769], +7942: [945, 787, 834], +7943: [945, 788, 834], +7944: [913, 787], +7945: [913, 788], +7946: [913, 787, 768], +7947: [913, 788, 768], +7948: [913, 787, 769], +7949: [913, 788, 769], +7950: [913, 787, 834], +7951: [913, 788, 834], +7952: [949, 787], +7953: [949, 788], +7954: [949, 787, 768], +7955: [949, 788, 768], +7956: [949, 787, 769], +7957: [949, 788, 769], +7960: [917, 787], +7961: [917, 788], +7962: [917, 787, 768], +7963: [917, 788, 768], +7964: [917, 787, 769], +7965: [917, 788, 769], +7968: [951, 787], +7969: [951, 788], +7970: [951, 787, 768], +7971: [951, 788, 768], +7972: [951, 787, 769], +7973: [951, 788, 769], +7974: [951, 787, 834], +7975: [951, 788, 834], +7976: [919, 787], +7977: [919, 788], +7978: [919, 787, 768], +7979: [919, 788, 768], +7980: [919, 787, 769], +7981: [919, 788, 769], +7982: [919, 787, 834], +7983: [919, 788, 834], +7984: [953, 787], +7985: [953, 788], +7986: [953, 787, 768], +7987: [953, 788, 768], +7988: [953, 787, 769], +7989: [953, 788, 769], +7990: [953, 787, 834], +7991: [953, 788, 834], +7992: [921, 787], +7993: [921, 788], +7994: [921, 787, 768], +7995: [921, 788, 768], +7996: [921, 787, 769], +7997: [921, 788, 769], +7998: [921, 787, 834], +7999: [921, 788, 834], +8000: [959, 787], +8001: [959, 788], +8002: [959, 787, 768], +8003: [959, 788, 768], +8004: [959, 787, 769], +8005: [959, 788, 769], +8008: [927, 787], +8009: [927, 788], +8010: [927, 787, 768], +8011: [927, 788, 768], +8012: [927, 787, 769], +8013: [927, 788, 769], +8016: [965, 787], +8017: [965, 788], +8018: [965, 787, 768], +8019: [965, 788, 768], +8020: [965, 787, 769], +8021: [965, 788, 769], +8022: [965, 787, 834], +8023: [965, 788, 834], +8025: [933, 788], +8027: [933, 788, 768], +8029: [933, 788, 769], +8031: [933, 788, 834], +8032: [969, 787], +8033: [969, 788], +8034: [969, 787, 768], +8035: [969, 788, 768], +8036: [969, 787, 769], +8037: [969, 788, 769], +8038: [969, 787, 834], +8039: [969, 788, 834], +8040: [937, 787], +8041: [937, 788], +8042: [937, 787, 768], +8043: [937, 788, 768], +8044: [937, 787, 769], +8045: [937, 788, 769], +8046: [937, 787, 834], +8047: [937, 788, 834], +8048: [945, 768], +8049: [945, 769], +8050: [949, 768], +8051: [949, 769], +8052: [951, 768], +8053: [951, 769], +8054: [953, 768], +8055: [953, 769], +8056: [959, 768], +8057: [959, 769], +8058: [965, 768], +8059: [965, 769], +8060: [969, 768], +8061: [969, 769], +8064: [945, 787, 837], +8065: [945, 788, 837], +8066: [945, 787, 768, 837], +8067: [945, 788, 768, 837], +8068: [945, 787, 769, 837], +8069: [945, 788, 769, 837], +8070: [945, 787, 834, 837], +8071: [945, 788, 834, 837], +8072: [913, 787, 837], +8073: [913, 788, 837], +8074: [913, 787, 768, 837], +8075: [913, 788, 768, 837], +8076: [913, 787, 769, 837], +8077: [913, 788, 769, 837], +8078: [913, 787, 834, 837], +8079: [913, 788, 834, 837], +8080: [951, 787, 837], +8081: [951, 788, 837], +8082: [951, 787, 768, 837], +8083: [951, 788, 768, 837], +8084: [951, 787, 769, 837], +8085: [951, 788, 769, 837], +8086: [951, 787, 834, 837], +8087: [951, 788, 834, 837], +8088: [919, 787, 837], +8089: [919, 788, 837], +8090: [919, 787, 768, 837], +8091: [919, 788, 768, 837], +8092: [919, 787, 769, 837], +8093: [919, 788, 769, 837], +8094: [919, 787, 834, 837], +8095: [919, 788, 834, 837], +8096: [969, 787, 837], +8097: [969, 788, 837], +8098: [969, 787, 768, 837], +8099: [969, 788, 768, 837], +8100: [969, 787, 769, 837], +8101: [969, 788, 769, 837], +8102: [969, 787, 834, 837], +8103: [969, 788, 834, 837], +8104: [937, 787, 837], +8105: [937, 788, 837], +8106: [937, 787, 768, 837], +8107: [937, 788, 768, 837], +8108: [937, 787, 769, 837], +8109: [937, 788, 769, 837], +8110: [937, 787, 834, 837], +8111: [937, 788, 834, 837], +8112: [945, 774], +8113: [945, 772], +8114: [945, 768, 837], +8115: [945, 837], +8116: [945, 769, 837], +8118: [945, 834], +8119: [945, 834, 837], +8120: [913, 774], +8121: [913, 772], +8122: [913, 768], +8123: [913, 769], +8124: [913, 837], +8125: [32, 787], +8126: [953], +8127: [32, 787], +8128: [32, 834], +8129: [32, 776, 834], +8130: [951, 768, 837], +8131: [951, 837], +8132: [951, 769, 837], +8134: [951, 834], +8135: [951, 834, 837], +8136: [917, 768], +8137: [917, 769], +8138: [919, 768], +8139: [919, 769], +8140: [919, 837], +8141: [32, 787, 768], +8142: [32, 787, 769], +8143: [32, 787, 834], +8144: [953, 774], +8145: [953, 772], +8146: [953, 776, 768], +8147: [953, 776, 769], +8150: [953, 834], +8151: [953, 776, 834], +8152: [921, 774], +8153: [921, 772], +8154: [921, 768], +8155: [921, 769], +8157: [32, 788, 768], +8158: [32, 788, 769], +8159: [32, 788, 834], +8160: [965, 774], +8161: [965, 772], +8162: [965, 776, 768], +8163: [965, 776, 769], +8164: [961, 787], +8165: [961, 788], +8166: [965, 834], +8167: [965, 776, 834], +8168: [933, 774], +8169: [933, 772], +8170: [933, 768], +8171: [933, 769], +8172: [929, 788], +8173: [32, 776, 768], +8174: [32, 776, 769], +8175: [96], +8178: [969, 768, 837], +8179: [969, 837], +8180: [969, 769, 837], +8182: [969, 834], +8183: [969, 834, 837], +8184: [927, 768], +8185: [927, 769], +8186: [937, 768], +8187: [937, 769], +8188: [937, 837], +8189: [32, 769], +8190: [32, 788], +8192: [32], +8193: [32], +8194: [32], +8195: [32], +8196: [32], +8197: [32], +8198: [32], +8199: [32], +8200: [32], +8201: [32], +8202: [32], +8209: [8208], +8215: [32, 819], +8228: [46], +8229: [46, 46], +8230: [46, 46, 46], +8239: [32], +8243: [8242, 8242], +8244: [8242, 8242, 8242], +8246: [8245, 8245], +8247: [8245, 8245, 8245], +8252: [33, 33], +8254: [32, 773], +8263: [63, 63], +8264: [63, 33], +8265: [33, 63], +8279: [8242, 8242, 8242, 8242], +8287: [32], +8304: [48], +8305: [105], +8308: [52], +8309: [53], +8310: [54], +8311: [55], +8312: [56], +8313: [57], +8314: [43], +8315: [8722], +8316: [61], +8317: [40], +8318: [41], +8319: [110], +8320: [48], +8321: [49], +8322: [50], +8323: [51], +8324: [52], +8325: [53], +8326: [54], +8327: [55], +8328: [56], +8329: [57], +8330: [43], +8331: [8722], +8332: [61], +8333: [40], +8334: [41], +8360: [82, 115], +8448: [97, 47, 99], +8449: [97, 47, 115], +8450: [67], +8451: [176, 67], +8453: [99, 47, 111], +8454: [99, 47, 117], +8455: [400], +8457: [176, 70], +8458: [103], +8459: [72], +8460: [72], +8461: [72], +8462: [104], +8463: [295], +8464: [73], +8465: [73], +8466: [76], +8467: [108], +8469: [78], +8470: [78, 111], +8473: [80], +8474: [81], +8475: [82], +8476: [82], +8477: [82], +8480: [83, 77], +8481: [84, 69, 76], +8482: [84, 77], +8484: [90], +8486: [937], +8488: [90], +8490: [75], +8491: [65, 778], +8492: [66], +8493: [67], +8495: [101], +8496: [69], +8497: [70], +8499: [77], +8500: [111], +8501: [1488], +8502: [1489], +8503: [1490], +8504: [1491], +8505: [105], +8509: [947], +8510: [915], +8511: [928], +8512: [8721], +8517: [68], +8518: [100], +8519: [101], +8520: [105], +8521: [106], +8531: [49, 8260, 51], +8532: [50, 8260, 51], +8533: [49, 8260, 53], +8534: [50, 8260, 53], +8535: [51, 8260, 53], +8536: [52, 8260, 53], +8537: [49, 8260, 54], +8538: [53, 8260, 54], +8539: [49, 8260, 56], +8540: [51, 8260, 56], +8541: [53, 8260, 56], +8542: [55, 8260, 56], +8543: [49, 8260], +8544: [73], +8545: [73, 73], +8546: [73, 73, 73], +8547: [73, 86], +8548: [86], +8549: [86, 73], +8550: [86, 73, 73], +8551: [86, 73, 73, 73], +8552: [73, 88], +8553: [88], +8554: [88, 73], +8555: [88, 73, 73], +8556: [76], +8557: [67], +8558: [68], +8559: [77], +8560: [105], +8561: [105, 105], +8562: [105, 105, 105], +8563: [105, 118], +8564: [118], +8565: [118, 105], +8566: [118, 105, 105], +8567: [118, 105, 105, 105], +8568: [105, 120], +8569: [120], +8570: [120, 105], +8571: [120, 105, 105], +8572: [108], +8573: [99], +8574: [100], +8575: [109], +8602: [8592, 824], +8603: [8594, 824], +8622: [8596, 824], +8653: [8656, 824], +8654: [8660, 824], +8655: [8658, 824], +8708: [8707, 824], +8713: [8712, 824], +8716: [8715, 824], +8740: [8739, 824], +8742: [8741, 824], +8748: [8747, 8747], +8749: [8747, 8747, 8747], +8751: [8750, 8750], +8752: [8750, 8750, 8750], +8769: [8764, 824], +8772: [8771, 824], +8775: [8773, 824], +8777: [8776, 824], +8800: [61, 824], +8802: [8801, 824], +8813: [8781, 824], +8814: [60, 824], +8815: [62, 824], +8816: [8804, 824], +8817: [8805, 824], +8820: [8818, 824], +8821: [8819, 824], +8824: [8822, 824], +8825: [8823, 824], +8832: [8826, 824], +8833: [8827, 824], +8836: [8834, 824], +8837: [8835, 824], +8840: [8838, 824], +8841: [8839, 824], +8876: [8866, 824], +8877: [8872, 824], +8878: [8873, 824], +8879: [8875, 824], +8928: [8828, 824], +8929: [8829, 824], +8930: [8849, 824], +8931: [8850, 824], +8938: [8882, 824], +8939: [8883, 824], +8940: [8884, 824], +8941: [8885, 824], +9001: [12296], +9002: [12297], +9312: [49], +9313: [50], +9314: [51], +9315: [52], +9316: [53], +9317: [54], +9318: [55], +9319: [56], +9320: [57], +9321: [49, 48], +9322: [49, 49], +9323: [49, 50], +9324: [49, 51], +9325: [49, 52], +9326: [49, 53], +9327: [49, 54], +9328: [49, 55], +9329: [49, 56], +9330: [49, 57], +9331: [50, 48], +9332: [40, 49, 41], +9333: [40, 50, 41], +9334: [40, 51, 41], +9335: [40, 52, 41], +9336: [40, 53, 41], +9337: [40, 54, 41], +9338: [40, 55, 41], +9339: [40, 56, 41], +9340: [40, 57, 41], +9341: [40, 49, 48, 41], +9342: [40, 49, 49, 41], +9343: [40, 49, 50, 41], +9344: [40, 49, 51, 41], +9345: [40, 49, 52, 41], +9346: [40, 49, 53, 41], +9347: [40, 49, 54, 41], +9348: [40, 49, 55, 41], +9349: [40, 49, 56, 41], +9350: [40, 49, 57, 41], +9351: [40, 50, 48, 41], +9352: [49, 46], +9353: [50, 46], +9354: [51, 46], +9355: [52, 46], +9356: [53, 46], +9357: [54, 46], +9358: [55, 46], +9359: [56, 46], +9360: [57, 46], +9361: [49, 48, 46], +9362: [49, 49, 46], +9363: [49, 50, 46], +9364: [49, 51, 46], +9365: [49, 52, 46], +9366: [49, 53, 46], +9367: [49, 54, 46], +9368: [49, 55, 46], +9369: [49, 56, 46], +9370: [49, 57, 46], +9371: [50, 48, 46], +9372: [40, 97, 41], +9373: [40, 98, 41], +9374: [40, 99, 41], +9375: [40, 100, 41], +9376: [40, 101, 41], +9377: [40, 102, 41], +9378: [40, 103, 41], +9379: [40, 104, 41], +9380: [40, 105, 41], +9381: [40, 106, 41], +9382: [40, 107, 41], +9383: [40, 108, 41], +9384: [40, 109, 41], +9385: [40, 110, 41], +9386: [40, 111, 41], +9387: [40, 112, 41], +9388: [40, 113, 41], +9389: [40, 114, 41], +9390: [40, 115, 41], +9391: [40, 116, 41], +9392: [40, 117, 41], +9393: [40, 118, 41], +9394: [40, 119, 41], +9395: [40, 120, 41], +9396: [40, 121, 41], +9397: [40, 122, 41], +9398: [65], +9399: [66], +9400: [67], +9401: [68], +9402: [69], +9403: [70], +9404: [71], +9405: [72], +9406: [73], +9407: [74], +9408: [75], +9409: [76], +9410: [77], +9411: [78], +9412: [79], +9413: [80], +9414: [81], +9415: [82], +9416: [83], +9417: [84], +9418: [85], +9419: [86], +9420: [87], +9421: [88], +9422: [89], +9423: [90], +9424: [97], +9425: [98], +9426: [99], +9427: [100], +9428: [101], +9429: [102], +9430: [103], +9431: [104], +9432: [105], +9433: [106], +9434: [107], +9435: [108], +9436: [109], +9437: [110], +9438: [111], +9439: [112], +9440: [113], +9441: [114], +9442: [115], +9443: [116], +9444: [117], +9445: [118], +9446: [119], +9447: [120], +9448: [121], +9449: [122], +9450: [48], +10764: [8747, 8747, 8747, 8747], +10868: [58, 58, 61], +10869: [61, 61], +10870: [61, 61, 61], +10972: [10973, 824], +11935: [27597], +12019: [40863], +12032: [19968], +12033: [20008], +12034: [20022], +12035: [20031], +12036: [20057], +12037: [20101], +12038: [20108], +12039: [20128], +12040: [20154], +12041: [20799], +12042: [20837], +12043: [20843], +12044: [20866], +12045: [20886], +12046: [20907], +12047: [20960], +12048: [20981], +12049: [20992], +12050: [21147], +12051: [21241], +12052: [21269], +12053: [21274], +12054: [21304], +12055: [21313], +12056: [21340], +12057: [21353], +12058: [21378], +12059: [21430], +12060: [21448], +12061: [21475], +12062: [22231], +12063: [22303], +12064: [22763], +12065: [22786], +12066: [22794], +12067: [22805], +12068: [22823], +12069: [22899], +12070: [23376], +12071: [23424], +12072: [23544], +12073: [23567], +12074: [23586], +12075: [23608], +12076: [23662], +12077: [23665], +12078: [24027], +12079: [24037], +12080: [24049], +12081: [24062], +12082: [24178], +12083: [24186], +12084: [24191], +12085: [24308], +12086: [24318], +12087: [24331], +12088: [24339], +12089: [24400], +12090: [24417], +12091: [24435], +12092: [24515], +12093: [25096], +12094: [25142], +12095: [25163], +12096: [25903], +12097: [25908], +12098: [25991], +12099: [26007], +12100: [26020], +12101: [26041], +12102: [26080], +12103: [26085], +12104: [26352], +12105: [26376], +12106: [26408], +12107: [27424], +12108: [27490], +12109: [27513], +12110: [27571], +12111: [27595], +12112: [27604], +12113: [27611], +12114: [27663], +12115: [27668], +12116: [27700], +12117: [28779], +12118: [29226], +12119: [29238], +12120: [29243], +12121: [29247], +12122: [29255], +12123: [29273], +12124: [29275], +12125: [29356], +12126: [29572], +12127: [29577], +12128: [29916], +12129: [29926], +12130: [29976], +12131: [29983], +12132: [29992], +12133: [30000], +12134: [30091], +12135: [30098], +12136: [30326], +12137: [30333], +12138: [30382], +12139: [30399], +12140: [30446], +12141: [30683], +12142: [30690], +12143: [30707], +12144: [31034], +12145: [31160], +12146: [31166], +12147: [31348], +12148: [31435], +12149: [31481], +12150: [31859], +12151: [31992], +12152: [32566], +12153: [32593], +12154: [32650], +12155: [32701], +12156: [32769], +12157: [32780], +12158: [32786], +12159: [32819], +12160: [32895], +12161: [32905], +12162: [33251], +12163: [33258], +12164: [33267], +12165: [33276], +12166: [33292], +12167: [33307], +12168: [33311], +12169: [33390], +12170: [33394], +12171: [33400], +12172: [34381], +12173: [34411], +12174: [34880], +12175: [34892], +12176: [34915], +12177: [35198], +12178: [35211], +12179: [35282], +12180: [35328], +12181: [35895], +12182: [35910], +12183: [35925], +12184: [35960], +12185: [35997], +12186: [36196], +12187: [36208], +12188: [36275], +12189: [36523], +12190: [36554], +12191: [36763], +12192: [36784], +12193: [36789], +12194: [37009], +12195: [37193], +12196: [37318], +12197: [37324], +12198: [37329], +12199: [38263], +12200: [38272], +12201: [38428], +12202: [38582], +12203: [38585], +12204: [38632], +12205: [38737], +12206: [38750], +12207: [38754], +12208: [38761], +12209: [38859], +12210: [38893], +12211: [38899], +12212: [38913], +12213: [39080], +12214: [39131], +12215: [39135], +12216: [39318], +12217: [39321], +12218: [39340], +12219: [39592], +12220: [39640], +12221: [39647], +12222: [39717], +12223: [39727], +12224: [39730], +12225: [39740], +12226: [39770], +12227: [40165], +12228: [40565], +12229: [40575], +12230: [40613], +12231: [40635], +12232: [40643], +12233: [40653], +12234: [40657], +12235: [40697], +12236: [40701], +12237: [40718], +12238: [40723], +12239: [40736], +12240: [40763], +12241: [40778], +12242: [40786], +12243: [40845], +12244: [40860], +12245: [40864], +12288: [32], +12342: [12306], +12344: [21313], +12345: [21316], +12346: [21317], +12364: [12363, 12441], +12366: [12365, 12441], +12368: [12367, 12441], +12370: [12369, 12441], +12372: [12371, 12441], +12374: [12373, 12441], +12376: [12375, 12441], +12378: [12377, 12441], +12380: [12379, 12441], +12382: [12381, 12441], +12384: [12383, 12441], +12386: [12385, 12441], +12389: [12388, 12441], +12391: [12390, 12441], +12393: [12392, 12441], +12400: [12399, 12441], +12401: [12399, 12442], +12403: [12402, 12441], +12404: [12402, 12442], +12406: [12405, 12441], +12407: [12405, 12442], +12409: [12408, 12441], +12410: [12408, 12442], +12412: [12411, 12441], +12413: [12411, 12442], +12436: [12358, 12441], +12443: [32, 12441], +12444: [32, 12442], +12446: [12445, 12441], +12447: [12424, 12426], +12460: [12459, 12441], +12462: [12461, 12441], +12464: [12463, 12441], +12466: [12465, 12441], +12468: [12467, 12441], +12470: [12469, 12441], +12472: [12471, 12441], +12474: [12473, 12441], +12476: [12475, 12441], +12478: [12477, 12441], +12480: [12479, 12441], +12482: [12481, 12441], +12485: [12484, 12441], +12487: [12486, 12441], +12489: [12488, 12441], +12496: [12495, 12441], +12497: [12495, 12442], +12499: [12498, 12441], +12500: [12498, 12442], +12502: [12501, 12441], +12503: [12501, 12442], +12505: [12504, 12441], +12506: [12504, 12442], +12508: [12507, 12441], +12509: [12507, 12442], +12532: [12454, 12441], +12535: [12527, 12441], +12536: [12528, 12441], +12537: [12529, 12441], +12538: [12530, 12441], +12542: [12541, 12441], +12543: [12467, 12488], +12593: [4352], +12594: [4353], +12595: [4522], +12596: [4354], +12597: [4524], +12598: [4525], +12599: [4355], +12600: [4356], +12601: [4357], +12602: [4528], +12603: [4529], +12604: [4530], +12605: [4531], +12606: [4532], +12607: [4533], +12608: [4378], +12609: [4358], +12610: [4359], +12611: [4360], +12612: [4385], +12613: [4361], +12614: [4362], +12615: [4363], +12616: [4364], +12617: [4365], +12618: [4366], +12619: [4367], +12620: [4368], +12621: [4369], +12622: [4370], +12623: [4449], +12624: [4450], +12625: [4451], +12626: [4452], +12627: [4453], +12628: [4454], +12629: [4455], +12630: [4456], +12631: [4457], +12632: [4458], +12633: [4459], +12634: [4460], +12635: [4461], +12636: [4462], +12637: [4463], +12638: [4464], +12639: [4465], +12640: [4466], +12641: [4467], +12642: [4468], +12643: [4469], +12644: [4448], +12645: [4372], +12646: [4373], +12647: [4551], +12648: [4552], +12649: [4556], +12650: [4558], +12651: [4563], +12652: [4567], +12653: [4569], +12654: [4380], +12655: [4573], +12656: [4575], +12657: [4381], +12658: [4382], +12659: [4384], +12660: [4386], +12661: [4387], +12662: [4391], +12663: [4393], +12664: [4395], +12665: [4396], +12666: [4397], +12667: [4398], +12668: [4399], +12669: [4402], +12670: [4406], +12671: [4416], +12672: [4423], +12673: [4428], +12674: [4593], +12675: [4594], +12676: [4439], +12677: [4440], +12678: [4441], +12679: [4484], +12680: [4485], +12681: [4488], +12682: [4497], +12683: [4498], +12684: [4500], +12685: [4510], +12686: [4513], +12690: [19968], +12691: [20108], +12692: [19977], +12693: [22235], +12694: [19978], +12695: [20013], +12696: [19979], +12697: [30002], +12698: [20057], +12699: [19993], +12700: [19969], +12701: [22825], +12702: [22320], +12703: [20154], +12800: [40, 4352, 41], +12801: [40, 4354, 41], +12802: [40, 4355, 41], +12803: [40, 4357, 41], +12804: [40, 4358, 41], +12805: [40, 4359, 41], +12806: [40, 4361, 41], +12807: [40, 4363, 41], +12808: [40, 4364, 41], +12809: [40, 4366, 41], +12810: [40, 4367, 41], +12811: [40, 4368, 41], +12812: [40, 4369, 41], +12813: [40, 4370, 41], +12814: [40, 4352, 4449, 41], +12815: [40, 4354, 4449, 41], +12816: [40, 4355, 4449, 41], +12817: [40, 4357, 4449, 41], +12818: [40, 4358, 4449, 41], +12819: [40, 4359, 4449, 41], +12820: [40, 4361, 4449, 41], +12821: [40, 4363, 4449, 41], +12822: [40, 4364, 4449, 41], +12823: [40, 4366, 4449, 41], +12824: [40, 4367, 4449, 41], +12825: [40, 4368, 4449, 41], +12826: [40, 4369, 4449, 41], +12827: [40, 4370, 4449, 41], +12828: [40, 4364, 4462, 41], +12832: [40, 19968, 41], +12833: [40, 20108, 41], +12834: [40, 19977, 41], +12835: [40, 22235, 41], +12836: [40, 20116, 41], +12837: [40, 20845, 41], +12838: [40, 19971, 41], +12839: [40, 20843, 41], +12840: [40, 20061, 41], +12841: [40, 21313, 41], +12842: [40, 26376, 41], +12843: [40, 28779, 41], +12844: [40, 27700, 41], +12845: [40, 26408, 41], +12846: [40, 37329, 41], +12847: [40, 22303, 41], +12848: [40, 26085, 41], +12849: [40, 26666, 41], +12850: [40, 26377, 41], +12851: [40, 31038, 41], +12852: [40, 21517, 41], +12853: [40, 29305, 41], +12854: [40, 36001, 41], +12855: [40, 31069, 41], +12856: [40, 21172, 41], +12857: [40, 20195, 41], +12858: [40, 21628, 41], +12859: [40, 23398, 41], +12860: [40, 30435, 41], +12861: [40, 20225, 41], +12862: [40, 36039, 41], +12863: [40, 21332, 41], +12864: [40, 31085, 41], +12865: [40, 20241, 41], +12866: [40, 33258, 41], +12867: [40, 33267, 41], +12881: [50, 49], +12882: [50, 50], +12883: [50, 51], +12884: [50, 52], +12885: [50, 53], +12886: [50, 54], +12887: [50, 55], +12888: [50, 56], +12889: [50, 57], +12890: [51, 48], +12891: [51, 49], +12892: [51, 50], +12893: [51, 51], +12894: [51, 52], +12895: [51, 53], +12896: [4352], +12897: [4354], +12898: [4355], +12899: [4357], +12900: [4358], +12901: [4359], +12902: [4361], +12903: [4363], +12904: [4364], +12905: [4366], +12906: [4367], +12907: [4368], +12908: [4369], +12909: [4370], +12910: [4352, 4449], +12911: [4354, 4449], +12912: [4355, 4449], +12913: [4357, 4449], +12914: [4358, 4449], +12915: [4359, 4449], +12916: [4361, 4449], +12917: [4363, 4449], +12918: [4364, 4449], +12919: [4366, 4449], +12920: [4367, 4449], +12921: [4368, 4449], +12922: [4369, 4449], +12923: [4370, 4449], +12928: [19968], +12929: [20108], +12930: [19977], +12931: [22235], +12932: [20116], +12933: [20845], +12934: [19971], +12935: [20843], +12936: [20061], +12937: [21313], +12938: [26376], +12939: [28779], +12940: [27700], +12941: [26408], +12942: [37329], +12943: [22303], +12944: [26085], +12945: [26666], +12946: [26377], +12947: [31038], +12948: [21517], +12949: [29305], +12950: [36001], +12951: [31069], +12952: [21172], +12953: [31192], +12954: [30007], +12955: [22899], +12956: [36969], +12957: [20778], +12958: [21360], +12959: [27880], +12960: [38917], +12961: [20241], +12962: [20889], +12963: [27491], +12964: [19978], +12965: [20013], +12966: [19979], +12967: [24038], +12968: [21491], +12969: [21307], +12970: [23447], +12971: [23398], +12972: [30435], +12973: [20225], +12974: [36039], +12975: [21332], +12976: [22812], +12977: [51, 54], +12978: [51, 55], +12979: [51, 56], +12980: [51, 57], +12981: [52, 48], +12982: [52, 49], +12983: [52, 50], +12984: [52, 51], +12985: [52, 52], +12986: [52, 53], +12987: [52, 54], +12988: [52, 55], +12989: [52, 56], +12990: [52, 57], +12991: [53, 48], +12992: [49, 26376], +12993: [50, 26376], +12994: [51, 26376], +12995: [52, 26376], +12996: [53, 26376], +12997: [54, 26376], +12998: [55, 26376], +12999: [56, 26376], +13000: [57, 26376], +13001: [49, 48, 26376], +13002: [49, 49, 26376], +13003: [49, 50, 26376], +13008: [12450], +13009: [12452], +13010: [12454], +13011: [12456], +13012: [12458], +13013: [12459], +13014: [12461], +13015: [12463], +13016: [12465], +13017: [12467], +13018: [12469], +13019: [12471], +13020: [12473], +13021: [12475], +13022: [12477], +13023: [12479], +13024: [12481], +13025: [12484], +13026: [12486], +13027: [12488], +13028: [12490], +13029: [12491], +13030: [12492], +13031: [12493], +13032: [12494], +13033: [12495], +13034: [12498], +13035: [12501], +13036: [12504], +13037: [12507], +13038: [12510], +13039: [12511], +13040: [12512], +13041: [12513], +13042: [12514], +13043: [12516], +13044: [12518], +13045: [12520], +13046: [12521], +13047: [12522], +13048: [12523], +13049: [12524], +13050: [12525], +13051: [12527], +13052: [12528], +13053: [12529], +13054: [12530], +13056: [12450, 12495, 12442, 12540, 12488], +13057: [12450, 12523, 12501, 12449], +13058: [12450, 12531, 12504, 12442, 12450], +13059: [12450, 12540, 12523], +13060: [12452, 12491, 12531, 12463, 12441], +13061: [12452, 12531, 12481], +13062: [12454, 12457, 12531], +13063: [12456, 12473, 12463, 12540, 12488, 12441], +13064: [12456, 12540, 12459, 12540], +13065: [12458, 12531, 12473], +13066: [12458, 12540, 12512], +13067: [12459, 12452, 12522], +13068: [12459, 12521, 12483, 12488], +13069: [12459, 12525, 12522, 12540], +13070: [12459, 12441, 12525, 12531], +13071: [12459, 12441, 12531, 12510], +13072: [12461, 12441, 12459, 12441], +13073: [12461, 12441, 12491, 12540], +13074: [12461, 12517, 12522, 12540], +13075: [12461, 12441, 12523, 12479, 12441, 12540], +13076: [12461, 12525], +13077: [12461, 12525, 12463, 12441, 12521, 12512], +13078: [12461, 12525, 12513, 12540, 12488, 12523], +13079: [12461, 12525, 12527, 12483, 12488], +13080: [12463, 12441, 12521, 12512], +13081: [12463, 12441, 12521, 12512, 12488, 12531], +13082: [12463, 12523, 12475, 12441, 12452, 12525], +13083: [12463, 12525, 12540, 12493], +13084: [12465, 12540, 12473], +13085: [12467, 12523, 12490], +13086: [12467, 12540, 12507, 12442], +13087: [12469, 12452, 12463, 12523], +13088: [12469, 12531, 12481, 12540, 12512], +13089: [12471, 12522, 12531, 12463, 12441], +13090: [12475, 12531, 12481], +13091: [12475, 12531, 12488], +13092: [12479, 12441, 12540, 12473], +13093: [12486, 12441, 12471], +13094: [12488, 12441, 12523], +13095: [12488, 12531], +13096: [12490, 12494], +13097: [12494, 12483, 12488], +13098: [12495, 12452, 12484], +13099: [12495, 12442, 12540, 12475, 12531, 12488], +13100: [12495, 12442, 12540, 12484], +13101: [12495, 12441, 12540, 12524, 12523], +13102: [12498, 12442, 12450, 12473, 12488, 12523], +13103: [12498, 12442, 12463, 12523], +13104: [12498, 12442, 12467], +13105: [12498, 12441, 12523], +13106: [12501, 12449, 12521, 12483, 12488, 12441], +13107: [12501, 12451, 12540, 12488], +13108: [12501, 12441, 12483, 12471, 12455, 12523], +13109: [12501, 12521, 12531], +13110: [12504, 12463, 12479, 12540, 12523], +13111: [12504, 12442, 12477], +13112: [12504, 12442, 12491, 12498], +13113: [12504, 12523, 12484], +13114: [12504, 12442, 12531, 12473], +13115: [12504, 12442, 12540, 12471, 12441], +13116: [12504, 12441, 12540, 12479], +13117: [12507, 12442, 12452, 12531, 12488], +13118: [12507, 12441, 12523, 12488], +13119: [12507, 12531], +13120: [12507, 12442, 12531, 12488, 12441], +13121: [12507, 12540, 12523], +13122: [12507, 12540, 12531], +13123: [12510, 12452, 12463, 12525], +13124: [12510, 12452, 12523], +13125: [12510, 12483, 12495], +13126: [12510, 12523, 12463], +13127: [12510, 12531, 12471, 12519, 12531], +13128: [12511, 12463, 12525, 12531], +13129: [12511, 12522], +13130: [12511, 12522, 12495, 12441, 12540, 12523], +13131: [12513, 12459, 12441], +13132: [12513, 12459, 12441, 12488, 12531], +13133: [12513, 12540, 12488, 12523], +13134: [12516, 12540, 12488, 12441], +13135: [12516, 12540, 12523], +13136: [12518, 12450, 12531], +13137: [12522, 12483, 12488, 12523], +13138: [12522, 12521], +13139: [12523, 12498, 12442, 12540], +13140: [12523, 12540, 12501, 12441, 12523], +13141: [12524, 12512], +13142: [12524, 12531, 12488, 12465, 12441, 12531], +13143: [12527, 12483, 12488], +13144: [48, 28857], +13145: [49, 28857], +13146: [50, 28857], +13147: [51, 28857], +13148: [52, 28857], +13149: [53, 28857], +13150: [54, 28857], +13151: [55, 28857], +13152: [56, 28857], +13153: [57, 28857], +13154: [49, 48, 28857], +13155: [49, 49, 28857], +13156: [49, 50, 28857], +13157: [49, 51, 28857], +13158: [49, 52, 28857], +13159: [49, 53, 28857], +13160: [49, 54, 28857], +13161: [49, 55, 28857], +13162: [49, 56, 28857], +13163: [49, 57, 28857], +13164: [50, 48, 28857], +13165: [50, 49, 28857], +13166: [50, 50, 28857], +13167: [50, 51, 28857], +13168: [50, 52, 28857], +13169: [104, 80, 97], +13170: [100, 97], +13171: [65, 85], +13172: [98, 97, 114], +13173: [111, 86], +13174: [112, 99], +13179: [24179, 25104], +13180: [26157, 21644], +13181: [22823, 27491], +13182: [26126, 27835], +13183: [26666, 24335, 20250, 31038], +13184: [112, 65], +13185: [110, 65], +13186: [956, 65], +13187: [109, 65], +13188: [107, 65], +13189: [75, 66], +13190: [77, 66], +13191: [71, 66], +13192: [99, 97, 108], +13193: [107, 99, 97, 108], +13194: [112, 70], +13195: [110, 70], +13196: [956, 70], +13197: [956, 103], +13198: [109, 103], +13199: [107, 103], +13200: [72, 122], +13201: [107, 72, 122], +13202: [77, 72, 122], +13203: [71, 72, 122], +13204: [84, 72, 122], +13205: [956, 108], +13206: [109, 108], +13207: [100, 108], +13208: [107, 108], +13209: [102, 109], +13210: [110, 109], +13211: [956, 109], +13212: [109, 109], +13213: [99, 109], +13214: [107, 109], +13215: [109, 109, 50], +13216: [99, 109, 50], +13217: [109, 50], +13218: [107, 109, 50], +13219: [109, 109, 51], +13220: [99, 109, 51], +13221: [109, 51], +13222: [107, 109, 51], +13223: [109, 8725, 115], +13224: [109, 8725, 115, 50], +13225: [80, 97], +13226: [107, 80, 97], +13227: [77, 80, 97], +13228: [71, 80, 97], +13229: [114, 97, 100], +13230: [114, 97, 100, 8725, 115], +13231: [114, 97, 100, 8725, 115, 50], +13232: [112, 115], +13233: [110, 115], +13234: [956, 115], +13235: [109, 115], +13236: [112, 86], +13237: [110, 86], +13238: [956, 86], +13239: [109, 86], +13240: [107, 86], +13241: [77, 86], +13242: [112, 87], +13243: [110, 87], +13244: [956, 87], +13245: [109, 87], +13246: [107, 87], +13247: [77, 87], +13248: [107, 937], +13249: [77, 937], +13250: [97, 46, 109, 46], +13251: [66, 113], +13252: [99, 99], +13253: [99, 100], +13254: [67, 8725, 107, 103], +13255: [67, 111, 46], +13256: [100, 66], +13257: [71, 121], +13258: [104, 97], +13259: [72, 80], +13260: [105, 110], +13261: [75, 75], +13262: [75, 77], +13263: [107, 116], +13264: [108, 109], +13265: [108, 110], +13266: [108, 111, 103], +13267: [108, 120], +13268: [109, 98], +13269: [109, 105, 108], +13270: [109, 111, 108], +13271: [80, 72], +13272: [112, 46, 109, 46], +13273: [80, 80, 77], +13274: [80, 82], +13275: [115, 114], +13276: [83, 118], +13277: [87, 98], +13280: [49, 26085], +13281: [50, 26085], +13282: [51, 26085], +13283: [52, 26085], +13284: [53, 26085], +13285: [54, 26085], +13286: [55, 26085], +13287: [56, 26085], +13288: [57, 26085], +13289: [49, 48, 26085], +13290: [49, 49, 26085], +13291: [49, 50, 26085], +13292: [49, 51, 26085], +13293: [49, 52, 26085], +13294: [49, 53, 26085], +13295: [49, 54, 26085], +13296: [49, 55, 26085], +13297: [49, 56, 26085], +13298: [49, 57, 26085], +13299: [50, 48, 26085], +13300: [50, 49, 26085], +13301: [50, 50, 26085], +13302: [50, 51, 26085], +13303: [50, 52, 26085], +13304: [50, 53, 26085], +13305: [50, 54, 26085], +13306: [50, 55, 26085], +13307: [50, 56, 26085], +13308: [50, 57, 26085], +13309: [51, 48, 26085], +13310: [51, 49, 26085], +63744: [35912], +63745: [26356], +63746: [36554], +63747: [36040], +63748: [28369], +63749: [20018], +63750: [21477], +63751: [40860], +63752: [40860], +63753: [22865], +63754: [37329], +63755: [21895], +63756: [22856], +63757: [25078], +63758: [30313], +63759: [32645], +63760: [34367], +63761: [34746], +63762: [35064], +63763: [37007], +63764: [27138], +63765: [27931], +63766: [28889], +63767: [29662], +63768: [33853], +63769: [37226], +63770: [39409], +63771: [20098], +63772: [21365], +63773: [27396], +63774: [29211], +63775: [34349], +63776: [40478], +63777: [23888], +63778: [28651], +63779: [34253], +63780: [35172], +63781: [25289], +63782: [33240], +63783: [34847], +63784: [24266], +63785: [26391], +63786: [28010], +63787: [29436], +63788: [37070], +63789: [20358], +63790: [20919], +63791: [21214], +63792: [25796], +63793: [27347], +63794: [29200], +63795: [30439], +63796: [32769], +63797: [34310], +63798: [34396], +63799: [36335], +63800: [38706], +63801: [39791], +63802: [40442], +63803: [30860], +63804: [31103], +63805: [32160], +63806: [33737], +63807: [37636], +63808: [40575], +63809: [35542], +63810: [22751], +63811: [24324], +63812: [31840], +63813: [32894], +63814: [29282], +63815: [30922], +63816: [36034], +63817: [38647], +63818: [22744], +63819: [23650], +63820: [27155], +63821: [28122], +63822: [28431], +63823: [32047], +63824: [32311], +63825: [38475], +63826: [21202], +63827: [32907], +63828: [20956], +63829: [20940], +63830: [31260], +63831: [32190], +63832: [33777], +63833: [38517], +63834: [35712], +63835: [25295], +63836: [27138], +63837: [35582], +63838: [20025], +63839: [23527], +63840: [24594], +63841: [29575], +63842: [30064], +63843: [21271], +63844: [30971], +63845: [20415], +63846: [24489], +63847: [19981], +63848: [27852], +63849: [25976], +63850: [32034], +63851: [21443], +63852: [22622], +63853: [30465], +63854: [33865], +63855: [35498], +63856: [27578], +63857: [36784], +63858: [27784], +63859: [25342], +63860: [33509], +63861: [25504], +63862: [30053], +63863: [20142], +63864: [20841], +63865: [20937], +63866: [26753], +63867: [31975], +63868: [33391], +63869: [35538], +63870: [37327], +63871: [21237], +63872: [21570], +63873: [22899], +63874: [24300], +63875: [26053], +63876: [28670], +63877: [31018], +63878: [38317], +63879: [39530], +63880: [40599], +63881: [40654], +63882: [21147], +63883: [26310], +63884: [27511], +63885: [36706], +63886: [24180], +63887: [24976], +63888: [25088], +63889: [25754], +63890: [28451], +63891: [29001], +63892: [29833], +63893: [31178], +63894: [32244], +63895: [32879], +63896: [36646], +63897: [34030], +63898: [36899], +63899: [37706], +63900: [21015], +63901: [21155], +63902: [21693], +63903: [28872], +63904: [35010], +63905: [35498], +63906: [24265], +63907: [24565], +63908: [25467], +63909: [27566], +63910: [31806], +63911: [29557], +63912: [20196], +63913: [22265], +63914: [23527], +63915: [23994], +63916: [24604], +63917: [29618], +63918: [29801], +63919: [32666], +63920: [32838], +63921: [37428], +63922: [38646], +63923: [38728], +63924: [38936], +63925: [20363], +63926: [31150], +63927: [37300], +63928: [38584], +63929: [24801], +63930: [20102], +63931: [20698], +63932: [23534], +63933: [23615], +63934: [26009], +63935: [27138], +63936: [29134], +63937: [30274], +63938: [34044], +63939: [36988], +63940: [40845], +63941: [26248], +63942: [38446], +63943: [21129], +63944: [26491], +63945: [26611], +63946: [27969], +63947: [28316], +63948: [29705], +63949: [30041], +63950: [30827], +63951: [32016], +63952: [39006], +63953: [20845], +63954: [25134], +63955: [38520], +63956: [20523], +63957: [23833], +63958: [28138], +63959: [36650], +63960: [24459], +63961: [24900], +63962: [26647], +63963: [29575], +63964: [38534], +63965: [21033], +63966: [21519], +63967: [23653], +63968: [26131], +63969: [26446], +63970: [26792], +63971: [27877], +63972: [29702], +63973: [30178], +63974: [32633], +63975: [35023], +63976: [35041], +63977: [37324], +63978: [38626], +63979: [21311], +63980: [28346], +63981: [21533], +63982: [29136], +63983: [29848], +63984: [34298], +63985: [38563], +63986: [40023], +63987: [40607], +63988: [26519], +63989: [28107], +63990: [33256], +63991: [31435], +63992: [31520], +63993: [31890], +63994: [29376], +63995: [28825], +63996: [35672], +63997: [20160], +63998: [33590], +63999: [21050], +64000: [20999], +64001: [24230], +64002: [25299], +64003: [31958], +64004: [23429], +64005: [27934], +64006: [26292], +64007: [36667], +64008: [34892], +64009: [38477], +64010: [35211], +64011: [24275], +64012: [20800], +64013: [21952], +64016: [22618], +64018: [26228], +64021: [20958], +64022: [29482], +64023: [30410], +64024: [31036], +64025: [31070], +64026: [31077], +64027: [31119], +64028: [38742], +64029: [31934], +64030: [32701], +64032: [34322], +64034: [35576], +64037: [36920], +64038: [37117], +64042: [39151], +64043: [39164], +64044: [39208], +64045: [40372], +64048: [20398], +64049: [20711], +64050: [20813], +64051: [21193], +64052: [21220], +64053: [21329], +64054: [21917], +64055: [22022], +64056: [22120], +64057: [22592], +64058: [22696], +64059: [23652], +64060: [23662], +64061: [24724], +64062: [24936], +64063: [24974], +64064: [25074], +64065: [25935], +64066: [26082], +64067: [26257], +64068: [26757], +64069: [28023], +64070: [28186], +64071: [28450], +64072: [29038], +64073: [29227], +64074: [29730], +64075: [30865], +64076: [31038], +64077: [31049], +64078: [31048], +64079: [31056], +64080: [31062], +64081: [31069], +64082: [31117], +64083: [31118], +64084: [31296], +64085: [31361], +64086: [31680], +64087: [32244], +64088: [32265], +64089: [32321], +64090: [32626], +64091: [32773], +64092: [33261], +64093: [33401], +64094: [33401], +64095: [33879], +64096: [35088], +64097: [35222], +64098: [35585], +64099: [35641], +64100: [36051], +64101: [36104], +64102: [36790], +64103: [36920], +64104: [38627], +64105: [38911], +64106: [38971], +64256: [102, 102], +64257: [102, 105], +64258: [102, 108], +64259: [102, 102, 105], +64260: [102, 102, 108], +64261: [115, 116], +64262: [115, 116], +64275: [1396, 1398], +64276: [1396, 1381], +64277: [1396, 1387], +64278: [1406, 1398], +64279: [1396, 1389], +64285: [1497, 1460], +64287: [1522, 1463], +64288: [1506], +64289: [1488], +64290: [1491], +64291: [1492], +64292: [1499], +64293: [1500], +64294: [1501], +64295: [1512], +64296: [1514], +64297: [43], +64298: [1513, 1473], +64299: [1513, 1474], +64300: [1513, 1468, 1473], +64301: [1513, 1468, 1474], +64302: [1488, 1463], +64303: [1488, 1464], +64304: [1488, 1468], +64305: [1489, 1468], +64306: [1490, 1468], +64307: [1491, 1468], +64308: [1492, 1468], +64309: [1493, 1468], +64310: [1494, 1468], +64312: [1496, 1468], +64313: [1497, 1468], +64314: [1498, 1468], +64315: [1499, 1468], +64316: [1500, 1468], +64318: [1502, 1468], +64320: [1504, 1468], +64321: [1505, 1468], +64323: [1507, 1468], +64324: [1508, 1468], +64326: [1510, 1468], +64327: [1511, 1468], +64328: [1512, 1468], +64329: [1513, 1468], +64330: [1514, 1468], +64331: [1493, 1465], +64332: [1489, 1471], +64333: [1499, 1471], +64334: [1508, 1471], +64335: [1488, 1500], +64336: [1649], +64337: [1649], +64338: [1659], +64339: [1659], +64340: [1659], +64341: [1659], +64342: [1662], +64343: [1662], +64344: [1662], +64345: [1662], +64346: [1664], +64347: [1664], +64348: [1664], +64349: [1664], +64350: [1658], +64351: [1658], +64352: [1658], +64353: [1658], +64354: [1663], +64355: [1663], +64356: [1663], +64357: [1663], +64358: [1657], +64359: [1657], +64360: [1657], +64361: [1657], +64362: [1700], +64363: [1700], +64364: [1700], +64365: [1700], +64366: [1702], +64367: [1702], +64368: [1702], +64369: [1702], +64370: [1668], +64371: [1668], +64372: [1668], +64373: [1668], +64374: [1667], +64375: [1667], +64376: [1667], +64377: [1667], +64378: [1670], +64379: [1670], +64380: [1670], +64381: [1670], +64382: [1671], +64383: [1671], +64384: [1671], +64385: [1671], +64386: [1677], +64387: [1677], +64388: [1676], +64389: [1676], +64390: [1678], +64391: [1678], +64392: [1672], +64393: [1672], +64394: [1688], +64395: [1688], +64396: [1681], +64397: [1681], +64398: [1705], +64399: [1705], +64400: [1705], +64401: [1705], +64402: [1711], +64403: [1711], +64404: [1711], +64405: [1711], +64406: [1715], +64407: [1715], +64408: [1715], +64409: [1715], +64410: [1713], +64411: [1713], +64412: [1713], +64413: [1713], +64414: [1722], +64415: [1722], +64416: [1723], +64417: [1723], +64418: [1723], +64419: [1723], +64420: [1749, 1620], +64421: [1749, 1620], +64422: [1729], +64423: [1729], +64424: [1729], +64425: [1729], +64426: [1726], +64427: [1726], +64428: [1726], +64429: [1726], +64430: [1746], +64431: [1746], +64432: [1746, 1620], +64433: [1746, 1620], +64467: [1709], +64468: [1709], +64469: [1709], +64470: [1709], +64471: [1735], +64472: [1735], +64473: [1734], +64474: [1734], +64475: [1736], +64476: [1736], +64477: [1735, 1652], +64478: [1739], +64479: [1739], +64480: [1733], +64481: [1733], +64482: [1737], +64483: [1737], +64484: [1744], +64485: [1744], +64486: [1744], +64487: [1744], +64488: [1609], +64489: [1609], +64490: [1610, 1620, 1575], +64491: [1610, 1620, 1575], +64492: [1610, 1620, 1749], +64493: [1610, 1620, 1749], +64494: [1610, 1620, 1608], +64495: [1610, 1620, 1608], +64496: [1610, 1620, 1735], +64497: [1610, 1620, 1735], +64498: [1610, 1620, 1734], +64499: [1610, 1620, 1734], +64500: [1610, 1620, 1736], +64501: [1610, 1620, 1736], +64502: [1610, 1620, 1744], +64503: [1610, 1620, 1744], +64504: [1610, 1620, 1744], +64505: [1610, 1620, 1609], +64506: [1610, 1620, 1609], +64507: [1610, 1620, 1609], +64508: [1740], +64509: [1740], +64510: [1740], +64511: [1740], +64512: [1610, 1620, 1580], +64513: [1610, 1620, 1581], +64514: [1610, 1620, 1605], +64515: [1610, 1620, 1609], +64516: [1610, 1620, 1610], +64517: [1576, 1580], +64518: [1576, 1581], +64519: [1576, 1582], +64520: [1576, 1605], +64521: [1576, 1609], +64522: [1576, 1610], +64523: [1578, 1580], +64524: [1578, 1581], +64525: [1578, 1582], +64526: [1578, 1605], +64527: [1578, 1609], +64528: [1578, 1610], +64529: [1579, 1580], +64530: [1579, 1605], +64531: [1579, 1609], +64532: [1579, 1610], +64533: [1580, 1581], +64534: [1580, 1605], +64535: [1581, 1580], +64536: [1581, 1605], +64537: [1582, 1580], +64538: [1582, 1581], +64539: [1582, 1605], +64540: [1587, 1580], +64541: [1587, 1581], +64542: [1587, 1582], +64543: [1587, 1605], +64544: [1589, 1581], +64545: [1589, 1605], +64546: [1590, 1580], +64547: [1590, 1581], +64548: [1590, 1582], +64549: [1590, 1605], +64550: [1591, 1581], +64551: [1591, 1605], +64552: [1592, 1605], +64553: [1593, 1580], +64554: [1593, 1605], +64555: [1594, 1580], +64556: [1594, 1605], +64557: [1601, 1580], +64558: [1601, 1581], +64559: [1601, 1582], +64560: [1601, 1605], +64561: [1601, 1609], +64562: [1601, 1610], +64563: [1602, 1581], +64564: [1602, 1605], +64565: [1602, 1609], +64566: [1602, 1610], +64567: [1603, 1575], +64568: [1603, 1580], +64569: [1603, 1581], +64570: [1603, 1582], +64571: [1603, 1604], +64572: [1603, 1605], +64573: [1603, 1609], +64574: [1603, 1610], +64575: [1604, 1580], +64576: [1604, 1581], +64577: [1604, 1582], +64578: [1604, 1605], +64579: [1604, 1609], +64580: [1604, 1610], +64581: [1605, 1580], +64582: [1605, 1581], +64583: [1605, 1582], +64584: [1605, 1605], +64585: [1605, 1609], +64586: [1605, 1610], +64587: [1606, 1580], +64588: [1606, 1581], +64589: [1606, 1582], +64590: [1606, 1605], +64591: [1606, 1609], +64592: [1606, 1610], +64593: [1607, 1580], +64594: [1607, 1605], +64595: [1607, 1609], +64596: [1607, 1610], +64597: [1610, 1580], +64598: [1610, 1581], +64599: [1610, 1582], +64600: [1610, 1605], +64601: [1610, 1609], +64602: [1610, 1610], +64603: [1584, 1648], +64604: [1585, 1648], +64605: [1609, 1648], +64606: [32, 1612, 1617], +64607: [32, 1613, 1617], +64608: [32, 1614, 1617], +64609: [32, 1615, 1617], +64610: [32, 1616, 1617], +64611: [32, 1617, 1648], +64612: [1610, 1620, 1585], +64613: [1610, 1620, 1586], +64614: [1610, 1620, 1605], +64615: [1610, 1620, 1606], +64616: [1610, 1620, 1609], +64617: [1610, 1620, 1610], +64618: [1576, 1585], +64619: [1576, 1586], +64620: [1576, 1605], +64621: [1576, 1606], +64622: [1576, 1609], +64623: [1576, 1610], +64624: [1578, 1585], +64625: [1578, 1586], +64626: [1578, 1605], +64627: [1578, 1606], +64628: [1578, 1609], +64629: [1578, 1610], +64630: [1579, 1585], +64631: [1579, 1586], +64632: [1579, 1605], +64633: [1579, 1606], +64634: [1579, 1609], +64635: [1579, 1610], +64636: [1601, 1609], +64637: [1601, 1610], +64638: [1602, 1609], +64639: [1602, 1610], +64640: [1603, 1575], +64641: [1603, 1604], +64642: [1603, 1605], +64643: [1603, 1609], +64644: [1603, 1610], +64645: [1604, 1605], +64646: [1604, 1609], +64647: [1604, 1610], +64648: [1605, 1575], +64649: [1605, 1605], +64650: [1606, 1585], +64651: [1606, 1586], +64652: [1606, 1605], +64653: [1606, 1606], +64654: [1606, 1609], +64655: [1606, 1610], +64656: [1609, 1648], +64657: [1610, 1585], +64658: [1610, 1586], +64659: [1610, 1605], +64660: [1610, 1606], +64661: [1610, 1609], +64662: [1610, 1610], +64663: [1610, 1620, 1580], +64664: [1610, 1620, 1581], +64665: [1610, 1620, 1582], +64666: [1610, 1620, 1605], +64667: [1610, 1620, 1607], +64668: [1576, 1580], +64669: [1576, 1581], +64670: [1576, 1582], +64671: [1576, 1605], +64672: [1576, 1607], +64673: [1578, 1580], +64674: [1578, 1581], +64675: [1578, 1582], +64676: [1578, 1605], +64677: [1578, 1607], +64678: [1579, 1605], +64679: [1580, 1581], +64680: [1580, 1605], +64681: [1581, 1580], +64682: [1581, 1605], +64683: [1582, 1580], +64684: [1582, 1605], +64685: [1587, 1580], +64686: [1587, 1581], +64687: [1587, 1582], +64688: [1587, 1605], +64689: [1589, 1581], +64690: [1589, 1582], +64691: [1589, 1605], +64692: [1590, 1580], +64693: [1590, 1581], +64694: [1590, 1582], +64695: [1590, 1605], +64696: [1591, 1581], +64697: [1592, 1605], +64698: [1593, 1580], +64699: [1593, 1605], +64700: [1594, 1580], +64701: [1594, 1605], +64702: [1601, 1580], +64703: [1601, 1581], +64704: [1601, 1582], +64705: [1601, 1605], +64706: [1602, 1581], +64707: [1602, 1605], +64708: [1603, 1580], +64709: [1603, 1581], +64710: [1603, 1582], +64711: [1603, 1604], +64712: [1603, 1605], +64713: [1604, 1580], +64714: [1604, 1581], +64715: [1604, 1582], +64716: [1604, 1605], +64717: [1604, 1607], +64718: [1605, 1580], +64719: [1605, 1581], +64720: [1605, 1582], +64721: [1605, 1605], +64722: [1606, 1580], +64723: [1606, 1581], +64724: [1606, 1582], +64725: [1606, 1605], +64726: [1606, 1607], +64727: [1607, 1580], +64728: [1607, 1605], +64729: [1607, 1648], +64730: [1610, 1580], +64731: [1610, 1581], +64732: [1610, 1582], +64733: [1610, 1605], +64734: [1610, 1607], +64735: [1610, 1620, 1605], +64736: [1610, 1620, 1607], +64737: [1576, 1605], +64738: [1576, 1607], +64739: [1578, 1605], +64740: [1578, 1607], +64741: [1579, 1605], +64742: [1579, 1607], +64743: [1587, 1605], +64744: [1587, 1607], +64745: [1588, 1605], +64746: [1588, 1607], +64747: [1603, 1604], +64748: [1603, 1605], +64749: [1604, 1605], +64750: [1606, 1605], +64751: [1606, 1607], +64752: [1610, 1605], +64753: [1610, 1607], +64754: [1600, 1614, 1617], +64755: [1600, 1615, 1617], +64756: [1600, 1616, 1617], +64757: [1591, 1609], +64758: [1591, 1610], +64759: [1593, 1609], +64760: [1593, 1610], +64761: [1594, 1609], +64762: [1594, 1610], +64763: [1587, 1609], +64764: [1587, 1610], +64765: [1588, 1609], +64766: [1588, 1610], +64767: [1581, 1609], +64768: [1581, 1610], +64769: [1580, 1609], +64770: [1580, 1610], +64771: [1582, 1609], +64772: [1582, 1610], +64773: [1589, 1609], +64774: [1589, 1610], +64775: [1590, 1609], +64776: [1590, 1610], +64777: [1588, 1580], +64778: [1588, 1581], +64779: [1588, 1582], +64780: [1588, 1605], +64781: [1588, 1585], +64782: [1587, 1585], +64783: [1589, 1585], +64784: [1590, 1585], +64785: [1591, 1609], +64786: [1591, 1610], +64787: [1593, 1609], +64788: [1593, 1610], +64789: [1594, 1609], +64790: [1594, 1610], +64791: [1587, 1609], +64792: [1587, 1610], +64793: [1588, 1609], +64794: [1588, 1610], +64795: [1581, 1609], +64796: [1581, 1610], +64797: [1580, 1609], +64798: [1580, 1610], +64799: [1582, 1609], +64800: [1582, 1610], +64801: [1589, 1609], +64802: [1589, 1610], +64803: [1590, 1609], +64804: [1590, 1610], +64805: [1588, 1580], +64806: [1588, 1581], +64807: [1588, 1582], +64808: [1588, 1605], +64809: [1588, 1585], +64810: [1587, 1585], +64811: [1589, 1585], +64812: [1590, 1585], +64813: [1588, 1580], +64814: [1588, 1581], +64815: [1588, 1582], +64816: [1588, 1605], +64817: [1587, 1607], +64818: [1588, 1607], +64819: [1591, 1605], +64820: [1587, 1580], +64821: [1587, 1581], +64822: [1587, 1582], +64823: [1588, 1580], +64824: [1588, 1581], +64825: [1588, 1582], +64826: [1591, 1605], +64827: [1592, 1605], +64828: [1575, 1611], +64829: [1575, 1611], +64848: [1578, 1580, 1605], +64849: [1578, 1581, 1580], +64850: [1578, 1581, 1580], +64851: [1578, 1581, 1605], +64852: [1578, 1582, 1605], +64853: [1578, 1605, 1580], +64854: [1578, 1605, 1581], +64855: [1578, 1605, 1582], +64856: [1580, 1605, 1581], +64857: [1580, 1605, 1581], +64858: [1581, 1605, 1610], +64859: [1581, 1605, 1609], +64860: [1587, 1581, 1580], +64861: [1587, 1580, 1581], +64862: [1587, 1580, 1609], +64863: [1587, 1605, 1581], +64864: [1587, 1605, 1581], +64865: [1587, 1605, 1580], +64866: [1587, 1605, 1605], +64867: [1587, 1605, 1605], +64868: [1589, 1581, 1581], +64869: [1589, 1581, 1581], +64870: [1589, 1605, 1605], +64871: [1588, 1581, 1605], +64872: [1588, 1581, 1605], +64873: [1588, 1580, 1610], +64874: [1588, 1605, 1582], +64875: [1588, 1605, 1582], +64876: [1588, 1605, 1605], +64877: [1588, 1605, 1605], +64878: [1590, 1581, 1609], +64879: [1590, 1582, 1605], +64880: [1590, 1582, 1605], +64881: [1591, 1605, 1581], +64882: [1591, 1605, 1581], +64883: [1591, 1605, 1605], +64884: [1591, 1605, 1610], +64885: [1593, 1580, 1605], +64886: [1593, 1605, 1605], +64887: [1593, 1605, 1605], +64888: [1593, 1605, 1609], +64889: [1594, 1605, 1605], +64890: [1594, 1605, 1610], +64891: [1594, 1605, 1609], +64892: [1601, 1582, 1605], +64893: [1601, 1582, 1605], +64894: [1602, 1605, 1581], +64895: [1602, 1605, 1605], +64896: [1604, 1581, 1605], +64897: [1604, 1581, 1610], +64898: [1604, 1581, 1609], +64899: [1604, 1580, 1580], +64900: [1604, 1580, 1580], +64901: [1604, 1582, 1605], +64902: [1604, 1582, 1605], +64903: [1604, 1605, 1581], +64904: [1604, 1605, 1581], +64905: [1605, 1581, 1580], +64906: [1605, 1581, 1605], +64907: [1605, 1581, 1610], +64908: [1605, 1580, 1581], +64909: [1605, 1580, 1605], +64910: [1605, 1582, 1580], +64911: [1605, 1582, 1605], +64914: [1605, 1580, 1582], +64915: [1607, 1605, 1580], +64916: [1607, 1605, 1605], +64917: [1606, 1581, 1605], +64918: [1606, 1581, 1609], +64919: [1606, 1580, 1605], +64920: [1606, 1580, 1605], +64921: [1606, 1580, 1609], +64922: [1606, 1605, 1610], +64923: [1606, 1605, 1609], +64924: [1610, 1605, 1605], +64925: [1610, 1605, 1605], +64926: [1576, 1582, 1610], +64927: [1578, 1580, 1610], +64928: [1578, 1580, 1609], +64929: [1578, 1582, 1610], +64930: [1578, 1582, 1609], +64931: [1578, 1605, 1610], +64932: [1578, 1605, 1609], +64933: [1580, 1605, 1610], +64934: [1580, 1581, 1609], +64935: [1580, 1605, 1609], +64936: [1587, 1582, 1609], +64937: [1589, 1581, 1610], +64938: [1588, 1581, 1610], +64939: [1590, 1581, 1610], +64940: [1604, 1580, 1610], +64941: [1604, 1605, 1610], +64942: [1610, 1581, 1610], +64943: [1610, 1580, 1610], +64944: [1610, 1605, 1610], +64945: [1605, 1605, 1610], +64946: [1602, 1605, 1610], +64947: [1606, 1581, 1610], +64948: [1602, 1605, 1581], +64949: [1604, 1581, 1605], +64950: [1593, 1605, 1610], +64951: [1603, 1605, 1610], +64952: [1606, 1580, 1581], +64953: [1605, 1582, 1610], +64954: [1604, 1580, 1605], +64955: [1603, 1605, 1605], +64956: [1604, 1580, 1605], +64957: [1606, 1580, 1581], +64958: [1580, 1581, 1610], +64959: [1581, 1580, 1610], +64960: [1605, 1580, 1610], +64961: [1601, 1605, 1610], +64962: [1576, 1581, 1610], +64963: [1603, 1605, 1605], +64964: [1593, 1580, 1605], +64965: [1589, 1605, 1605], +64966: [1587, 1582, 1610], +64967: [1606, 1580, 1610], +65008: [1589, 1604, 1746], +65009: [1602, 1604, 1746], +65010: [1575, 1604, 1604, 1607], +65011: [1575, 1603, 1576, 1585], +65012: [1605, 1581, 1605, 1583], +65013: [1589, 1604, 1593, 1605], +65014: [1585, 1587, 1608, 1604], +65015: [1593, 1604, 1610, 1607], +65016: [1608, 1587, 1604, 1605], +65017: [1589, 1604, 1609], +65018: [1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, 1605], +65019: [1580, 1604, 32, 1580, 1604, 1575, 1604, 1607], +65020: [1585, 1740, 1575, 1604], +65072: [46, 46], +65073: [8212], +65074: [8211], +65075: [95], +65076: [95], +65077: [40], +65078: [41], +65079: [123], +65080: [125], +65081: [12308], +65082: [12309], +65083: [12304], +65084: [12305], +65085: [12298], +65086: [12299], +65087: [12296], +65088: [12297], +65089: [12300], +65090: [12301], +65091: [12302], +65092: [12303], +65097: [32, 773], +65098: [32, 773], +65099: [32, 773], +65100: [32, 773], +65101: [95], +65102: [95], +65103: [95], +65104: [44], +65105: [12289], +65106: [46], +65108: [59], +65109: [58], +65110: [63], +65111: [33], +65112: [8212], +65113: [40], +65114: [41], +65115: [123], +65116: [125], +65117: [12308], +65118: [12309], +65119: [35], +65120: [38], +65121: [42], +65122: [43], +65123: [45], +65124: [60], +65125: [62], +65126: [61], +65128: [92], +65129: [36], +65130: [37], +65131: [64], +65136: [32, 1611], +65137: [1600, 1611], +65138: [32, 1612], +65140: [32, 1613], +65142: [32, 1614], +65143: [1600, 1614], +65144: [32, 1615], +65145: [1600, 1615], +65146: [32, 1616], +65147: [1600, 1616], +65148: [32, 1617], +65149: [1600, 1617], +65150: [32, 1618], +65151: [1600, 1618], +65152: [1569], +65153: [1575, 1619], +65154: [1575, 1619], +65155: [1575, 1620], +65156: [1575, 1620], +65157: [1608, 1620], +65158: [1608, 1620], +65159: [1575, 1621], +65160: [1575, 1621], +65161: [1610, 1620], +65162: [1610, 1620], +65163: [1610, 1620], +65164: [1610, 1620], +65165: [1575], +65166: [1575], +65167: [1576], +65168: [1576], +65169: [1576], +65170: [1576], +65171: [1577], +65172: [1577], +65173: [1578], +65174: [1578], +65175: [1578], +65176: [1578], +65177: [1579], +65178: [1579], +65179: [1579], +65180: [1579], +65181: [1580], +65182: [1580], +65183: [1580], +65184: [1580], +65185: [1581], +65186: [1581], +65187: [1581], +65188: [1581], +65189: [1582], +65190: [1582], +65191: [1582], +65192: [1582], +65193: [1583], +65194: [1583], +65195: [1584], +65196: [1584], +65197: [1585], +65198: [1585], +65199: [1586], +65200: [1586], +65201: [1587], +65202: [1587], +65203: [1587], +65204: [1587], +65205: [1588], +65206: [1588], +65207: [1588], +65208: [1588], +65209: [1589], +65210: [1589], +65211: [1589], +65212: [1589], +65213: [1590], +65214: [1590], +65215: [1590], +65216: [1590], +65217: [1591], +65218: [1591], +65219: [1591], +65220: [1591], +65221: [1592], +65222: [1592], +65223: [1592], +65224: [1592], +65225: [1593], +65226: [1593], +65227: [1593], +65228: [1593], +65229: [1594], +65230: [1594], +65231: [1594], +65232: [1594], +65233: [1601], +65234: [1601], +65235: [1601], +65236: [1601], +65237: [1602], +65238: [1602], +65239: [1602], +65240: [1602], +65241: [1603], +65242: [1603], +65243: [1603], +65244: [1603], +65245: [1604], +65246: [1604], +65247: [1604], +65248: [1604], +65249: [1605], +65250: [1605], +65251: [1605], +65252: [1605], +65253: [1606], +65254: [1606], +65255: [1606], +65256: [1606], +65257: [1607], +65258: [1607], +65259: [1607], +65260: [1607], +65261: [1608], +65262: [1608], +65263: [1609], +65264: [1609], +65265: [1610], +65266: [1610], +65267: [1610], +65268: [1610], +65269: [1604, 1575, 1619], +65270: [1604, 1575, 1619], +65271: [1604, 1575, 1620], +65272: [1604, 1575, 1620], +65273: [1604, 1575, 1621], +65274: [1604, 1575, 1621], +65275: [1604, 1575], +65276: [1604, 1575], +65281: [33], +65282: [34], +65283: [35], +65284: [36], +65285: [37], +65286: [38], +65287: [39], +65288: [40], +65289: [41], +65290: [42], +65291: [43], +65292: [44], +65293: [45], +65294: [46], +65295: [47], +65296: [48], +65297: [49], +65298: [50], +65299: [51], +65300: [52], +65301: [53], +65302: [54], +65303: [55], +65304: [56], +65305: [57], +65306: [58], +65307: [59], +65308: [60], +65309: [61], +65310: [62], +65311: [63], +65312: [64], +65313: [65], +65314: [66], +65315: [67], +65316: [68], +65317: [69], +65318: [70], +65319: [71], +65320: [72], +65321: [73], +65322: [74], +65323: [75], +65324: [76], +65325: [77], +65326: [78], +65327: [79], +65328: [80], +65329: [81], +65330: [82], +65331: [83], +65332: [84], +65333: [85], +65334: [86], +65335: [87], +65336: [88], +65337: [89], +65338: [90], +65339: [91], +65340: [92], +65341: [93], +65342: [94], +65343: [95], +65344: [96], +65345: [97], +65346: [98], +65347: [99], +65348: [100], +65349: [101], +65350: [102], +65351: [103], +65352: [104], +65353: [105], +65354: [106], +65355: [107], +65356: [108], +65357: [109], +65358: [110], +65359: [111], +65360: [112], +65361: [113], +65362: [114], +65363: [115], +65364: [116], +65365: [117], +65366: [118], +65367: [119], +65368: [120], +65369: [121], +65370: [122], +65371: [123], +65372: [124], +65373: [125], +65374: [126], +65375: [10629], +65376: [10630], +65377: [12290], +65378: [12300], +65379: [12301], +65380: [12289], +65381: [12539], +65382: [12530], +65383: [12449], +65384: [12451], +65385: [12453], +65386: [12455], +65387: [12457], +65388: [12515], +65389: [12517], +65390: [12519], +65391: [12483], +65392: [12540], +65393: [12450], +65394: [12452], +65395: [12454], +65396: [12456], +65397: [12458], +65398: [12459], +65399: [12461], +65400: [12463], +65401: [12465], +65402: [12467], +65403: [12469], +65404: [12471], +65405: [12473], +65406: [12475], +65407: [12477], +65408: [12479], +65409: [12481], +65410: [12484], +65411: [12486], +65412: [12488], +65413: [12490], +65414: [12491], +65415: [12492], +65416: [12493], +65417: [12494], +65418: [12495], +65419: [12498], +65420: [12501], +65421: [12504], +65422: [12507], +65423: [12510], +65424: [12511], +65425: [12512], +65426: [12513], +65427: [12514], +65428: [12516], +65429: [12518], +65430: [12520], +65431: [12521], +65432: [12522], +65433: [12523], +65434: [12524], +65435: [12525], +65436: [12527], +65437: [12531], +65438: [12441], +65439: [12442], +65440: [4448], +65441: [4352], +65442: [4353], +65443: [4522], +65444: [4354], +65445: [4524], +65446: [4525], +65447: [4355], +65448: [4356], +65449: [4357], +65450: [4528], +65451: [4529], +65452: [4530], +65453: [4531], +65454: [4532], +65455: [4533], +65456: [4378], +65457: [4358], +65458: [4359], +65459: [4360], +65460: [4385], +65461: [4361], +65462: [4362], +65463: [4363], +65464: [4364], +65465: [4365], +65466: [4366], +65467: [4367], +65468: [4368], +65469: [4369], +65470: [4370], +65474: [4449], +65475: [4450], +65476: [4451], +65477: [4452], +65478: [4453], +65479: [4454], +65482: [4455], +65483: [4456], +65484: [4457], +65485: [4458], +65486: [4459], +65487: [4460], +65490: [4461], +65491: [4462], +65492: [4463], +65493: [4464], +65494: [4465], +65495: [4466], +65498: [4467], +65499: [4468], +65500: [4469], +65504: [162], +65505: [163], +65506: [172], +65507: [32, 772], +65508: [166], +65509: [165], +65510: [8361], +65512: [9474], +65513: [8592], +65514: [8593], +65515: [8594], +65516: [8595], +65517: [9632], +65518: [9675], +119134: [119127, 119141], +119135: [119128, 119141], +119136: [119128, 119141, 119150], +119137: [119128, 119141, 119151], +119138: [119128, 119141, 119152], +119139: [119128, 119141, 119153], +119140: [119128, 119141, 119154], +119227: [119225, 119141], +119228: [119226, 119141], +119229: [119225, 119141, 119150], +119230: [119226, 119141, 119150], +119231: [119225, 119141, 119151], +119232: [119226, 119141, 119151], +119808: [65], +119809: [66], +119810: [67], +119811: [68], +119812: [69], +119813: [70], +119814: [71], +119815: [72], +119816: [73], +119817: [74], +119818: [75], +119819: [76], +119820: [77], +119821: [78], +119822: [79], +119823: [80], +119824: [81], +119825: [82], +119826: [83], +119827: [84], +119828: [85], +119829: [86], +119830: [87], +119831: [88], +119832: [89], +119833: [90], +119834: [97], +119835: [98], +119836: [99], +119837: [100], +119838: [101], +119839: [102], +119840: [103], +119841: [104], +119842: [105], +119843: [106], +119844: [107], +119845: [108], +119846: [109], +119847: [110], +119848: [111], +119849: [112], +119850: [113], +119851: [114], +119852: [115], +119853: [116], +119854: [117], +119855: [118], +119856: [119], +119857: [120], +119858: [121], +119859: [122], +119860: [65], +119861: [66], +119862: [67], +119863: [68], +119864: [69], +119865: [70], +119866: [71], +119867: [72], +119868: [73], +119869: [74], +119870: [75], +119871: [76], +119872: [77], +119873: [78], +119874: [79], +119875: [80], +119876: [81], +119877: [82], +119878: [83], +119879: [84], +119880: [85], +119881: [86], +119882: [87], +119883: [88], +119884: [89], +119885: [90], +119886: [97], +119887: [98], +119888: [99], +119889: [100], +119890: [101], +119891: [102], +119892: [103], +119894: [105], +119895: [106], +119896: [107], +119897: [108], +119898: [109], +119899: [110], +119900: [111], +119901: [112], +119902: [113], +119903: [114], +119904: [115], +119905: [116], +119906: [117], +119907: [118], +119908: [119], +119909: [120], +119910: [121], +119911: [122], +119912: [65], +119913: [66], +119914: [67], +119915: [68], +119916: [69], +119917: [70], +119918: [71], +119919: [72], +119920: [73], +119921: [74], +119922: [75], +119923: [76], +119924: [77], +119925: [78], +119926: [79], +119927: [80], +119928: [81], +119929: [82], +119930: [83], +119931: [84], +119932: [85], +119933: [86], +119934: [87], +119935: [88], +119936: [89], +119937: [90], +119938: [97], +119939: [98], +119940: [99], +119941: [100], +119942: [101], +119943: [102], +119944: [103], +119945: [104], +119946: [105], +119947: [106], +119948: [107], +119949: [108], +119950: [109], +119951: [110], +119952: [111], +119953: [112], +119954: [113], +119955: [114], +119956: [115], +119957: [116], +119958: [117], +119959: [118], +119960: [119], +119961: [120], +119962: [121], +119963: [122], +119964: [65], +119966: [67], +119967: [68], +119970: [71], +119973: [74], +119974: [75], +119977: [78], +119978: [79], +119979: [80], +119980: [81], +119982: [83], +119983: [84], +119984: [85], +119985: [86], +119986: [87], +119987: [88], +119988: [89], +119989: [90], +119990: [97], +119991: [98], +119992: [99], +119993: [100], +119995: [102], +119997: [104], +119998: [105], +119999: [106], +120000: [107], +120002: [109], +120003: [110], +120005: [112], +120006: [113], +120007: [114], +120008: [115], +120009: [116], +120010: [117], +120011: [118], +120012: [119], +120013: [120], +120014: [121], +120015: [122], +120016: [65], +120017: [66], +120018: [67], +120019: [68], +120020: [69], +120021: [70], +120022: [71], +120023: [72], +120024: [73], +120025: [74], +120026: [75], +120027: [76], +120028: [77], +120029: [78], +120030: [79], +120031: [80], +120032: [81], +120033: [82], +120034: [83], +120035: [84], +120036: [85], +120037: [86], +120038: [87], +120039: [88], +120040: [89], +120041: [90], +120042: [97], +120043: [98], +120044: [99], +120045: [100], +120046: [101], +120047: [102], +120048: [103], +120049: [104], +120050: [105], +120051: [106], +120052: [107], +120053: [108], +120054: [109], +120055: [110], +120056: [111], +120057: [112], +120058: [113], +120059: [114], +120060: [115], +120061: [116], +120062: [117], +120063: [118], +120064: [119], +120065: [120], +120066: [121], +120067: [122], +120068: [65], +120069: [66], +120071: [68], +120072: [69], +120073: [70], +120074: [71], +120077: [74], +120078: [75], +120079: [76], +120080: [77], +120081: [78], +120082: [79], +120083: [80], +120084: [81], +120086: [83], +120087: [84], +120088: [85], +120089: [86], +120090: [87], +120091: [88], +120092: [89], +120094: [97], +120095: [98], +120096: [99], +120097: [100], +120098: [101], +120099: [102], +120100: [103], +120101: [104], +120102: [105], +120103: [106], +120104: [107], +120105: [108], +120106: [109], +120107: [110], +120108: [111], +120109: [112], +120110: [113], +120111: [114], +120112: [115], +120113: [116], +120114: [117], +120115: [118], +120116: [119], +120117: [120], +120118: [121], +120119: [122], +120120: [65], +120121: [66], +120123: [68], +120124: [69], +120125: [70], +120126: [71], +120128: [73], +120129: [74], +120130: [75], +120131: [76], +120132: [77], +120134: [79], +120138: [83], +120139: [84], +120140: [85], +120141: [86], +120142: [87], +120143: [88], +120144: [89], +120146: [97], +120147: [98], +120148: [99], +120149: [100], +120150: [101], +120151: [102], +120152: [103], +120153: [104], +120154: [105], +120155: [106], +120156: [107], +120157: [108], +120158: [109], +120159: [110], +120160: [111], +120161: [112], +120162: [113], +120163: [114], +120164: [115], +120165: [116], +120166: [117], +120167: [118], +120168: [119], +120169: [120], +120170: [121], +120171: [122], +120172: [65], +120173: [66], +120174: [67], +120175: [68], +120176: [69], +120177: [70], +120178: [71], +120179: [72], +120180: [73], +120181: [74], +120182: [75], +120183: [76], +120184: [77], +120185: [78], +120186: [79], +120187: [80], +120188: [81], +120189: [82], +120190: [83], +120191: [84], +120192: [85], +120193: [86], +120194: [87], +120195: [88], +120196: [89], +120197: [90], +120198: [97], +120199: [98], +120200: [99], +120201: [100], +120202: [101], +120203: [102], +120204: [103], +120205: [104], +120206: [105], +120207: [106], +120208: [107], +120209: [108], +120210: [109], +120211: [110], +120212: [111], +120213: [112], +120214: [113], +120215: [114], +120216: [115], +120217: [116], +120218: [117], +120219: [118], +120220: [119], +120221: [120], +120222: [121], +120223: [122], +120224: [65], +120225: [66], +120226: [67], +120227: [68], +120228: [69], +120229: [70], +120230: [71], +120231: [72], +120232: [73], +120233: [74], +120234: [75], +120235: [76], +120236: [77], +120237: [78], +120238: [79], +120239: [80], +120240: [81], +120241: [82], +120242: [83], +120243: [84], +120244: [85], +120245: [86], +120246: [87], +120247: [88], +120248: [89], +120249: [90], +120250: [97], +120251: [98], +120252: [99], +120253: [100], +120254: [101], +120255: [102], +120256: [103], +120257: [104], +120258: [105], +120259: [106], +120260: [107], +120261: [108], +120262: [109], +120263: [110], +120264: [111], +120265: [112], +120266: [113], +120267: [114], +120268: [115], +120269: [116], +120270: [117], +120271: [118], +120272: [119], +120273: [120], +120274: [121], +120275: [122], +120276: [65], +120277: [66], +120278: [67], +120279: [68], +120280: [69], +120281: [70], +120282: [71], +120283: [72], +120284: [73], +120285: [74], +120286: [75], +120287: [76], +120288: [77], +120289: [78], +120290: [79], +120291: [80], +120292: [81], +120293: [82], +120294: [83], +120295: [84], +120296: [85], +120297: [86], +120298: [87], +120299: [88], +120300: [89], +120301: [90], +120302: [97], +120303: [98], +120304: [99], +120305: [100], +120306: [101], +120307: [102], +120308: [103], +120309: [104], +120310: [105], +120311: [106], +120312: [107], +120313: [108], +120314: [109], +120315: [110], +120316: [111], +120317: [112], +120318: [113], +120319: [114], +120320: [115], +120321: [116], +120322: [117], +120323: [118], +120324: [119], +120325: [120], +120326: [121], +120327: [122], +120328: [65], +120329: [66], +120330: [67], +120331: [68], +120332: [69], +120333: [70], +120334: [71], +120335: [72], +120336: [73], +120337: [74], +120338: [75], +120339: [76], +120340: [77], +120341: [78], +120342: [79], +120343: [80], +120344: [81], +120345: [82], +120346: [83], +120347: [84], +120348: [85], +120349: [86], +120350: [87], +120351: [88], +120352: [89], +120353: [90], +120354: [97], +120355: [98], +120356: [99], +120357: [100], +120358: [101], +120359: [102], +120360: [103], +120361: [104], +120362: [105], +120363: [106], +120364: [107], +120365: [108], +120366: [109], +120367: [110], +120368: [111], +120369: [112], +120370: [113], +120371: [114], +120372: [115], +120373: [116], +120374: [117], +120375: [118], +120376: [119], +120377: [120], +120378: [121], +120379: [122], +120380: [65], +120381: [66], +120382: [67], +120383: [68], +120384: [69], +120385: [70], +120386: [71], +120387: [72], +120388: [73], +120389: [74], +120390: [75], +120391: [76], +120392: [77], +120393: [78], +120394: [79], +120395: [80], +120396: [81], +120397: [82], +120398: [83], +120399: [84], +120400: [85], +120401: [86], +120402: [87], +120403: [88], +120404: [89], +120405: [90], +120406: [97], +120407: [98], +120408: [99], +120409: [100], +120410: [101], +120411: [102], +120412: [103], +120413: [104], +120414: [105], +120415: [106], +120416: [107], +120417: [108], +120418: [109], +120419: [110], +120420: [111], +120421: [112], +120422: [113], +120423: [114], +120424: [115], +120425: [116], +120426: [117], +120427: [118], +120428: [119], +120429: [120], +120430: [121], +120431: [122], +120432: [65], +120433: [66], +120434: [67], +120435: [68], +120436: [69], +120437: [70], +120438: [71], +120439: [72], +120440: [73], +120441: [74], +120442: [75], +120443: [76], +120444: [77], +120445: [78], +120446: [79], +120447: [80], +120448: [81], +120449: [82], +120450: [83], +120451: [84], +120452: [85], +120453: [86], +120454: [87], +120455: [88], +120456: [89], +120457: [90], +120458: [97], +120459: [98], +120460: [99], +120461: [100], +120462: [101], +120463: [102], +120464: [103], +120465: [104], +120466: [105], +120467: [106], +120468: [107], +120469: [108], +120470: [109], +120471: [110], +120472: [111], +120473: [112], +120474: [113], +120475: [114], +120476: [115], +120477: [116], +120478: [117], +120479: [118], +120480: [119], +120481: [120], +120482: [121], +120483: [122], +120488: [913], +120489: [914], +120490: [915], +120491: [916], +120492: [917], +120493: [918], +120494: [919], +120495: [920], +120496: [921], +120497: [922], +120498: [923], +120499: [924], +120500: [925], +120501: [926], +120502: [927], +120503: [928], +120504: [929], +120505: [920], +120506: [931], +120507: [932], +120508: [933], +120509: [934], +120510: [935], +120511: [936], +120512: [937], +120513: [8711], +120514: [945], +120515: [946], +120516: [947], +120517: [948], +120518: [949], +120519: [950], +120520: [951], +120521: [952], +120522: [953], +120523: [954], +120524: [955], +120525: [956], +120526: [957], +120527: [958], +120528: [959], +120529: [960], +120530: [961], +120531: [962], +120532: [963], +120533: [964], +120534: [965], +120535: [966], +120536: [967], +120537: [968], +120538: [969], +120539: [8706], +120540: [949], +120541: [952], +120542: [954], +120543: [966], +120544: [961], +120545: [960], +120546: [913], +120547: [914], +120548: [915], +120549: [916], +120550: [917], +120551: [918], +120552: [919], +120553: [920], +120554: [921], +120555: [922], +120556: [923], +120557: [924], +120558: [925], +120559: [926], +120560: [927], +120561: [928], +120562: [929], +120563: [920], +120564: [931], +120565: [932], +120566: [933], +120567: [934], +120568: [935], +120569: [936], +120570: [937], +120571: [8711], +120572: [945], +120573: [946], +120574: [947], +120575: [948], +120576: [949], +120577: [950], +120578: [951], +120579: [952], +120580: [953], +120581: [954], +120582: [955], +120583: [956], +120584: [957], +120585: [958], +120586: [959], +120587: [960], +120588: [961], +120589: [962], +120590: [963], +120591: [964], +120592: [965], +120593: [966], +120594: [967], +120595: [968], +120596: [969], +120597: [8706], +120598: [949], +120599: [952], +120600: [954], +120601: [966], +120602: [961], +120603: [960], +120604: [913], +120605: [914], +120606: [915], +120607: [916], +120608: [917], +120609: [918], +120610: [919], +120611: [920], +120612: [921], +120613: [922], +120614: [923], +120615: [924], +120616: [925], +120617: [926], +120618: [927], +120619: [928], +120620: [929], +120621: [920], +120622: [931], +120623: [932], +120624: [933], +120625: [934], +120626: [935], +120627: [936], +120628: [937], +120629: [8711], +120630: [945], +120631: [946], +120632: [947], +120633: [948], +120634: [949], +120635: [950], +120636: [951], +120637: [952], +120638: [953], +120639: [954], +120640: [955], +120641: [956], +120642: [957], +120643: [958], +120644: [959], +120645: [960], +120646: [961], +120647: [962], +120648: [963], +120649: [964], +120650: [965], +120651: [966], +120652: [967], +120653: [968], +120654: [969], +120655: [8706], +120656: [949], +120657: [952], +120658: [954], +120659: [966], +120660: [961], +120661: [960], +120662: [913], +120663: [914], +120664: [915], +120665: [916], +120666: [917], +120667: [918], +120668: [919], +120669: [920], +120670: [921], +120671: [922], +120672: [923], +120673: [924], +120674: [925], +120675: [926], +120676: [927], +120677: [928], +120678: [929], +120679: [920], +120680: [931], +120681: [932], +120682: [933], +120683: [934], +120684: [935], +120685: [936], +120686: [937], +120687: [8711], +120688: [945], +120689: [946], +120690: [947], +120691: [948], +120692: [949], +120693: [950], +120694: [951], +120695: [952], +120696: [953], +120697: [954], +120698: [955], +120699: [956], +120700: [957], +120701: [958], +120702: [959], +120703: [960], +120704: [961], +120705: [962], +120706: [963], +120707: [964], +120708: [965], +120709: [966], +120710: [967], +120711: [968], +120712: [969], +120713: [8706], +120714: [949], +120715: [952], +120716: [954], +120717: [966], +120718: [961], +120719: [960], +120720: [913], +120721: [914], +120722: [915], +120723: [916], +120724: [917], +120725: [918], +120726: [919], +120727: [920], +120728: [921], +120729: [922], +120730: [923], +120731: [924], +120732: [925], +120733: [926], +120734: [927], +120735: [928], +120736: [929], +120737: [920], +120738: [931], +120739: [932], +120740: [933], +120741: [934], +120742: [935], +120743: [936], +120744: [937], +120745: [8711], +120746: [945], +120747: [946], +120748: [947], +120749: [948], +120750: [949], +120751: [950], +120752: [951], +120753: [952], +120754: [953], +120755: [954], +120756: [955], +120757: [956], +120758: [957], +120759: [958], +120760: [959], +120761: [960], +120762: [961], +120763: [962], +120764: [963], +120765: [964], +120766: [965], +120767: [966], +120768: [967], +120769: [968], +120770: [969], +120771: [8706], +120772: [949], +120773: [952], +120774: [954], +120775: [966], +120776: [961], +120777: [960], +120782: [48], +120783: [49], +120784: [50], +120785: [51], +120786: [52], +120787: [53], +120788: [54], +120789: [55], +120790: [56], +120791: [57], +120792: [48], +120793: [49], +120794: [50], +120795: [51], +120796: [52], +120797: [53], +120798: [54], +120799: [55], +120800: [56], +120801: [57], +120802: [48], +120803: [49], +120804: [50], +120805: [51], +120806: [52], +120807: [53], +120808: [54], +120809: [55], +120810: [56], +120811: [57], +120812: [48], +120813: [49], +120814: [50], +120815: [51], +120816: [52], +120817: [53], +120818: [54], +120819: [55], +120820: [56], +120821: [57], +120822: [48], +120823: [49], +120824: [50], +120825: [51], +120826: [52], +120827: [53], +120828: [54], +120829: [55], +120830: [56], +120831: [57], +194560: [20029], +194561: [20024], +194562: [20033], +194563: [131362], +194564: [20320], +194565: [20398], +194566: [20411], +194567: [20482], +194568: [20602], +194569: [20633], +194570: [20711], +194571: [20687], +194572: [13470], +194573: [132666], +194574: [20813], +194575: [20820], +194576: [20836], +194577: [20855], +194578: [132380], +194579: [13497], +194580: [20839], +194581: [20877], +194582: [132427], +194583: [20887], +194584: [20900], +194585: [20172], +194586: [20908], +194587: [20917], +194588: [168415], +194589: [20981], +194590: [20995], +194591: [13535], +194592: [21051], +194593: [21062], +194594: [21106], +194595: [21111], +194596: [13589], +194597: [21191], +194598: [21193], +194599: [21220], +194600: [21242], +194601: [21253], +194602: [21254], +194603: [21271], +194604: [21321], +194605: [21329], +194606: [21338], +194607: [21363], +194608: [21373], +194609: [21375], +194610: [21375], +194611: [21375], +194612: [133676], +194613: [28784], +194614: [21450], +194615: [21471], +194616: [133987], +194617: [21483], +194618: [21489], +194619: [21510], +194620: [21662], +194621: [21560], +194622: [21576], +194623: [21608], +194624: [21666], +194625: [21750], +194626: [21776], +194627: [21843], +194628: [21859], +194629: [21892], +194630: [21892], +194631: [21913], +194632: [21931], +194633: [21939], +194634: [21954], +194635: [22294], +194636: [22022], +194637: [22295], +194638: [22097], +194639: [22132], +194640: [20999], +194641: [22766], +194642: [22478], +194643: [22516], +194644: [22541], +194645: [22411], +194646: [22578], +194647: [22577], +194648: [22700], +194649: [136420], +194650: [22770], +194651: [22775], +194652: [22790], +194653: [22810], +194654: [22818], +194655: [22882], +194656: [136872], +194657: [136938], +194658: [23020], +194659: [23067], +194660: [23079], +194661: [23000], +194662: [23142], +194663: [14062], +194664: [136042], +194665: [23304], +194666: [23358], +194667: [23358], +194668: [137672], +194669: [23491], +194670: [23512], +194671: [23527], +194672: [23539], +194673: [138008], +194674: [23551], +194675: [23558], +194676: [24371], +194677: [23586], +194678: [14209], +194679: [23648], +194680: [23662], +194681: [23744], +194682: [23693], +194683: [138724], +194684: [23875], +194685: [138726], +194686: [23918], +194687: [23915], +194688: [23932], +194689: [24033], +194690: [24034], +194691: [14383], +194692: [24061], +194693: [24104], +194694: [24125], +194695: [24169], +194696: [14434], +194697: [139651], +194698: [14460], +194699: [24240], +194700: [24243], +194701: [24246], +194702: [24266], +194703: [172946], +194704: [24318], +194705: [140081], +194706: [140081], +194707: [33281], +194708: [24354], +194709: [24354], +194710: [14535], +194711: [144056], +194712: [156122], +194713: [24418], +194714: [24427], +194715: [14563], +194716: [24474], +194717: [24525], +194718: [24535], +194719: [24569], +194720: [24705], +194721: [14650], +194722: [14620], +194723: [24724], +194724: [141012], +194725: [24775], +194726: [24904], +194727: [24908], +194728: [24910], +194729: [24908], +194730: [24954], +194731: [24974], +194732: [25010], +194733: [24996], +194734: [25007], +194735: [25054], +194736: [25074], +194737: [25078], +194738: [25104], +194739: [25115], +194740: [25181], +194741: [25265], +194742: [25300], +194743: [25424], +194744: [142092], +194745: [25405], +194746: [25340], +194747: [25448], +194748: [25475], +194749: [25572], +194750: [142321], +194751: [25634], +194752: [25541], +194753: [25513], +194754: [14894], +194755: [25705], +194756: [25726], +194757: [25757], +194758: [25719], +194759: [14956], +194760: [25935], +194761: [25964], +194762: [143370], +194763: [26083], +194764: [26360], +194765: [26185], +194766: [15129], +194767: [26257], +194768: [15112], +194769: [15076], +194770: [20882], +194771: [20885], +194772: [26368], +194773: [26268], +194774: [32941], +194775: [17369], +194776: [26391], +194777: [26395], +194778: [26401], +194779: [26462], +194780: [26451], +194781: [144323], +194782: [15177], +194783: [26618], +194784: [26501], +194785: [26706], +194786: [26757], +194787: [144493], +194788: [26766], +194789: [26655], +194790: [26900], +194791: [15261], +194792: [26946], +194793: [27043], +194794: [27114], +194795: [27304], +194796: [145059], +194797: [27355], +194798: [15384], +194799: [27425], +194800: [145575], +194801: [27476], +194802: [15438], +194803: [27506], +194804: [27551], +194805: [27578], +194806: [27579], +194807: [146061], +194808: [138507], +194809: [146170], +194810: [27726], +194811: [146620], +194812: [27839], +194813: [27853], +194814: [27751], +194815: [27926], +194816: [27966], +194817: [28023], +194818: [27969], +194819: [28009], +194820: [28024], +194821: [28037], +194822: [146718], +194823: [27956], +194824: [28207], +194825: [28270], +194826: [15667], +194827: [28363], +194828: [28359], +194829: [147153], +194830: [28153], +194831: [28526], +194832: [147294], +194833: [147342], +194834: [28614], +194835: [28729], +194836: [28702], +194837: [28699], +194838: [15766], +194839: [28746], +194840: [28797], +194841: [28791], +194842: [28845], +194843: [132389], +194844: [28997], +194845: [148067], +194846: [29084], +194847: [17323], +194848: [29224], +194849: [29237], +194850: [29264], +194851: [149000], +194852: [29312], +194853: [29333], +194854: [149301], +194855: [149524], +194856: [29562], +194857: [29579], +194858: [16044], +194859: [29605], +194860: [16056], +194861: [16056], +194862: [29767], +194863: [29788], +194864: [29809], +194865: [29829], +194866: [29898], +194867: [16155], +194868: [29988], +194869: [150582], +194870: [30014], +194871: [150674], +194872: [30064], +194873: [139679], +194874: [30224], +194875: [151457], +194876: [151480], +194877: [151620], +194878: [16380], +194879: [16392], +194880: [30452], +194881: [151795], +194882: [151794], +194883: [151833], +194884: [151859], +194885: [30494], +194886: [30495], +194887: [30495], +194888: [30538], +194889: [16441], +194890: [30603], +194891: [16454], +194892: [16534], +194893: [152605], +194894: [30798], +194895: [30860], +194896: [30924], +194897: [16611], +194898: [153126], +194899: [31062], +194900: [153242], +194901: [153285], +194902: [31119], +194903: [31211], +194904: [16687], +194905: [31296], +194906: [31306], +194907: [31311], +194908: [153980], +194909: [154279], +194910: [154279], +194911: [31406], +194912: [16898], +194913: [154539], +194914: [31686], +194915: [31689], +194916: [16935], +194917: [154752], +194918: [31954], +194919: [17056], +194920: [31976], +194921: [31971], +194922: [32000], +194923: [155526], +194924: [32099], +194925: [17153], +194926: [32199], +194927: [32258], +194928: [32325], +194929: [17204], +194930: [156200], +194931: [156231], +194932: [17241], +194933: [156377], +194934: [32634], +194935: [156478], +194936: [32661], +194937: [32762], +194938: [32773], +194939: [156890], +194940: [156963], +194941: [32864], +194942: [157096], +194943: [32880], +194944: [144223], +194945: [17365], +194946: [32946], +194947: [33027], +194948: [17419], +194949: [33086], +194950: [23221], +194951: [157607], +194952: [157621], +194953: [144275], +194954: [144284], +194955: [33281], +194956: [33284], +194957: [36766], +194958: [17515], +194959: [33425], +194960: [33419], +194961: [33437], +194962: [21171], +194963: [33457], +194964: [33459], +194965: [33469], +194966: [33510], +194967: [158524], +194968: [33509], +194969: [33565], +194970: [33635], +194971: [33709], +194972: [33571], +194973: [33725], +194974: [33767], +194975: [33879], +194976: [33619], +194977: [33738], +194978: [33740], +194979: [33756], +194980: [158774], +194981: [159083], +194982: [158933], +194983: [17707], +194984: [34033], +194985: [34035], +194986: [34070], +194987: [160714], +194988: [34148], +194989: [159532], +194990: [17757], +194991: [17761], +194992: [159665], +194993: [159954], +194994: [17771], +194995: [34384], +194996: [34396], +194997: [34407], +194998: [34409], +194999: [34473], +195000: [34440], +195001: [34574], +195002: [34530], +195003: [34681], +195004: [34600], +195005: [34667], +195006: [34694], +195007: [19799], +195008: [34785], +195009: [34817], +195010: [17913], +195011: [34912], +195012: [34915], +195013: [161383], +195014: [35031], +195015: [35038], +195016: [17973], +195017: [35066], +195018: [13499], +195019: [161966], +195020: [162150], +195021: [18110], +195022: [18119], +195023: [35488], +195024: [35565], +195025: [35722], +195026: [35925], +195027: [162984], +195028: [36011], +195029: [36033], +195030: [36123], +195031: [36215], +195032: [163631], +195033: [133124], +195034: [36299], +195035: [36284], +195036: [36336], +195037: [133342], +195038: [36564], +195039: [36664], +195040: [165330], +195041: [165357], +195042: [37012], +195043: [37105], +195044: [37137], +195045: [165678], +195046: [37147], +195047: [37432], +195048: [37591], +195049: [37592], +195050: [37500], +195051: [37881], +195052: [37909], +195053: [166906], +195054: [38283], +195055: [18837], +195056: [38327], +195057: [167287], +195058: [18918], +195059: [38595], +195060: [23986], +195061: [38691], +195062: [168261], +195063: [168474], +195064: [19054], +195065: [19062], +195066: [38880], +195067: [168970], +195068: [19122], +195069: [169110], +195070: [38923], +195071: [38923], +195072: [38953], +195073: [169398], +195074: [39138], +195075: [19251], +195076: [39209], +195077: [39335], +195078: [39362], +195079: [39422], +195080: [19406], +195081: [170800], +195082: [39698], +195083: [40000], +195084: [40189], +195085: [19662], +195086: [19693], +195087: [40295], +195088: [172238], +195089: [19704], +195090: [172293], +195091: [172558], +195092: [172689], +195093: [40635], +195094: [19798], +195095: [40697], +195096: [40702], +195097: [40709], +195098: [40719], +195099: [40726], +195100: [40763], +195101: [173568], +} Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Wed Jun 8 18:21:37 2005 @@ -290,9 +290,9 @@ self.wrap("character code not in range(256)")) return W_StringObject(self, ''.join(chars)) - def newunicode(self, chars_w): + def newunicode(self, chars): try: - chars = [unichr(self.int_w(w_c)) for w_c in chars_w] + chars = [unichr(c) for c in chars] except ValueError, e: # unichr(out-of-range) raise OperationError(self.w_ValueError, self.wrap("character code not in range(0x110000)")) From adim at codespeak.net Wed Jun 8 18:45:46 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 8 Jun 2005 18:45:46 +0200 (CEST) Subject: [pypy-svn] r13189 - pypy/branch/pycompiler/module/recparser/test Message-ID: <20050608164546.357E927B55@code1.codespeak.net> Author: adim Date: Wed Jun 8 18:45:27 2005 New Revision: 13189 Modified: pypy/branch/pycompiler/module/recparser/test/test_lookahead.py Log: added testcases for lookahead Modified: pypy/branch/pycompiler/module/recparser/test/test_lookahead.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_lookahead.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_lookahead.py Wed Jun 8 18:45:27 2005 @@ -15,13 +15,13 @@ def test_basic_alternative(self): - alt = Alternative('alt', *self.tokens) + alt = Alternative('alt', self.tokens) build_first_sets([alt]) assert alt.first_set == self.tokens def test_basic_sequence(self): - seq = Sequence('seq', *self.tokens) + seq = Sequence('seq', self.tokens) build_first_sets([seq]) assert seq.first_set == [self.tokens[0]] @@ -35,18 +35,33 @@ assert kstar.first_set == [tok1, EmptyToken] -def test_token_comparison(): - assert Token('t1', 'foo') == Token('t1', 'foo') - assert ('t1', 'foo') == Token('t1', 'foo') + def test_maybe_empty_sequence(self): + """S -> tok1{0,2} tok2{0,2} + ==> S.first_set = [tok1, tok2, EmptyToken] + """ + tok1, tok2, tok3 = self.tokens + k1 = KleenStar('k1', 0, 2, tok1) + k2 = KleenStar('k1', 0, 2, tok2) + seq = Sequence('seq', [k1, k2]) + build_first_sets([k1, k2, seq]) + assert seq.first_set == [tok1, tok2, EmptyToken] - # assert Token('t1', 'foo') == Token('t1', None) - assert ('t1', 'foo') == Token('t1', None) - assert Token('t1', 'foo') != Token('t2', 'foo') - assert ('t1', 'foo') != Token('t2', 'foo') + def test_not_empty_sequence(self): + """S -> tok1{0,2} tok2{1,2} + ==> S.first_set = [tok1, tok2] + """ + tok1, tok2, tok3 = self.tokens + k1 = KleenStar('k1', 0, 2, tok1) + k2 = KleenStar('k1', 1, 2, tok2) + seq = Sequence('seq', [k1, k2]) + build_first_sets([k1, k2, seq]) + assert seq.first_set == [tok1, tok2] +def test_token_comparison(): + assert Token('t1', 'foo') == Token('t1', 'foo') + assert Token('t1', 'foo') != Token('t2', 'foo') assert Token('t2', 'foo') != Token('t1', None) - assert ('t2', 'foo') != Token('t1', None) class TestLookAhead: @@ -54,17 +69,16 @@ def setup_method(self, method): self.LOW = Token('LOW', 'low') self.CAP = Token('CAP' ,'cap') - self.A = Alternative('A') + self.A = Alternative('A', []) k1 = KleenStar('k1', 0, rule=self.LOW) k2 = KleenStar('k2', 0, rule=self.CAP) - self.B = Sequence('B', k1, self.A) - self.C = Sequence('C', k2, self.A) + self.B = Sequence('B', [k1, self.A]) + self.C = Sequence('C', [k2, self.A]) self.A.args = [self.B, self.C] build_first_sets([self.A, self.B, self.C, self.LOW, self.CAP, k1, k2]) def test_S_first_set(self): - for s in [('LOW', 'low'), EmptyToken, ('CAP', 'cap')]: + for s in [Token('LOW', 'low'), EmptyToken, Token('CAP', 'cap')]: assert s in self.A.first_set assert s in self.B.first_set assert s in self.C.first_set - From adim at codespeak.net Wed Jun 8 18:46:49 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 8 Jun 2005 18:46:49 +0200 (CEST) Subject: [pypy-svn] r13190 - pypy/branch/pycompiler/module/recparser Message-ID: <20050608164649.A43EE27B56@code1.codespeak.net> Author: adim Date: Wed Jun 8 18:46:48 2005 New Revision: 13190 Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py Log: added a PythonSource which use Jonhathan's tokenizer Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonlexer.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonlexer.py Wed Jun 8 18:46:48 2005 @@ -82,6 +82,7 @@ self.stack_pos = 0 self.comment = '' self.encoding = None + def current_line(self): return self._current_line @@ -289,138 +290,328 @@ lineno = self.line return 'line %s : %s' % (lineno, self._lines[lineno-1]) - ## ONLY refactor ideas ########################################### -## def _mynext(self): -## """returns the next token from source""" -## inp = self.input -## pos = self.pos -## input_length = len(inp) -## if pos >= input_length: -## return self.end_of_file() -## # Beginning of line -## if self.atbol: -## self.linestart = pos -## col = 0 -## m = py_ws.match(inp, pos) -## pos = m.end() -## col = pos - self.linestart -## self.atbol = False -## # skip blanklines -## m = py_comment.match(inp, pos) -## if m: -## self.pos = m.end() + 1 -## self.line += 1 -## self.atbol = True -## return self._next() -## # the current block is more indented than the previous one -## if col > self.indentstack[-1]: -## self.indentstack.append(col) -## return "INDENT", None -## # the current block is less indented than the previous one -## while col < self.indentstack[-1]: -## self.pendin += 1 -## self.indentstack.pop(-1) -## if col != self.indentstack[-1]: -## raise SyntaxError("Indentation Error") -## if self.pendin > 0: -## self.pendin -= 1 -## return "DEDENT", None -## m = py_skip.match(inp, pos) -## if m.group(0)[-1:] == '\n': -## self.line += 1 -## pos = m.end() # always match -## if pos >= input_length: -## return self.end_of_file() -## self.pos = pos - -## c = inp[pos] -## chain = (self._check_string, self._check_name, self._check_number, -## self._check_newline, self._check_backslash, self._check_punct) -## for check_meth in chain: -## token_val_pair = check_meth(c, pos) -## if token_val_pair is not None: -## return token_val_pair + +################################################################################ +class StringAsFile(object): + """XXX: Is StringIO RPython ?""" + + def __init__(self, inpstring): + self.lines = inpstring.splitlines(True) + self.lineno = 0 + + def readline(self): + if self.lineno < len(self.lines): + line = self.lines[self.lineno] + self.lineno += 1 + return line + return '' + + +import token as tokenmod +from pypy.module.parser.pytokenize import generate_tokens, tabsize, \ + whiteSpaceDFA, triple_quoted, endDFAs, single_quoted, pseudoDFA + +# adopt pytokenize notations / values +tokenmod.COMMENT = tokenmod.N_TOKENS +tokenmod.NL = tokenmod.N_TOKENS + 1 + +class TokenError(Exception): + """Raised when EOF is found prematuerly""" + def __init__(self, msg, strstart, token_stack): + Exception.__init__(self, msg) + self.strstart = strstart + self.token_stack = token_stack + + +def generate_tokens(readline): + """ + This is a rewrite of pypy.module.parser.pytokenize.generate_tokens since + the original function is not RPYTHON (uses yield) + It was also slightly modified to generate Token instances instead + of the original 5-tuples + + Original docstring :: + + The generate_tokens() generator requires one argment, readline, which + must be a callable object which provides the same interface as the + readline() method of built-in file objects. Each call to the function + should return one line of input as a string. + + The generator produces 5-tuples with these members: the token type; the + token string; a 2-tuple (srow, scol) of ints specifying the row and + column where the token begins in the source; a 2-tuple (erow, ecol) of + ints specifying the row and column where the token ends in the source; + and the line on which the token was found. The line passed is the + logical line; continuation lines are included. + """ + token_list = [] + lnum = parenlev = continued = 0 + namechars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' + numchars = '0123456789' + contstr, needcont = '', 0 + contline = None + indents = [0] + last_comment = '' + encoding = None + strstart = (0, 0) + + while 1: # loop over lines in stream + line = readline() + lnum = lnum + 1 + pos, max = 0, len(line) + + if contstr: # continued string + if not line: + raise TokenError("EOF in multi-line string", strstart, token_list) + endmatch = endDFA.recognize(line) + if -1 != endmatch: + pos = end = endmatch + tok = token_from_values(tokenmod.STRING, contstr + line[:end]) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((STRING, contstr + line[:end], + # strstart, (lnum, end), contline + line)) + contstr, needcont = '', 0 + contline = None + elif needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n': + tok = token_from_values(tokenmod.ERRORTOKEN, contstr + line) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((ERRORTOKEN, contstr + line, + # strstart, (lnum, len(line)), contline)) + contstr = '' + contline = None + continue + else: + contstr = contstr + line + contline = contline + line + continue + + elif parenlev == 0 and not continued: # new statement + if not line: break + column = 0 + while pos < max: # measure leading whitespace + if line[pos] == ' ': column = column + 1 + elif line[pos] == '\t': column = (column/tabsize + 1)*tabsize + elif line[pos] == '\f': column = 0 + else: break + pos = pos + 1 + if pos == max: break + + if line[pos] in '#\r\n': # skip comments or blank lines + if line[pos] == '#': + tok = token_from_values(tokenmod.COMMENT, line[pos:]) + last_comment = line[pos:] + if lnum <= 2: + m_enc = py_encoding.search(last_comment) + if m_enc is not None: + encoding = _normalize_encoding(m_enc.group(1)) + else: + tok = token_from_values(tokenmod.NL, line[pos:]) + last_comment = '' + # XXX Skip NL and COMMENT Tokens # token_list.append((tok, line)) + # token_list.append(((NL, COMMENT)[line[pos] == '#'], line[pos:], + # (lnum, pos), (lnum, len(line)), line)) + continue + + if column > indents[-1]: # count indents or dedents + indents.append(column) + tok = token_from_values(tokenmod.INDENT, line[:pos]) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((INDENT, line[:pos], (lnum, 0), (lnum, pos), line)) + while column < indents[-1]: + indents = indents[:-1] + tok = token_from_values(tokenmod.DEDENT, '') + token_list.append((tok, line)) + last_comment = '' + # token_list.append((DEDENT, '', (lnum, pos), (lnum, pos), line)) + + else: # continued statement + if not line: + raise TokenError("EOF in multi-line statement", (lnum, 0), token_list) + continued = 0 + + while pos < max: + pseudomatch = pseudoDFA.recognize(line, pos) + if -1 != pseudomatch: # scan for tokens + # JDR: Modified + start = whiteSpaceDFA.recognize(line, pos) + if -1 == start: + start = pos + end = pseudomatch + + spos, epos, pos = (lnum, start), (lnum, end), end + token, initial = line[start:end], line[start] + + if initial in numchars or \ + (initial == '.' and token != '.'): # ordinary number + tok = token_from_values(tokenmod.NUMBER, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((NUMBER, token, spos, epos, line)) + elif initial in '\r\n': + if parenlev > 0: + tok = token_from_values(tokenmod.NL, token) + last_comment = '' + # XXX Skip NL + else: + tok = token_from_values(tokenmod.NEWLINE, token) + # XXX YUCK ! + tok.value = last_comment + token_list.append((tok, line)) + last_comment = '' + # token_list.append((parenlev > 0 and NL or NEWLINE, token, spos, epos, line)) + elif initial == '#': + tok = token_from_values(tokenmod.COMMENT, token) + last_comment = token + if lnum <= 2: + m_enc = py_encoding.search(last_comment) + if m_enc is not None: + encoding = _normalize_encoding(m_enc.group(1)) + # XXX Skip # token_list.append((tok, line)) + # token_list.append((COMMENT, token, spos, epos, line)) + elif token in triple_quoted: + endDFA = endDFAs[token] + endmatch = endDFA.recognize(line, pos) + if -1 != endmatch: # all on one line + pos = endmatch + token = line[start:pos] + tok = token_from_values(tokenmod.STRING, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((STRING, token, spos, (lnum, pos), line)) + else: + strstart = (lnum, start) # multiple lines + contstr = line[start:] + contline = line + break + elif initial in single_quoted or \ + token[:2] in single_quoted or \ + token[:3] in single_quoted: + if token[-1] == '\n': # continued string + strstart = (lnum, start) + endDFA = (endDFAs[initial] or endDFAs[token[1]] or + endDFAs[token[2]]) + contstr, needcont = line[start:], 1 + contline = line + break + else: # ordinary string + tok = token_from_values(tokenmod.STRING, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((STRING, token, spos, epos, line)) + elif initial in namechars: # ordinary name + tok = token_from_values(tokenmod.NAME, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((NAME, token, spos, epos, line)) + elif initial == '\\': # continued stmt + continued = 1 + else: + if initial in '([{': parenlev = parenlev + 1 + elif initial in ')]}': parenlev = parenlev - 1 + tok = token_from_values(tokenmod.OP, token) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((OP, token, spos, epos, line)) + else: + tok = token_from_values(tokenmod.ERRORTOKEN, line[pos]) + token_list.append((tok, line)) + last_comment = '' + # token_list.append((ERRORTOKEN, line[pos], + # (lnum, pos), (lnum, pos+1), line)) + pos = pos + 1 + + last_comment = '' + for indent in indents[1:]: # pop remaining indent levels + tok = token_from_values(tokenmod.DEDENT, '') + token_list.append((tok, line)) + # token_list.append((DEDENT, '', (lnum, 0), (lnum, 0), '')) + + ## adim + token_list.append((Token('NEWLINE', ''), line)) + ## + tok = token_from_values(tokenmod.ENDMARKER, '',) + token_list.append((tok, line)) + # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) + return token_list, encoding + + +class PythonSource2(TokenSource): + """This source uses Jonathan's tokenizer""" + def __init__(self, inpstring): + TokenSource.__init__(self) + tokens, encoding = generate_tokens(StringAsFile(inpstring).readline) + self.token_stack = tokens + self.encoding = encoding + self._current_line = '' # the current line (as a string) + self.stack_pos = 0 + + def next(self): + if self.stack_pos >= len(self.token_stack): + raise StopIteration("Remove me") + tok, line = self.token_stack[self.stack_pos] + self.stack_pos += 1 + self._current_line = line + return tok + + def current_line(self): + return self._current_line + + def context(self): + return self.stack_pos + + def restore(self, ctx): + self.stack_pos = ctx + + def peek(self): + """returns next token without consuming it""" + ctx = self.context() + token = self.next() + self.restore(ctx) + return token + + #### methods below have to be translated + def offset(self, ctx=None): + if ctx is None: + return self.stack_pos + else: + assert type(ctx)==int + return ctx + + def get_pos(self): + if self.stack_pos >= len(self.stack): + return self.pos + else: + token, line, pos = self.stack[self.stack_pos] + return pos + + def get_source_text(self, pos0, pos1 ): + return self.input[pos0:pos1] + def debug(self): + """return context for debug information""" + return 'line %s : %s' % ('XXX', self._current_line) -## def _check_string(self, c, pos): -## inp = self.input -## input_length = len(inp) -## # STRING -## if c in ('r', 'R'): -## if pos < input_length-1 and inp[pos+1] in ("'",'"'): -## return self.next_string(raw=1) -## elif c in ('u','U'): -## if pos < input_length - 1: -## if inp[pos+1] in ("r", 'R'): -## if pos 0: -## return self._next() -## else: -## self.atbol = True -## return "NEWLINE", None -## return None - -## def _check_backslash(self, c, pos): -## inp = self.input -## input_length = len(inp) -## if c == '\\': -## if pos < input_length-1 and inp[pos+1] == '\n': -## self.pos += 2 -## return self._next() -## return None - -## def _check_punct(self, c, pos): -## inp = self.input -## input_length = len(inp) -## m = py_punct.match(inp, pos) -## if m: -## punct = m.group(0) -## if punct in ( '(', '{' ): -## self.level += 1 -## if punct in ( ')', '}' ): -## self.level -= 1 -## self.pos = m.end() -## return punct, None -## raise SyntaxError("Unrecognized token '%s'" % inp[pos:pos+20] ) +NONE_LIST = [tokenmod.ENDMARKER, tokenmod.INDENT, tokenmod.DEDENT,] +NAMED_LIST = [tokenmod.OP, ] +def token_from_values(tok_type, tok_string): + """XXX Compatibility layer between both parsers""" + if tok_type in NONE_LIST: + return Token(tokenmod.tok_name[tok_type], None) + if tok_type in NAMED_LIST: + return Token(tok_string, None) + if tok_type == tokenmod.NEWLINE: + return Token('NEWLINE', '') # XXX pending comment ? + return Token(tokenmod.tok_name[tok_type], tok_string) +Source = PythonSource2 def tokenize_file(filename): f = file(filename).read() - src = PythonSource(f) + src = Source(f) token = src.next() while token!=("ENDMARKER",None) and token!=(None,None): print token From adim at codespeak.net Wed Jun 8 18:48:10 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 8 Jun 2005 18:48:10 +0200 (CEST) Subject: [pypy-svn] r13191 - pypy/branch/pycompiler/module/recparser/test Message-ID: <20050608164810.D932D27B59@code1.codespeak.net> Author: adim Date: Wed Jun 8 18:48:09 2005 New Revision: 13191 Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py pypy/branch/pycompiler/module/recparser/test/test_samples.py Log: - added tests for both lexer Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py Wed Jun 8 18:48:09 2005 @@ -1,10 +1,10 @@ -from pypy.module.recparser.pythonlexer import PythonSource, py_number, \ - g_symdef, g_string, py_name, py_punct +from pypy.module.recparser.pythonlexer import Source, py_number, \ + g_symdef, g_string, py_name, py_punct, TokenError from pypy.module.recparser.grammar import Token def parse_source(source): """returns list of parsed tokens""" - lexer = PythonSource(source) + lexer = Source(source) tokens = [] last_token = Token(None, None) while last_token.name != 'ENDMARKER': @@ -22,7 +22,8 @@ '+=', '>>=', '=', '&=', '/=', '-=', ',', '^', '>>', '&', '+', '*', '-', '/', '.', '**', '%', '<<', '//', '|', ')', '(', ';', ':', - '@', '[', ']', '`', '{', '}', + # '@', # XXX This one is skipped for now (?!) + '[', ']', '`', '{', '}', ] NUMBERS = [ @@ -76,9 +77,14 @@ Token('NUMBER', '0x12L'), Token('NEWLINE', ''), Token('ENDMARKER', None)] +import sys + def test_punct(): """make sure each punctuation is correctly parsed""" for pstr in PUNCTS: - tokens = parse_source(pstr) + try: + tokens = parse_source(pstr) + except TokenError, error: + tokens = [tok for tok, line in error.token_stack] assert tokens[0].name == pstr Modified: pypy/branch/pycompiler/module/recparser/test/test_samples.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_samples.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_samples.py Wed Jun 8 18:48:09 2005 @@ -46,12 +46,15 @@ def test_samples(): samples_dir = osp.join(osp.dirname(__file__), 'samples') - for fname in os.listdir(samples_dir): - if not fname.endswith('.py'): - continue - abspath = osp.join(samples_dir, fname) - yield check_parse, abspath - + for use_lookahead in (True, False): + grammar.USE_LOOKAHEAD = use_lookahead + for fname in os.listdir(samples_dir): + if not fname.endswith('.py'): + continue + # if fname != 'snippet_encoding_declaration.py': + abspath = osp.join(samples_dir, fname) + yield check_parse, abspath + def check_parse(filepath): print "Testing:", filepath pypy_tuples = pypy_parse(filepath) From adim at codespeak.net Wed Jun 8 18:50:19 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 8 Jun 2005 18:50:19 +0200 (CEST) Subject: [pypy-svn] r13192 - pypy/branch/pycompiler/module/recparser Message-ID: <20050608165019.008F527B5B@code1.codespeak.net> Author: adim Date: Wed Jun 8 18:50:18 2005 New Revision: 13192 Modified: pypy/branch/pycompiler/module/recparser/pythonparse.py pypy/branch/pycompiler/module/recparser/syntaxtree.py Log: - cosemtic changes in syntaxtree - import Source rather than PythonSource in pythonparse Modified: pypy/branch/pycompiler/module/recparser/pythonparse.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonparse.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonparse.py Wed Jun 8 18:50:18 2005 @@ -1,5 +1,5 @@ #!/usr/bin/env python -from pythonlexer import PythonSource +from pythonlexer import Source from ebnfparse import parse_grammar import sys import os @@ -26,7 +26,7 @@ def parse_python_source( textsrc, gram, goal, builder=None ): """Parse a python source according to goal""" target = gram.rules[goal] - src = PythonSource(textsrc) + src = Source(textsrc) if builder is None: builder = grammar.BaseGrammarBuilder(debug=False, rules=gram.rules) result = target.match(src, builder) Modified: pypy/branch/pycompiler/module/recparser/syntaxtree.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/syntaxtree.py (original) +++ pypy/branch/pycompiler/module/recparser/syntaxtree.py Wed Jun 8 18:50:18 2005 @@ -102,6 +102,7 @@ return "(%s)" % self.name def visit(self, visitor): + """NOT RPYTHON, used only at bootstrap time anyway""" visit_meth = getattr(visitor, "visit_%s" % self.name, None) if visit_meth: return visit_meth(self) @@ -114,7 +115,7 @@ return [ self ] def totuple(self, lineno=False ): - symvalue = SYMBOLS.get( self.name, (0,self.name) ) + symvalue = SYMBOLS.get( self.name, (0, self.name) ) l = [ symvalue ] l += [node.totuple(lineno) for node in self.nodes] return tuple(l) From adim at codespeak.net Wed Jun 8 18:51:10 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 8 Jun 2005 18:51:10 +0200 (CEST) Subject: [pypy-svn] r13193 - pypy/branch/pycompiler/module/recparser Message-ID: <20050608165110.677DF27B5D@code1.codespeak.net> Author: adim Date: Wed Jun 8 18:51:09 2005 New Revision: 13193 Modified: pypy/branch/pycompiler/module/recparser/grammar.py Log: fixed tiny bug in lookahead algorithm Modified: pypy/branch/pycompiler/module/recparser/grammar.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/grammar.py (original) +++ pypy/branch/pycompiler/module/recparser/grammar.py Wed Jun 8 18:51:09 2005 @@ -69,6 +69,7 @@ if new_size != size: changed = True for r in rules: + assert len(r.first_set) > 0, "Error: ot Empty firstset for %s" % r r.reorder_rule() @@ -165,7 +166,8 @@ return self._match(source, builder, level) token = source.peek() - pos1 = source.get_pos() + if self._trace: + pos1 = source.get_pos() in_first_set = self.match_first_set(token) if not in_first_set: # and not EmptyToken in self.first_set: if EmptyToken in self.first_set: @@ -395,8 +397,11 @@ LAH(S) = LAH(A) """ for rule in self.args: + if not rule.first_set: + break if EmptyToken in self.first_set: self.first_set.remove( EmptyToken ) + # del self.first_set[EmptyToken] # while we're in this loop, keep agregating possible tokens for t in rule.first_set: From arigo at codespeak.net Wed Jun 8 19:40:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 19:40:43 +0200 (CEST) Subject: [pypy-svn] r13195 - in pypy/dist/pypy/rpython: . test Message-ID: <20050608174043.F2AF727B5D@code1.codespeak.net> Author: arigo Date: Wed Jun 8 19:40:41 2005 New Revision: 13195 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py Log: Problem with hash() of recursive structures. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Wed Jun 8 19:40:41 2005 @@ -28,7 +28,6 @@ items = self.items() items.sort() return hash(tuple(items)) - __hash__ = saferecursive(__hash__, 0) class LowLevelType(object): @@ -40,10 +39,21 @@ return not (self == other) def __hash__(self): + # cannot use saferecursive() -- see test_lltype.test_hash(). + # this version uses a compromize between computation time and + # collision-avoidance that can be customized if needed. + try: + if TLS.nested_hash_level >= 3: + return 0 + except AttributeError: + TLS.nested_hash_level = 0 items = self.__dict__.items() items.sort() - return hash((self.__class__,) + tuple(items)) - __hash__ = saferecursive(__hash__, 0) + TLS.nested_hash_level += 1 + try: + return hash((self.__class__,) + tuple(items)) + finally: + TLS.nested_hash_level -= 1 def __repr__(self): return '<%s>' % (self,) Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Wed Jun 8 19:40:41 2005 @@ -241,3 +241,12 @@ S = Struct('s') p0 = nullptr(S) assert not p0 + +def test_hash(): + S = ForwardReference() + S.become(Struct('S', ('p', Ptr(S)))) + assert S == S + S1 = Struct('S', ('p', Ptr(S))) + assert S1 == S + assert S == S1 + assert hash(S1) == hash(S) From arigo at codespeak.net Wed Jun 8 19:47:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 19:47:19 +0200 (CEST) Subject: [pypy-svn] r13196 - pypy/dist/pypy/rpython Message-ID: <20050608174719.4A9EF27B5F@code1.codespeak.net> Author: arigo Date: Wed Jun 8 19:47:19 2005 New Revision: 13196 Modified: pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rtyper.py Log: Small reorganizations needed by an ongoing far-fetched attempt of having translator.ccompile() use the new C compiler. Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Wed Jun 8 19:47:19 2005 @@ -2,7 +2,8 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import Void, Bool, Float, Signed, Char -from pypy.rpython.lltype import typeOf, LowLevelType +from pypy.rpython.lltype import typeOf, LowLevelType, Ptr, PyObject +from pypy.rpython.lltype import FuncType, functionptr class Repr: @@ -168,3 +169,18 @@ c = Constant(value) c.concretetype = lltype return c + +# __________ utilities __________ + +PyObjPtr = Ptr(PyObject) + +def getconcretetype(v): + return getattr(v, 'concretetype', PyObjPtr) + +def getfunctionptr(translator, func, getconcretetype=getconcretetype): + """Make a functionptr from the given Python function.""" + graph = translator.getflowgraph(func) + llinputs = [getconcretetype(v) for v in graph.getargs()] + lloutput = getconcretetype(graph.getreturnvar()) + FT = FuncType(llinputs, lloutput) + return functionptr(FT, func.func_name, graph = graph, _callable = func) Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Wed Jun 8 19:47:19 2005 @@ -1,6 +1,6 @@ from pypy.annotation.pairtype import pair, pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import PyObject, Ptr, Void, Bool +from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass @@ -18,6 +18,9 @@ class PyObjRepr(Repr): lowleveltype = Ptr(PyObject) + def convert_const(self, value): + return pyobjectptr(value) + pyobj_repr = PyObjRepr() Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 8 19:47:19 2005 @@ -8,7 +8,7 @@ from pypy.rpython.lltype import FuncType, functionptr, typeOf from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block -from pypy.rpython.rmodel import Repr, inputconst, TyperError +from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr from pypy.rpython.normalizecalls import perform_normalizations from pypy.rpython.annlowlevel import annotate_lowlevel_helper @@ -95,6 +95,10 @@ self.typererror = None #self.annotator.translator.view() raise exc, value, tb + # make sure that the return variables of all graphs are concretetype'd + for graph in self.annotator.translator.flowgraphs.values(): + v = graph.getreturnvar() + self.setconcretetype(v) def call_all_setups(self): # make sure all reprs so far have had their setup() called @@ -257,17 +261,9 @@ # __________ utilities __________ def getfunctionptr(self, func): - """Make a functionptr from the given Python function.""" - a = self.annotator - graph = a.translator.getflowgraph(func) - llinputs = [self.bindingrepr(v).lowleveltype for v in graph.getargs()] - s_output = a.binding(graph.getreturnvar(), None) - if s_output is None: - lloutput = Void - else: - lloutput = self.getrepr(s_output).lowleveltype - FT = FuncType(llinputs, lloutput) - return functionptr(FT, func.func_name, graph = graph, _callable = func) + def getconcretetype(v): + return self.bindingrepr(v).lowleveltype + return getfunctionptr(self.annotator.translator, func, getconcretetype) # ____________________________________________________________ From arigo at codespeak.net Wed Jun 8 19:51:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 19:51:08 +0200 (CEST) Subject: [pypy-svn] r13197 - in pypy/branch/translator-without-old-genc: . c c/test genc/test test Message-ID: <20050608175108.E51D427B61@code1.codespeak.net> Author: arigo Date: Wed Jun 8 19:51:03 2005 New Revision: 13197 Added: pypy/branch/translator-without-old-genc/ - copied from r13196, pypy/dist/pypy/translator/ Modified: pypy/branch/translator-without-old-genc/annrpython.py pypy/branch/translator-without-old-genc/c/database.py pypy/branch/translator-without-old-genc/c/funcgen.py pypy/branch/translator-without-old-genc/c/g_module.h pypy/branch/translator-without-old-genc/c/genc.py pypy/branch/translator-without-old-genc/c/node.py pypy/branch/translator-without-old-genc/c/pyobj.py pypy/branch/translator-without-old-genc/c/test/test_database.py pypy/branch/translator-without-old-genc/c/test/test_genc.py pypy/branch/translator-without-old-genc/c/wrapper.py pypy/branch/translator-without-old-genc/genc/test/test_lltyped.py pypy/branch/translator-without-old-genc/genc/test/test_typed.py pypy/branch/translator-without-old-genc/test/test_backends.py pypy/branch/translator-without-old-genc/transform.py pypy/branch/translator-without-old-genc/translator.py pypy/branch/translator-without-old-genc/unsimplify.py Log: Branching the pypy/translator subdirectory in an attempt to remove the old GenC. The point to branch this directory only is that in order to have all the old GenC's tests pass again, some progress will be needed in rpython/rtyper, and we want this to be done on the trunk. Modified: pypy/branch/translator-without-old-genc/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/branch/translator-without-old-genc/annrpython.py Wed Jun 8 19:51:03 2005 @@ -193,6 +193,13 @@ print "++-" * 20 raise AnnotatorError('%d blocks are still blocked' % self.annotated.values().count(False)) + # make sure that the return variables of all graphs is annotated + if self.translator is not None: + for graph in self.translator.flowgraphs.values(): + v = graph.getreturnvar() + if v not in self.bindings: + self.setbinding(v, annmodel.SomeImpossibleValue()) + # policy-dependent computation self.policy.compute_at_fixpoint(self) def binding(self, arg, extquery=False): @@ -305,12 +312,6 @@ for graph in self.translator.flowgraphs.values(): simplify.eliminate_empty_blocks(graph) - def specialize(self, specializer=None): - if specializer is None: - from pypy.translator.genc import ctyper - specializer = ctyper.GenCSpecializer - specializer(self).specialize() - #___ flowing annotations in blocks _____________________ Modified: pypy/branch/translator-without-old-genc/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/branch/translator-without-old-genc/c/database.py Wed Jun 8 19:51:03 2005 @@ -13,13 +13,13 @@ class LowLevelDatabase: - def __init__(self, rtyper=None): + def __init__(self, translator=None): self.structdefnodes = {} self.structdeflist = [] self.containernodes = {} self.containerlist = [] self.namespace = CNameManager() - self.pyobjmaker = PyObjMaker(self.namespace, self.get, rtyper) + self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator) def gettypedefnode(self, T, varlength=1): if varlength <= 1: @@ -37,6 +37,7 @@ else: raise Exception("don't know about %r" % (T,)) self.structdefnodes[key] = node + node.setup() self.structdeflist.append(node) return node Modified: pypy/branch/translator-without-old-genc/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/branch/translator-without-old-genc/c/funcgen.py Wed Jun 8 19:51:03 2005 @@ -3,8 +3,9 @@ from pypy.translator.c.support import llvalue_from_constant from pypy.objspace.flow.model import Variable, Constant, Block from pypy.objspace.flow.model import traverse, uniqueitems, last_exception -from pypy.rpython.lltype import Ptr, PyObject, Void +from pypy.rpython.lltype import Ptr, PyObject, Void, Bool from pypy.rpython.lltype import pyobjectptr, Struct, Array +from pypy.translator.unsimplify import remove_direct_loops PyObjPtr = Ptr(PyObject) @@ -17,6 +18,7 @@ def __init__(self, graph, db): self.graph = graph + remove_direct_loops(None, graph) self.db = db self.lltypemap = self.collecttypes() self.typemap = {} @@ -34,7 +36,9 @@ result.extend(op.args) result.append(op.result) for link in block.exits: + result.extend(link.getextravars()) result.extend(link.args) + result.append(Constant(link.exitcase)) traverse(visit, self.graph) resultvar = self.graph.getreturnvar() lltypemap = {resultvar: Void} # default value, normally overridden @@ -199,9 +203,16 @@ yield '\t\tPy_INCREF(Py_None);' yield '\t}' yield '\tPy_XDECREF(exc_tb);' - for op in gen_link(link, { - link.last_exception: 'exc_cls', - link.last_exc_value: 'exc_value'}): + d = {} + if isinstance(link.last_exception, Variable): + d[link.last_exception] = 'exc_cls' + else: + yield '\tPy_XDECREF(exc_cls);' + if isinstance(link.last_exc_value, Variable): + d[link.last_exc_value] = 'exc_value' + else: + yield '\tPy_XDECREF(exc_value);' + for op in gen_link(link, d): yield '\t' + op yield '}' err_reachable = True @@ -211,8 +222,19 @@ for link in block.exits[:-1]: assert link.exitcase in (False, True) expr = self.expr(block.exitswitch) - if not link.exitcase: - expr = '!' + expr + if TYPE == Bool: + if not link.exitcase: + expr = '!' + expr + elif TYPE == PyObjPtr: + yield 'assert(%s == Py_True || %s == Py_False);' % ( + expr, expr) + if link.exitcase: + expr = '%s == Py_True' % expr + else: + expr = '%s == Py_False' % expr + else: + raise TypeError("switches can only be on Bool or " + "PyObjPtr. Got %r" % (TYPE,)) yield 'if (%s) {' % expr for op in gen_link(link): yield '\t' + op Modified: pypy/branch/translator-without-old-genc/c/g_module.h ============================================================================== --- pypy/dist/pypy/translator/c/g_module.h (original) +++ pypy/branch/translator-without-old-genc/c/g_module.h Wed Jun 8 19:51:03 2005 @@ -40,6 +40,7 @@ typedef struct { PyObject** p; + char* gfunc_name; PyMethodDef ml; } globalfunctiondef_t; @@ -64,8 +65,6 @@ static int setup_globalfunctions(globalfunctiondef_t* def) { PyObject* fn; - PyObject* name; - int len; for (; def->p != NULL; def++) { fn = PyCFunction_New(&def->ml, NULL); @@ -74,17 +73,10 @@ fn->ob_type = &PyGenCFunction_Type; *def->p = fn; /* store the object ref in the global var */ - len = 0; - while (def->ml.ml_name[len] != 0) - len++; - name = PyString_FromStringAndSize(NULL, 6+len); - if (name == NULL) + if (PyDict_SetItemString(this_module_globals, + def->gfunc_name, + fn) < 0) return -1; - memcpy(PyString_AS_STRING(name), "gfunc_", 6); - memcpy(PyString_AS_STRING(name)+6, def->ml.ml_name, len); - if (PyDict_SetItem(this_module_globals, name, fn) < 0) - return -1; - Py_DECREF(name); } return 0; } Modified: pypy/branch/translator-without-old-genc/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/branch/translator-without-old-genc/c/genc.py Wed Jun 8 19:51:03 2005 @@ -1,19 +1,48 @@ import autopath -import os +import os, py from pypy.translator.c.node import PyObjectNode +from pypy.translator.c.database import LowLevelDatabase +from pypy.translator.gensupp import uniquemodulename +from pypy.translator.tool.buildpyxmodule import make_module_from_c +from pypy.rpython.lltype import pyobjectptr +from pypy.tool.udir import udir + + +def translator2database(translator): + pf = pyobjectptr(translator.entrypoint) + db = LowLevelDatabase(translator) + db.get(pf) + db.complete() + return db, pf + + +def genc(translator, targetdir=None, modulename=None, compile=True): + """Generate C code starting at the translator's entry point. + The files are written to the targetdir if specified. + If 'compile' is True, compile and return the new module. + If 'compile' is False, just return the name of the main '.c' file. + """ + db, pf = translator2database(translator) + + if modulename is None: + modulename = uniquemodulename('testing') + if targetdir is None: + targetdir = udir.join(modulename) + elif isinstance(targetdir, str): + targetdir = py.path.local(targetdir) + targetdir.ensure(dir=1) + cfile = gen_source(db, modulename, targetdir, + # defines={'COUNT_OP_MALLOCS': 1}, + exports = {translator.entrypoint.func_name: pf}) + if not compile: + return cfile + m = make_module_from_c(cfile, include_dirs = [autopath.this_dir]) + return m -def gen_source(database, modulename, targetdir, defines={}): - filename = os.path.join(targetdir, modulename + '.c') - f = open(filename, 'w') - - # - # Header - # - for key, value in defines.items(): - print >> f, '#define %s %s' % (key, value) - print >> f, '#include "g_include.h"' +# ____________________________________________________________ +def gen_readable_parts_of_main_c_file(f, database): # # All declarations # @@ -22,7 +51,10 @@ print >> f, '/*** Structure definitions ***/' print >> f for node in database.structdeflist: - for line in node.definition(): + for line in node.definition(phase=1): + print >> f, line + for node in database.structdeflist: + for line in node.definition(phase=2): print >> f, line print >> f print >> f, '/***********************************************************/' @@ -31,17 +63,40 @@ for node in database.globalcontainers(): for line in node.forward_declaration(): print >> f, line - # # Implementation of functions and global structures and arrays # print >> f print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' + blank = True for node in database.globalcontainers(): - print >> f + if blank: + print >> f + blank = False for line in node.implementation(): print >> f, line + blank = True + + +def gen_source(database, modulename, targetdir, defines={}, exports={}): + if isinstance(targetdir, str): + targetdir = py.path.local(targetdir) + filename = targetdir.join(modulename + '.c') + f = filename.open('w') + + # + # Header + # + for key, value in defines.items(): + print >> f, '#define %s %s' % (key, value) + print >> f, '#include "g_include.h"' + + # + # 1) All declarations + # 2) Implementation of functions and global structures and arrays + # + gen_readable_parts_of_main_c_file(f, database) # # PyObject support (strange) code @@ -67,9 +122,10 @@ wrappers = pyobjmaker.wrappers.items() wrappers.sort() for globalobject_name, (base_name, wrapper_name) in wrappers: - print >> f, ('\t{&%s, {"%s", (PyCFunction)%s, ' + print >> f, ('\t{&%s, "%s", {"%s", (PyCFunction)%s, ' 'METH_VARARGS|METH_KEYWORDS}},' % ( globalobject_name, + globalobject_name, base_name, wrapper_name)) print >> f, '\t{ NULL }\t/* Sentinel */' @@ -80,7 +136,7 @@ print >> f print >> f, 'static char *frozen_initcode[] = {"\\' bytecode, originalsource = database.pyobjmaker.getfrozenbytecode() - g = open(os.path.join(targetdir, 'frozen.py'), 'w') + g = targetdir.join('frozen.py').open('w') g.write(originalsource) g.close() def char_repr(c): @@ -104,7 +160,11 @@ print >> f, 'MODULE_INITFUNC(%s)' % modulename print >> f, '{' print >> f, '\tSETUP_MODULE(%s)' % modulename - #print >> f, '\tPyModule_AddObject(m, "%(entrypointname)s", %(entrypoint)s);' + for publicname, pyobjptr in exports.items(): + # some fishing needed to find the name of the obj + pyobjnode = database.containernodes[pyobjptr._obj] + print >> f, '\tPyModule_AddObject(m, "%s", %s);' % (publicname, + pyobjnode.name) print >> f, '}' f.close() @@ -112,10 +172,12 @@ # Generate a setup.py while we're at it # pypy_include_dir = autopath.this_dir - f = open(os.path.join(targetdir, 'setup.py'), 'w') + f = targetdir.join('setup.py').open('w') f.write(SETUP_PY % locals()) f.close() + return filename + SETUP_PY = ''' from distutils.core import setup Modified: pypy/branch/translator-without-old-genc/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/branch/translator-without-old-genc/c/node.py Wed Jun 8 19:51:03 2005 @@ -22,6 +22,12 @@ def __init__(self, db, STRUCT, varlength=1): self.db = db self.STRUCT = STRUCT + self.varlength = varlength + + def setup(self): + db = self.db + STRUCT = self.STRUCT + varlength = self.varlength if varlength == 1: basename = STRUCT._name else: @@ -64,14 +70,15 @@ fldname = self.c_struct_field_name(fldname) return '%s.%s' % (baseexpr, fldname) - def definition(self): - yield 'struct %s {' % self.name - if needs_refcount(self.STRUCT): - yield '\tlong refcount;' - for name, typename in self.fields: - yield '\t%s;' % cdecl(typename, name) - yield '};' - if self.deallocator: + def definition(self, phase): + if phase == 1: + yield 'struct %s {' % self.name + if needs_refcount(self.STRUCT): + yield '\tlong refcount;' + for name, typename in self.fields: + yield '\t%s;' % cdecl(typename, name) + yield '};' + elif phase == 2 and self.deallocator: yield 'void %s(struct %s *p) {' % (self.deallocator, self.name) for line in self.deallocator_lines('p->'): yield '\t' + line @@ -101,6 +108,12 @@ def __init__(self, db, ARRAY, varlength=1): self.db = db self.ARRAY = ARRAY + self.varlength = varlength + + def setup(self): + db = self.db + ARRAY = self.ARRAY + varlength = self.varlength if varlength == 1: basename = 'array' else: @@ -109,7 +122,6 @@ self.name = db.namespace.uniquename(basename) self.dependencies = {} self.structname = db.gettype(ARRAY.OF, who_asks=self) - self.varlength = varlength # look up the reference counter field if needs_refcount(ARRAY): @@ -122,14 +134,15 @@ def access_expr(self, baseexpr, index): return '%s.items[%d]' % (baseexpr, index) - def definition(self): - yield 'struct %s {' % self.name - if needs_refcount(self.ARRAY): - yield '\tlong refcount;' - yield '\tlong length;' - yield '\t%s;' % cdecl(self.structname, 'items[%d]' % self.varlength) - yield '};' - if self.deallocator: + def definition(self, phase): + if phase == 1: + yield 'struct %s {' % self.name + if needs_refcount(self.ARRAY): + yield '\tlong refcount;' + yield '\tlong length;' + yield '\t%s;' % cdecl(self.structname, 'items[%d]' % self.varlength) + yield '};' + elif phase == 2 and self.deallocator: yield 'void %s(struct %s *a) {' % (self.deallocator, self.name) for line in self.deallocator_lines('a->'): yield '\t' + line Modified: pypy/branch/translator-without-old-genc/c/pyobj.py ============================================================================== --- pypy/dist/pypy/translator/c/pyobj.py (original) +++ pypy/branch/translator-without-old-genc/c/pyobj.py Wed Jun 8 19:51:03 2005 @@ -22,10 +22,10 @@ reconstruct them. """ - def __init__(self, namespace, getvalue, rtyper=None): + def __init__(self, namespace, getvalue, translator=None): self.namespace = namespace self.getvalue = getvalue - self.rtyper = rtyper + self.translator = translator self.initcode = [ # list of lines for the module's initxxx() 'import new, types, sys', ] @@ -81,14 +81,19 @@ def nameof_NoneType(self, value): assert value is None - return 'Py_None' + name = self.uniquename('g_None') + self.initcode_python(name, "None") + return name def nameof_bool(self, value): assert value is False or value is True if value: - return 'Py_True' + name = 'True' else: - return 'Py_False' + name = 'False' + name = self.uniquename('g_' + name) + self.initcode_python(name, repr(value)) + return name def nameof_module(self, value): assert value is os or not hasattr(value, "__file__") or \ @@ -155,13 +160,12 @@ return name def nameof_function(self, func): - assert self.rtyper is not None, ( - "for now, rtyper must be specified to build a PyObject " + assert self.translator is not None, ( + "the Translator must be specified to build a PyObject " "wrapper for %r" % (func,)) # look for skipped functions - a = self.rtyper.annotator - if a.translator.frozen: - if func not in a.translator.flowgraphs: + if self.translator.frozen: + if func not in self.translator.flowgraphs: return self.skipped_function(func) else: if (func.func_doc and @@ -169,7 +173,7 @@ return self.skipped_function(func) from pypy.translator.c.wrapper import gen_wrapper - fwrapper = gen_wrapper(func, self.rtyper) + fwrapper = gen_wrapper(func, self.translator) pycfunctionobj = self.uniquename('gfunc_' + func.__name__) self.wrappers[pycfunctionobj] = func.__name__, self.getvalue(fwrapper) return pycfunctionobj Modified: pypy/branch/translator-without-old-genc/c/test/test_database.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_database.py (original) +++ pypy/branch/translator-without-old-genc/c/test/test_database.py Wed Jun 8 19:51:03 2005 @@ -1,16 +1,19 @@ import autopath, sys from pypy.rpython.lltype import * -from pypy.rpython.rtyper import RPythonTyper from pypy.translator.translator import Translator from pypy.translator.c.database import LowLevelDatabase from pypy.objspace.flow.model import Constant, Variable, SpaceOperation from pypy.objspace.flow.model import Block, Link, FunctionGraph +from pypy.rpython.rmodel import getfunctionptr def dump_on_stdout(database): print '/*********************************/' for node in database.structdeflist: - for line in node.definition(): + for line in node.definition(phase=1): + print line + for node in database.structdeflist: + for line in node.definition(phase=2): print line print for node in database.globalcontainers(): @@ -171,12 +174,12 @@ def f(x): return g(1, x) t = Translator(f) - a = t.annotate([int]) - RPythonTyper(t.annotator).specialize() + t.annotate([int]) + t.specialize() F = FuncType([Signed], Signed) f = functionptr(F, "f", graph=t.getflowgraph()) - db = LowLevelDatabase() + db = LowLevelDatabase(t) db.get(f) db.complete() dump_on_stdout(db) @@ -185,11 +188,10 @@ def f(x): return x+1 t = Translator(f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() + t.annotate([int]) + t.specialize() - db = LowLevelDatabase(rtyper) + db = LowLevelDatabase(t) db.get(pyobjectptr(f)) db.complete() dump_on_stdout(db) @@ -203,11 +205,11 @@ p.y = x+1 return p.x * p.y t = Translator(ll_f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() - db = LowLevelDatabase(rtyper) - db.get(rtyper.getfunctionptr(ll_f)) + t.annotate([int]) + t.specialize() + + db = LowLevelDatabase(t) + db.get(getfunctionptr(t, ll_f)) db.complete() dump_on_stdout(db) @@ -226,11 +228,11 @@ s.ptr2 = ptr2 return s.ptr1.x * s.ptr2.x t = Translator(ll_f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() - db = LowLevelDatabase(rtyper) - db.get(rtyper.getfunctionptr(ll_f)) + t.annotate([int]) + t.specialize() + + db = LowLevelDatabase(t) + db.get(getfunctionptr(t, ll_f)) db.complete() dump_on_stdout(db) @@ -247,11 +249,11 @@ s.ptr2 = ptr2 return s.head.x * s.ptr2.x t = Translator(ll_f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() - db = LowLevelDatabase(rtyper) - db.get(rtyper.getfunctionptr(ll_f)) + t.annotate([int]) + t.specialize() + + db = LowLevelDatabase(t) + db.get(getfunctionptr(t, ll_f)) db.complete() dump_on_stdout(db) @@ -262,3 +264,13 @@ db.get(a) db.complete() dump_on_stdout(db) + +def test_recursive_struct(): + S = GcForwardReference() + S.become(GcStruct('testing', ('p', Ptr(S)))) + p = malloc(S) + p.p = p + db = LowLevelDatabase() + db.get(p) + db.complete() + dump_on_stdout(db) Modified: pypy/branch/translator-without-old-genc/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/branch/translator-without-old-genc/c/test/test_genc.py Wed Jun 8 19:51:03 2005 @@ -1,6 +1,5 @@ import autopath, sys, os, py from pypy.rpython.lltype import * -from pypy.rpython.rtyper import RPythonTyper from pypy.translator.translator import Translator from pypy.translator.c.database import LowLevelDatabase from pypy.translator.c.genc import gen_source @@ -11,8 +10,9 @@ from pypy.translator.gensupp import uniquemodulename # XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() +# XXX tcc leaves some errors undetected! Bad! +#from pypy.translator.tool import buildpyxmodule +#buildpyxmodule.enable_fast_compilation() def compile_db(db): @@ -45,11 +45,10 @@ def f(x): return x*2 t = Translator(f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() + t.annotate([int]) + t.specialize() - db = LowLevelDatabase(rtyper) + db = LowLevelDatabase(t) entrypoint = db.get(pyobjectptr(f)) db.complete() module = compile_db(db) @@ -72,11 +71,10 @@ l.append(x+1) return l[0] * l[-1] t = Translator(f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() + t.annotate([int]) + t.specialize() - db = LowLevelDatabase(rtyper) + db = LowLevelDatabase(t) entrypoint = db.get(pyobjectptr(f)) db.complete() #t.view() @@ -102,11 +100,10 @@ else: return -42 t = Translator(f) - a = t.annotate([int]) - rtyper = RPythonTyper(t.annotator) - rtyper.specialize() + t.annotate([int]) + t.specialize() - db = LowLevelDatabase(rtyper) + db = LowLevelDatabase(t) entrypoint = db.get(pyobjectptr(f)) db.complete() #t.view() Modified: pypy/branch/translator-without-old-genc/c/wrapper.py ============================================================================== --- pypy/dist/pypy/translator/c/wrapper.py (original) +++ pypy/branch/translator-without-old-genc/c/wrapper.py Wed Jun 8 19:51:03 2005 @@ -3,14 +3,13 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltype import Ptr, PyObject, typeOf, Signed, Void from pypy.rpython.lltype import FuncType, functionptr -from pypy.rpython.rtyper import LowLevelOpList, inputconst +from pypy.rpython.rtyper import LowLevelOpList +from pypy.rpython.rmodel import inputconst, getfunctionptr, PyObjPtr from pypy.rpython.robject import pyobj_repr from pypy.interpreter.pycode import CO_VARARGS -PyObjPtr = Ptr(PyObject) - -def gen_wrapper(func, rtyper): +def gen_wrapper(func, translator): """generate a wrapper function for 'func' that can be put in a PyCFunction object. The wrapper has signature @@ -23,11 +22,12 @@ # get the fully typed low-level pointer to the function, if available nb_positional_args = func.func_code.co_argcount vararg = bool(func.func_code.co_flags & CO_VARARGS) - f = rtyper.getfunctionptr(func) + + f = getfunctionptr(translator, func) FUNCTYPE = typeOf(f).TO assert len(FUNCTYPE.ARGS) == nb_positional_args + vararg - newops = LowLevelOpList(rtyper) + newops = LowLevelOpList(None) # "def wrapper(self, args, kwds)" vself = Variable('self') @@ -82,21 +82,29 @@ # use the rtyper to produce the conversions inputargs = f._obj.graph.getargs() for i in range(len(varguments)): - # "argument_i = type_conversion_operations(argument_i)" - r_arg = rtyper.bindingrepr(inputargs[i]) - varguments[i] = newops.convertvar(varguments[i], - r_from = pyobj_repr, - r_to = r_arg) + if FUNCTYPE.ARGS[i] != PyObjPtr: + # "argument_i = type_conversion_operations(argument_i)" + rtyper = translator.rtyper + assert rtyper is not None, ( + "needs the rtyper to perform argument conversions") + r_arg = rtyper.bindingrepr(inputargs[i]) + varguments[i] = newops.convertvar(varguments[i], + r_from = pyobj_repr, + r_to = r_arg) # "result = direct_call(func, argument_0, argument_1, ..)" vlist = [inputconst(typeOf(f), f)] + varguments vresult = newops.genop('direct_call', vlist, resulttype=FUNCTYPE.RESULT) - # convert "result" back to a PyObject - r_result = rtyper.bindingrepr(f._obj.graph.getreturnvar()) - vresult = newops.convertvar(vresult, - r_from = r_result, - r_to = pyobj_repr) + if FUNCTYPE.RESULT != PyObjPtr: + # convert "result" back to a PyObject + rtyper = translator.rtyper + assert rtyper is not None, ( + "needs the rtyper to perform function result conversions") + r_result = rtyper.bindingrepr(f._obj.graph.getreturnvar()) + vresult = newops.convertvar(vresult, + r_from = r_result, + r_to = pyobj_repr) # "return result" block = Block([vself, vargs, vkwds]) Modified: pypy/branch/translator-without-old-genc/genc/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/test_lltyped.py (original) +++ pypy/branch/translator-without-old-genc/genc/test/test_lltyped.py Wed Jun 8 19:51:03 2005 @@ -1,7 +1,6 @@ from pypy.rpython.lltype import * from pypy.translator.tool.buildpyxmodule import skip_missing_compiler from pypy.translator.translator import Translator -from pypy.translator.genc.ctyper import GenCSpecializer class TestLowLevelType: @@ -12,7 +11,7 @@ # builds starting-types from func_defs a = t.annotate(argstypelist) a.simplify() - GenCSpecializer(a).specialize() + t.specialize() t.checkgraphs() #t.view() return skip_missing_compiler(t.ccompile) Modified: pypy/branch/translator-without-old-genc/genc/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/test_typed.py (original) +++ pypy/branch/translator-without-old-genc/genc/test/test_typed.py Wed Jun 8 19:51:03 2005 @@ -1,7 +1,6 @@ import autopath import sys import py.test -from pypy.translator.genc.ctyper import GenCSpecializer from pypy.translator.translator import Translator from pypy.translator.test import snippet from pypy.translator.tool.buildpyxmodule import skip_missing_compiler @@ -22,7 +21,7 @@ argstypelist.append(spec) a = t.annotate(argstypelist) a.simplify() - GenCSpecializer(a).specialize() + t.specialize() t.checkgraphs() return skip_missing_compiler(t.ccompile) Modified: pypy/branch/translator-without-old-genc/test/test_backends.py ============================================================================== --- pypy/dist/pypy/translator/test/test_backends.py (original) +++ pypy/branch/translator-without-old-genc/test/test_backends.py Wed Jun 8 19:51:03 2005 @@ -13,8 +13,6 @@ functions = 'forty_two'.split() #XXX add more functions here when RPythonTyper can handle them regenerate_code = '''def test_regenerate_%(function)s_%(backend)s(): - if %(backend)r == "c": - py.test.skip("the old genc back-end is on the way out") t = Translator(%(function)s) t.simplify() a = t.annotate([]) Modified: pypy/branch/translator-without-old-genc/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/branch/translator-without-old-genc/transform.py Wed Jun 8 19:51:03 2005 @@ -274,12 +274,6 @@ if len(block.exits) == 1: block.exitswitch = None block.exits[0].exitcase = None - # make sure that the return variables of all graphs is annotated - if self.translator is not None: - for graph in self.translator.flowgraphs.values(): - v = graph.getreturnvar() - if v not in self.bindings: - self.setbinding(v, annmodel.SomeImpossibleValue()) def cutoff_alwaysraising_block(self, block): "Fix a block whose end can never be reached at run-time." Modified: pypy/branch/translator-without-old-genc/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/branch/translator-without-old-genc/translator.py Wed Jun 8 19:51:03 2005 @@ -7,12 +7,7 @@ import autopath, os, sys from pypy.objspace.flow.model import * -from pypy.annotation.model import * -from pypy.translator.annrpython import RPythonAnnotator from pypy.translator.simplify import simplify_graph -from pypy.translator.pyrex.genpyrex import GenPyrex -from pypy.translator.gencl import GenCL -from pypy.translator.genc.genc import GenC from pypy.translator.gensupp import uniquemodulename from pypy.translator.tool.buildpyxmodule import make_module_from_pyxstring from pypy.translator.tool.buildpyxmodule import make_module_from_c @@ -34,12 +29,13 @@ def clear(self): """Clear all annotations and all flow graphs.""" self.annotator = None + self.rtyper = None self.flowgraphs = {} # {function: graph} self.functions = [] # the keys of self.flowgraphs, in creation order self.callgraph = {} # {opaque_tag: (caller, callee)} self.frozen = False # when frozen, no more flowgraphs can be generated - self.concretetypes = {} # see getconcretetype() - self.ctlist = [] # " + #self.concretetypes = {} # see getconcretetype() + #self.ctlist = [] # " if self.entrypoint: self.getflowgraph() @@ -121,6 +117,7 @@ """ func = func or self.entrypoint if self.annotator is None: + from pypy.translator.annrpython import RPythonAnnotator self.annotator = RPythonAnnotator(self, policy=policy) graph = self.getflowgraph(func) self.annotator.build_types(graph, input_args_types, func) @@ -130,6 +127,15 @@ for graph in self.flowgraphs.itervalues(): checkgraph(graph) + def specialize(self): + if self.annotator is None: + raise ValueError("you need to call annotate() first") + if self.rtyper is not None: + raise ValueError("cannot specialize() several times") + from pypy.rpython.rtyper import RPythonTyper + self.rtyper = RPythonTyper(self.annotator) + self.rtyper.specialize() + def source(self, func=None): """Returns original Python source. @@ -147,6 +153,7 @@ returns type annotated translation. Subsequent calls are not affected by this. """ + from pypy.translator.pyrex.genpyrex import GenPyrex return self.generatecode(GenPyrex, input_arg_types, func) def cl(self, input_arg_types=None, func=None): @@ -156,6 +163,7 @@ returns type annotated translation. Subsequent calls are not affected by this. """ + from pypy.translator.gencl import GenCL return self.generatecode(GenCL, input_arg_types, func) def c(self): @@ -163,10 +171,12 @@ Returns C (CPython) translation. """ - from StringIO import StringIO - out = StringIO() - genc = GenC(out, self) - return out.getvalue() + from pypy.translator.c import genc + from cStringIO import StringIO + f = StringIO() + database, ignored = genc.translator2database(self) + genc.gen_readable_parts_of_main_c_file(f, database) + return f.getvalue() def llvm(self): """llvm(self) -> LLVM translation @@ -183,6 +193,7 @@ if input_arg_types is None: ann = self.annotator else: + from pypy.translator.annrpython import RPythonAnnotator ann = RPythonAnnotator(self) if func is None: codes = [self.generatecode1(gencls, input_arg_types, @@ -228,22 +239,14 @@ def ccompile(self, really_compile=True): """Returns compiled function, compiled using the C generator. """ - from pypy.tool.udir import udir + from pypy.translator.c import genc if self.annotator is not None: self.frozen = True - name = uniquemodulename(self.entrypoint.func_name) - cfile = udir.join('%s.c' % name) - f = cfile.open('w') - f2 = udir.join('%s-init.py' % name).open('w+') - GenC(f, self, name, f2=f2) - f2.close() - f.close() - if not really_compile: - return cfile - mod = make_module_from_c(cfile, - include_dirs=[os.path.join(autopath.this_dir, 'genc')]) - self.concretetypes.clear() - return getattr(mod, self.entrypoint.func_name) + + result = genc.genc(self, compile=really_compile) + if really_compile: # result is the module + result = getattr(result, self.entrypoint.func_name) + return result def llvmcompile(self, optimize=True): """llvmcompile(self, optimize=True) -> LLVM translation @@ -276,15 +279,15 @@ ## # not actually start the analysis of the called function yet. ## return impossiblevalue - def getconcretetype(self, cls, *args): - "DEPRECATED. To be removed" - # Return a (cached) 'concrete type' object attached to this translator. - # Concrete types are what is put in the 'concretetype' attribute of - # the Variables and Constants of the flow graphs by typer.py to guide - # the code generators. - try: - return self.concretetypes[cls, args] - except KeyError: - result = self.concretetypes[cls, args] = cls(self, *args) - self.ctlist.append(result) - return result +## def getconcretetype(self, cls, *args): +## "DEPRECATED. To be removed" +## # Return a (cached) 'concrete type' object attached to this translator. +## # Concrete types are what is put in the 'concretetype' attribute of +## # the Variables and Constants of the flow graphs by typer.py to guide +## # the code generators. +## try: +## return self.concretetypes[cls, args] +## except KeyError: +## result = self.concretetypes[cls, args] = cls(self, *args) +## self.ctlist.append(result) +## return result Modified: pypy/branch/translator-without-old-genc/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/branch/translator-without-old-genc/unsimplify.py Wed Jun 8 19:51:03 2005 @@ -4,9 +4,10 @@ """Make a copy of the Variable v, preserving annotations and concretetype.""" assert isinstance(v, Variable) newvar = Variable(v) - annotator = translator.annotator - if annotator is not None and v in annotator.bindings: - annotator.bindings[newvar] = annotator.bindings[v] + if translator is not None: + annotator = translator.annotator + if annotator is not None and v in annotator.bindings: + annotator.bindings[newvar] = annotator.bindings[v] if hasattr(v, 'concretetype'): newvar.concretetype = v.concretetype return newvar From pedronis at codespeak.net Wed Jun 8 20:01:23 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 8 Jun 2005 20:01:23 +0200 (CEST) Subject: [pypy-svn] r13198 - pypy/dist/pypy/rpython Message-ID: <20050608180123.958FE27B66@code1.codespeak.net> Author: pedronis Date: Wed Jun 8 20:01:22 2005 New Revision: 13198 Modified: pypy/dist/pypy/rpython/rclass.py Log: don't use a forward ref for the base cases OBJECT_VTABLE, OBJECT Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 8 20:01:22 2005 @@ -69,7 +69,11 @@ def __init__(self, rtyper, classdef): self.rtyper = rtyper self.classdef = classdef - self.vtable_type = ForwardReference() + if classdef is None: + # 'object' root type + self.vtable_type = OBJECT_VTABLE + else: + self.vtable_type = ForwardReference() self.lowleveltype = Ptr(self.vtable_type) def __repr__(self): @@ -90,10 +94,7 @@ # partially-initialized dicts. clsfields = {} allmethods = {} - if self.classdef is None: - # 'object' root type - self.vtable_type.become(OBJECT_VTABLE) - else: + if self.classdef is not None: # class attributes llfields = [] attrs = self.classdef.attrs.items() @@ -252,7 +253,10 @@ def __init__(self, rtyper, classdef): self.rtyper = rtyper self.classdef = classdef - self.object_type = GcForwardReference() + if classdef is None: + self.object_type = OBJECT + else: + self.object_type = GcForwardReference() self.lowleveltype = Ptr(self.object_type) def __repr__(self): @@ -276,7 +280,6 @@ allinstancefields = {} if self.classdef is None: fields['__class__'] = 'typeptr', TYPEPTR - self.object_type.become(OBJECT) else: # instance attributes llfields = [] From arigo at codespeak.net Wed Jun 8 22:18:40 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 22:18:40 +0200 (CEST) Subject: [pypy-svn] r13200 - in pypy/dist/pypy: objspace/flow rpython rpython/test translator/c Message-ID: <20050608201840.A55F027B69@code1.codespeak.net> Author: arigo Date: Wed Jun 8 22:18:36 2005 New Revision: 13200 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/translator/c/funcgen.py Log: Conversions between an instance of a class and an instance of a subclass and back. test_virutal_methods() passes. Simplification of the varmapping mess, which was provoking strange errors. The problem is that two variables may have different SomeXxx annotations but the same low-level type; in this case we cannot really rename one into the other, because it confuses the rtyper -- which might find the wrong annotation and representation for the variable. (It also confuses people staring at flow graphs quite a lot.) Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Wed Jun 8 22:18:36 2005 @@ -171,6 +171,7 @@ for op in self.operations: op.args = [mapping.get(a, a) for a in op.args] op.result = mapping.get(op.result, op.result) + self.exitswitch = mapping.get(self.exitswitch, self.exitswitch) for link in self.exits: link.args = [mapping.get(a, a) for a in link.args] Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 8 22:18:36 2005 @@ -411,6 +411,35 @@ self.setfield(vinst, attr, vvalue, hop.llops) +class __extend__(pairtype(InstanceRepr, InstanceRepr)): + def convert_from_to((r_ins1, r_ins2), v, llops): + # which is a subclass of which? + if r_ins1.classdef is None or r_ins2.classdef is None: + return NotImplemented + basedef = r_ins1.classdef.commonbase(r_ins2.classdef) + if basedef == r_ins2.classdef: + # r_ins1 is an instance of the subclass: converting to parent + while r_ins1 != r_ins2: + v = r_ins1.parentpart(v, llops) + r_ins1 = r_ins1.rbase + return v + elif basedef == r_ins1.classdef: + # r_ins2 is an instance of the subclass: potentially unsafe + # casting, but we do it anyway (e.g. the annotator produces + # such casts after a successful isinstance() check) + cast_chain = [] + while r_ins2 != r_ins1: + cast_chain.append(r_ins2) + r_ins2 = r_ins2.rbase + cast_chain.reverse() + for r in cast_chain: + ctype = inputconst(Void, r.lowleveltype) + v = llops.genop('cast_parent', [ctype, v], + resulttype = r.lowleveltype) + return v + else: + return NotImplemented + # ____________________________________________________________ def rtype_new_instance(cls, hop): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 8 22:18:36 2005 @@ -119,6 +119,9 @@ return newops = LowLevelOpList(self) varmapping = {} + for v in block.getvariables(): + varmapping[v] = v # records existing Variables + for op in block.operations: try: hop = HighLevelOp(self, op, newops) @@ -128,15 +131,6 @@ return # cannot continue this block: no op.result.concretetype block.operations[:] = newops - # multiple renamings (v1->v2->v3->...) are possible - while True: - done = True - for v1, v2 in varmapping.items(): - if v2 in varmapping: - varmapping[v1] = varmapping[v2] - done = False - if done: - break block.renamevariables(varmapping) self.insert_link_conversions(block) @@ -202,9 +196,15 @@ "but rtype* says %r" % ( op.opname, hop.s_result, op.result.concretetype, resulttype)) - while resultvar in varmapping: - resultvar = varmapping[resultvar] - varmapping[resultvar] = op.result + # figure out if the resultvar is a completely fresh Variable or not + if (resultvar not in self.annotator.bindings and + resultvar not in varmapping): + # fresh Variable: rename it to the previously existing op.result + varmapping[resultvar] = op.result + else: + # renaming unsafe. Insert a 'same_as' operation... + hop.llops.append(SpaceOperation('same_as', [resultvar], + op.result)) else: # translate_meth() returned a Constant assert isinstance(resultvar, Constant) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Jun 8 22:18:36 2005 @@ -48,7 +48,7 @@ return obj.m(b) rtype(f, [int, int]) -def PROGRESSING_ON_test_virtual_method_call(): +def test_virtual_method_call(): def f(a, b): if a > 0: obj = MyBase() @@ -56,4 +56,4 @@ obj = MySubclass() obj.z = a return obj.m(b) - rtype(f, [int, int]).view() + rtype(f, [int, int]) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Wed Jun 8 22:18:36 2005 @@ -389,6 +389,14 @@ ] return '\t'.join(result) + def OP_SAME_AS(self, op, err): + result = ['%s = %s;' % (self.expr(op.result), + self.expr(op.args[0]))] + line = self.cincref(op.result) + if line: + result.append(line) + return '\t'.join(result) + def cincref(self, v): T = self.lltypemap[v] return self.db.cincrefstmt(v.name, T) From arigo at codespeak.net Wed Jun 8 22:19:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 22:19:54 +0200 (CEST) Subject: [pypy-svn] r13201 - pypy/branch/translator-without-old-genc/c Message-ID: <20050608201954.ADD2B27B6D@code1.codespeak.net> Author: arigo Date: Wed Jun 8 22:19:53 2005 New Revision: 13201 Modified: pypy/branch/translator-without-old-genc/c/funcgen.py Log: Merge the fix from the trunk. Modified: pypy/branch/translator-without-old-genc/c/funcgen.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/funcgen.py (original) +++ pypy/branch/translator-without-old-genc/c/funcgen.py Wed Jun 8 22:19:53 2005 @@ -411,6 +411,14 @@ ] return '\t'.join(result) + def OP_SAME_AS(self, op, err): + result = ['%s = %s;' % (self.expr(op.result), + self.expr(op.args[0]))] + line = self.cincref(op.result) + if line: + result.append(line) + return '\t'.join(result) + def cincref(self, v): T = self.lltypemap[v] return self.db.cincrefstmt(v.name, T) From arigo at codespeak.net Wed Jun 8 22:58:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 22:58:32 +0200 (CEST) Subject: [pypy-svn] r13202 - in pypy/dist/pypy: rpython rpython/test translator/c Message-ID: <20050608205832.69CD727B71@code1.codespeak.net> Author: arigo Date: Wed Jun 8 22:58:28 2005 New Revision: 13202 Added: pypy/dist/pypy/rpython/rtuple.py (contents, props changed) pypy/dist/pypy/rpython/test/test_rtuple.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/funcgen.py Log: Start of the rtuple implementation. Added: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rtuple.py Wed Jun 8 22:58:28 2005 @@ -0,0 +1,61 @@ +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.objspace.flow.model import Constant +from pypy.rpython.lltype import * +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr + +# ____________________________________________________________ +# +# Concrete implementation of RPython tuples: +# +# struct tuple { +# type0 item0; +# type1 item1; +# type2 item2; +# ... +# } + +class __extend__(annmodel.SomeTuple): + def rtyper_makerepr(self, rtyper): + return TupleRepr([rtyper.getrepr(s_item) for s_item in self.items]) + + +class TupleRepr(Repr): + + def __init__(self, items_r): + self.items_r = items_r + self.fieldnames = ['item%d' % i for i in range(len(items_r))] + self.lltypes = [r.lowleveltype for r in items_r] + fields = zip(self.fieldnames, self.lltypes) + self.lowleveltype = Ptr(GcStruct('tuple%d' % len(items_r), *fields)) + + def rtype_len(self, hop): + return hop.inputconst(Signed, len(self.items_r)) + + +class __extend__(pairtype(TupleRepr, IntegerRepr)): + + def rtype_getitem((r_tup, r_int), hop): + v_tuple, v_index = hop.inputargs(r_tup, Signed) + if not isinstance(v_index, Constant): + raise TyperError("non-constant tuple index") + index = v_index.value + name = r_tup.fieldnames[index] + llresult = r_tup.lltypes[index] + cname = hop.inputconst(Void, name) + return hop.genop('getfield', [v_tuple, cname], resulttype = llresult) + +# ____________________________________________________________ +# +# Irregular operations. + +def rtype_newtuple(hop): + nb_args = hop.nb_args + r_tuple = hop.r_result + c1 = hop.inputconst(Void, r_tuple.lowleveltype) + v_result = hop.genop('malloc', [c1], resulttype = r_tuple.lowleveltype) + for i in range(nb_args): + cname = hop.inputconst(Void, r_tuple.fieldnames[i]) + v_item = hop.inputarg(r_tuple.items_r[i], arg=i) + hop.genop('setfield', [v_result, cname, v_item]) + return v_result Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 8 22:58:28 2005 @@ -215,6 +215,8 @@ raise TyperError("constant mismatch: %r vs %r" % ( resultvar.value, hop.s_result.const)) op.result.concretetype = hop.r_result.lowleveltype + hop.llops.append(SpaceOperation('same_as', [resultvar], + op.result)) def gottypererror(self, e, block, position, llops): """Record a TyperError without crashing immediately. @@ -255,6 +257,9 @@ def translate_op_newlist(self, hop): return rlist.rtype_newlist(hop) + def translate_op_newtuple(self, hop): + return rtuple.rtype_newtuple(hop) + def missing_operation(self, hop): raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname) @@ -414,6 +419,6 @@ # and the rtyper_chooserepr() methods from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat -from pypy.rpython import rlist, rstr +from pypy.rpython import rlist, rstr, rtuple from pypy.rpython import rbuiltin, rpbc from pypy.rpython import rptr Added: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Wed Jun 8 22:58:28 2005 @@ -0,0 +1,46 @@ +from pypy.translator.translator import Translator +from pypy.rpython.lltype import * +from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.rtuple import * +from pypy.rpython.rint import signed_repr +from pypy.rpython.rbool import bool_repr + + +def test_rtuple(): + rtuple = TupleRepr([signed_repr, bool_repr]) + assert rtuple.lowleveltype == Ptr(GcStruct('tuple2', + ('item0', Signed), + ('item1', Bool), + )) + +# ____________________________________________________________ + +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() + return t + + +def test_simple(): + def dummyfn(x): + l = (10,x,30) + return l[2] + rtype(dummyfn, [int]) + +def test_len(): + def dummyfn(x): + l = (5,x) + return len(l) + rtype(dummyfn, [int]) + +##def test_iterate(): +## def dummyfn(): +## total = 0 +## for x in (1,3,5,7,9): +## total += x +## return total +## rtype(dummyfn) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Wed Jun 8 22:58:28 2005 @@ -390,11 +390,14 @@ return '\t'.join(result) def OP_SAME_AS(self, op, err): - result = ['%s = %s;' % (self.expr(op.result), - self.expr(op.args[0]))] - line = self.cincref(op.result) - if line: - result.append(line) + result = [] + assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] + if self.lltypemap[op.result] != Void: + result.append('%s = %s;' % (self.expr(op.result), + self.expr(op.args[0]))) + line = self.cincref(op.result) + if line: + result.append(line) return '\t'.join(result) def cincref(self, v): From arigo at codespeak.net Wed Jun 8 22:59:38 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 22:59:38 +0200 (CEST) Subject: [pypy-svn] r13203 - pypy/branch/translator-without-old-genc/c Message-ID: <20050608205938.DA91727B73@code1.codespeak.net> Author: arigo Date: Wed Jun 8 22:59:37 2005 New Revision: 13203 Modified: pypy/branch/translator-without-old-genc/c/funcgen.py Log: Merge. Modified: pypy/branch/translator-without-old-genc/c/funcgen.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/funcgen.py (original) +++ pypy/branch/translator-without-old-genc/c/funcgen.py Wed Jun 8 22:59:37 2005 @@ -412,11 +412,14 @@ return '\t'.join(result) def OP_SAME_AS(self, op, err): - result = ['%s = %s;' % (self.expr(op.result), - self.expr(op.args[0]))] - line = self.cincref(op.result) - if line: - result.append(line) + result = [] + assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] + if self.lltypemap[op.result] != Void: + result.append('%s = %s;' % (self.expr(op.result), + self.expr(op.args[0]))) + line = self.cincref(op.result) + if line: + result.append(line) return '\t'.join(result) def cincref(self, v): From arigo at codespeak.net Wed Jun 8 23:35:38 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 8 Jun 2005 23:35:38 +0200 (CEST) Subject: [pypy-svn] r13205 - pypy/dist/pypy/rpython Message-ID: <20050608213538.D090927B5F@code1.codespeak.net> Author: arigo Date: Wed Jun 8 23:35:32 2005 New Revision: 13205 Modified: pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/rtyper.py Log: Fix the caching logic in getrepr(). Now each rtyper_makerepr() method must come together with a rtyper_makekey(), which must return something hashable with the following rule: if two SomeXxx() instances would produce different representations with rtyper_makerepr(), then the keys must be different. In other words, rtyper_makekey() should return something like a tuple of all the data from the SomeXxx() instance that are relevant for choosing the representation. All this because SomeXxx() are not hashable -- which is good but not here :-/ Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Wed Jun 8 23:35:32 2005 @@ -9,6 +9,8 @@ class __extend__(annmodel.SomeBool): def rtyper_makerepr(self, rtyper): return bool_repr + def rtyper_makekey(self): + return None bool_repr = BoolRepr() Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Wed Jun 8 23:35:32 2005 @@ -20,6 +20,11 @@ assert self.methodname is not None return BuiltinMethodRepr(rtyper.getrepr(self.s_self), self.methodname) + def rtyper_makekey(self): + key = (getattr(self, 'const', None), self.methodname) + if self.s_self is not None: + key += (self.s_self.rtyper_makekey(),) + return key class BuiltinFunctionRepr(Repr): Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 8 23:35:32 2005 @@ -245,6 +245,8 @@ class __extend__(annmodel.SomeInstance): def rtyper_makerepr(self, rtyper): return getinstancerepr(rtyper, self.classdef) + def rtyper_makekey(self): + return self.classdef class InstanceRepr(Repr): Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Wed Jun 8 23:35:32 2005 @@ -10,6 +10,9 @@ class __extend__(annmodel.SomeFloat): def rtyper_makerepr(self, rtyper): return float_repr + def rtyper_makekey(self): + return None + float_repr = FloatRepr() Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Wed Jun 8 23:35:32 2005 @@ -13,6 +13,8 @@ return unsigned_repr else: return signed_repr + def rtyper_makekey(self): + return self.unsigned signed_repr = IntegerRepr() unsigned_repr = IntegerRepr() Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Wed Jun 8 23:35:32 2005 @@ -26,12 +26,14 @@ # cannot do the rtyper.getrepr() call immediately, for the case # of recursive structures -- i.e. if the listdef contains itself return ListRepr(lambda: rtyper.getrepr(listitem.s_value), - self.listdef) + listitem) + def rtyper_makekey(self): + return self.listdef.listitem class ListRepr(Repr): - def __init__(self, item_repr, listdef=None): + def __init__(self, item_repr, listitem=None): self.LIST = GcForwardReference() self.lowleveltype = Ptr(self.LIST) if not isinstance(item_repr, Repr): # not computed yet, done by setup() @@ -39,7 +41,7 @@ self._item_repr_computer = item_repr else: self.item_repr = item_repr - self.listdef = listdef + self.listitem = listitem # setup() needs to be called to finish this initialization def setup(self): @@ -75,9 +77,9 @@ class __extend__(pairtype(ListRepr, ListRepr)): def convert_from_to((r_lst1, r_lst2), v, llops): - if r_lst1.listdef is None or r_lst2.listdef is None: + if r_lst1.listitem is None or r_lst2.listitem is None: return NotImplemented - if not r_lst1.listdef.same_as(r_lst2.listdef): + if r_lst1.listitem is not r_lst2.listitem: return NotImplemented return v Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Wed Jun 8 23:35:32 2005 @@ -84,10 +84,14 @@ def rtyper_makerepr(self, rtyper): r_container = rtyper.getrepr(self.s_container) return r_container.make_iterator_repr() + def rtyper_makekey(self): + return self.s_container.rtyper_makekey() class __extend__(annmodel.SomeImpossibleValue): def rtyper_makerepr(self, rtyper): return impossible_repr + def rtyper_makekey(self): + return None # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Wed Jun 8 23:35:32 2005 @@ -13,6 +13,13 @@ return rclass.get_type_repr(rtyper) else: return pyobj_repr + def rtyper_makekey(self): + if self.is_constant(): + return "const" + if self.knowntype is type: + return "type" + else: + return "pyobj" class PyObjRepr(Repr): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jun 8 23:35:32 2005 @@ -51,6 +51,11 @@ reprcls, = choices return reprcls(rtyper, self) + def rtyper_makekey(self): + lst = self.prebuiltinstances.items() + lst.sort() + return tuple(lst) + # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Wed Jun 8 23:35:32 2005 @@ -11,6 +11,11 @@ return nullptr_repr else: return PtrRepr(self.ll_ptrtype) + def rtyper_makekey(self): + if self.is_constant(): + return None + else: + return self.ll_ptrtype class PtrRepr(Repr): Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Wed Jun 8 23:35:32 2005 @@ -24,10 +24,14 @@ class __extend__(annmodel.SomeString): def rtyper_makerepr(self, rtyper): return string_repr + def rtyper_makekey(self): + return None class __extend__(annmodel.SomeChar): def rtyper_makerepr(self, rtyper): return char_repr + def rtyper_makekey(self): + return None CONST_STR_CACHE = WeakValueDictionary() Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Wed Jun 8 23:35:32 2005 @@ -18,6 +18,9 @@ class __extend__(annmodel.SomeTuple): def rtyper_makerepr(self, rtyper): return TupleRepr([rtyper.getrepr(s_item) for s_item in self.items]) + def rtyper_makekey(self): + keys = [s_item.rtyper_makekey() for s_item in self.items] + return tuple(keys) class TupleRepr(Repr): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 8 23:35:32 2005 @@ -24,8 +24,7 @@ def __init__(self, annotator): self.annotator = annotator - self.reprs_by_id = {} - self.reprs_by_content = {} + self.reprs = {} self.reprs_must_call_setup = [] self.specialized_ll_functions = {} self.class_reprs = {} @@ -38,28 +37,17 @@ self.primitive_to_repr[r.lowleveltype] = r def getrepr(self, s_obj): - # s_objs are not hashable... try hard to find a hash anyway + # s_objs are not hashable... try hard to find a unique key anyway + key = s_obj.__class__, s_obj.rtyper_makekey() try: - result, s_obj = self.reprs_by_id[id(s_obj)] + result = self.reprs[key] except KeyError: - key = [s_obj.__class__] - items = s_obj.__dict__.items() - items.sort() - for name, value in items: - key.append(name) - key.append(Constant(value)) - key = tuple(key) - try: - result = self.reprs_by_content[key] - except KeyError: - # here is the code that actually builds a Repr instance - result = s_obj.rtyper_makerepr(self) - assert not isinstance(result.lowleveltype, ContainerType), ( - "missing a Ptr in the type specification " - "of %s:\n%r" % (s_obj, result.lowleveltype)) - self.reprs_by_content[key] = result - self.reprs_must_call_setup.append(result) - self.reprs_by_id[id(s_obj)] = result, s_obj + result = s_obj.rtyper_makerepr(self) + assert not isinstance(result.lowleveltype, ContainerType), ( + "missing a Ptr in the type specification " + "of %s:\n%r" % (s_obj, result.lowleveltype)) + self.reprs[key] = result + self.reprs_must_call_setup.append(result) return result def binding(self, var): From arigo at codespeak.net Thu Jun 9 00:23:49 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 00:23:49 +0200 (CEST) Subject: [pypy-svn] r13206 - in pypy: branch/translator-without-old-genc/c dist/pypy/rpython Message-ID: <20050608222349.DD4BE27B76@code1.codespeak.net> Author: arigo Date: Thu Jun 9 00:23:43 2005 New Revision: 13206 Modified: pypy/branch/translator-without-old-genc/c/g_support.h pypy/branch/translator-without-old-genc/c/genc.py pypy/branch/translator-without-old-genc/c/node.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/rtyper.py Log: Conversions between PyTupleObjects and rtuples. Bug fix discovered by it in the C translator. Modified: pypy/branch/translator-without-old-genc/c/g_support.h ============================================================================== --- pypy/branch/translator-without-old-genc/c/g_support.h (original) +++ pypy/branch/translator-without-old-genc/c/g_support.h Thu Jun 9 00:23:43 2005 @@ -352,3 +352,18 @@ } return 0; } + +/************************************************************/ + +static PyObject *PyTuple_GetItem_WithIncref(PyObject *tuple, int index) +{ + PyObject *result = PyTuple_GetItem(tuple, index); + Py_XINCREF(result); + return result; +} + +static int PyTuple_SetItem_WithIncref(PyObject *tuple, int index, PyObject *o) +{ + Py_INCREF(o); + return PyTuple_SetItem(tuple, index, o); +} Modified: pypy/branch/translator-without-old-genc/c/genc.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/genc.py (original) +++ pypy/branch/translator-without-old-genc/c/genc.py Thu Jun 9 00:23:43 2005 @@ -109,9 +109,8 @@ print >> f, 'static globalobjectdef_t globalobjectdefs[] = {' for node in database.globalcontainers(): if isinstance(node, PyObjectNode): - name = node.name - if name not in pyobjmaker.wrappers: - print >> f, '\t{&%s, "%s"},' % (name, name) + for target in node.where_to_copy_me: + print >> f, '\t{%s, "%s"},' % (target, node.name) print >> f, '\t{ NULL }\t/* Sentinel */' print >> f, '};' print >> f Modified: pypy/branch/translator-without-old-genc/c/node.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/node.py (original) +++ pypy/branch/translator-without-old-genc/c/node.py Thu Jun 9 00:23:43 2005 @@ -1,7 +1,7 @@ from __future__ import generators from pypy.rpython.lltype import Struct, Array, FuncType, PyObjectType, typeOf from pypy.rpython.lltype import GcStruct, GcArray, GC_CONTAINER, ContainerType -from pypy.rpython.lltype import parentlink, Ptr +from pypy.rpython.lltype import parentlink, Ptr, PyObject from pypy.translator.c.funcgen import FunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom @@ -191,7 +191,7 @@ parentnode = db.getcontainernode(parent) defnode = db.gettypedefnode(parentnode.T) self.name = defnode.access_expr(parentnode.name, parentindex) - self.ptrname = '&%s' % self.name + self.ptrname = '(&%s)' % self.name if self.typename != self.implementationtypename: self.ptrname = '((%s)(void*)%s)' % (self.typename.replace('@', '*'), self.ptrname) @@ -228,6 +228,10 @@ array = getattr(self.obj, self.T._arrayfld) return len(array.items) + def c_struct_field_name(self, fieldname): + defnode = self.db.gettypedefnode(self.T) + return defnode.c_struct_field_name(fieldname) + def initializationexpr(self, prefix=''): yield '{' if needs_refcount(self.T): @@ -239,7 +243,14 @@ expr = '\n'.join(node.initializationexpr(prefix+name+'.')) expr += ',' else: - expr = self.db.get(value) + if typeOf(value) == Ptr(PyObject) and value: + # cannot just write 'gxxx' as a constant in a structure :-( + node = self.db.getcontainernode(value._obj) + expr = 'NULL /* %s */' % node.name + c_name = self.c_struct_field_name(name) + node.where_to_copy_me.append('&%s.%s' % (self.name, c_name)) + else: + expr = self.db.get(value) i = expr.find('\n') if i<0: i = len(expr) expr = '%s,\t/* %s%s */%s' % (expr[:i], prefix, name, expr[i:]) @@ -386,6 +397,12 @@ self.obj = obj self.name = db.pyobjmaker.computenameof(obj.value) self.ptrname = self.name + # a list of expressions giving places where this constant PyObject + # must be copied. Normally just in the global variable of the same + # name, but see also StructNode.initializationexpr() :-( + self.where_to_copy_me = [] + if self.name not in db.pyobjmaker.wrappers: + self.where_to_copy_me.append('&%s' % self.name) def enum_dependencies(self): return [] Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Thu Jun 9 00:23:43 2005 @@ -2,7 +2,8 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import * -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst +from pypy.rpython.robject import PyObjRepr, pyobj_repr # ____________________________________________________________ # @@ -32,6 +33,13 @@ fields = zip(self.fieldnames, self.lltypes) self.lowleveltype = Ptr(GcStruct('tuple%d' % len(items_r), *fields)) + def convert_const(self, value): + assert isinstance(value, tuple) and len(value) == len(self.items_r) + p = malloc(self.lowleveltype.TO) + for obj, r, name in zip(value, self.items_r, self.fieldnames): + setattr(p, name, r.convert_const(obj)) + return p + def rtype_len(self, hop): return hop.inputconst(Signed, len(self.items_r)) @@ -52,13 +60,46 @@ # # Irregular operations. +def newtuple(llops, r_tuple, items_v): + c1 = inputconst(Void, r_tuple.lowleveltype) + v_result = llops.genop('malloc', [c1], resulttype = r_tuple.lowleveltype) + for i in range(len(r_tuple.items_r)): + cname = inputconst(Void, r_tuple.fieldnames[i]) + llops.genop('setfield', [v_result, cname, items_v[i]]) + return v_result + def rtype_newtuple(hop): - nb_args = hop.nb_args r_tuple = hop.r_result - c1 = hop.inputconst(Void, r_tuple.lowleveltype) - v_result = hop.genop('malloc', [c1], resulttype = r_tuple.lowleveltype) - for i in range(nb_args): - cname = hop.inputconst(Void, r_tuple.fieldnames[i]) - v_item = hop.inputarg(r_tuple.items_r[i], arg=i) - hop.genop('setfield', [v_result, cname, v_item]) - return v_result + vlist = hop.inputargs(*r_tuple.items_r) + return newtuple(hop.llops, r_tuple, vlist) + +# +# _________________________ Conversions _________________________ + +class __extend__(pairtype(PyObjRepr, TupleRepr)): + def convert_from_to((r_from, r_to), v, llops): + vlist = [] + for i in range(len(r_to.items_r)): + ci = inputconst(Signed, i) + v_item = llops.gencapicall('PyTuple_GetItem_WithIncref', [v, ci], + resulttype = pyobj_repr) + v_converted = llops.convertvar(v_item, pyobj_repr, + r_to.items_r[i]) + vlist.append(v_converted) + return newtuple(llops, r_to, vlist) + +class __extend__(pairtype(TupleRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + ci = inputconst(Signed, len(r_from.items_r)) + v_result = llops.gencapicall('PyTuple_New', [ci], + resulttype = pyobj_repr) + for i in range(len(r_from.items_r)): + cname = inputconst(Void, r_from.fieldnames[i]) + v_item = llops.genop('getfield', [v, cname], + resulttype = r_from.items_r[i].lowleveltype) + v_converted = llops.convertvar(v_item, r_from.items_r[i], + pyobj_repr) + ci = inputconst(Signed, i) + llops.gencapicall('PyTuple_SetItem_WithIncref', [v_result, ci, + v_converted]) + return v_result Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 9 00:23:43 2005 @@ -392,11 +392,11 @@ return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) - def gencapicall(self, cfnname, args_v, resulttype): + def gencapicall(self, cfnname, args_v, resulttype=None): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] - FUNCTYPE = FuncType(argtypes, resulttype) + FUNCTYPE = FuncType(argtypes, resulttype or Void) f = functionptr(FUNCTYPE, cfnname, external="C") cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf]+list(args_v), resulttype) From arigo at codespeak.net Thu Jun 9 00:34:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 00:34:26 +0200 (CEST) Subject: [pypy-svn] r13207 - pypy/branch/translator-without-old-genc/c Message-ID: <20050608223426.3797427B75@code1.codespeak.net> Author: arigo Date: Thu Jun 9 00:34:24 2005 New Revision: 13207 Modified: pypy/branch/translator-without-old-genc/c/node.py Log: Ignore 'void' fields in structures. Modified: pypy/branch/translator-without-old-genc/c/node.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/node.py (original) +++ pypy/branch/translator-without-old-genc/c/node.py Thu Jun 9 00:34:24 2005 @@ -1,9 +1,10 @@ from __future__ import generators from pypy.rpython.lltype import Struct, Array, FuncType, PyObjectType, typeOf from pypy.rpython.lltype import GcStruct, GcArray, GC_CONTAINER, ContainerType -from pypy.rpython.lltype import parentlink, Ptr, PyObject +from pypy.rpython.lltype import parentlink, Ptr, PyObject, Void from pypy.translator.c.funcgen import FunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom +from pypy.translator.c.primitive import PrimitiveType def needs_refcount(T): @@ -76,7 +77,10 @@ if needs_refcount(self.STRUCT): yield '\tlong refcount;' for name, typename in self.fields: - yield '\t%s;' % cdecl(typename, name) + line = '%s;' % cdecl(typename, name) + if typename == PrimitiveType[Void]: + line = '/* %s */' % line + yield '\t' + line yield '};' elif phase == 2 and self.deallocator: yield 'void %s(struct %s *p) {' % (self.deallocator, self.name) @@ -243,6 +247,7 @@ expr = '\n'.join(node.initializationexpr(prefix+name+'.')) expr += ',' else: + comma = ',' if typeOf(value) == Ptr(PyObject) and value: # cannot just write 'gxxx' as a constant in a structure :-( node = self.db.getcontainernode(value._obj) @@ -251,9 +256,12 @@ node.where_to_copy_me.append('&%s.%s' % (self.name, c_name)) else: expr = self.db.get(value) + if typeOf(value) == Void: + comma = '' i = expr.find('\n') if i<0: i = len(expr) - expr = '%s,\t/* %s%s */%s' % (expr[:i], prefix, name, expr[i:]) + expr = '%s%s\t/* %s%s */%s' % (expr[:i], comma, + prefix, name, expr[i:]) expr = expr.replace('\n', '\n\t') # indentation yield '\t%s' % expr yield '}' From arigo at codespeak.net Thu Jun 9 00:41:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 00:41:05 +0200 (CEST) Subject: [pypy-svn] r13208 - pypy/dist/pypy/rpython Message-ID: <20050608224105.E296F27B7A@code1.codespeak.net> Author: arigo Date: Thu Jun 9 00:41:03 2005 New Revision: 13208 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rtyper.py Log: Implement the 'alloc_and_set' operation (which comes out of transform.py as a shorthand for [something] * count ). Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 00:41:03 2005 @@ -140,6 +140,21 @@ hop.gendirectcall(ll_setitem_nonneg, v_result, ci, v_item) return v_result +def ll_alloc_and_set(LISTPTR, count, item): + l = malloc(LISTPTR.TO) + l.items = malloc(LISTPTR.TO.items.TO, count) + i = 0 + while i < count: + l.items[i].item = item + i += 1 + return l + +def rtype_alloc_and_set(hop): + r_list = hop.r_result + v_count, v_item = hop.inputargs(Signed, r_list.item_repr) + c1 = hop.inputconst(Void, r_list.lowleveltype) + return hop.gendirectcall(ll_alloc_and_set, c1, v_count, v_item) + # ____________________________________________________________ # # Iteration. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 9 00:41:03 2005 @@ -245,6 +245,9 @@ def translate_op_newlist(self, hop): return rlist.rtype_newlist(hop) + def translate_op_alloc_and_set(self, hop): + return rlist.rtype_alloc_and_set(hop) + def translate_op_newtuple(self, hop): return rtuple.rtype_newtuple(hop) From arigo at codespeak.net Thu Jun 9 00:44:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 00:44:36 +0200 (CEST) Subject: [pypy-svn] r13209 - pypy/dist/pypy/rpython Message-ID: <20050608224436.BCCD927B80@code1.codespeak.net> Author: arigo Date: Thu Jun 9 00:44:35 2005 New Revision: 13209 Modified: pypy/dist/pypy/rpython/rlist.py Log: setitem on lists. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 00:44:35 2005 @@ -74,6 +74,13 @@ llfn = ll_getitem return hop.gendirectcall(llfn, v_lst, v_index) + def rtype_setitem((r_lst, r_int), hop): + v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr) + if hop.args_s[1].nonneg: + llfn = ll_setitem_nonneg + else: + llfn = ll_setitem + return hop.gendirectcall(llfn, v_lst, v_index, v_item) class __extend__(pairtype(ListRepr, ListRepr)): def convert_from_to((r_lst1, r_lst2), v, llops): From pedronis at codespeak.net Thu Jun 9 02:26:41 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 9 Jun 2005 02:26:41 +0200 (CEST) Subject: [pypy-svn] r13210 - in pypy/dist/pypy/rpython: . test Message-ID: <20050609002641.E3C9927B44@code1.codespeak.net> Author: pedronis Date: Thu Jun 9 02:26:40 2005 New Revision: 13210 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: string concatenation Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 9 02:26:40 2005 @@ -88,6 +88,11 @@ return hop.gendirectcall(llfn, v_str, v_index) +class __extend__(pairtype(StringRepr, StringRepr)): + def rtype_add(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_strconcat, v_str1, v_str2) + class __extend__(CharRepr): def rtype_len(_, hop): @@ -165,3 +170,22 @@ x = -1 s.hash = intmask(x) return x + +def ll_strconcat(s1, s2): + len1 = len(s1.chars) + len2 = len(s2.chars) + newstr = malloc(STR, len1 + len2) + i = 0 + j = 0 + while i < len1: + newstr.chars[j].ch = s1.chars[i].ch + i += 1 + j += 1 + i = 0 + while i < len2: + newstr.chars[j].ch = s2.chars[i].ch + i += 1 + j += 1 + return newstr + + Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Jun 9 02:26:40 2005 @@ -42,3 +42,14 @@ typer.specialize() #t.view() t.checkgraphs() + +def test_concat(): + def dummyfn(s1, s2): + return s1 + s2 + + t = Translator(dummyfn) + t.annotate([str, str]) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() From pedronis at codespeak.net Thu Jun 9 03:11:41 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 9 Jun 2005 03:11:41 +0200 (CEST) Subject: [pypy-svn] r13211 - pypy/branch/translator-without-old-genc/c Message-ID: <20050609011141.C0D4827B44@code1.codespeak.net> Author: pedronis Date: Thu Jun 9 03:11:39 2005 New Revision: 13211 Modified: pypy/branch/translator-without-old-genc/c/funcgen.py Log: less buggy OP_MALLOC_VARSIZE Modified: pypy/branch/translator-without-old-genc/c/funcgen.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/funcgen.py (original) +++ pypy/branch/translator-without-old-genc/c/funcgen.py Thu Jun 9 03:11:39 2005 @@ -392,8 +392,12 @@ def OP_MALLOC_VARSIZE(self, op, err): TYPE = self.lltypemap[op.result].TO typename = self.db.gettype(TYPE) + lenfld = 'length' + nodedef = self.db.gettypedefnode(TYPE) if isinstance(TYPE, Struct): - TYPE = TYPE._arrayfld + arfld = TYPE._arrayfld + lenfld = "%s.length" % nodedef.c_struct_field_name(arfld) + TYPE = TYPE._flds[TYPE._arrayfld] assert isinstance(TYPE, Array) itemtypename = self.db.gettype(TYPE.OF) elength = self.expr(op.args[1]) @@ -404,10 +408,10 @@ result = ['OP_ZERO_MALLOC(%s, %s, %s)' % (size, eresult, err), - '%s->length = %s;' % (eresult, - elength), + '%s->%s = %s;' % (eresult, lenfld, + elength), '%s->%s = 1;' % (eresult, - self.db.gettypedefnode(TYPE).refcount), + nodedef.refcount), ] return '\t'.join(result) From arigo at codespeak.net Thu Jun 9 08:25:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 08:25:05 +0200 (CEST) Subject: [pypy-svn] r13212 - pypy/dist/pypy/rpython Message-ID: <20050609062505.087BB27B59@code1.codespeak.net> Author: arigo Date: Thu Jun 9 08:25:03 2005 New Revision: 13212 Modified: pypy/dist/pypy/rpython/rstr.py Log: Optimization. Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 9 08:25:03 2005 @@ -175,11 +175,9 @@ len1 = len(s1.chars) len2 = len(s2.chars) newstr = malloc(STR, len1 + len2) - i = 0 j = 0 - while i < len1: - newstr.chars[j].ch = s1.chars[i].ch - i += 1 + while j < len1: + newstr.chars[j].ch = s1.chars[j].ch j += 1 i = 0 while i < len2: From arigo at codespeak.net Thu Jun 9 08:51:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 08:51:11 +0200 (CEST) Subject: [pypy-svn] r13213 - in pypy: branch/translator-without-old-genc/c dist/pypy/rpython Message-ID: <20050609065111.A2A9427B5B@code1.codespeak.net> Author: arigo Date: Thu Jun 9 08:51:08 2005 New Revision: 13213 Modified: pypy/branch/translator-without-old-genc/c/g_support.h pypy/dist/pypy/rpython/rstr.py Log: Conversions rstring -> PyStringObject. Starts to become hackish. Didn't figure out how to write the reverse conversion. Needs some redesign... Modified: pypy/branch/translator-without-old-genc/c/g_support.h ============================================================================== --- pypy/branch/translator-without-old-genc/c/g_support.h (original) +++ pypy/branch/translator-without-old-genc/c/g_support.h Thu Jun 9 08:51:08 2005 @@ -367,3 +367,6 @@ Py_INCREF(o); return PyTuple_SetItem(tuple, index, o); } + +#define PyString_FromStringAndSize_Hack(s, size) \ + PyString_FromStringAndSize((char*)(s), size) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 9 08:51:08 2005 @@ -5,6 +5,7 @@ from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst from pypy.rpython.rarithmetic import intmask +from pypy.rpython.robject import PyObjRepr, pyobj_repr # ____________________________________________________________ # @@ -124,6 +125,28 @@ string_repr = StringRepr() char_repr = CharRepr() +# +# _________________________ Conversions _________________________ + +##class __extend__(pairtype(PyObjRepr, StringRepr)): +## def convert_from_to((r_from, r_to), v, llops): +## XXX + +class __extend__(pairtype(StringRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + v = llops.convertvar(v, r_from, string_repr) + cchars = inputconst(Void, "chars") + v_chars = llops.genop('getsubstruct', [v, cchars], + resulttype=Ptr(STR.chars)) + v_size = llops.genop('getarraysize', [v_chars], + resulttype=Signed) + czero = inputconst(Signed, 0) + v_char0ptr = llops.genop('getarrayitem', [v_chars, czero], + resulttype=Ptr(STR.chars.OF)) + return llops.gencapicall('PyString_FromStringAndSize_Hack', + [v_char0ptr, v_size], + resulttype=pyobj_repr) + # ____________________________________________________________ # # Low-level methods. These can be run for testing, but are meant to From arigo at codespeak.net Thu Jun 9 09:11:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 09:11:18 +0200 (CEST) Subject: [pypy-svn] r13214 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050609071118.3521627B57@code1.codespeak.net> Author: arigo Date: Thu Jun 9 09:11:15 2005 New Revision: 13214 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: List concatenation, .extend and +=. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 9 09:11:15 2005 @@ -290,6 +290,11 @@ add = union + def inplace_add((lst1, lst2)): # force the union of lst1 and lst2 + lst1.listdef.resize() + lst1.listdef.union(lst2.listdef) + return lst1 + class __extend__(pairtype(SomeList, SomeObject)): Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 09:11:15 2005 @@ -60,6 +60,10 @@ v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) + def rtype_method_extend(self, hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + hop.gendirectcall(ll_extend, v_lst1, v_lst2) + def make_iterator_repr(self): return ListIteratorRepr(self) @@ -90,6 +94,15 @@ return NotImplemented return v + def rtype_add((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + return hop.gendirectcall(ll_concat, v_lst1, v_lst2) + + def rtype_inplace_add((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + hop.gendirectcall(ll_extend, v_lst1, v_lst2) + return v_lst1 + # ____________________________________________________________ # # Low-level methods. These can be run for testing, but are meant to @@ -125,6 +138,38 @@ def ll_setitem_nonneg(l, i, newitem): l.items[i].item = newitem +def ll_concat(l1, l2): + len1 = len(l1.items) + len2 = len(l2.items) + newitems = malloc(typeOf(l1).TO.items.TO, len1 + len2) + j = 0 + while j < len1: + newitems[j].item = l1.items[j].item + j += 1 + i = 0 + while i < len2: + newitems[j].item = l2.items[i].item + i += 1 + j += 1 + l = malloc(typeOf(l1).TO) + l.items = newitems + return l + +def ll_extend(l1, l2): + len1 = len(l1.items) + len2 = len(l2.items) + newitems = malloc(typeOf(l1).TO.items.TO, len1 + len2) + j = 0 + while j < len1: + newitems[j].item = l1.items[j].item + j += 1 + i = 0 + while i < len2: + newitems[j].item = l2.items[i].item + i += 1 + j += 1 + l1.items = newitems + # ____________________________________________________________ # # Irregular operations. Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 9 09:11:15 2005 @@ -18,6 +18,15 @@ assert ll_getitem(l, 2) == 44 assert ll_getitem(l, 3) == 45 assert ll_len(l) == 4 + ll_extend(l, l) + assert ll_len(l) == 8 + for i, x in zip(range(8), [42, 43, 44, 45, 42, 43, 44, 45]): + assert ll_getitem_nonneg(l, i) == x + l1 = ll_concat(l, l) + assert l1 != l + assert ll_len(l1) == 16 + for i, x in zip(range(16), [42, 43, 44, 45] * 4): + assert ll_getitem_nonneg(l1, i) == x # ____________________________________________________________ @@ -67,3 +76,10 @@ N -= 1 return len(l) rtype(dummyfn, [int]) #.view() + +def test_add(): + def dummyfn(): + l = [5] + l += [6,7] + return l + [8] + rtype(dummyfn) From arigo at codespeak.net Thu Jun 9 09:21:30 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 09:21:30 +0200 (CEST) Subject: [pypy-svn] r13216 - pypy/branch/translator-without-old-genc/genc/test Message-ID: <20050609072130.35B7527B60@code1.codespeak.net> Author: arigo Date: Thu Jun 9 09:21:28 2005 New Revision: 13216 Modified: pypy/branch/translator-without-old-genc/genc/test/test_typed.py Log: Cannot return a list from a compiled function: the rtyper cannot convert from an rlist to a PyListObject. (This is some kind of deep limitation that would require more efforts than it's worth ATM.) Modified: pypy/branch/translator-without-old-genc/genc/test/test_typed.py ============================================================================== --- pypy/branch/translator-without-old-genc/genc/test/test_typed.py (original) +++ pypy/branch/translator-without-old-genc/genc/test/test_typed.py Thu Jun 9 09:21:28 2005 @@ -25,6 +25,16 @@ t.checkgraphs() return skip_missing_compiler(t.ccompile) + def test_call_five(self): + # -- the result of call_five() isn't a real list, but an rlist + # that can't be converted to a PyListObject + def wrapper(): + lst = snippet.call_five() + return len(lst), lst[0] + call_five = self.getcompiled(snippet.call_five) + result = call_five() + assert result == (1, 5) + def test_int_overflow(self): fn = self.getcompiled(snippet.add_func) raises(OverflowError, fn, sys_maxint()) From arigo at codespeak.net Thu Jun 9 09:27:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 09:27:58 +0200 (CEST) Subject: [pypy-svn] r13217 - in pypy: branch/translator-without-old-genc/c dist/pypy/rpython Message-ID: <20050609072758.9131127B5D@code1.codespeak.net> Author: arigo Date: Thu Jun 9 09:27:55 2005 New Revision: 13217 Modified: pypy/branch/translator-without-old-genc/c/node.py pypy/dist/pypy/rpython/rstr.py Log: += for strings. C syntax problem in array initializers. Modified: pypy/branch/translator-without-old-genc/c/node.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/node.py (original) +++ pypy/branch/translator-without-old-genc/c/node.py Thu Jun 9 09:27:55 2005 @@ -282,14 +282,14 @@ yield '{' if needs_refcount(self.T): yield '\t1,' - yield '\t%d,' % len(self.obj.items) + yield '\t%d, {' % len(self.obj.items) for j in range(len(self.obj.items)): node = self.db.getcontainernode(self.obj.items[j]) expr = '\n'.join(node.initializationexpr('%s%d.' % (prefix, j))) expr += ',' expr = expr.replace('\n', '\n\t') # indentation yield '\t%s' % expr - yield '}' + yield '} }' class FuncNode(ContainerNode): Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 9 09:27:55 2005 @@ -93,6 +93,7 @@ def rtype_add(_, hop): v_str1, v_str2 = hop.inputargs(string_repr, string_repr) return hop.gendirectcall(ll_strconcat, v_str1, v_str2) + rtype_inplace_add = rtype_add class __extend__(CharRepr): From arigo at codespeak.net Thu Jun 9 09:44:35 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 09:44:35 +0200 (CEST) Subject: [pypy-svn] r13218 - in pypy: branch/translator-without-old-genc/c dist/pypy/rpython Message-ID: <20050609074435.3744E27B61@code1.codespeak.net> Author: arigo Date: Thu Jun 9 09:44:31 2005 New Revision: 13218 Modified: pypy/branch/translator-without-old-genc/c/funcgen.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py Log: Support for cast_parent in rtyper. Sort local variable declarations in the generated C function in a futile attempt to make them slightly more readable. Modified: pypy/branch/translator-without-old-genc/c/funcgen.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/funcgen.py (original) +++ pypy/branch/translator-without-old-genc/c/funcgen.py Thu Jun 9 09:44:31 2005 @@ -85,12 +85,15 @@ for a in self.graph.getargs(): inputargset[a] = True + result_by_name = [] for v in self.allvariables(): if v not in inputargset: result = cdecl(self.typemap[v], v.name) + ';' if self.lltypemap[v] == Void: result = '/*%s*/' % result - yield result + result_by_name.append((v._name, result)) + result_by_name.sort() + return [result for name, result in result_by_name] # ____________________________________________________________ @@ -415,6 +418,13 @@ ] return '\t'.join(result) + def OP_CAST_PARENT(self, op, err): + TYPE = self.lltypemap[op.result] + typename = self.db.gettype(TYPE) + return '%s = (%s)%s;' % (self.expr(op.result), + cdecl(typename, ''), + self.expr(op.args[0])) + def OP_SAME_AS(self, op, err): result = [] assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Thu Jun 9 09:44:31 2005 @@ -6,6 +6,7 @@ from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range from pypy.rpython.rmodel import Repr, TyperError +from pypy.rpython import rptr class __extend__(annmodel.SomeBuiltin): @@ -119,8 +120,16 @@ def rtype_const_result(hop): return hop.inputconst(Void, hop.s_result.const) +def rtype_cast_parent(hop): + assert hop.args_s[0].is_constant() + assert isinstance(hop.args_r[1], rptr.PtrRepr) + v_type, v_input = hop.inputargs(Void, hop.args_r[1]) + return hop.genop('cast_parent', [v_input], # v_type implicit in r_result + resulttype = hop.r_result.lowleveltype) + BUILTIN_TYPER[lltype.malloc] = rtype_malloc +BUILTIN_TYPER[lltype.cast_parent] = rtype_cast_parent BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 9 09:44:31 2005 @@ -189,8 +189,7 @@ def fromparentpart(self, v_vtableptr, llops): """Return the vtable pointer cast from the parent vtable's type to self's vtable type.""" - ctype = inputconst(Void, self.lowleveltype) - return llops.genop('cast_parent', [ctype, v_vtableptr], + return llops.genop('cast_parent', [v_vtableptr], resulttype=self.lowleveltype) def fromtypeptr(self, vcls, llops): @@ -435,8 +434,7 @@ r_ins2 = r_ins2.rbase cast_chain.reverse() for r in cast_chain: - ctype = inputconst(Void, r.lowleveltype) - v = llops.genop('cast_parent', [ctype, v], + v = llops.genop('cast_parent', [v], resulttype = r.lowleveltype) return v else: From arigo at codespeak.net Thu Jun 9 10:07:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 10:07:54 +0200 (CEST) Subject: [pypy-svn] r13219 - pypy/dist/pypy/rpython Message-ID: <20050609080754.7719127B66@code1.codespeak.net> Author: arigo Date: Thu Jun 9 10:07:52 2005 New Revision: 13219 Modified: pypy/dist/pypy/rpython/rclass.py Log: Put the expected values in the vtables and prebuilt instances. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 9 10:07:52 2005 @@ -182,7 +182,19 @@ # initialize the 'parenttypeptr' field vtable.parenttypeptr = rsubcls.rbase.getvtable() else: - # XXX setup class attributes + # setup class attributes: for each attribute name at the level + # of 'self', look up its value in the subclass rsubcls + mro = list(rsubcls.classdef.getmro()) + for fldname in self.clsfields: + mangled_name, r = self.clsfields[fldname] + if r.lowleveltype == Void: + continue + for clsdef in mro: + if fldname in clsdef.cls.__dict__: + value = clsdef.cls.__dict__[fldname] + llvalue = r.convert_const(value) + setattr(vtable, mangled_name, llvalue) + break # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls) @@ -280,7 +292,7 @@ fields = {} allinstancefields = {} if self.classdef is None: - fields['__class__'] = 'typeptr', TYPEPTR + fields['__class__'] = 'typeptr', get_type_repr(self.rtyper) else: # instance attributes llfields = [] @@ -324,7 +336,12 @@ self.rbase.convert_const(value, targetptr = targetptr.super, vtable = vtable) - # XXX add instance attributes from this level + # add instance attributes from this level + for name, (mangled_name, r) in self.fields.items(): + attrvalue = getattr(value, name) + # XXX RECURSIVE PREBUILT DATA STRUCTURES XXX + llattrvalue = r.convert_const(attrvalue) + setattr(targetptr, mangled_name, llattrvalue) return targetptr def parentpart(self, vinst, llops): @@ -378,14 +395,18 @@ flds = self.allinstancefields.keys() flds.sort() mro = list(self.classdef.getmro()) - mro.reverse() - for clsdef in mro: - for fldname in flds: + for fldname in flds: + if fldname == '__class__': + continue + mangled_name, r = self.allinstancefields[fldname] + if r.lowleveltype == Void: + continue + for clsdef in mro: if fldname in clsdef.cls.__dict__: - mangled_name, r = self.allinstancefields[fldname] value = clsdef.cls.__dict__[fldname] cvalue = inputconst(r, value) self.setfield(vptr, fldname, cvalue, llops) + break return vptr def rtype_type(self, hop): From arigo at codespeak.net Thu Jun 9 10:44:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 10:44:43 +0200 (CEST) Subject: [pypy-svn] r13220 - in pypy/dist/pypy/rpython: . test Message-ID: <20050609084443.62FA927B69@code1.codespeak.net> Author: arigo Date: Thu Jun 9 10:44:40 2005 New Revision: 13220 Added: pypy/dist/pypy/rpython/rslice.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rlist.py Log: Slices and getslice for lists. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 10:44:40 2005 @@ -4,6 +4,8 @@ from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython import rrange +from pypy.rpython.rslice import SliceRepr +from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr # ____________________________________________________________ # @@ -86,6 +88,17 @@ llfn = ll_setitem return hop.gendirectcall(llfn, v_lst, v_index, v_item) +class __extend__(pairtype(ListRepr, SliceRepr)): + + def rtype_getitem((r_lst, r_slic), hop): + if r_slic == startonly_slice_repr: + v_lst, v_start = hop.inputargs(r_lst, startonly_slice_repr) + return hop.gendirectcall(ll_listslice_startonly, v_lst, v_start) + if r_slic == startstop_slice_repr: + v_lst, v_slice = hop.inputargs(r_lst, startstop_slice_repr) + return hop.gendirectcall(ll_listslice, v_lst, v_slice) + raise TyperError(r_slic) + class __extend__(pairtype(ListRepr, ListRepr)): def convert_from_to((r_lst1, r_lst2), v, llops): if r_lst1.listitem is None or r_lst2.listitem is None: @@ -170,6 +183,31 @@ j += 1 l1.items = newitems +def ll_listslice_startonly(l1, start): + len1 = len(l1.items) + newitems = malloc(typeOf(l1).TO.items.TO, len1 - start) + j = 0 + while start < len1: + newitems[j].item = l1.items[start].item + start += 1 + j += 1 + l = malloc(typeOf(l1).TO) + l.items = newitems + return l + +def ll_listslice(l1, slice): + start = slice.start + stop = slice.stop + newitems = malloc(typeOf(l1).TO.items.TO, stop - start) + j = 0 + while start < stop: + newitems[j].item = l1.items[start].item + start += 1 + j += 1 + l = malloc(typeOf(l1).TO) + l.items = newitems + return l + # ____________________________________________________________ # # Irregular operations. Added: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rslice.py Thu Jun 9 10:44:40 2005 @@ -0,0 +1,75 @@ +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.objspace.flow.model import Constant +from pypy.rpython.lltype import * +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +import sys + +# ____________________________________________________________ +# +# Concrete implementation of RPython slice objects: +# +# - if stop is None, use only a Signed +# - if stop is not None: +# +# struct slice { +# Signed start; +# Signed stop; +# // step is always 1 +# } + +SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed)) + + +class __extend__(annmodel.SomeSlice): + def rtyper_makerepr(self, rtyper): + if not self.step.is_constant() or self.step.const not in (None, 1): + raise TyperError("only supports slices with step 1") + if isinstance(self.start, annmodel.SomeInteger): + if not self.start.nonneg: + raise TyperError("slice start must be proved non-negative") + if isinstance(self.stop, annmodel.SomeInteger): + if not self.stop.nonneg: + raise TyperError("slice stop must be proved non-negative") + if self.stop.is_constant() and self.stop.const is None: + return startonly_slice_repr + else: + return startstop_slice_repr + def rtyper_makekey(self): + return self.stop.rtyper_makekey(), self.step.rtyper_makekey() + + +class SliceRepr(Repr): + pass + +startstop_slice_repr = SliceRepr() +startstop_slice_repr.lowleveltype = Ptr(SLICE) +startonly_slice_repr = SliceRepr() +startonly_slice_repr.lowleveltype = Signed + +# ____________________________________________________________ + +def ll_newslice(start, stop): + s = malloc(SLICE) + s.start = start + s.stop = stop + return s + +def rtype_newslice(hop): + sig = [] + for s in hop.args_s: + if s.is_constant() and s.const is None: + sig.append(Void) + else: + sig.append(Signed) + v_start, v_stop, v_step = hop.inputargs(*sig) + assert isinstance(v_step, Constant) and v_step.value in (None, 1) + if isinstance(v_start, Constant) and v_start.value is None: + v_start = hop.inputconst(Signed, 0) + if isinstance(v_stop, Constant) and v_stop.value is None: + # start-only slice + # NB. cannot just return v_start in case it is a constant + return hop.genop('same_as', [v_start], resulttype=startonly_slice_repr) + else: + # start-stop slice + return hop.gendirectcall(ll_newslice, v_start, v_stop) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 9 10:44:40 2005 @@ -251,6 +251,9 @@ def translate_op_newtuple(self, hop): return rtuple.rtype_newtuple(hop) + def translate_op_newslice(self, hop): + return rslice.rtype_newslice(hop) + def missing_operation(self, hop): raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname) @@ -410,6 +413,7 @@ # and the rtyper_chooserepr() methods from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat +from pypy.rpython import rslice from pypy.rpython import rlist, rstr, rtuple from pypy.rpython import rbuiltin, rpbc from pypy.rpython import rptr Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 9 10:44:40 2005 @@ -2,10 +2,11 @@ from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rlist import * +from pypy.rpython.rslice import ll_newslice from pypy.rpython.rint import signed_repr -def test_rlist(): +def sample_list(): rlist = ListRepr(signed_repr) rlist.setup() l = ll_newlist(rlist.lowleveltype, 3) @@ -13,20 +14,41 @@ ll_setitem(l, -2, 43) ll_setitem_nonneg(l, 2, 44) ll_append(l, 45) + return l + +def check_list(l1, expected): + assert ll_len(l1) == len(expected) + for i, x in zip(range(len(expected)), expected): + assert ll_getitem_nonneg(l1, i) == x + +def test_rlist_basic(): + l = sample_list() assert ll_getitem(l, -4) == 42 assert ll_getitem_nonneg(l, 1) == 43 assert ll_getitem(l, 2) == 44 assert ll_getitem(l, 3) == 45 assert ll_len(l) == 4 + check_list(l, [42, 43, 44, 45]) + +def test_rlist_extend_concat(): + l = sample_list() ll_extend(l, l) - assert ll_len(l) == 8 - for i, x in zip(range(8), [42, 43, 44, 45, 42, 43, 44, 45]): - assert ll_getitem_nonneg(l, i) == x + check_list(l, [42, 43, 44, 45] * 2) l1 = ll_concat(l, l) assert l1 != l - assert ll_len(l1) == 16 - for i, x in zip(range(16), [42, 43, 44, 45] * 4): - assert ll_getitem_nonneg(l1, i) == x + check_list(l1, [42, 43, 44, 45] * 4) + +def test_rlist_slice(): + l = sample_list() + check_list(ll_listslice_startonly(l, 0), [42, 43, 44, 45]) + check_list(ll_listslice_startonly(l, 1), [43, 44, 45]) + check_list(ll_listslice_startonly(l, 2), [44, 45]) + check_list(ll_listslice_startonly(l, 3), [45]) + check_list(ll_listslice_startonly(l, 4), []) + for start in range(5): + for stop in range(start, 5): + s = ll_newslice(start, stop) + check_list(ll_listslice(l, s), [42, 43, 44, 45][start:stop]) # ____________________________________________________________ @@ -83,3 +105,9 @@ l += [6,7] return l + [8] rtype(dummyfn) + +def test_slice(): + def dummyfn(): + l = [5, 6, 7, 8, 9] + return l[:2], l[1:4], l[3:] + rtype(dummyfn).view() From arigo at codespeak.net Thu Jun 9 10:53:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 10:53:32 +0200 (CEST) Subject: [pypy-svn] r13221 - in pypy/dist/pypy/rpython: . test Message-ID: <20050609085332.783A327B6D@code1.codespeak.net> Author: arigo Date: Thu Jun 9 10:53:30 2005 New Revision: 13221 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: list.delitem; tests. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 10:53:30 2005 @@ -88,6 +88,14 @@ llfn = ll_setitem return hop.gendirectcall(llfn, v_lst, v_index, v_item) + def rtype_delitem((r_lst, r_int), hop): + v_lst, v_index = hop.inputargs(r_lst, Signed) + if hop.args_s[1].nonneg: + llfn = ll_delitem_nonneg + else: + llfn = ll_delitem + return hop.gendirectcall(llfn, v_lst, v_index) + class __extend__(pairtype(ListRepr, SliceRepr)): def rtype_getitem((r_lst, r_slic), hop): @@ -143,13 +151,39 @@ i += len(l.items) return l.items[i].item +def ll_setitem_nonneg(l, i, newitem): + l.items[i].item = newitem + def ll_setitem(l, i, newitem): if i<0: i += len(l.items) l.items[i].item = newitem -def ll_setitem_nonneg(l, i, newitem): - l.items[i].item = newitem +def ll_delitem(l, i): + if i < 0: + i += len(l.items) + newlength = len(l.items) - 1 + newitems = malloc(typeOf(l).TO.items.TO, newlength) + j = 0 + while j < i: + newitems[j].item = l.items[j].item + j += 1 + while j < newlength: + newitems[j].item = l.items[j+1].item + j += 1 + l.items = newitems + +def ll_delitem_nonneg(l, i): + newlength = len(l.items) - 1 + newitems = malloc(typeOf(l).TO.items.TO, newlength) + j = 0 + while j < i: + newitems[j].item = l.items[j].item + j += 1 + while j < newlength: + newitems[j].item = l.items[j+1].item + j += 1 + l.items = newitems def ll_concat(l1, l2): len1 = len(l1.items) Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 9 10:53:30 2005 @@ -30,6 +30,21 @@ assert ll_len(l) == 4 check_list(l, [42, 43, 44, 45]) +def test_rlist_set_del(): + l = sample_list() + ll_setitem(l, -1, 99) + check_list(l, [42, 43, 44, 99]) + ll_setitem_nonneg(l, 1, 77) + check_list(l, [42, 77, 44, 99]) + ll_delitem_nonneg(l, 0) + check_list(l, [77, 44, 99]) + ll_delitem(l, -2) + check_list(l, [77, 99]) + ll_delitem(l, 1) + check_list(l, [77]) + ll_delitem(l, 0) + check_list(l, []) + def test_rlist_extend_concat(): l = sample_list() ll_extend(l, l) @@ -110,4 +125,13 @@ def dummyfn(): l = [5, 6, 7, 8, 9] return l[:2], l[1:4], l[3:] - rtype(dummyfn).view() + rtype(dummyfn) + +def test_set_del_item(): + def dummyfn(): + l = [5, 6, 7] + l[1] = 55 + l[-1] = 66 + del l[0] + del l[-1] + rtype(dummyfn) From arigo at codespeak.net Thu Jun 9 11:05:50 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 11:05:50 +0200 (CEST) Subject: [pypy-svn] r13222 - in pypy/dist/pypy/rpython: . test Message-ID: <20050609090550.A10E027B80@code1.codespeak.net> Author: arigo Date: Thu Jun 9 11:05:48 2005 New Revision: 13222 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: list.delslice. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 9 11:05:48 2005 @@ -107,6 +107,17 @@ return hop.gendirectcall(ll_listslice, v_lst, v_slice) raise TyperError(r_slic) + def rtype_delitem((r_lst, r_slic), hop): + if r_slic == startonly_slice_repr: + v_lst, v_start = hop.inputargs(r_lst, startonly_slice_repr) + hop.gendirectcall(ll_listdelslice_startonly, v_lst, v_start) + return + if r_slic == startstop_slice_repr: + v_lst, v_slice = hop.inputargs(r_lst, startstop_slice_repr) + hop.gendirectcall(ll_listdelslice, v_lst, v_slice) + return + raise TyperError(r_slic) + class __extend__(pairtype(ListRepr, ListRepr)): def convert_from_to((r_lst1, r_lst2), v, llops): if r_lst1.listitem is None or r_lst2.listitem is None: @@ -242,6 +253,29 @@ l.items = newitems return l +def ll_listdelslice_startonly(l1, start): + newitems = malloc(typeOf(l1).TO.items.TO, start) + j = 0 + while j < start: + newitems[j].item = l1.items[j].item + j += 1 + l1.items = newitems + +def ll_listdelslice(l1, slice): + start = slice.start + stop = slice.stop + newlength = len(l1.items) - (stop-start) + newitems = malloc(typeOf(l1).TO.items.TO, newlength) + j = 0 + while j < start: + newitems[j].item = l1.items[j].item + j += 1 + while j < newlength: + newitems[j].item = l1.items[stop].item + stop += 1 + j += 1 + l1.items = newitems + # ____________________________________________________________ # # Irregular operations. Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 9 11:05:48 2005 @@ -65,6 +65,21 @@ s = ll_newslice(start, stop) check_list(ll_listslice(l, s), [42, 43, 44, 45][start:stop]) +def test_rlist_delslice(): + l = sample_list() + ll_listdelslice_startonly(l, 3) + check_list(l, [42, 43, 44]) + ll_listdelslice_startonly(l, 0) + check_list(l, []) + for start in range(5): + for stop in range(start, 5): + l = sample_list() + s = ll_newslice(start, stop) + ll_listdelslice(l, s) + expected = [42, 43, 44, 45] + del expected[start:stop] + check_list(l, expected) + # ____________________________________________________________ def rtype(fn, argtypes=[]): @@ -134,4 +149,5 @@ l[-1] = 66 del l[0] del l[-1] + del l[:] rtype(dummyfn) From ac at codespeak.net Thu Jun 9 16:12:03 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Thu, 9 Jun 2005 16:12:03 +0200 (CEST) Subject: [pypy-svn] r13228 - pypy/dist/pypy/module/unicodedata Message-ID: <20050609141203.771A327B9A@code1.codespeak.net> Author: ac Date: Thu Jun 9 16:12:03 2005 New Revision: 13228 Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py Log: Minor code cleanup. Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/generate_unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/generate_unicodedb.py Thu Jun 9 16:12:03 2005 @@ -215,7 +215,7 @@ for record in db_records: print >> outfile, '%r,'%(record,) print >> outfile, ')' - print >> outfile, '_db_pgtbl = "".join([' + print >> outfile, '_db_pgtbl = (' pages = [] line = [] for i in range(0, len(table), pgsize): @@ -235,14 +235,13 @@ line = [] if len(line) > 0: print >> outfile, repr(''.join(line)) - print >> outfile, '])' + print >> outfile, ')' # Dump pgtbl print >> outfile, '_db_pages = ( ' for page_string in pages: - print >> outfile, '"".join([' for index in range(0, len(page_string), chunksize): print >> outfile, repr(page_string[index:index + chunksize]) - print >> outfile, ']),' + print >> outfile, ',' print >> outfile, ')' print >> outfile, ''' def _get_record(code): @@ -281,7 +280,7 @@ print >> outfile, '%r: %r,'%(code, table[code].name) print >> outfile, '''} -_code_by_name = dict(zip(_charnames.itervalues(), _charnames.iterkeys())) +_code_by_name = dict(map(lambda x:(x[1],x[0]), _charnames.iteritems())) _cjk_prefix = "CJK UNIFIED IDEOGRAPH-" _hangul_prefix = 'HANGUL SYLLABLE ' Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Thu Jun 9 16:12:03 2005 @@ -13796,7 +13796,7 @@ 917631: 'CANCEL TAG', } -_code_by_name = dict(zip(_charnames.itervalues(), _charnames.iterkeys())) +_code_by_name = dict(map(lambda x:(x[1],x[0]), _charnames.iteritems())) _cjk_prefix = "CJK UNIFIED IDEOGRAPH-" _hangul_prefix = 'HANGUL SYLLABLE ' @@ -14106,7 +14106,7 @@ ('Cf', 'LRE', 'N', 0, 0), ('Mn', 'NSM', 'W', 0, 218), ) -_db_pgtbl = "".join([ +_db_pgtbl = ( '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x08\x08\x08\x08\x08\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%\x08\x08\x08&\'()*+,,,,,,,,,,,,' ',,,,,,,,,,,,,-,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,' ',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,.,,,,/\x08\x08\x08\x08\x08\x08\x08,,,,,,,,,,,,,,,,,,,,' @@ -14175,422 +14175,353 @@ '2222222222222222222222222222222222222222222222222222222222222222' '2222222222222222222222222222222222222222222222222222222222222222' '222222222222222222222222222222222222222222222222222222222222222D' -]) +) _db_pages = ( -"".join([ '\x85\x85\x85\x85\x85\x85\x85\x85\x85c\x1ac&\x1a\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x1a\x1a\x1ac\x05\x7f\x7f\x8a\xb7\x8a\x7f\x7f\xd0\x00\x7f\xa0E\xb6E\xd1\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2E\x7f\x8d\xb3\x8d\x7f' '\x7fxxxxxxxxxxxxxxxxxxxxxxxxxx\xd0\x7f\x00\x84\xad\x84\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\xd0\xb3\x00\xb3\x85' '\x85\x85\x85\x85\x85\x1a\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85V\x80\xb7\xb7\x17\xb7;\xd7`\xa5\x10\x9b\xb3\xcf\xd7\x84y\xa4\x19\x19`:\xd7\x80`\x19\x10\x89\x9e\x9e\x9e\x80' '______\x95_________\x95______\x0c\x95_____\x95\x10\x10\x10::::\x10:\x10\x10\x10:\x10\x10::\x10:\x10\x10:::\x0c\x10\x10\x10:\x10:\x10:' -]), -"".join([ +, '_\x10_:_:_:_:_:_:_:_\x10_\x10_:_:_:_\x10_:_:_:_:_:\x95\x10_:_\x10_:_:_\x10\x95\x10_:_:\x10_:_:_:\x95' '\x10\x95\x10_\x10_:_\x10\x10\x95\x10_\x10_:_:\x95\x10_:_:_:_:_:_:_:_:_:\x95\x10_:_\x10_:_:_:_:_:_:__:_:_::' ':__:_:__:___::____:__:___:::__:__:_:_:__:_::_:__:___:_:__::\xd3_:::' '\xd3\xd3\xd3\xd3_q:_q:_q:_\x10_\x10_\x10_\x10_\x10_\x10_\x10_\x10:_:_:_:_:_:_:_:_:_::_q:_:___:_:_:_:' -]), -"".join([ +, '_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_\xb0_:_:_:_:_:_:_:_:_:\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' '\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0:\x10:::::::::::::::\x10::::::::::::::::::::::::::::::' '::::::::::::::::::::::::::::::::::::::::::::::\xb0\xb0\x93\x93\x93\x93\x93\x93\x93\x93\x93DD\x93\x93\x93\x93\x93' '\x93\x93DD`DD`D```D`DD\xb2\x93DDDDDD````D`D`\x93\x93\x93\x93\x93DDDDDDDDD\x93\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -]), -"".join([ +, 'rrrrrrrrrrrrrrrrrrrrrt\x87\x87\x87\x87tk\x87\x87\x87\x87\x87hh\x87\x87\x87\x87hh\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x15\x15\x15\x15\x15\x87\x87\x87\x87rrr' 'rrrrrwr\x87\x87\x87rrr\x87\x87\x01\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0uusrrrrrrrrrrrrr\xb0\xb0\xb0\xb0DD\xb0\xb0\xb0\xb0\x93\xb0\xb0\xb0\xcd\xb0' '\xb0\xb0\xb0\xb0DD_\xcd___\xb0_\xb0__:\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\xb0\x95\x95\x95\x95\x95\x95\x95__:::::\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' '\x10\x10:\x10\x10\x10\x10\x10\x10\x10:::::\xb0::___:::_:_:_:_:_:_:_:_:_:_:_:_:::::_:M\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -]), -"".join([ +, '_\x95______________\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' '\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10:\x10::::::::::::::_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:' '_:GWWWW\xb0mm_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:' '__:_:_:_:_:_:_:\xb0_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:\xb0\xb0_:\xb0\xb0\xb0\xb0\xb0\xb0' -]), -"".join([ +, '_:_:_:_:_:_:_:_:\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0_______________' '_______________________\xb0\xb0\x93HHHHHH\xb0:::::::::::::::::::::::::::::::' '::::::::\xb0H\x97\xb0\xb0\xb0\xb0\xb0\xb0TWWWWTWWWSTWWWWWW\xb0TTTTTWWTWWSYW%\xca#$!"./,-\xb0*+(J)' 'J67JW\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0000000000000000000000000000\xb0\xb0\xb0\xb0\xb0000JJ\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0' -]), -"".join([ +, '\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xba\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0{\xb0\xb0\xb0{\xb0\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xb0\xb0\xb0\xb0\xb0' '\xc4\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f523\x071>? Author: pedronis Date: Thu Jun 9 16:25:41 2005 New Revision: 13229 Modified: pypy/branch/translator-without-old-genc/c/test/test_database.py Log: tests were out-of-sync with code Modified: pypy/branch/translator-without-old-genc/c/test/test_database.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/test/test_database.py (original) +++ pypy/branch/translator-without-old-genc/c/test/test_database.py Thu Jun 9 16:25:41 2005 @@ -35,7 +35,7 @@ S = GcStruct('test', ('x', Signed)) s = malloc(S) s.x = 42 - assert db.get(s).startswith('&g_') + assert db.get(s).startswith('(&g_') assert db.containernodes.keys() == [s._obj] assert db.structdefnodes.keys() == [S] @@ -44,7 +44,7 @@ S = GcStruct('test', ('x', Struct('subtest', ('y', Signed)))) s = malloc(S) s.x.y = 42 - assert db.get(s).startswith('&g_') + assert db.get(s).startswith('(&g_') assert db.containernodes.keys() == [s._obj] assert len(db.structdefnodes) == 2 assert S in db.structdefnodes @@ -57,7 +57,7 @@ s = malloc(S) s.x = malloc(T) s.x.y = 42 - assert db.get(s).startswith('&g_') + assert db.get(s).startswith('(&g_') assert db.containernodes.keys() == [s._obj] db.complete() assert len(db.containernodes) == 2 From pedronis at codespeak.net Thu Jun 9 16:33:26 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 9 Jun 2005 16:33:26 +0200 (CEST) Subject: [pypy-svn] r13230 - pypy/dist/pypy/annotation Message-ID: <20050609143326.51F5527B9C@code1.codespeak.net> Author: pedronis Date: Thu Jun 9 16:33:24 2005 New Revision: 13230 Modified: pypy/dist/pypy/annotation/unaryop.py Log: use _defl and not _example for the value set in ptr setattr annotation Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Thu Jun 9 16:33:24 2005 @@ -442,7 +442,7 @@ assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype v_lltype = annotation_to_lltype(s_value) setattr(p.ll_ptrtype._example(), s_attr.const, - v_lltype._example()) + v_lltype._defl()) def simple_call(p, *args_s): llargs = [annotation_to_lltype(arg_s)._example() for arg_s in args_s] From pedronis at codespeak.net Thu Jun 9 18:26:47 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 9 Jun 2005 18:26:47 +0200 (CEST) Subject: [pypy-svn] r13233 - in pypy/branch/translator-without-old-genc: . genc/test Message-ID: <20050609162647.6852027B4B@code1.codespeak.net> Author: pedronis Date: Thu Jun 9 18:26:43 2005 New Revision: 13233 Modified: pypy/branch/translator-without-old-genc/annrpython.py pypy/branch/translator-without-old-genc/genc/test/test_typed.py pypy/branch/translator-without-old-genc/gencl.py pypy/branch/translator-without-old-genc/transform.py Log: - don't have typed tests with negative starting slices for now - let's cherry-pick extra transforms - only gencl needs transform_slice Modified: pypy/branch/translator-without-old-genc/annrpython.py ============================================================================== --- pypy/branch/translator-without-old-genc/annrpython.py (original) +++ pypy/branch/translator-without-old-genc/annrpython.py Thu Jun 9 18:26:43 2005 @@ -310,7 +310,7 @@ transform.transform_graph(self) from pypy.translator import simplify for graph in self.translator.flowgraphs.values(): - simplify.eliminate_empty_blocks(graph) + simplify.eliminate_empty_blocks(graph) #___ flowing annotations in blocks _____________________ Modified: pypy/branch/translator-without-old-genc/genc/test/test_typed.py ============================================================================== --- pypy/branch/translator-without-old-genc/genc/test/test_typed.py (original) +++ pypy/branch/translator-without-old-genc/genc/test/test_typed.py Thu Jun 9 18:26:43 2005 @@ -35,6 +35,21 @@ result = call_five() assert result == (1, 5) + def test_get_set_del_slice(self): + def get_set_del_nonneg_slice(l=list): # no neg slices for now! + del l[:1] + del l[len(l)-1:] + del l[2:4] + l[:1] = [3] + l[len(l)-1:] = [9] + l[2:4] = [8,11] + return l[:2], l[5:], l[3:5] + fn = self.getcompiled(get_set_del_nonneg_slice) + l = list('abcdefghij') + result = fn(l) + assert l == [3, 'c', 8, 11, 'h', 9] + assert result == ([3, 'c'], [9], [11, 'h']) + def test_int_overflow(self): fn = self.getcompiled(snippet.add_func) raises(OverflowError, fn, sys_maxint()) Modified: pypy/branch/translator-without-old-genc/gencl.py ============================================================================== --- pypy/branch/translator-without-old-genc/gencl.py (original) +++ pypy/branch/translator-without-old-genc/gencl.py Thu Jun 9 18:26:43 2005 @@ -2,7 +2,7 @@ from pypy.translator.annrpython import RPythonAnnotator from pypy.translator.simplify import simplify_graph -from pypy.translator.transform import transform_graph +from pypy.translator.transform import transform_graph, default_extra_passes, transform_slice DEBUG = False @@ -166,7 +166,8 @@ self.fun = fun self.blockref = {} self.annotate(input_arg_types) - transform_graph(self.ann) + transform_graph(self.ann, extra_passes=default_extra_passes + +[transform_slice]) def annotate(self, input_arg_types): ann = RPythonAnnotator() ann.build_types(self.fun, input_arg_types) Modified: pypy/branch/translator-without-old-genc/transform.py ============================================================================== --- pypy/branch/translator-without-old-genc/transform.py (original) +++ pypy/branch/translator-without-old-genc/transform.py Thu Jun 9 18:26:43 2005 @@ -314,17 +314,22 @@ # make sure the bookkeeper knows about AssertionError self.bookkeeper.getclassdef(AssertionError) +default_extra_passes = [ + transform_allocate, + ] -def transform_graph(ann): +def transform_graph(ann, extra_passes=default_extra_passes): """Apply set of transformations available.""" # WARNING: this produces incorrect results if the graph has been # modified by t.simplify() after it had been annotated. if ann.translator: ann.translator.checkgraphs() transform_dead_code(ann) - transform_allocate(ann) - transform_slice(ann) + for pass_ in extra_passes: + pass_(ann) ##transform_listextend(ann) # do this last, after the previous transformations had a # chance to remove dependency on certain variables transform_dead_op_vars(ann) + if ann.translator: + ann.translator.checkgraphs() From arigo at codespeak.net Thu Jun 9 18:34:07 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 18:34:07 +0200 (CEST) Subject: [pypy-svn] r13234 - pypy/branch/translator-without-old-genc/genc/test Message-ID: <20050609163407.ED0B527B4B@code1.codespeak.net> Author: arigo Date: Thu Jun 9 18:34:06 2005 New Revision: 13234 Modified: pypy/branch/translator-without-old-genc/genc/test/test_typed.py Log: Disabled test_slice_long, which makes no sense in this context. Modified: pypy/branch/translator-without-old-genc/genc/test/test_typed.py ============================================================================== --- pypy/branch/translator-without-old-genc/genc/test/test_typed.py (original) +++ pypy/branch/translator-without-old-genc/genc/test/test_typed.py Thu Jun 9 18:34:06 2005 @@ -50,6 +50,9 @@ assert l == [3, 'c', 8, 11, 'h', 9] assert result == ([3, 'c'], [9], [11, 'h']) + def test_slice_long(self): + "the parent's test_slice_long() makes no sense here" + def test_int_overflow(self): fn = self.getcompiled(snippet.add_func) raises(OverflowError, fn, sys_maxint()) From cfbolz at codespeak.net Thu Jun 9 19:11:58 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 9 Jun 2005 19:11:58 +0200 (CEST) Subject: [pypy-svn] r13235 - pypy/dist/pypy/bin Message-ID: <20050609171158.3DFC527B5A@code1.codespeak.net> Author: cfbolz Date: Thu Jun 9 19:11:58 2005 New Revision: 13235 Modified: pypy/dist/pypy/bin/translator.py Log: added import of llvm snippets and made the RPythonTyper avaiable, when in interactive use. Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Thu Jun 9 19:11:58 2005 @@ -207,6 +207,8 @@ if __name__ == '__main__': from pypy.translator.test import snippet as test + from pypy.translator.llvm.test import llvmsnippet as test2 + from pypy.rpython.rtyper import RPythonTyper if (os.getcwd() not in sys.path and os.path.curdir not in sys.path): sys.path.insert(0, os.getcwd()) From cfbolz at codespeak.net Thu Jun 9 19:30:01 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 9 Jun 2005 19:30:01 +0200 (CEST) Subject: [pypy-svn] r13236 - pypy/dist/pypy/translator/llvm Message-ID: <20050609173001.E12CE27B5F@code1.codespeak.net> Author: cfbolz Date: Thu Jun 9 19:30:01 2005 New Revision: 13236 Removed: pypy/dist/pypy/translator/llvm/operations.ll Modified: pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/llvm/representation.py pypy/dist/pypy/translator/llvm/typerepr.py Log: deleted operations, since it will be no longer neccessary. fixed some comments and added same_as to fix some failing tests. Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Thu Jun 9 19:30:01 2005 @@ -1,6 +1,5 @@ """ -This is the entry point of genllvm. This file can also be used with python -i -to interactively test genllvm. +This is the entry point of genllvm.d The class LLVMGenerator coordinates the creation of LLVM representations and drives the creation of the .ll file and the compilation: @@ -158,7 +157,6 @@ return result if isinstance(concretetype, lltype.Ptr): return pointerrepr.PointerRepr(obj.value, self) - #XXX find the right type if it is not a Primitive except AttributeError: pass for cl in self.repr_classes: Deleted: /pypy/dist/pypy/translator/llvm/operations.ll ============================================================================== --- /pypy/dist/pypy/translator/llvm/operations.ll Thu Jun 9 19:30:01 2005 +++ (empty file) @@ -1,2457 +0,0 @@ -implementation -internal double %std.add(double %a, double %b) { - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(double %a, double %b) { - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(double %a, double %b) { - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(double %a, double %b) { - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(double %a, double %b) { - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(double %a, double %b) { - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(double %a, double %b) { - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(double %a, double %b) { - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(double %a, double %b) { - %a = cast double %a to int - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(double %a, double %b) { - %a = cast double %a to int - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(double %a, double %b) { - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(double %a, double %b) { - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(double %a, double %b) { - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(double %a, double %b) { - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(double %a, double %b) { - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(double %a, double %b) { - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(double %a, double %b) { - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(double %a, double %b) { - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(double %a, double %b) { - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(double %a, double %b) { - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(double %a, double %b) { - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal double %std.add(double %a, uint %b) { - %b = cast uint %b to double - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(double %a, uint %b) { - %b = cast uint %b to double - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(double %a, uint %b) { - %b = cast uint %b to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(double %a, uint %b) { - %b = cast uint %b to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(double %a, uint %b) { - %b = cast uint %b to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(double %a, uint %b) { - %b = cast uint %b to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(double %a, uint %b) { - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(double %a, uint %b) { - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(double %a, uint %b) { - %a = cast double %a to int - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(double %a, uint %b) { - %a = cast double %a to int - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(double %a, uint %b) { - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(double %a, uint %b) { - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(double %a, uint %b) { - %b = cast uint %b to double - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(double %a, uint %b) { - %b = cast uint %b to double - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(double %a, uint %b) { - %b = cast uint %b to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(double %a, uint %b) { - %b = cast uint %b to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(double %a, uint %b) { - %b = cast uint %b to double - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(double %a, uint %b) { - %b = cast uint %b to double - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(double %a, uint %b) { - %b = cast uint %b to double - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(double %a, uint %b) { - %b = cast uint %b to double - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(double %a, uint %b) { - %b = cast uint %b to double - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal double %std.add(double %a, int %b) { - %b = cast int %b to double - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(double %a, int %b) { - %b = cast int %b to double - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(double %a, int %b) { - %b = cast int %b to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(double %a, int %b) { - %b = cast int %b to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(double %a, int %b) { - %b = cast int %b to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(double %a, int %b) { - %b = cast int %b to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(double %a, int %b) { - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(double %a, int %b) { - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(double %a, int %b) { - %a = cast double %a to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(double %a, int %b) { - %a = cast double %a to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(double %a, int %b) { - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(double %a, int %b) { - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(double %a, int %b) { - %b = cast int %b to double - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(double %a, int %b) { - %b = cast int %b to double - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(double %a, int %b) { - %b = cast int %b to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(double %a, int %b) { - %b = cast int %b to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(double %a, int %b) { - %b = cast int %b to double - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(double %a, int %b) { - %b = cast int %b to double - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(double %a, int %b) { - %b = cast int %b to double - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(double %a, int %b) { - %b = cast int %b to double - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(double %a, int %b) { - %b = cast int %b to double - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal double %std.add(double %a, bool %b) { - %b = cast bool %b to double - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(double %a, bool %b) { - %b = cast bool %b to double - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(double %a, bool %b) { - %b = cast bool %b to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(double %a, bool %b) { - %b = cast bool %b to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(double %a, bool %b) { - %b = cast bool %b to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(double %a, bool %b) { - %b = cast bool %b to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(double %a, bool %b) { - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(double %a, bool %b) { - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(double %a, bool %b) { - %a = cast double %a to int - %b = cast bool %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(double %a, bool %b) { - %a = cast double %a to int - %b = cast bool %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(double %a, bool %b) { - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(double %a, bool %b) { - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(double %a, bool %b) { - %b = cast bool %b to double - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(double %a, bool %b) { - %b = cast bool %b to double - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(double %a, bool %b) { - %b = cast bool %b to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(double %a, bool %b) { - %b = cast bool %b to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(double %a, bool %b) { - %b = cast bool %b to double - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(double %a, bool %b) { - %b = cast bool %b to double - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(double %a, bool %b) { - %b = cast bool %b to double - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(double %a, bool %b) { - %b = cast bool %b to double - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(double %a, bool %b) { - %b = cast bool %b to double - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal double %std.add(uint %a, double %b) { - %a = cast uint %a to double - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(uint %a, double %b) { - %a = cast uint %a to double - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(uint %a, double %b) { - %a = cast uint %a to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(uint %a, double %b) { - %a = cast uint %a to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(uint %a, double %b) { - %a = cast uint %a to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(uint %a, double %b) { - %a = cast uint %a to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(uint %a, double %b) { - %a = cast uint %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(uint %a, double %b) { - %a = cast uint %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(uint %a, double %b) { - %a = cast uint %a to int - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(uint %a, double %b) { - %a = cast uint %a to int - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(uint %a, double %b) { - %a = cast uint %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(uint %a, double %b) { - %a = cast uint %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(uint %a, double %b) { - %a = cast uint %a to double - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(uint %a, double %b) { - %a = cast uint %a to double - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(uint %a, double %b) { - %a = cast uint %a to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(uint %a, double %b) { - %a = cast uint %a to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(uint %a, double %b) { - %a = cast uint %a to double - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(uint %a, double %b) { - %a = cast uint %a to double - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(uint %a, double %b) { - %a = cast uint %a to double - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(uint %a, double %b) { - %a = cast uint %a to double - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(uint %a, double %b) { - %a = cast uint %a to double - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal uint %std.add(uint %a, uint %b) { - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.inplace_add(uint %a, uint %b) { - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.sub(uint %a, uint %b) { - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.inplace_sub(uint %a, uint %b) { - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.mul(uint %a, uint %b) { - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mul(uint %a, uint %b) { - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.div(uint %a, uint %b) { - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.inplace_div(uint %a, uint %b) { - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.floordiv(uint %a, uint %b) { - %a = cast uint %a to int - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal uint %std.inplace_floordiv(uint %a, uint %b) { - %a = cast uint %a to int - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal double %std.truediv(uint %a, uint %b) { - %a = cast uint %a to double - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(uint %a, uint %b) { - %a = cast uint %a to double - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal uint %std.mod(uint %a, uint %b) { - %r = rem uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mod(uint %a, uint %b) { - %r = rem uint %a, %b - ret uint %r -} - -internal bool %std.is_(uint %a, uint %b) { - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.eq(uint %a, uint %b) { - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.lt(uint %a, uint %b) { - %r = setlt uint %a, %b - ret bool %r -} - -internal bool %std.le(uint %a, uint %b) { - %r = setle uint %a, %b - ret bool %r -} - -internal bool %std.ge(uint %a, uint %b) { - %r = setge uint %a, %b - ret bool %r -} - -internal bool %std.gt(uint %a, uint %b) { - %r = setgt uint %a, %b - ret bool %r -} - -internal bool %std.neq(uint %a, uint %b) { - %r = setgt uint %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal uint %std.add(uint %a, int %b) { - %b = cast int %b to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.inplace_add(uint %a, int %b) { - %b = cast int %b to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.sub(uint %a, int %b) { - %b = cast int %b to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.inplace_sub(uint %a, int %b) { - %b = cast int %b to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.mul(uint %a, int %b) { - %b = cast int %b to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mul(uint %a, int %b) { - %b = cast int %b to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.div(uint %a, int %b) { - %b = cast int %b to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.inplace_div(uint %a, int %b) { - %b = cast int %b to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.floordiv(uint %a, int %b) { - %a = cast uint %a to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal uint %std.inplace_floordiv(uint %a, int %b) { - %a = cast uint %a to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal double %std.truediv(uint %a, int %b) { - %a = cast uint %a to double - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(uint %a, int %b) { - %a = cast uint %a to double - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal uint %std.mod(uint %a, int %b) { - %b = cast int %b to uint - %r = rem uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mod(uint %a, int %b) { - %b = cast int %b to uint - %r = rem uint %a, %b - ret uint %r -} - -internal bool %std.is_(uint %a, int %b) { - %b = cast int %b to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.eq(uint %a, int %b) { - %b = cast int %b to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.lt(uint %a, int %b) { - %b = cast int %b to uint - %r = setlt uint %a, %b - ret bool %r -} - -internal bool %std.le(uint %a, int %b) { - %b = cast int %b to uint - %r = setle uint %a, %b - ret bool %r -} - -internal bool %std.ge(uint %a, int %b) { - %b = cast int %b to uint - %r = setge uint %a, %b - ret bool %r -} - -internal bool %std.gt(uint %a, int %b) { - %b = cast int %b to uint - %r = setgt uint %a, %b - ret bool %r -} - -internal bool %std.neq(uint %a, int %b) { - %b = cast int %b to uint - %r = setgt uint %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal uint %std.add(uint %a, bool %b) { - %b = cast bool %b to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.inplace_add(uint %a, bool %b) { - %b = cast bool %b to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.sub(uint %a, bool %b) { - %b = cast bool %b to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.inplace_sub(uint %a, bool %b) { - %b = cast bool %b to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.mul(uint %a, bool %b) { - %b = cast bool %b to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mul(uint %a, bool %b) { - %b = cast bool %b to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.div(uint %a, bool %b) { - %b = cast bool %b to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.inplace_div(uint %a, bool %b) { - %b = cast bool %b to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.floordiv(uint %a, bool %b) { - %a = cast uint %a to int - %b = cast bool %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal uint %std.inplace_floordiv(uint %a, bool %b) { - %a = cast uint %a to int - %b = cast bool %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal double %std.truediv(uint %a, bool %b) { - %a = cast uint %a to double - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(uint %a, bool %b) { - %a = cast uint %a to double - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal uint %std.mod(uint %a, bool %b) { - %b = cast bool %b to uint - %r = rem uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mod(uint %a, bool %b) { - %b = cast bool %b to uint - %r = rem uint %a, %b - ret uint %r -} - -internal bool %std.is_(uint %a, bool %b) { - %b = cast bool %b to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.eq(uint %a, bool %b) { - %b = cast bool %b to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.lt(uint %a, bool %b) { - %b = cast bool %b to uint - %r = setlt uint %a, %b - ret bool %r -} - -internal bool %std.le(uint %a, bool %b) { - %b = cast bool %b to uint - %r = setle uint %a, %b - ret bool %r -} - -internal bool %std.ge(uint %a, bool %b) { - %b = cast bool %b to uint - %r = setge uint %a, %b - ret bool %r -} - -internal bool %std.gt(uint %a, bool %b) { - %b = cast bool %b to uint - %r = setgt uint %a, %b - ret bool %r -} - -internal bool %std.neq(uint %a, bool %b) { - %b = cast bool %b to uint - %r = setgt uint %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal double %std.add(int %a, double %b) { - %a = cast int %a to double - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(int %a, double %b) { - %a = cast int %a to double - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(int %a, double %b) { - %a = cast int %a to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(int %a, double %b) { - %a = cast int %a to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(int %a, double %b) { - %a = cast int %a to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(int %a, double %b) { - %a = cast int %a to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(int %a, double %b) { - %a = cast int %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(int %a, double %b) { - %a = cast int %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(int %a, double %b) { - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(int %a, double %b) { - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(int %a, double %b) { - %a = cast int %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(int %a, double %b) { - %a = cast int %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(int %a, double %b) { - %a = cast int %a to double - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(int %a, double %b) { - %a = cast int %a to double - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(int %a, double %b) { - %a = cast int %a to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(int %a, double %b) { - %a = cast int %a to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(int %a, double %b) { - %a = cast int %a to double - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(int %a, double %b) { - %a = cast int %a to double - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(int %a, double %b) { - %a = cast int %a to double - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(int %a, double %b) { - %a = cast int %a to double - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(int %a, double %b) { - %a = cast int %a to double - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal uint %std.add(int %a, uint %b) { - %a = cast int %a to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.inplace_add(int %a, uint %b) { - %a = cast int %a to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.sub(int %a, uint %b) { - %a = cast int %a to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.inplace_sub(int %a, uint %b) { - %a = cast int %a to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.mul(int %a, uint %b) { - %a = cast int %a to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mul(int %a, uint %b) { - %a = cast int %a to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.div(int %a, uint %b) { - %a = cast int %a to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.inplace_div(int %a, uint %b) { - %a = cast int %a to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.floordiv(int %a, uint %b) { - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal uint %std.inplace_floordiv(int %a, uint %b) { - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal double %std.truediv(int %a, uint %b) { - %a = cast int %a to double - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(int %a, uint %b) { - %a = cast int %a to double - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal uint %std.mod(int %a, uint %b) { - %a = cast int %a to uint - %r = rem uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mod(int %a, uint %b) { - %a = cast int %a to uint - %r = rem uint %a, %b - ret uint %r -} - -internal bool %std.is_(int %a, uint %b) { - %a = cast int %a to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.eq(int %a, uint %b) { - %a = cast int %a to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.lt(int %a, uint %b) { - %a = cast int %a to uint - %r = setlt uint %a, %b - ret bool %r -} - -internal bool %std.le(int %a, uint %b) { - %a = cast int %a to uint - %r = setle uint %a, %b - ret bool %r -} - -internal bool %std.ge(int %a, uint %b) { - %a = cast int %a to uint - %r = setge uint %a, %b - ret bool %r -} - -internal bool %std.gt(int %a, uint %b) { - %a = cast int %a to uint - %r = setgt uint %a, %b - ret bool %r -} - -internal bool %std.neq(int %a, uint %b) { - %a = cast int %a to uint - %r = setgt uint %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal int %std.add(int %a, int %b) { - %r = add int %a, %b - ret int %r -} - -internal int %std.inplace_add(int %a, int %b) { - %r = add int %a, %b - ret int %r -} - -internal int %std.sub(int %a, int %b) { - %r = sub int %a, %b - ret int %r -} - -internal int %std.inplace_sub(int %a, int %b) { - %r = sub int %a, %b - ret int %r -} - -internal int %std.mul(int %a, int %b) { - %r = mul int %a, %b - ret int %r -} - -internal int %std.inplace_mul(int %a, int %b) { - %r = mul int %a, %b - ret int %r -} - -internal int %std.div(int %a, int %b) { - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_div(int %a, int %b) { - %r = div int %a, %b - ret int %r -} - -internal int %std.floordiv(int %a, int %b) { - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_floordiv(int %a, int %b) { - %r = div int %a, %b - ret int %r -} - -internal double %std.truediv(int %a, int %b) { - %a = cast int %a to double - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(int %a, int %b) { - %a = cast int %a to double - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal int %std.mod(int %a, int %b) { - %r = rem int %a, %b - ret int %r -} - -internal int %std.inplace_mod(int %a, int %b) { - %r = rem int %a, %b - ret int %r -} - -internal bool %std.is_(int %a, int %b) { - %r = seteq int %a, %b - ret bool %r -} - -internal bool %std.eq(int %a, int %b) { - %r = seteq int %a, %b - ret bool %r -} - -internal bool %std.lt(int %a, int %b) { - %r = setlt int %a, %b - ret bool %r -} - -internal bool %std.le(int %a, int %b) { - %r = setle int %a, %b - ret bool %r -} - -internal bool %std.ge(int %a, int %b) { - %r = setge int %a, %b - ret bool %r -} - -internal bool %std.gt(int %a, int %b) { - %r = setgt int %a, %b - ret bool %r -} - -internal bool %std.neq(int %a, int %b) { - %r = setgt int %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal int %std.add(int %a, bool %b) { - %b = cast bool %b to int - %r = add int %a, %b - ret int %r -} - -internal int %std.inplace_add(int %a, bool %b) { - %b = cast bool %b to int - %r = add int %a, %b - ret int %r -} - -internal int %std.sub(int %a, bool %b) { - %b = cast bool %b to int - %r = sub int %a, %b - ret int %r -} - -internal int %std.inplace_sub(int %a, bool %b) { - %b = cast bool %b to int - %r = sub int %a, %b - ret int %r -} - -internal int %std.mul(int %a, bool %b) { - %b = cast bool %b to int - %r = mul int %a, %b - ret int %r -} - -internal int %std.inplace_mul(int %a, bool %b) { - %b = cast bool %b to int - %r = mul int %a, %b - ret int %r -} - -internal int %std.div(int %a, bool %b) { - %b = cast bool %b to int - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_div(int %a, bool %b) { - %b = cast bool %b to int - %r = div int %a, %b - ret int %r -} - -internal int %std.floordiv(int %a, bool %b) { - %b = cast bool %b to int - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_floordiv(int %a, bool %b) { - %b = cast bool %b to int - %r = div int %a, %b - ret int %r -} - -internal double %std.truediv(int %a, bool %b) { - %a = cast int %a to double - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(int %a, bool %b) { - %a = cast int %a to double - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal int %std.mod(int %a, bool %b) { - %b = cast bool %b to int - %r = rem int %a, %b - ret int %r -} - -internal int %std.inplace_mod(int %a, bool %b) { - %b = cast bool %b to int - %r = rem int %a, %b - ret int %r -} - -internal bool %std.is_(int %a, bool %b) { - %b = cast bool %b to int - %r = seteq int %a, %b - ret bool %r -} - -internal bool %std.eq(int %a, bool %b) { - %b = cast bool %b to int - %r = seteq int %a, %b - ret bool %r -} - -internal bool %std.lt(int %a, bool %b) { - %b = cast bool %b to int - %r = setlt int %a, %b - ret bool %r -} - -internal bool %std.le(int %a, bool %b) { - %b = cast bool %b to int - %r = setle int %a, %b - ret bool %r -} - -internal bool %std.ge(int %a, bool %b) { - %b = cast bool %b to int - %r = setge int %a, %b - ret bool %r -} - -internal bool %std.gt(int %a, bool %b) { - %b = cast bool %b to int - %r = setgt int %a, %b - ret bool %r -} - -internal bool %std.neq(int %a, bool %b) { - %b = cast bool %b to int - %r = setgt int %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal double %std.add(bool %a, double %b) { - %a = cast bool %a to double - %r = add double %a, %b - ret double %r -} - -internal double %std.inplace_add(bool %a, double %b) { - %a = cast bool %a to double - %r = add double %a, %b - ret double %r -} - -internal double %std.sub(bool %a, double %b) { - %a = cast bool %a to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.inplace_sub(bool %a, double %b) { - %a = cast bool %a to double - %r = sub double %a, %b - ret double %r -} - -internal double %std.mul(bool %a, double %b) { - %a = cast bool %a to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.inplace_mul(bool %a, double %b) { - %a = cast bool %a to double - %r = mul double %a, %b - ret double %r -} - -internal double %std.div(bool %a, double %b) { - %a = cast bool %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_div(bool %a, double %b) { - %a = cast bool %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.floordiv(bool %a, double %b) { - %a = cast bool %a to int - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.inplace_floordiv(bool %a, double %b) { - %a = cast bool %a to int - %b = cast double %b to int - %r = div int %a, %b - %r = cast int %r to double - ret double %r -} - -internal double %std.truediv(bool %a, double %b) { - %a = cast bool %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(bool %a, double %b) { - %a = cast bool %a to double - %r = div double %a, %b - ret double %r -} - -internal double %std.mod(bool %a, double %b) { - %a = cast bool %a to double - %r = rem double %a, %b - ret double %r -} - -internal double %std.inplace_mod(bool %a, double %b) { - %a = cast bool %a to double - %r = rem double %a, %b - ret double %r -} - -internal bool %std.is_(bool %a, double %b) { - %a = cast bool %a to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.eq(bool %a, double %b) { - %a = cast bool %a to double - %r = seteq double %a, %b - ret bool %r -} - -internal bool %std.lt(bool %a, double %b) { - %a = cast bool %a to double - %r = setlt double %a, %b - ret bool %r -} - -internal bool %std.le(bool %a, double %b) { - %a = cast bool %a to double - %r = setle double %a, %b - ret bool %r -} - -internal bool %std.ge(bool %a, double %b) { - %a = cast bool %a to double - %r = setge double %a, %b - ret bool %r -} - -internal bool %std.gt(bool %a, double %b) { - %a = cast bool %a to double - %r = setgt double %a, %b - ret bool %r -} - -internal bool %std.neq(bool %a, double %b) { - %a = cast bool %a to double - %r = setgt double %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal uint %std.add(bool %a, uint %b) { - %a = cast bool %a to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.inplace_add(bool %a, uint %b) { - %a = cast bool %a to uint - %r = add uint %a, %b - ret uint %r -} - -internal uint %std.sub(bool %a, uint %b) { - %a = cast bool %a to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.inplace_sub(bool %a, uint %b) { - %a = cast bool %a to uint - %r = sub uint %a, %b - ret uint %r -} - -internal uint %std.mul(bool %a, uint %b) { - %a = cast bool %a to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mul(bool %a, uint %b) { - %a = cast bool %a to uint - %r = mul uint %a, %b - ret uint %r -} - -internal uint %std.div(bool %a, uint %b) { - %a = cast bool %a to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.inplace_div(bool %a, uint %b) { - %a = cast bool %a to uint - %r = div uint %a, %b - ret uint %r -} - -internal uint %std.floordiv(bool %a, uint %b) { - %a = cast bool %a to int - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal uint %std.inplace_floordiv(bool %a, uint %b) { - %a = cast bool %a to int - %b = cast uint %b to int - %r = div int %a, %b - %r = cast int %r to uint - ret uint %r -} - -internal double %std.truediv(bool %a, uint %b) { - %a = cast bool %a to double - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(bool %a, uint %b) { - %a = cast bool %a to double - %b = cast uint %b to double - %r = div double %a, %b - ret double %r -} - -internal uint %std.mod(bool %a, uint %b) { - %a = cast bool %a to uint - %r = rem uint %a, %b - ret uint %r -} - -internal uint %std.inplace_mod(bool %a, uint %b) { - %a = cast bool %a to uint - %r = rem uint %a, %b - ret uint %r -} - -internal bool %std.is_(bool %a, uint %b) { - %a = cast bool %a to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.eq(bool %a, uint %b) { - %a = cast bool %a to uint - %r = seteq uint %a, %b - ret bool %r -} - -internal bool %std.lt(bool %a, uint %b) { - %a = cast bool %a to uint - %r = setlt uint %a, %b - ret bool %r -} - -internal bool %std.le(bool %a, uint %b) { - %a = cast bool %a to uint - %r = setle uint %a, %b - ret bool %r -} - -internal bool %std.ge(bool %a, uint %b) { - %a = cast bool %a to uint - %r = setge uint %a, %b - ret bool %r -} - -internal bool %std.gt(bool %a, uint %b) { - %a = cast bool %a to uint - %r = setgt uint %a, %b - ret bool %r -} - -internal bool %std.neq(bool %a, uint %b) { - %a = cast bool %a to uint - %r = setgt uint %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal int %std.add(bool %a, int %b) { - %a = cast bool %a to int - %r = add int %a, %b - ret int %r -} - -internal int %std.inplace_add(bool %a, int %b) { - %a = cast bool %a to int - %r = add int %a, %b - ret int %r -} - -internal int %std.sub(bool %a, int %b) { - %a = cast bool %a to int - %r = sub int %a, %b - ret int %r -} - -internal int %std.inplace_sub(bool %a, int %b) { - %a = cast bool %a to int - %r = sub int %a, %b - ret int %r -} - -internal int %std.mul(bool %a, int %b) { - %a = cast bool %a to int - %r = mul int %a, %b - ret int %r -} - -internal int %std.inplace_mul(bool %a, int %b) { - %a = cast bool %a to int - %r = mul int %a, %b - ret int %r -} - -internal int %std.div(bool %a, int %b) { - %a = cast bool %a to int - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_div(bool %a, int %b) { - %a = cast bool %a to int - %r = div int %a, %b - ret int %r -} - -internal int %std.floordiv(bool %a, int %b) { - %a = cast bool %a to int - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_floordiv(bool %a, int %b) { - %a = cast bool %a to int - %r = div int %a, %b - ret int %r -} - -internal double %std.truediv(bool %a, int %b) { - %a = cast bool %a to double - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(bool %a, int %b) { - %a = cast bool %a to double - %b = cast int %b to double - %r = div double %a, %b - ret double %r -} - -internal int %std.mod(bool %a, int %b) { - %a = cast bool %a to int - %r = rem int %a, %b - ret int %r -} - -internal int %std.inplace_mod(bool %a, int %b) { - %a = cast bool %a to int - %r = rem int %a, %b - ret int %r -} - -internal bool %std.is_(bool %a, int %b) { - %a = cast bool %a to int - %r = seteq int %a, %b - ret bool %r -} - -internal bool %std.eq(bool %a, int %b) { - %a = cast bool %a to int - %r = seteq int %a, %b - ret bool %r -} - -internal bool %std.lt(bool %a, int %b) { - %a = cast bool %a to int - %r = setlt int %a, %b - ret bool %r -} - -internal bool %std.le(bool %a, int %b) { - %a = cast bool %a to int - %r = setle int %a, %b - ret bool %r -} - -internal bool %std.ge(bool %a, int %b) { - %a = cast bool %a to int - %r = setge int %a, %b - ret bool %r -} - -internal bool %std.gt(bool %a, int %b) { - %a = cast bool %a to int - %r = setgt int %a, %b - ret bool %r -} - -internal bool %std.neq(bool %a, int %b) { - %a = cast bool %a to int - %r = setgt int %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal int %std.add(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = add int %a, %b - ret int %r -} - -internal int %std.inplace_add(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = add int %a, %b - ret int %r -} - -internal int %std.sub(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = sub int %a, %b - ret int %r -} - -internal int %std.inplace_sub(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = sub int %a, %b - ret int %r -} - -internal int %std.mul(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = mul int %a, %b - ret int %r -} - -internal int %std.inplace_mul(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = mul int %a, %b - ret int %r -} - -internal int %std.div(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = div int %a, %b - ret int %r -} - -internal int %std.inplace_div(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = div int %a, %b - ret int %r -} - -internal bool %std.floordiv(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = div int %a, %b - %r = cast int %r to bool - ret bool %r -} - -internal bool %std.inplace_floordiv(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = div int %a, %b - %r = cast int %r to bool - ret bool %r -} - -internal double %std.truediv(bool %a, bool %b) { - %a = cast bool %a to double - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal double %std.inplace_truediv(bool %a, bool %b) { - %a = cast bool %a to double - %b = cast bool %b to double - %r = div double %a, %b - ret double %r -} - -internal int %std.mod(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = rem int %a, %b - ret int %r -} - -internal int %std.inplace_mod(bool %a, bool %b) { - %a = cast bool %a to int - %b = cast bool %b to int - %r = rem int %a, %b - ret int %r -} - -internal bool %std.is_(bool %a, bool %b) { - %r = seteq bool %a, %b - ret bool %r -} - -internal bool %std.eq(bool %a, bool %b) { - %r = seteq bool %a, %b - ret bool %r -} - -internal bool %std.lt(bool %a, bool %b) { - %r = setlt bool %a, %b - ret bool %r -} - -internal bool %std.le(bool %a, bool %b) { - %r = setle bool %a, %b - ret bool %r -} - -internal bool %std.ge(bool %a, bool %b) { - %r = setge bool %a, %b - ret bool %r -} - -internal bool %std.gt(bool %a, bool %b) { - %r = setgt bool %a, %b - ret bool %r -} - -internal bool %std.neq(bool %a, bool %b) { - %r = setgt bool %a, %b - %r1 = xor bool %r, true - ret bool %r1 -} - -internal uint %std.and_(uint %a, uint %b) { - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.inplace_and(uint %a, uint %b) { - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.or_(uint %a, uint %b) { - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.inplace_or(uint %a, uint %b) { - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.xor(uint %a, uint %b) { - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.inplace_xor(uint %a, uint %b) { - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.and_(uint %a, int %b) { - %b = cast int %b to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.inplace_and(uint %a, int %b) { - %b = cast int %b to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.or_(uint %a, int %b) { - %b = cast int %b to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.inplace_or(uint %a, int %b) { - %b = cast int %b to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.xor(uint %a, int %b) { - %b = cast int %b to uint - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.inplace_xor(uint %a, int %b) { - %b = cast int %b to uint - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.and_(uint %a, bool %b) { - %b = cast bool %b to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.inplace_and(uint %a, bool %b) { - %b = cast bool %b to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.or_(uint %a, bool %b) { - %b = cast bool %b to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.inplace_or(uint %a, bool %b) { - %b = cast bool %b to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.xor(uint %a, bool %b) { - %b = cast bool %b to uint - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.inplace_xor(uint %a, bool %b) { - %b = cast bool %b to uint - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.and_(int %a, uint %b) { - %a = cast int %a to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.inplace_and(int %a, uint %b) { - %a = cast int %a to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.or_(int %a, uint %b) { - %a = cast int %a to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.inplace_or(int %a, uint %b) { - %a = cast int %a to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.xor(int %a, uint %b) { - %a = cast int %a to uint - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.inplace_xor(int %a, uint %b) { - %a = cast int %a to uint - %r = xor uint %a, %b - ret uint %r -} - -internal int %std.and_(int %a, int %b) { - %r = and int %a, %b - ret int %r -} - -internal int %std.inplace_and(int %a, int %b) { - %r = and int %a, %b - ret int %r -} - -internal int %std.or_(int %a, int %b) { - %r = or int %a, %b - ret int %r -} - -internal int %std.inplace_or(int %a, int %b) { - %r = or int %a, %b - ret int %r -} - -internal int %std.xor(int %a, int %b) { - %r = xor int %a, %b - ret int %r -} - -internal int %std.inplace_xor(int %a, int %b) { - %r = xor int %a, %b - ret int %r -} - -internal int %std.and_(int %a, bool %b) { - %b = cast bool %b to int - %r = and int %a, %b - ret int %r -} - -internal int %std.inplace_and(int %a, bool %b) { - %b = cast bool %b to int - %r = and int %a, %b - ret int %r -} - -internal int %std.or_(int %a, bool %b) { - %b = cast bool %b to int - %r = or int %a, %b - ret int %r -} - -internal int %std.inplace_or(int %a, bool %b) { - %b = cast bool %b to int - %r = or int %a, %b - ret int %r -} - -internal int %std.xor(int %a, bool %b) { - %b = cast bool %b to int - %r = xor int %a, %b - ret int %r -} - -internal int %std.inplace_xor(int %a, bool %b) { - %b = cast bool %b to int - %r = xor int %a, %b - ret int %r -} - -internal uint %std.and_(bool %a, uint %b) { - %a = cast bool %a to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.inplace_and(bool %a, uint %b) { - %a = cast bool %a to uint - %r = and uint %a, %b - ret uint %r -} - -internal uint %std.or_(bool %a, uint %b) { - %a = cast bool %a to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.inplace_or(bool %a, uint %b) { - %a = cast bool %a to uint - %r = or uint %a, %b - ret uint %r -} - -internal uint %std.xor(bool %a, uint %b) { - %a = cast bool %a to uint - %r = xor uint %a, %b - ret uint %r -} - -internal uint %std.inplace_xor(bool %a, uint %b) { - %a = cast bool %a to uint - %r = xor uint %a, %b - ret uint %r -} - -internal int %std.and_(bool %a, int %b) { - %a = cast bool %a to int - %r = and int %a, %b - ret int %r -} - -internal int %std.inplace_and(bool %a, int %b) { - %a = cast bool %a to int - %r = and int %a, %b - ret int %r -} - -internal int %std.or_(bool %a, int %b) { - %a = cast bool %a to int - %r = or int %a, %b - ret int %r -} - -internal int %std.inplace_or(bool %a, int %b) { - %a = cast bool %a to int - %r = or int %a, %b - ret int %r -} - -internal int %std.xor(bool %a, int %b) { - %a = cast bool %a to int - %r = xor int %a, %b - ret int %r -} - -internal int %std.inplace_xor(bool %a, int %b) { - %a = cast bool %a to int - %r = xor int %a, %b - ret int %r -} - -internal bool %std.and_(bool %a, bool %b) { - %r = and bool %a, %b - ret bool %r -} - -internal bool %std.inplace_and(bool %a, bool %b) { - %r = and bool %a, %b - ret bool %r -} - -internal bool %std.or_(bool %a, bool %b) { - %r = or bool %a, %b - ret bool %r -} - -internal bool %std.inplace_or(bool %a, bool %b) { - %r = or bool %a, %b - ret bool %r -} - -internal bool %std.xor(bool %a, bool %b) { - %r = xor bool %a, %b - ret bool %r -} - -internal bool %std.inplace_xor(bool %a, bool %b) { - %r = xor bool %a, %b - ret bool %r -} - -internal uint %std.lshift(uint %a, uint %b) { - %b = cast uint %b to ubyte - %r = shl uint %a, ubyte %b - ret uint %r -} - -internal uint %std.rshift(uint %a, uint %b) { - %b = cast uint %b to ubyte - %r = shr uint %a, ubyte %b - ret uint %r -} - -internal uint %std.lshift(uint %a, int %b) { - %b = cast int %b to ubyte - %r = shl uint %a, ubyte %b - ret uint %r -} - -internal uint %std.rshift(uint %a, int %b) { - %b = cast int %b to ubyte - %r = shr uint %a, ubyte %b - ret uint %r -} - -internal int %std.lshift(int %a, uint %b) { - %b = cast uint %b to ubyte - %r = shl int %a, ubyte %b - ret int %r -} - -internal int %std.rshift(int %a, uint %b) { - %b = cast uint %b to ubyte - %r = shr int %a, ubyte %b - ret int %r -} - -internal int %std.lshift(int %a, int %b) { - %b = cast int %b to ubyte - %r = shl int %a, ubyte %b - ret int %r -} - -internal int %std.rshift(int %a, int %b) { - %b = cast int %b to ubyte - %r = shr int %a, ubyte %b - ret int %r -} - -internal int %std.int(double %a) { - %r = cast double %a to int - ret int %r -} - -internal bool %std.bool(double %a) { - %r = cast double %a to bool - ret bool %r -} - -internal bool %std.is_true(double %a) { - %r = cast double %a to bool - ret bool %r -} - -internal int %std.int(uint %a) { - %r = cast uint %a to int - ret int %r -} - -internal bool %std.bool(uint %a) { - %r = cast uint %a to bool - ret bool %r -} - -internal bool %std.is_true(uint %a) { - %r = cast uint %a to bool - ret bool %r -} - -internal int %std.int(int %a) { - %r = cast int %a to int - ret int %r -} - -internal bool %std.bool(int %a) { - %r = cast int %a to bool - ret bool %r -} - -internal bool %std.is_true(int %a) { - %r = cast int %a to bool - ret bool %r -} - -internal int %std.int(bool %a) { - %r = cast bool %a to int - ret int %r -} - -internal bool %std.bool(bool %a) { - %r = cast bool %a to bool - ret bool %r -} - -internal bool %std.is_true(bool %a) { - %r = cast bool %a to bool - ret bool %r -} - Modified: pypy/dist/pypy/translator/llvm/representation.py ============================================================================== --- pypy/dist/pypy/translator/llvm/representation.py (original) +++ pypy/dist/pypy/translator/llvm/representation.py Thu Jun 9 19:30:01 2005 @@ -55,26 +55,27 @@ def setup(self): pass - def get_globals(self): #this is called when the global definitions are collected + def get_globals(self): # this is called to collect global definitions return "" - def get_functions(self): #this is called, when functions are collected + def get_functions(self): # this is called, when functions are collected return "" - def collect_init_code(self, lblock, l_func): #this collects init code - pass #it is only executed once at module import time + def collect_init_code(self, lblock, l_func): # this collects init code + pass # it is only executed once at + # module import time - def llvmname(self): #this is the name of the object in LLVM world: "5" for the int 5 - return self.name + def llvmname(self): # this is the name of the object in LLVM world: + return self.name # "5" for the int 5 - def llvmtype(self): #this is the name of the type of the object: "long" for and int - return self.type.typename() + def llvmtype(self): # this is the name of the type of + return self.type.typename() # the object: "long" for and int - def llvmsize(self): #this is the size in bytes -- not really used yet, but will be soon + def llvmsize(self): #this is the size in bytes -- used for allocation raise NotImplementedError, "This object has no size!" - def op(self, opname, l_target, args, lblock, l_func): #This is used when code is generated: - if hasattr(self, "type") and hasattr(self.type, "t_op"): #I'll tell you about it soon + def op(self, opname, l_target, args, lblock, l_func): + if hasattr(self, "type") and hasattr(self.type, "t_op"): return self.type.t_op(opname, l_target, args, lblock, l_func) raise CompileError, "op '%s' not supported" % opname Modified: pypy/dist/pypy/translator/llvm/typerepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/typerepr.py (original) +++ pypy/dist/pypy/translator/llvm/typerepr.py Thu Jun 9 19:30:01 2005 @@ -138,9 +138,16 @@ def typename(self): return "bool" + def t_op_same_as(self, l_target, args, lblock, l_func): + l_arg0 = self.gen.get_repr(args[0]) + l_func.dependencies.add(l_arg0) + lblock.instruction("%s = or %s, false" % (l_target.llvmname(), + l_arg0.typed_name())) + def llvmsize(self): return 1 + class FloatTypeRepr(TypeRepr): directly_supported_ops = { "float_add": "add", From cfbolz at codespeak.net Thu Jun 9 19:39:41 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 9 Jun 2005 19:39:41 +0200 (CEST) Subject: [pypy-svn] r13237 - pypy/dist/pypy/translator/llvm Message-ID: <20050609173941.3670D27B44@code1.codespeak.net> Author: cfbolz Date: Thu Jun 9 19:39:40 2005 New Revision: 13237 Removed: pypy/dist/pypy/translator/llvm/int_list.ll pypy/dist/pypy/translator/llvm/intlist.c pypy/dist/pypy/translator/llvm/list.c pypy/dist/pypy/translator/llvm/list_template.ll pypy/dist/pypy/translator/llvm/make_runtime.py Modified: pypy/dist/pypy/translator/llvm/genllvm.py Log: removing more files obsoleted by the rtyper. disabling respective modules in genllvm (soon they will probably go, too). Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Thu Jun 9 19:39:40 2005 @@ -72,8 +72,7 @@ self.global_counts = {} self.local_counts = {} self.repr_classes = [] - for mod in [representation, funcrepr, typerepr, seqrepr, classrepr, - pbcrepr, pointerrepr]: + for mod in [representation, funcrepr, typerepr, pointerrepr]: self.repr_classes += [getattr(mod, s) for s in dir(mod) if "Repr" in s] #if debug: @@ -188,7 +187,7 @@ for l_repr in traverse_dependencies(self.l_entrypoint, seen_reprs): l_repr.collect_init_code(init_block, self.l_entrypoint) if include == True: - include_files = ["operations.ll", "class.ll"] + include_files = ["class.ll"] else: include_files = [] for i, fn in enumerate(include_files): Deleted: /pypy/dist/pypy/translator/llvm/int_list.ll ============================================================================== --- /pypy/dist/pypy/translator/llvm/int_list.ll Thu Jun 9 19:39:40 2005 +++ (empty file) @@ -1,39 +0,0 @@ - - -internal %std.list.int* %std.range(int %length) { -entry: - %tmp.1 = setlt int %length, 1 - %tmp.3 = malloc %std.list.int - %tmp.6 = getelementptr %std.list.int* %tmp.3, int 0, uint 0 - br bool %tmp.1, label %then, label %endif - -then: - store uint 0, uint* %tmp.6 - %tmp.8 = getelementptr %std.list.int* %tmp.3, int 0, uint 1 - store int* null, int** %tmp.8 - ret %std.list.int* %tmp.3 - -endif: - %tmp.15 = cast int %length to uint - store uint %tmp.15, uint* %tmp.6 - %tmp.17 = getelementptr %std.list.int* %tmp.3, int 0, uint 1 - %tmp.18 = malloc int, uint %tmp.15 - store int* %tmp.18, int** %tmp.17 - %tmp.255 = setgt int %length, 0 - br bool %tmp.255, label %no_exit, label %UnifiedReturnBlock - -no_exit: - %indvar = phi uint [ %indvar.next, %no_exit ], [ 0, %endif ] - %i.0.0 = cast uint %indvar to int - %tmp.29 = load int** %tmp.17 - %tmp.31 = getelementptr int* %tmp.29, uint %indvar - store int %i.0.0, int* %tmp.31 - %tmp.34 = add int %i.0.0, 1 - %tmp.25 = setlt int %tmp.34, %length - %indvar.next = add uint %indvar, 1 - br bool %tmp.25, label %no_exit, label %UnifiedReturnBlock - -UnifiedReturnBlock: - %UnifiedRetVal = phi %std.list.int* [ %tmp.3, %endif ], [ %tmp.3, %no_exit ] - ret %std.list.int* %UnifiedRetVal -} Deleted: /pypy/dist/pypy/translator/llvm/intlist.c ============================================================================== --- /pypy/dist/pypy/translator/llvm/intlist.c Thu Jun 9 19:39:40 2005 +++ (empty file) @@ -1,27 +0,0 @@ -/* implementation of range. This file is transformed to int_list.ll by -make_runtime.py */ -#include - -struct list_int { - unsigned int length; - int* data; -}; - -struct list_int* range(int length) { - int i = 0; - if (length <= 0) { - struct list_int* nlist = malloc(sizeof(struct list_int)); - nlist->length = 0; - nlist->data = NULL; - return nlist; - } - struct list_int* nlist = malloc(sizeof(struct list_int)); - nlist->length = length; - nlist->data = malloc(sizeof(int) * length); - while (i < length) { - nlist->data[i] = i; - i += 1; - } - return nlist; -} - Deleted: /pypy/dist/pypy/translator/llvm/list.c ============================================================================== --- /pypy/dist/pypy/translator/llvm/list.c Thu Jun 9 19:39:40 2005 +++ (empty file) @@ -1,188 +0,0 @@ -/* implementation of list methods. This file is transformed to list_template.ll - by make_runtime.py */ -#include - -signed char unwind(); - -struct item { - char* dummy; -}; - -struct class { - char dummy; -}; - - -struct class* LAST_EXCEPTION_TYPE = 0; -struct class INDEX_ERROR = {0}; - - - -struct list { - unsigned int length; - struct item** data; -}; - -void copy(struct item** from, struct item** to, unsigned int length) { - unsigned int i = 0; - while(i < length) { - to[i] = from[i]; - i += 1; - } -} - -int len(struct list* l) { - return (int) l->length; -} - -int valid_index(int i, struct list* l) { - if (i < 0) - return 0; - if (i >= len(l)) - return 0; - return 1; -} - -struct list* newlist() { - struct list* nlist = malloc(sizeof(struct list)); - nlist->length = 0; - nlist->data = NULL; - return nlist; -} - -struct list* alloc_and_set(int length, struct item* init) { - unsigned int i = 0; - struct list* nlist = malloc(sizeof(struct list)); - nlist->length = (unsigned int)length; - nlist->data = malloc(sizeof(struct item*) * length); - while (i < length) { - nlist->data[i] = init; - i += 1; - } - return nlist; -} - -struct item* getitem(struct list* l, int index) { - if (index < 0) - index = l->length + index; - return l->data[index]; -} - -struct item* getitem_EXCEPTION(struct list* l, int index) { - if (index < 0) - index = l->length + index; - if (valid_index(index, l) == 0) { - LAST_EXCEPTION_TYPE = &INDEX_ERROR; - return unwind(); - } - return l->data[index]; -} - -void setitem(struct list* l, int index, struct item* value) { - if (index < 0) - index = l->length + index; - l->data[index] = value; -} - -void setitem_EXCEPTION(struct list* l, int index, struct item* value) { - if (index < 0) - index = l->length + index; - if (valid_index(index, l) == 0) { - LAST_EXCEPTION_TYPE = &INDEX_ERROR; - unwind(); - return; - } - l->data[index] = value; -} - -struct list* add(struct list* a, struct list* b) { - struct list* nlist = malloc(sizeof(struct list)); - unsigned int newlength = a->length + b->length; - nlist->length = newlength; - nlist->data = malloc(sizeof(struct item*) * newlength); - copy(a->data, nlist->data, a->length); - copy(b->data, nlist->data + a->length, newlength - a->length); - return nlist; -} - -struct list* mul(struct list* a, int times) { - struct list* nlist = malloc(sizeof(struct list)); - unsigned int newlength = a->length * times; - int i = 0; - nlist->length = newlength; - nlist->data = malloc(sizeof(struct item*) * newlength); - while (i < times) { - copy(a->data, nlist->data + i * a->length, a->length); - i += 1; - } - return nlist; -} - -struct list* inplace_add(struct list* a, struct list* b) { - struct item** newdata = malloc(sizeof(struct item*) * (a->length + b->length)); - copy(a->data, newdata, a->length); - copy(b->data, newdata + a->length, b->length); - a->length += b->length; - free(a->data); - a->data = newdata; - return a; -} - -void append(struct list* a, struct item* value) { - struct item** newdata = malloc(sizeof(struct item*) * (a->length + 1)); - newdata[a->length] = value; - copy(a->data, newdata, a->length); - a->length += 1; - free(a->data); - a->data = newdata; -} - -struct item* pop(struct list* a, int index) { - if (index < 0) - index = a->length + index; - struct item* ret = a->data[index]; - struct item** newdata = malloc(sizeof(struct item*) * (a->length - 1)); - copy(a->data, newdata, index); - copy(a->data + index + 1, newdata + index, a->length - 1 - index); - a->length -= 1; - free(a->data); - a->data = newdata; - return ret; -} - -struct item* pop_EXCEPTION(struct list* a, int index) { - if (index < 0) - index = a->length + index; - if (valid_index(index, a) == 0) { - LAST_EXCEPTION_TYPE = &INDEX_ERROR; - return unwind(); - } - struct item* ret = a->data[index]; - struct item** newdata = malloc(sizeof(struct item*) * (a->length - 1)); - copy(a->data, newdata, index); - copy(a->data + index + 1, newdata + index, a->length - 1 - index); - a->length -= 1; - free(a->data); - a->data = newdata; - return ret; -} - - -struct item* pop_ALTERNATIVE1(struct list* a) { - return pop(a, a->length - 1); -} - - -void reverse(struct list* a) { - unsigned int lo = 0; - unsigned int hi = a->length - 1; - struct item* temp; - while (lo < hi) { - temp = a->data[lo]; - a->data[lo] = a->data[hi]; - a->data[hi] = temp; - lo += 1; - hi -= 1; - } -} - Deleted: /pypy/dist/pypy/translator/llvm/list_template.ll ============================================================================== --- /pypy/dist/pypy/translator/llvm/list_template.ll Thu Jun 9 19:39:40 2005 +++ (empty file) @@ -1,546 +0,0 @@ - - -internal void %std.copy(%(item)s* %from, %(item)s* %to, uint %length) { -entry: - %tmp.25 = seteq uint %length, 0 - br bool %tmp.25, label %return, label %no_exit - -no_exit: - %i.0.0 = phi uint [ %tmp.14, %no_exit ], [ 0, %entry ] - %tmp.7 = getelementptr %(item)s* %to, uint %i.0.0 - %tmp.11 = getelementptr %(item)s* %from, uint %i.0.0 - %tmp.12 = load %(item)s* %tmp.11 - store %(item)s %tmp.12, %(item)s* %tmp.7 - %tmp.14 = add uint %i.0.0, 1 - %tmp.2 = setlt uint %tmp.14, %length - br bool %tmp.2, label %no_exit, label %return - -return: - ret void -} - -internal int %std.len(%(name)s* %l) { -entry: - %tmp.1 = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.2 = load uint* %tmp.1 - %tmp.3 = cast uint %tmp.2 to int - ret int %tmp.3 -} - -internal int %std.valid_index(int %i, %(name)s* %l) { -entry: - %tmp.1 = setlt int %i, 0 - br bool %tmp.1, label %UnifiedReturnBlock, label %endif.0 - -endif.0: - %tmp.1.i = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.2.i = load uint* %tmp.1.i - %tmp.3.i = cast uint %tmp.2.i to int - %not.tmp.6 = setgt int %tmp.3.i, %i - %retval = cast bool %not.tmp.6 to int - ret int %retval - -UnifiedReturnBlock: - ret int 0 -} - -internal %(name)s* %std.newlist() { -entry: - %tmp.0 = malloc %(name)s - %tmp.3 = getelementptr %(name)s* %tmp.0, int 0, uint 0 - store uint 0, uint* %tmp.3 - %tmp.5 = getelementptr %(name)s* %tmp.0, int 0, uint 1 - store %(item)s* null, %(item)s** %tmp.5 - ret %(name)s* %tmp.0 -} - -internal %(name)s* %std.alloc_and_set(int %length, %(item)s %init) { -entry: - %tmp.0 = malloc %(name)s - %tmp.3 = getelementptr %(name)s* %tmp.0, int 0, uint 0 - %tmp.5 = cast int %length to uint - store uint %tmp.5, uint* %tmp.3 - %tmp.7 = getelementptr %(name)s* %tmp.0, int 0, uint 1 - %tmp.8 = malloc %(item)s, uint %tmp.5 - store %(item)s* %tmp.8, %(item)s** %tmp.7 - %tmp.165 = seteq int %length, 0 - br bool %tmp.165, label %loopexit, label %no_exit - -no_exit: - %i.0.0 = phi uint [ %tmp.26, %no_exit ], [ 0, %entry ] - %tmp.20 = load %(item)s** %tmp.7 - %tmp.23 = getelementptr %(item)s* %tmp.20, uint %i.0.0 - store %(item)s %init, %(item)s* %tmp.23 - %tmp.26 = add uint %i.0.0, 1 - %tmp.16 = setgt uint %tmp.5, %tmp.26 - br bool %tmp.16, label %no_exit, label %loopexit - -loopexit: - ret %(name)s* %tmp.0 -} - -internal %(item)s %std.getitem(%(name)s* %l, int %index.1) { -entry: - %tmp.1 = setlt int %index.1, 0 - %tmp.11 = getelementptr %(name)s* %l, int 0, uint 1 - br bool %tmp.1, label %then, label %endif - -then: - %tmp.4 = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.5 = load uint* %tmp.4 - %tmp.5 = cast uint %tmp.5 to int - %tmp.9 = add int %tmp.5, %index.1 - %tmp.121 = load %(item)s** %tmp.11 - %tmp.142 = getelementptr %(item)s* %tmp.121, int %tmp.9 - %tmp.153 = load %(item)s* %tmp.142 - ret %(item)s %tmp.153 - -endif: - %tmp.12 = load %(item)s** %tmp.11 - %tmp.14 = getelementptr %(item)s* %tmp.12, int %index.1 - %tmp.15 = load %(item)s* %tmp.14 - ret %(item)s %tmp.15 -} - -internal %(item)s %std.getitem.exc(%(name)s* %l, int %index.1) { -entry: - %tmp.1 = setlt int %index.1, 0 - br bool %tmp.1, label %then.0, label %endif.0.i - -then.0: - %tmp.4 = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.5 = load uint* %tmp.4 - %tmp.5 = cast uint %tmp.5 to int - %tmp.9 = add int %tmp.5, %index.1 - %tmp.1.i5 = setlt int %tmp.9, 0 - br bool %tmp.1.i5, label %then.1, label %endif.0.i - -endif.0.i: - %index_addr.0.0 = phi int [ %tmp.9, %then.0 ], [ %index.1, %entry ] - %tmp.1.i.i = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.2.i.i = load uint* %tmp.1.i.i - %tmp.3.i.i = cast uint %tmp.2.i.i to int - %tmp.6.i = setgt int %tmp.3.i.i, %index_addr.0.0 - br bool %tmp.6.i, label %endif.1, label %then.1 - -then.1: - store %std.class* %glb.class.IndexError.object, %std.class** %std.last_exception.type - unwind -endif.1: - %tmp.19 = getelementptr %(name)s* %l, int 0, uint 1 - %tmp.20 = load %(item)s** %tmp.19 - %tmp.22 = getelementptr %(item)s* %tmp.20, int %index_addr.0.0 - %tmp.23 = load %(item)s* %tmp.22 - ret %(item)s %tmp.23 -} - - -internal void %std.setitem(%(name)s* %l, int %index.1, %(item)s %value) { -entry: - %tmp.1 = setlt int %index.1, 0 - %tmp.11 = getelementptr %(name)s* %l, int 0, uint 1 - br bool %tmp.1, label %then, label %endif - -then: - %tmp.4 = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.5 = load uint* %tmp.4 - %tmp.5 = cast uint %tmp.5 to int - %tmp.9 = add int %tmp.5, %index.1 - %tmp.121 = load %(item)s** %tmp.11 - %tmp.142 = getelementptr %(item)s* %tmp.121, int %tmp.9 - store %(item)s %value, %(item)s* %tmp.142 - ret void - -endif: - %tmp.12 = load %(item)s** %tmp.11 - %tmp.14 = getelementptr %(item)s* %tmp.12, int %index.1 - store %(item)s %value, %(item)s* %tmp.14 - ret void -} - -internal void %std.setitem.exc(%(name)s* %l, int %index.1, %(item)s %value) { -entry: - %tmp.1 = setlt int %index.1, 0 - br bool %tmp.1, label %then.0, label %endif.0.i - -then.0: - %tmp.4 = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.5 = load uint* %tmp.4 - %tmp.5 = cast uint %tmp.5 to int - %tmp.9 = add int %tmp.5, %index.1 - %tmp.1.i5 = setlt int %tmp.9, 0 - br bool %tmp.1.i5, label %then.1, label %endif.0.i - -endif.0.i: - %index_addr.0.0 = phi int [ %tmp.9, %then.0 ], [ %index.1, %entry ] - %tmp.1.i.i = getelementptr %(name)s* %l, int 0, uint 0 - %tmp.2.i.i = load uint* %tmp.1.i.i - %tmp.3.i.i = cast uint %tmp.2.i.i to int - %tmp.6.i = setgt int %tmp.3.i.i, %index_addr.0.0 - br bool %tmp.6.i, label %endif.1, label %then.1 - -then.1: - store %std.class* %glb.class.IndexError.object, %std.class** %std.last_exception.type - unwind -endif.1: - %tmp.17 = getelementptr %(name)s* %l, int 0, uint 1 - %tmp.18 = load %(item)s** %tmp.17 - %tmp.20 = getelementptr %(item)s* %tmp.18, int %index_addr.0.0 - store %(item)s %value, %(item)s* %tmp.20 - ret void -} - -internal %(name)s* %std.add(%(name)s* %a, %(name)s* %b) { -entry: - %tmp.0 = malloc %(name)s - %tmp.3 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.4 = load uint* %tmp.3 - %tmp.6 = getelementptr %(name)s* %b, int 0, uint 0 - %tmp.7 = load uint* %tmp.6 - %tmp.8 = add uint %tmp.7, %tmp.4 - %tmp.10 = getelementptr %(name)s* %tmp.0, int 0, uint 0 - store uint %tmp.8, uint* %tmp.10 - %tmp.13 = getelementptr %(name)s* %tmp.0, int 0, uint 1 - %tmp.14 = malloc %(item)s, uint %tmp.8 - store %(item)s* %tmp.14, %(item)s** %tmp.13 - %tmp.19 = getelementptr %(name)s* %a, int 0, uint 1 - %tmp.20 = load %(item)s** %tmp.19 - %tmp.2.i14 = seteq uint %tmp.4, 0 - br bool %tmp.2.i14, label %copy.entry, label %no_exit.i - -no_exit.i: - %i.0.i.0 = phi uint [ %tmp.14.i, %no_exit.i ], [ 0, %entry ] - %tmp.7.i = getelementptr %(item)s* %tmp.14, uint %i.0.i.0 - %tmp.11.i = getelementptr %(item)s* %tmp.20, uint %i.0.i.0 - %tmp.12.i = load %(item)s* %tmp.11.i - store %(item)s %tmp.12.i, %(item)s* %tmp.7.i - %tmp.14.i = add uint %i.0.i.0, 1 - %tmp.2.i = setlt uint %tmp.14.i, %tmp.4 - br bool %tmp.2.i, label %no_exit.i, label %copy.entry - -copy.entry: - %tmp.28 = getelementptr %(name)s* %b, int 0, uint 1 - %tmp.29 = load %(item)s** %tmp.28 - %tmp.42 = sub uint %tmp.8, %tmp.4 - %tmp.2.i319 = seteq uint %tmp.8, %tmp.4 - br bool %tmp.2.i319, label %copy.entry9, label %no_exit.i4 - -no_exit.i4: - %i.0.i2.0 = phi uint [ %tmp.14.i8, %no_exit.i4 ], [ 0, %copy.entry ] - %tmp.37.sum = add uint %i.0.i2.0, %tmp.4 - %tmp.7.i5 = getelementptr %(item)s* %tmp.14, uint %tmp.37.sum - %tmp.11.i6 = getelementptr %(item)s* %tmp.29, uint %i.0.i2.0 - %tmp.12.i7 = load %(item)s* %tmp.11.i6 - store %(item)s %tmp.12.i7, %(item)s* %tmp.7.i5 - %tmp.14.i8 = add uint %i.0.i2.0, 1 - %tmp.2.i3 = setlt uint %tmp.14.i8, %tmp.42 - br bool %tmp.2.i3, label %no_exit.i4, label %copy.entry9 - -copy.entry9: - ret %(name)s* %tmp.0 -} - -internal %(name)s* %std.mul(%(name)s* %a, int %times) { -entry: - %tmp.0 = malloc %(name)s - %tmp.3 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.4 = load uint* %tmp.3 - %tmp.6 = cast int %times to uint - %tmp.7 = mul uint %tmp.4, %tmp.6 - %tmp.9 = getelementptr %(name)s* %tmp.0, int 0, uint 0 - store uint %tmp.7, uint* %tmp.9 - %tmp.12 = getelementptr %(name)s* %tmp.0, int 0, uint 1 - %tmp.13 = malloc %(item)s, uint %tmp.7 - store %(item)s* %tmp.13, %(item)s** %tmp.12 - %tmp.194 = setgt int %times, 0 - br bool %tmp.194, label %no_exit.preheader, label %loopexit - -no_exit.preheader: - %tmp.22 = getelementptr %(name)s* %a, int 0, uint 1 - br label %no_exit - -no_exit: - %indvar = phi uint [ 0, %no_exit.preheader ], [ %indvar.next10, %copy.entry ] - %i.0.0 = cast uint %indvar to int - %tmp.23 = load %(item)s** %tmp.22 - %tmp.26 = load %(item)s** %tmp.12 - %tmp.29 = load uint* %tmp.3 - %tmp.32 = mul uint %indvar, %tmp.29 - %tmp.2.i9 = seteq uint %tmp.29, 0 - br bool %tmp.2.i9, label %copy.entry, label %no_exit.i - -no_exit.i: - %i.0.i.2 = phi uint [ %tmp.14.i, %no_exit.i ], [ 0, %no_exit ] - %tmp.34.sum = add uint %i.0.i.2, %tmp.32 - %tmp.7.i = getelementptr %(item)s* %tmp.26, uint %tmp.34.sum - %tmp.11.i = getelementptr %(item)s* %tmp.23, uint %i.0.i.2 - %tmp.12.i = load %(item)s* %tmp.11.i - store %(item)s %tmp.12.i, %(item)s* %tmp.7.i - %tmp.14.i = add uint %i.0.i.2, 1 - %tmp.2.i = setlt uint %tmp.14.i, %tmp.29 - br bool %tmp.2.i, label %no_exit.i, label %copy.entry - -copy.entry: - %tmp.39 = add int %i.0.0, 1 - %tmp.19 = setlt int %tmp.39, %times - %indvar.next10 = add uint %indvar, 1 - br bool %tmp.19, label %no_exit, label %loopexit - -loopexit: - ret %(name)s* %tmp.0 -} - -internal %(name)s* %std.inplace_add(%(name)s* %a, %(name)s* %b) { -entry: - %tmp.2 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.3 = load uint* %tmp.2 - %tmp.5 = getelementptr %(name)s* %b, int 0, uint 0 - %tmp.6 = load uint* %tmp.5 - %tmp.7 = add uint %tmp.6, %tmp.3 - %tmp.0 = malloc %(item)s, uint %tmp.7 - %tmp.11 = getelementptr %(name)s* %a, int 0, uint 1 - %tmp.12 = load %(item)s** %tmp.11 - %tmp.2.i14 = seteq uint %tmp.3, 0 - br bool %tmp.2.i14, label %copy.entry, label %no_exit.i - -no_exit.i: - %i.0.i.0 = phi uint [ %tmp.14.i, %no_exit.i ], [ 0, %entry ] - %tmp.7.i = getelementptr %(item)s* %tmp.0, uint %i.0.i.0 - %tmp.11.i = getelementptr %(item)s* %tmp.12, uint %i.0.i.0 - %tmp.12.i = load %(item)s* %tmp.11.i - store %(item)s %tmp.12.i, %(item)s* %tmp.7.i - %tmp.14.i = add uint %i.0.i.0, 1 - %tmp.2.i = setlt uint %tmp.14.i, %tmp.3 - br bool %tmp.2.i, label %no_exit.i, label %copy.entry - -copy.entry: - %tmp.18 = getelementptr %(name)s* %b, int 0, uint 1 - %tmp.19 = load %(item)s** %tmp.18 - %tmp.2.i319 = seteq uint %tmp.6, 0 - br bool %tmp.2.i319, label %copy.entry9, label %no_exit.i4 - -no_exit.i4: - %i.0.i2.0 = phi uint [ %tmp.14.i8, %no_exit.i4 ], [ 0, %copy.entry ] - %tmp.25.sum = add uint %i.0.i2.0, %tmp.3 - %tmp.7.i5 = getelementptr %(item)s* %tmp.0, uint %tmp.25.sum - %tmp.11.i6 = getelementptr %(item)s* %tmp.19, uint %i.0.i2.0 - %tmp.12.i7 = load %(item)s* %tmp.11.i6 - store %(item)s %tmp.12.i7, %(item)s* %tmp.7.i5 - %tmp.14.i8 = add uint %i.0.i2.0, 1 - %tmp.2.i3 = setlt uint %tmp.14.i8, %tmp.6 - br bool %tmp.2.i3, label %no_exit.i4, label %copy.entry9 - -copy.entry9: - store uint %tmp.7, uint* %tmp.2 - free %(item)s* %tmp.12 - store %(item)s* %tmp.0, %(item)s** %tmp.11 - ret %(name)s* %a -} - -internal void %std.append(%(name)s* %a, %(item)s %value) { -entry: - %tmp.2 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.3 = load uint* %tmp.2 - %tmp.3-off = add uint %tmp.3, 1 - %tmp.0 = malloc %(item)s, uint %tmp.3-off - %tmp.12 = getelementptr %(item)s* %tmp.0, uint %tmp.3 - store %(item)s %value, %(item)s* %tmp.12 - %tmp.15 = getelementptr %(name)s* %a, int 0, uint 1 - %tmp.16 = load %(item)s** %tmp.15 - %tmp.2.i5 = seteq uint %tmp.3, 0 - br bool %tmp.2.i5, label %copy.entry, label %no_exit.i - -no_exit.i: - %i.0.i.0 = phi uint [ %tmp.14.i, %no_exit.i ], [ 0, %entry ] - %tmp.7.i = getelementptr %(item)s* %tmp.0, uint %i.0.i.0 - %tmp.11.i = getelementptr %(item)s* %tmp.16, uint %i.0.i.0 - %tmp.12.i = load %(item)s* %tmp.11.i - store %(item)s %tmp.12.i, %(item)s* %tmp.7.i - %tmp.14.i = add uint %i.0.i.0, 1 - %tmp.2.i = setlt uint %tmp.14.i, %tmp.3 - br bool %tmp.2.i, label %no_exit.i, label %copy.entry - -copy.entry: - store uint %tmp.3-off, uint* %tmp.2 - free %(item)s* %tmp.16 - store %(item)s* %tmp.0, %(item)s** %tmp.15 - ret void -} - -internal %(item)s %std.pop(%(name)s* %a, int %index.1) { -entry: - %tmp.1 = setlt int %index.1, 0 - br bool %tmp.1, label %then, label %endif - -then: - %tmp.4 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.5 = load uint* %tmp.4 - %tmp.5 = cast uint %tmp.5 to int - %tmp.9 = add int %tmp.5, %index.1 - br label %endif - -endif: - %index_addr.0 = phi int [ %tmp.9, %then ], [ %index.1, %entry ] - %tmp.11 = getelementptr %(name)s* %a, int 0, uint 1 - %tmp.12 = load %(item)s** %tmp.11 - %tmp.14 = getelementptr %(item)s* %tmp.12, int %index_addr.0 - %tmp.15 = load %(item)s* %tmp.14 - %tmp.18 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.19 = load uint* %tmp.18 - %tmp.19-off = add uint %tmp.19, 1073741823 - %tmp.16 = malloc %(item)s, uint %tmp.19-off - %tmp.28 = cast int %index_addr.0 to uint - %tmp.2.i14 = seteq int %index_addr.0, 0 - br bool %tmp.2.i14, label %copy.entry, label %no_exit.i - -no_exit.i: - %i.0.i.0 = phi uint [ %tmp.14.i, %no_exit.i ], [ 0, %endif ] - %tmp.7.i = getelementptr %(item)s* %tmp.16, uint %i.0.i.0 - %tmp.11.i = getelementptr %(item)s* %tmp.12, uint %i.0.i.0 - %tmp.12.i = load %(item)s* %tmp.11.i - store %(item)s %tmp.12.i, %(item)s* %tmp.7.i - %tmp.14.i = add uint %i.0.i.0, 1 - %tmp.2.i = setlt uint %tmp.14.i, %tmp.28 - br bool %tmp.2.i, label %no_exit.i, label %copy.entry - -copy.entry: - %tmp.35.sum = add int %index_addr.0, 1 - %tmp.48 = add uint %tmp.19, 4294967295 - %tmp.49 = sub uint %tmp.48, %tmp.28 - %tmp.2.i319 = seteq uint %tmp.48, %tmp.28 - br bool %tmp.2.i319, label %copy.entry9, label %no_exit.i4 - -no_exit.i4: - %i.0.i2.0 = phi uint [ %tmp.14.i8, %no_exit.i4 ], [ 0, %copy.entry ] - %i.0.i2.020 = cast uint %i.0.i2.0 to int - %tmp.42.sum = add int %i.0.i2.020, %index_addr.0 - %tmp.7.i5 = getelementptr %(item)s* %tmp.16, int %tmp.42.sum - %tmp.37.sum = add int %i.0.i2.020, %tmp.35.sum - %tmp.11.i6 = getelementptr %(item)s* %tmp.12, int %tmp.37.sum - %tmp.12.i7 = load %(item)s* %tmp.11.i6 - store %(item)s %tmp.12.i7, %(item)s* %tmp.7.i5 - %tmp.14.i8 = add uint %i.0.i2.0, 1 - %tmp.2.i3 = setlt uint %tmp.14.i8, %tmp.49 - br bool %tmp.2.i3, label %no_exit.i4, label %copy.entry9 - -copy.entry9: - store uint %tmp.48, uint* %tmp.18 - free %(item)s* %tmp.12 - store %(item)s* %tmp.16, %(item)s** %tmp.11 - ret %(item)s %tmp.15 -} - -internal %(item)s %std.pop.exc(%(name)s* %a, int %index.1) { -entry: - %tmp.1 = setlt int %index.1, 0 - br bool %tmp.1, label %then.0, label %endif.0.i - -then.0: - %tmp.4 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.5 = load uint* %tmp.4 - %tmp.5 = cast uint %tmp.5 to int - %tmp.9 = add int %tmp.5, %index.1 - %tmp.1.i20 = setlt int %tmp.9, 0 - br bool %tmp.1.i20, label %then.1, label %endif.0.i - -endif.0.i: - %index_addr.0.0 = phi int [ %tmp.9, %then.0 ], [ %index.1, %entry ] - %tmp.1.i.i = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.2.i.i = load uint* %tmp.1.i.i - %tmp.3.i.i = cast uint %tmp.2.i.i to int - %tmp.6.i = setgt int %tmp.3.i.i, %index_addr.0.0 - br bool %tmp.6.i, label %endif.1, label %then.1 - -then.1: - store %std.class* %glb.class.IndexError.object, %std.class** %std.last_exception.type - unwind -endif.1: - %tmp.19 = getelementptr %(name)s* %a, int 0, uint 1 - %tmp.20 = load %(item)s** %tmp.19 - %tmp.22 = getelementptr %(item)s* %tmp.20, int %index_addr.0.0 - %tmp.23 = load %(item)s* %tmp.22 - %tmp.27-off = add uint %tmp.2.i.i, 1073741823 - %tmp.24 = malloc %(item)s, uint %tmp.27-off - %tmp.36 = cast int %index_addr.0.0 to uint - %tmp.2.i526 = seteq int %index_addr.0.0, 0 - br bool %tmp.2.i526, label %copy.entry12, label %no_exit.i6 - -no_exit.i6: - %i.0.i4.0 = phi uint [ %tmp.14.i10, %no_exit.i6 ], [ 0, %endif.1 ] - %tmp.7.i7 = getelementptr %(item)s* %tmp.24, uint %i.0.i4.0 - %tmp.11.i8 = getelementptr %(item)s* %tmp.20, uint %i.0.i4.0 - %tmp.12.i9 = load %(item)s* %tmp.11.i8 - store %(item)s %tmp.12.i9, %(item)s* %tmp.7.i7 - %tmp.14.i10 = add uint %i.0.i4.0, 1 - %tmp.2.i5 = setlt uint %tmp.14.i10, %tmp.36 - br bool %tmp.2.i5, label %no_exit.i6, label %copy.entry12 - -copy.entry12: - %tmp.43.sum = add int %index_addr.0.0, 1 - %tmp.56 = add uint %tmp.2.i.i, 4294967295 - %tmp.57 = sub uint %tmp.56, %tmp.36 - %tmp.2.i31 = seteq uint %tmp.56, %tmp.36 - br bool %tmp.2.i31, label %copy.entry, label %no_exit.i - -no_exit.i: - %i.0.i.0 = phi uint [ %tmp.14.i, %no_exit.i ], [ 0, %copy.entry12 ] - %i.0.i.032 = cast uint %i.0.i.0 to int - %tmp.50.sum = add int %i.0.i.032, %index_addr.0.0 - %tmp.7.i = getelementptr %(item)s* %tmp.24, int %tmp.50.sum - %tmp.45.sum = add int %i.0.i.032, %tmp.43.sum - %tmp.11.i = getelementptr %(item)s* %tmp.20, int %tmp.45.sum - %tmp.12.i = load %(item)s* %tmp.11.i - store %(item)s %tmp.12.i, %(item)s* %tmp.7.i - %tmp.14.i = add uint %i.0.i.0, 1 - %tmp.2.i = setlt uint %tmp.14.i, %tmp.57 - br bool %tmp.2.i, label %no_exit.i, label %copy.entry - -copy.entry: - store uint %tmp.56, uint* %tmp.1.i.i - free %(item)s* %tmp.20 - store %(item)s* %tmp.24, %(item)s** %tmp.19 - ret %(item)s %tmp.23 -} - -internal %(item)s %std.pop(%(name)s* %a) { -entry: - %tmp.3 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.4 = load uint* %tmp.3 - %tmp.4 = cast uint %tmp.4 to int - %tmp.6 = add int %tmp.4, -1 - %tmp.0 = call %(item)s %std.pop( %(name)s* %a, int %tmp.6 ) - ret %(item)s %tmp.0 -} - -internal void %std.reverse(%(name)s* %a) { -entry: - %tmp.1 = getelementptr %(name)s* %a, int 0, uint 0 - %tmp.2 = load uint* %tmp.1 - %tmp.610 = seteq uint %tmp.2, 1 - br bool %tmp.610, label %return, label %no_exit.preheader - -no_exit.preheader: - %tmp.9 = getelementptr %(name)s* %a, int 0, uint 1 - br label %no_exit - -no_exit: - %lo.0.0 = phi uint [ 0, %no_exit.preheader ], [ %tmp.36, %no_exit ] - %tmp. = add uint %tmp.2, 4294967295 - %hi.0.0 = sub uint %tmp., %lo.0.0 - %tmp.10 = load %(item)s** %tmp.9 - %tmp.13 = getelementptr %(item)s* %tmp.10, uint %lo.0.0 - %tmp.14 = load %(item)s* %tmp.13 - %tmp.26 = getelementptr %(item)s* %tmp.10, uint %hi.0.0 - %tmp.27 = load %(item)s* %tmp.26 - store %(item)s %tmp.27, %(item)s* %tmp.13 - %tmp.30 = load %(item)s** %tmp.9 - %tmp.33 = getelementptr %(item)s* %tmp.30, uint %hi.0.0 - store %(item)s %tmp.14, %(item)s* %tmp.33 - %tmp.36 = add uint %lo.0.0, 1 - %hi.0 = add uint %hi.0.0, 4294967295 - %tmp.6 = setlt uint %tmp.36, %hi.0 - br bool %tmp.6, label %no_exit, label %return - -return: - ret void -} Deleted: /pypy/dist/pypy/translator/llvm/make_runtime.py ============================================================================== --- /pypy/dist/pypy/translator/llvm/make_runtime.py Thu Jun 9 19:39:40 2005 +++ (empty file) @@ -1,274 +0,0 @@ -""" -This file produces the .ll files with the implementations of lists and the -implementations of simple space operations (like add, mul, sub, div for float, -bool, int). -""" - -import autopath - -import os -from pypy.tool.udir import udir -from py.process import cmdexec -from py import path - -def get_llvm_code(cfile): - include_dir = autopath.this_dir - print "include_dir", include_dir - cfile = include_dir + "/" + cfile - print cfile - bytecode = udir.join("temp.bc") - lastdir = path.local() - ops = ["llvm-gcc -enable-correct-eh-support-O3 -c %s -o %s" % \ - (cfile, bytecode), "llvm-dis %s -f" % bytecode] - for op in ops: - print op - cmdexec(op) - f = udir.join("temp.ll").open("r") - return f.read() - -def remove_comments(code): - ret = [] - for line in code.split("\n"): - line = line.split(";") - ret.append(line[0].rstrip()) - return "\n".join(ret) - -def add_std(code): - with_std = [] - functions = [] - for line in code.split("\n"): - if "{" in line and "(" in line and ")" in line: - s1 = line.split("(") - s2 = s1[0].split("%") - functions.append(s2[-1]) - s2[-1] = "std." + s2[-1] - s2 = "%".join(s2) - s1[0] = s2 - with_std.append("(".join(s1)) - else: - with_std.append(line) - ret = [] - for line in with_std: - if "call" in line: - for f in functions: - if f in line: - line = line.replace(f, "std." + f) - ret.append(line) - break - else: - ret.append(line) - else: - ret.append(line) - return "\n".join(ret) - -def remove_alternatives(code): - for i in range(1, 10): - code = code.replace("_ALTERNATIVE%i" % i, "") - return code - -def create_exceptions(code): - code = code.replace("%LAST_EXCEPTION_TYPE", "%std.last_exception.type") - code = code.replace("%INDEX_ERROR", "%glb.class.IndexError.object") - return code - -def remove_exception(code): - code = code.replace("_EXCEPTION", ".exc") - return code - -def remove_header(code): - code = code.split("implementation") - return code[1] - -def internal_functions(code): - ret = [] - for line in code.split("\n"): - if "{" in line and "(" in line and ")" in line: - ret.append("internal " + line) - else: - ret.append(line) - return "\n".join(ret) - -def create_unwind(code): - ret = [] - remove = False - for line in code.split("\n"): - if "call" in line and "%unwind(" in line: - ret.append("\tunwind") - remove = True - elif "declare" in line and "unwind" in line: - pass - elif remove: - if not line.startswith("\t") and ":" in line: - remove = False - ret.append(line) - else: - ret.append(line) - return "\n".join(ret) - -def remove_structs(code): - code = code.replace("struct.class", "std.class") - return code - -def cleanup_code(code): - code = remove_comments(code) - code = add_std(code) - code = remove_header(code) - code = internal_functions(code) - code = remove_alternatives(code) - code = create_exceptions(code) - code = remove_exception(code) - code = remove_structs(code) - code = create_unwind(code) - return code - -def make_list_template(): - code = get_llvm_code("list.c") - code = cleanup_code(code) - code = code.replace("%struct.list", "%(name)s") - code = code.replace("%struct.item*", "%(item)s") - f = open(autopath.this_dir + "/list_template.ll", "w") - print (autopath.this_dir + "/list_template.ll") - f.write(code) - f.close() - -def make_int_list(): - code = get_llvm_code("intlist.c") - code = cleanup_code(code) - code = code.replace("struct.list_int", "std.list.int") - f = open(autopath.this_dir + "/int_list.ll", "w") - print (autopath.this_dir + "/int_list.ll") - f.write(code) - f.close() - -MAP_ARITHM_OPS = [("add", ("add", None, None)), - ("inplace_add", ("add", None, None)), - ("sub", ("sub", None, None)), - ("inplace_sub", ("sub", None, None)), - ("mul", ("mul", None, None)), - ("inplace_mul", ("mul", None, None)), - ("div", ("div", None, None)), - ("inplace_div", ("div", None, None)), - ("floordiv", ("div", "int", None)), - ("inplace_floordiv", ("div", "int", None)), - ("truediv", ("div", "double", "double")), - ("inplace_truediv", ("div", "double", "double")), - ("mod", ("rem", None, None)), - ("inplace_mod", ("rem", None, None)) - ] - -MAP_LOGICAL_OPS = [("and_", ("and", None, None)), - ("inplace_and", ("and", None, None)), - ("or_", ("or", None, None)), - ("inplace_or", ("or", None, None)), - ("xor", ("xor", None, None)), - ("inplace_xor", ("xor", None, None)) - ] - -MAP_COMPAR_OPS = [("is_", "seteq"), - ("eq", "seteq"), - ("lt", "setlt"), - ("le", "setle"), - ("ge", "setge"), - ("gt", "setgt")] - -types = ((0, "double"), (1, "uint"), (2, "int"), (3, "bool")) - -def make_binary_ops(): - code = ["implementation\n"] - def normalize_type(t1, t, var): - if t1 != t: - code.append("\t%%%s = cast %s %%%s to %s\n" % (var, t1, var, t)) - for type1 in types: - for type2 in types: - #Arithmetic operators - for op, (llvmop, calctype, rettype) in MAP_ARITHM_OPS: - if calctype is None: - calctype = min(type1, type2)[1] - if rettype is None: - rettype = min(type1, type2)[1] - if calctype == "bool": - calctype = rettype = "int" - code.append("internal %s %%std.%s(%s %%a, %s %%b) {\n" % - (rettype, op, type1[1], type2[1])) - normalize_type(type1[1], calctype, "a") - normalize_type(type2[1], calctype, "b") - code.append("\t%%r = %s %s %%a, %%b\n" % - (llvmop, calctype)) - normalize_type(calctype, rettype, "r") - code.append("\tret %s %%r\n}\n\n" % rettype) - calctype = min(type1, type2)[1] - #Comparison operators - for op, llvmop in MAP_COMPAR_OPS: - code.append("internal bool %%std.%s(%s %%a, %s %%b) {\n" % - (op, type1[1], type2[1])) - normalize_type(type1[1], calctype, "a") - normalize_type(type2[1], calctype, "b") - code.append("\t%%r = %s %s %%a, %%b\n" % - (llvmop, calctype)) - code.append("\tret bool %r\n}\n\n") - code.append("internal bool %%std.neq(%s %%a, %s %%b) {\n" % - (type1[1], type2[1])) - normalize_type(type1[1], calctype, "a") - normalize_type(type2[1], calctype, "b") - code.append("\t%%r = %s %s %%a, %%b\n" % - (llvmop, calctype)) - code.append("\t%r1 = xor bool %r, true\n\tret bool %r1\n}\n\n") - #Logical operators - for type1 in types[1:]: - for type2 in types[1:]: - for op, (llvmop, calctype, rettype) in MAP_LOGICAL_OPS: - if calctype is None: - calctype = min(type1, type2)[1] - if rettype is None: - rettype = min(type1, type2)[1] - code.append("internal %s %%std.%s(%s %%a, %s %%b) {\n" % - (rettype, op, type1[1], type2[1])) - normalize_type(type1[1], calctype, "a") - normalize_type(type2[1], calctype, "b") - code.append("\t%%r = %s %s %%a, %%b\n" % - (llvmop, calctype)) - normalize_type(calctype, rettype, "r") - code.append("\tret %s %%r\n}\n\n" % rettype) - #Shift - for type1 in types[1:-1]: - for type2 in types[1:-1]: - for op, llvmop in (("lshift", "shl"), ("rshift", "shr")): - code.append("internal %s %%std.%s(%s %%a, %s %%b) {\n" % - (type1[1], op, type1[1], type2[1])) - code.append("\t%%b = cast %s %%b to ubyte\n" % type2[1]) - code.append("\t%%r = %s %s %%a, ubyte %%b\n" % - (llvmop, type1[1])) - code.append("\tret %s %%r\n}\n\n" % type1[1]) - return code - -def make_unary_ops(): - code = [] - def normalize_type(t1, t, var): - if t1 != t: - code.append("\t%%%s = cast %s %%%s to %s\n" % (var, t1, var, t)) - for type1 in types: - #"casts" int, bool - for type2 in ("int", "bool"): - code.append("internal %s %%std.%s(%s %%a) {\n" % - (type2, type2, type1[1])) - code.append("\t%%r = cast %s %%a to %s\n" % (type1[1], type2)) - code.append("\tret %s %%r\n}\n\n" % type2) - #is_true - code.append("internal bool %%std.is_true(%s %%a) {\n" % type1[1]) - code.append("\t%%r = cast %s %%a to bool\n" % type1[1]) - code.append("\tret bool %r\n}\n\n") - return code - - -def make_operations(): - code = make_binary_ops() - code += make_unary_ops() - f = open(autopath.this_dir + "/operations.ll", "w") - f.write("".join(code)) - f.close() - -if __name__ == '__main__': - make_operations() - make_list_template() - make_int_list() - From pedronis at codespeak.net Thu Jun 9 20:26:56 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 9 Jun 2005 20:26:56 +0200 (CEST) Subject: [pypy-svn] r13238 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050609182656.A921F27B55@code1.codespeak.net> Author: pedronis Date: Thu Jun 9 20:26:52 2005 New Revision: 13238 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/rpython/test/test_lltype.py Log: support in lltype and annotation for low-level arrays of non-container types Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 9 20:26:52 2005 @@ -519,7 +519,7 @@ return SomeImpossibleValue() # annotation of low-level types -from pypy.annotation.model import SomePtr, ll_to_annotation +from pypy.annotation.model import SomePtr, ll_to_annotation, annotation_to_lltype class __extend__(pairtype(SomePtr, SomePtr)): def union((p1, p2)): @@ -533,6 +533,10 @@ v = p.ll_ptrtype._example()[0] return ll_to_annotation(v) + def setitem((p, int1), s_value): + v_lltype = annotation_to_lltype(s_value) + p.ll_ptrtype._example()[0] = v_lltype._defl() + class __extend__(pairtype(SomePtr, SomeObject)): def union((p, obj)): assert False, ("mixing pointer type %r with something else %r" % (p.ll_ptrtype, obj)) @@ -541,7 +545,7 @@ assert False,"ptr %r getitem index not an int: %r" % (p.ll_ptrtype, obj) def settitem((p, obj)): - assert False,"ptr setitem is not a valid operation" + assert False,"ptr setitem with index is not a valid operation" class __extend__(pairtype(SomeObject, SomePtr)): def union((obj, p2)): Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Thu Jun 9 20:26:52 2005 @@ -113,7 +113,7 @@ def _inline_is_varsize(self, last): if self._arrayfld: raise TypeError("cannot inline a var-sized struct " - "inside another struct") + "inside another container") return False def __getattr__(self, name): @@ -147,19 +147,37 @@ class Array(ContainerType): __name__ = 'array' + _anonym_struct = False + def __init__(self, *fields): - self.OF = Struct("", *fields) - if self.OF._arrayfld is not None: - raise TypeError("array cannot contain an inlined array") + if len(fields) == 1 and isinstance(fields[0], LowLevelType): + self.OF = fields[0] + else: + self.OF = Struct("", *fields) + self._anonym_struct = True + if isinstance(self.OF, GcStruct): + raise TypeError("cannot have a GC structure as array item type") + self.OF._inline_is_varsize(False) def _inline_is_varsize(self, last): if not last: - raise TypeError("array field must be last") + raise TypeError("cannot inline an array in another container" + " unless as the last field of a structure") return True + def _str_fields(self): + if isinstance(self.OF, Struct): + of = self.OF + if self._anonym_struct: + return "{ %s }" % of._str_fields() + else: + return "%s { %s }" % (of._name, of._str_fields()) + else: + return self.OF + def __str__(self): - return "%s of { %s }" % (self.__class__.__name__, - self.OF._str_fields(),) + return "%s of %s " % (self.__class__.__name__, + self._str_fields(),) def _container_example(self): return _array(self, 1) @@ -430,7 +448,18 @@ def __setitem__(self, i, val): # ! not allowed ! if isinstance(self._T, Array): - raise TypeError("cannot directly assign to array items") + T1 = self._T.OF + if isinstance(T1, ContainerType): + raise TypeError("cannot directly assign to container array items") + T2 = typeOf(val) + if T2 != T1: + raise TypeError("%r items:\n" + "expect %r\n" + " got %r" % (self._T, T1, T2)) + if not (0 <= i < len(self._obj.items)): + raise IndexError("array index out of bounds") + self._obj.items[i] = val + return raise TypeError("%r instance is not an array" % (self._T,)) def __len__(self): @@ -539,8 +568,18 @@ def __repr__(self): return '<%s>' % (self,) + def _str_item(self, item): + if isinstance(self._TYPE.OF, Struct): + of = self._TYPE.OF + if self._TYPE._anonym_struct: + return "{%s}" % item._str_fields() + else: + return "%s {%s}" % (of._name, item._str_fields()) + else: + return item + def __str__(self): - return 'array [ %s ]' % (', '.join(['{%s}' % item._str_fields() + return 'array [ %s ]' % (', '.join(['%s' % self._str_item(item) for item in self.items]),) class _func(object): Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Thu Jun 9 20:26:52 2005 @@ -34,6 +34,25 @@ a = self.RPythonAnnotator() s = a.build_types(llf, []) assert s.knowntype == int + + def test_prim_array(self): + A = GcArray(Signed) + def llf(): + a = malloc(A, 1) + return a[0] + a = self.RPythonAnnotator() + s = a.build_types(llf, []) + assert s.knowntype == int + + def test_prim_array_setitem(self): + A = GcArray(Signed) + def llf(): + a = malloc(A, 1) + a[0] = 3 + return a[0] + a = self.RPythonAnnotator() + s = a.build_types(llf, []) + assert s.knowntype == int def test_cast_parent(self): S2 = Struct("s2", ('a', Signed)) Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Thu Jun 9 20:26:52 2005 @@ -250,3 +250,28 @@ assert S1 == S assert S == S1 assert hash(S1) == hash(S) + +def test_array_with_non_container_elements(): + As = GcArray(Signed) + a = malloc(As, 3) + assert typeOf(a) == Ptr(As) + assert a[0] == 0 + assert a[1] == 0 + assert a[2] == 0 + a[1] = 3 + assert a[1] == 3 + S = GcStruct('s', ('x', Signed)) + s = malloc(S) + py.test.raises(TypeError, "a[1] = s") + S = GcStruct('s', ('x', Signed)) + py.test.raises(TypeError, "Array(S)") + py.test.raises(TypeError, "Array(As)") + S = Struct('s', ('x', Signed)) + A = Array(S) + a = malloc(A, 2) + s = S._container_example() # should not happen anyway + py.test.raises(TypeError, "a[0] = s") + S = Struct('s', ('last', A)) + py.test.raises(TypeError, "Array(S)") + + From pedronis at codespeak.net Thu Jun 9 20:32:14 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 9 Jun 2005 20:32:14 +0200 (CEST) Subject: [pypy-svn] r13239 - pypy/dist/pypy/annotation Message-ID: <20050609183214.B430327B55@code1.codespeak.net> Author: pedronis Date: Thu Jun 9 20:32:12 2005 New Revision: 13239 Modified: pypy/dist/pypy/annotation/binaryop.py Log: oops, more meaningful error msg Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 9 20:32:12 2005 @@ -545,7 +545,7 @@ assert False,"ptr %r getitem index not an int: %r" % (p.ll_ptrtype, obj) def settitem((p, obj)): - assert False,"ptr setitem with index is not a valid operation" + assert False,"ptr %r setitem index not an int: %r" % (p.ll_ptrtype, obj) class __extend__(pairtype(SomeObject, SomePtr)): def union((obj, p2)): From arigo at codespeak.net Thu Jun 9 20:51:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 20:51:18 +0200 (CEST) Subject: [pypy-svn] r13240 - in pypy/dist/pypy: documentation rpython rpython/test Message-ID: <20050609185118.B473227B55@code1.codespeak.net> Author: arigo Date: Thu Jun 9 20:51:15 2005 New Revision: 13240 Modified: pypy/dist/pypy/documentation/translation.txt pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py Log: Documentation: Arrays can now be of any primitive or pointer type too. Make malloc() of a non-GC struct or array complain, unless the immortal flag is specified. Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Thu Jun 9 20:51:15 2005 @@ -604,10 +604,15 @@ An array type is built as an instance of ``pypy.rpython.lltype.Array``:: + MyIntArray = Array(Signed) + MyOtherArray = Array(MyItemType) + MyOtherArray = GcArray(MyItemType) + +Or, for arrays whose items are structures, as a shortcut:: + MyArrayType = Array(('field1', Type1), ('field2', Type2)...) - MyArrayType = GcArray(('field1', Type1), ('field2', Type2)...) -The items of an array are always structures; the arguments to Array() give the fields of these structures (it can of course be a single field). The allowed field types follow the same rules as for Struct(), except that you cannot inline an array into the items' structure. +You can build arrays whose items are either primitive or pointer types, or (non-GC non-varsize) structures. GcArrays can be malloc()ed. The length must be specified when malloc() is called, and arrays cannot be resized; this length is stored explicitely in a header. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Thu Jun 9 20:51:15 2005 @@ -624,6 +624,8 @@ o = _array(T, n) else: raise TypeError, "malloc for Structs and Arrays only" + if not isinstance(T, GC_CONTAINER) and not immortal: + raise TypeError, "malloc of a non-GC non-immortal structure" return _ptr(Ptr(T), o, immortal) def functionptr(TYPE, name, **attrs): Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Thu Jun 9 20:51:15 2005 @@ -267,11 +267,11 @@ py.test.raises(TypeError, "Array(S)") py.test.raises(TypeError, "Array(As)") S = Struct('s', ('x', Signed)) - A = Array(S) + A = GcArray(S) a = malloc(A, 2) s = S._container_example() # should not happen anyway py.test.raises(TypeError, "a[0] = s") - S = Struct('s', ('last', A)) + S = Struct('s', ('last', Array(S))) py.test.raises(TypeError, "Array(S)") From ericvrp at codespeak.net Thu Jun 9 21:07:02 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Thu, 9 Jun 2005 21:07:02 +0200 (CEST) Subject: [pypy-svn] r13241 - pypy/dist/pypy/translator/llvm/test Message-ID: <20050609190702.982F727B53@code1.codespeak.net> Author: ericvrp Date: Thu Jun 9 21:07:01 2005 New Revision: 13241 Modified: pypy/dist/pypy/translator/llvm/test/test_snippet.py Log: enabled 10 (out of 16) tests again because they no longer fail Modified: pypy/dist/pypy/translator/llvm/test/test_snippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_snippet.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_snippet.py Thu Jun 9 21:07:01 2005 @@ -14,7 +14,6 @@ class TestSnippet(object): def setup_method(self, method): - py.test.skip("nothing works for now") if not llvm_found: py.test.skip("llvm-as not found on path.") @@ -41,10 +40,12 @@ assert f(0) == 0 def test_two_plus_two(self): + py.test.skip("two_plus_two not working yet") f = compile_function(test.two_plus_two, []) assert f() == 4 def test_sieve_of_eratosthenes(self): + py.test.skip("sieve_of_eratosthenes not working yet") f = compile_function(test.sieve_of_eratosthenes, []) assert f() == 1028 @@ -76,6 +77,7 @@ assert factorial(5) == 120 def test_set_attr(self): + py.test.skip("set_attr not working yet") set_attr = compile_function(test.set_attr, []) assert set_attr() == 2 @@ -85,14 +87,17 @@ assert try_raise_choose(i) == i def test_merge_setattr(self): + py.test.skip("merge_setattr not working yet") merge_setattr = compile_function(test.merge_setattr, [bool]) assert merge_setattr(1) == 1 def test_simple_method(self): + py.test.skip("simple_method not working yet") simple_method = compile_function(test.simple_method, [int]) assert simple_method(65) == 65 def test_with_init(self): + py.test.skip("with_init not working yet") with_init = compile_function(test.with_init, [int]) assert with_init(42) == 42 From arigo at codespeak.net Thu Jun 9 22:19:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:19:20 +0200 (CEST) Subject: [pypy-svn] r13242 - in pypy: branch/translator-without-old-genc/c branch/translator-without-old-genc/c/test dist/pypy/rpython Message-ID: <20050609201920.3B91B27B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:19:15 2005 New Revision: 13242 Modified: pypy/branch/translator-without-old-genc/c/funcgen.py pypy/branch/translator-without-old-genc/c/node.py pypy/branch/translator-without-old-genc/c/test/test_database.py pypy/branch/translator-without-old-genc/c/test/test_genc.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rstr.py Log: Support for array of primitives in rtyper and genc. Fix bugs thus discovered in node.py. This change breaks tests in the svn head. Working on merging now... Modified: pypy/branch/translator-without-old-genc/c/funcgen.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/funcgen.py (original) +++ pypy/branch/translator-without-old-genc/c/funcgen.py Thu Jun 9 22:19:15 2005 @@ -313,35 +313,24 @@ r, args[0], ', '.join(args[1:]), err) # low-level operations - def OP_GETFIELD(self, op, err, ampersand=''): - assert isinstance(op.args[1], Constant) - STRUCT = self.lltypemap[op.args[0]].TO - structdef = self.db.gettypedefnode(STRUCT) - fieldname = structdef.c_struct_field_name(op.args[1].value) + def generic_get(self, op, sourceexpr): newvalue = self.expr(op.result) - result = ['%s = %s%s->%s;' % (newvalue, - ampersand, - self.expr(op.args[0]), - fieldname)] + result = ['%s = %s;' % (newvalue, sourceexpr)] # need to adjust the refcount of the result T = self.lltypemap[op.result] increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: result.append(increfstmt) - return '\t'.join(result) + result = '\t'.join(result) + if T == Void: + result = '/* %s */' % result + return result - def OP_SETFIELD(self, op, err): - assert isinstance(op.args[1], Constant) - STRUCT = self.lltypemap[op.args[0]].TO - structdef = self.db.gettypedefnode(STRUCT) - fieldname = structdef.c_struct_field_name(op.args[1].value) - oldvalue = '%s->%s' % (self.expr(op.args[0]), - fieldname) + def generic_set(self, op, targetexpr): newvalue = self.expr(op.args[2]) - result = ['%s = %s;' % (oldvalue, newvalue)] - + result = ['%s = %s;' % (targetexpr, newvalue)] # need to adjust some refcounts - T = structdef.c_struct_field_type(op.args[1].value) + T = self.lltypemap[op.args[2]] decrefstmt = self.db.cdecrefstmt('prev', T) increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: @@ -349,23 +338,51 @@ if decrefstmt: result.insert(0, '{ %s = %s;' % ( cdecl(self.typemap[op.args[2]], 'prev'), - oldvalue)) + targetexpr)) result.append(decrefstmt) result.append('}') - return '\t'.join(result) + result = '\t'.join(result) + if T == Void: + result = '/* %s */' % result + return result + + def OP_GETFIELD(self, op, err, ampersand=''): + assert isinstance(op.args[1], Constant) + STRUCT = self.lltypemap[op.args[0]].TO + structdef = self.db.gettypedefnode(STRUCT) + fieldname = structdef.c_struct_field_name(op.args[1].value) + return self.generic_get(op, '%s%s->%s' % (ampersand, + self.expr(op.args[0]), + fieldname)) + + def OP_SETFIELD(self, op, err): + assert isinstance(op.args[1], Constant) + STRUCT = self.lltypemap[op.args[0]].TO + structdef = self.db.gettypedefnode(STRUCT) + fieldname = structdef.c_struct_field_name(op.args[1].value) + return self.generic_set(op, '%s->%s' % (self.expr(op.args[0]), + fieldname)) def OP_GETSUBSTRUCT(self, op, err): return self.OP_GETFIELD(op, err, ampersand='&') + def OP_GETARRAYSIZE(self, op, err): + return '%s = %s->length;' % (self.expr(op.result), + self.expr(op.args[0])) + def OP_GETARRAYITEM(self, op, err): + return self.generic_get(op, '%s->items[%s]' % (self.expr(op.args[0]), + self.expr(op.args[1]))) + + def OP_SETARRAYITEM(self, op, err): + return self.generic_set(op, '%s->items[%s]' % (self.expr(op.args[0]), + self.expr(op.args[1]))) + + def OP_GETARRAYSUBSTRUCT(self, op, err): return '%s = %s->items + %s;' % (self.expr(op.result), self.expr(op.args[0]), self.expr(op.args[1])) - def OP_GETARRAYSIZE(self, op, err): - return '%s = %s->length;' % (self.expr(op.result), - self.expr(op.args[0])) - def OP_PTR_NONZERO(self, op, err): return '%s = (%s != NULL);' % (self.expr(op.result), self.expr(op.args[0])) @@ -405,9 +422,12 @@ itemtypename = self.db.gettype(TYPE.OF) elength = self.expr(op.args[1]) eresult = self.expr(op.result) - size = 'sizeof(%s)+((%s-1)*sizeof(%s))' % (cdecl(typename, ''), - elength, - cdecl(itemtypename, '')) + if TYPE.OF == Void: # strange + size = 'sizeof(%s)' % (cdecl(typename, ''),) + else: + size = 'sizeof(%s)+((%s-1)*sizeof(%s))' % (cdecl(typename, ''), + elength, + cdecl(itemtypename, '')) result = ['OP_ZERO_MALLOC(%s, %s, %s)' % (size, eresult, err), Modified: pypy/branch/translator-without-old-genc/c/node.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/node.py (original) +++ pypy/branch/translator-without-old-genc/c/node.py Thu Jun 9 22:19:15 2005 @@ -93,16 +93,11 @@ STRUCT = self.STRUCT for name in STRUCT._names: FIELD_T = self.c_struct_field_type(name) - if isinstance(FIELD_T, Ptr) and FIELD_T._needsgc(): - cname = self.c_struct_field_name(name) - line = self.db.cdecrefstmt('%s%s' % (prefix, cname), FIELD_T) - if line: - yield line - elif isinstance(FIELD_T, ContainerType): - defnode = self.db.gettypedefnode(FIELD_T) - cname = self.c_struct_field_name(name) - for line in defnode.deallocator_lines('%s%s.' %(prefix, cname)): - yield line + cname = self.c_struct_field_name(name) + for line in generic_dealloc(self.db, + '%s%s' % (prefix, cname), + FIELD_T): + yield line class ArrayDefNode: @@ -125,7 +120,7 @@ basename = '%s_len%d' % (basename, varlength) self.name = db.namespace.uniquename(basename) self.dependencies = {} - self.structname = db.gettype(ARRAY.OF, who_asks=self) + self.itemtypename = db.gettype(ARRAY.OF, who_asks=self) # look up the reference counter field if needs_refcount(ARRAY): @@ -144,7 +139,10 @@ if needs_refcount(self.ARRAY): yield '\tlong refcount;' yield '\tlong length;' - yield '\t%s;' % cdecl(self.structname, 'items[%d]' % self.varlength) + line = '%s;' % cdecl(self.itemtypename, 'items[%d]'% self.varlength) + if self.ARRAY.OF == Void: # strange + line = '/* %s */' % line + yield '\t' + line yield '};' elif phase == 2 and self.deallocator: yield 'void %s(struct %s *a) {' % (self.deallocator, self.name) @@ -155,18 +153,22 @@ def deallocator_lines(self, prefix): ARRAY = self.ARRAY - defnode = self.db.gettypedefnode(ARRAY.OF) - varname = 'p%d' % len(prefix) - body = list(defnode.deallocator_lines('%s->' % varname)) + # we need a unique name for this C variable, or at least one that does + # not collide with the expression in 'prefix' + i = 0 + varname = 'p0' + while prefix.find(varname) >= 0: + i += 1 + varname = 'p%d' % i + body = list(generic_dealloc(self.db, '(*%s)' % varname, ARRAY.OF)) if body: yield '{' - yield '\tstruct %s *%s = %sitems;' % (defnode.name, - varname, - prefix) - yield '\tstruct %s *%s_end = %s + %slength;' % (defnode.name, - varname, - varname, - prefix) + yield '\t%s = %sitems;' % (cdecl(self.itemtypename, '*' + varname), + prefix) + yield '\t%s = %s + %slength;' % (cdecl(self.itemtypename, + '*%s_end' % varname), + varname, + prefix) yield '\twhile (%s != %s_end) {' % (varname, varname) for line in body: yield '\t\t' + line @@ -174,6 +176,17 @@ yield '\t}' yield '}' + +def generic_dealloc(db, expr, T): + if isinstance(T, Ptr) and T._needsgc(): + line = db.cdecrefstmt(expr, T) + if line: + yield line + elif isinstance(T, ContainerType): + defnode = db.gettypedefnode(T) + for line in defnode.deallocator_lines('%s.' % expr): + yield line + # ____________________________________________________________ @@ -232,37 +245,17 @@ array = getattr(self.obj, self.T._arrayfld) return len(array.items) - def c_struct_field_name(self, fieldname): - defnode = self.db.gettypedefnode(self.T) - return defnode.c_struct_field_name(fieldname) - - def initializationexpr(self, prefix=''): + def initializationexpr(self, decoration=''): yield '{' if needs_refcount(self.T): yield '\t1,' + defnode = self.db.gettypedefnode(self.T) for name in self.T._names: value = getattr(self.obj, name) - if isinstance(typeOf(value), ContainerType): - node = self.db.getcontainernode(value) - expr = '\n'.join(node.initializationexpr(prefix+name+'.')) - expr += ',' - else: - comma = ',' - if typeOf(value) == Ptr(PyObject) and value: - # cannot just write 'gxxx' as a constant in a structure :-( - node = self.db.getcontainernode(value._obj) - expr = 'NULL /* %s */' % node.name - c_name = self.c_struct_field_name(name) - node.where_to_copy_me.append('&%s.%s' % (self.name, c_name)) - else: - expr = self.db.get(value) - if typeOf(value) == Void: - comma = '' - i = expr.find('\n') - if i<0: i = len(expr) - expr = '%s%s\t/* %s%s */%s' % (expr[:i], comma, - prefix, name, expr[i:]) - expr = expr.replace('\n', '\n\t') # indentation + c_name = defnode.c_struct_field_name(name) + expr = generic_initializationexpr(self.db, value, + '%s.%s' % (self.name, c_name), + decoration + name) yield '\t%s' % expr yield '}' @@ -278,18 +271,47 @@ def getlength(self): return len(self.obj.items) - def initializationexpr(self, prefix=''): + def initializationexpr(self, decoration=''): yield '{' if needs_refcount(self.T): yield '\t1,' - yield '\t%d, {' % len(self.obj.items) - for j in range(len(self.obj.items)): - node = self.db.getcontainernode(self.obj.items[j]) - expr = '\n'.join(node.initializationexpr('%s%d.' % (prefix, j))) - expr += ',' - expr = expr.replace('\n', '\n\t') # indentation - yield '\t%s' % expr - yield '} }' + if self.T.OF == Void: + yield '\t%d' % len(self.obj.items) + yield '}' + else: + yield '\t%d, {' % len(self.obj.items) + for j in range(len(self.obj.items)): + value = self.obj.items[j] + expr = generic_initializationexpr(self.db, value, + '%s.items[%d]' % (self.name, j), + '%s%d' % (decoration, j)) + yield '\t%s' % expr + yield '} }' + + +def generic_initializationexpr(db, value, access_expr, decoration): + if isinstance(typeOf(value), ContainerType): + node = db.getcontainernode(value) + expr = '\n'.join(node.initializationexpr(decoration+'.')) + expr += ',' + else: + comma = ',' + if typeOf(value) == Ptr(PyObject) and value: + # cannot just write 'gxxx' as a constant in a structure :-( + node = db.getcontainernode(value._obj) + expr = 'NULL /*%s*/' % node.name + node.where_to_copy_me.append('&%s' % access_expr) + else: + expr = db.get(value) + if typeOf(value) == Void: + comma = '' + expr += comma + i = expr.find('\n') + if i<0: i = len(expr) + expr = '%s\t/* %s */%s' % (expr[:i], decoration, expr[i:]) + return expr.replace('\n', '\n\t') # indentation + +# ____________________________________________________________ class FuncNode(ContainerNode): Modified: pypy/branch/translator-without-old-genc/c/test/test_database.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/test/test_database.py (original) +++ pypy/branch/translator-without-old-genc/c/test/test_database.py Thu Jun 9 22:19:15 2005 @@ -260,6 +260,26 @@ def test_array(): A = GcArray(('obj', Ptr(PyObject))) a = malloc(A, 10) + a[3].obj = pyobjectptr(5) + db = LowLevelDatabase() + db.get(a) + db.complete() + dump_on_stdout(db) + +def test_array_of_char(): + A = GcArray(Char) + a = malloc(A, 11) + for i, c in zip(range(11), 'hello world'): + a[i] = c + db = LowLevelDatabase() + db.get(a) + db.complete() + dump_on_stdout(db) + +def test_array_of_pyobj(): + A = GcArray(Ptr(PyObject)) + a = malloc(A, 10) + a[3] = pyobjectptr(5) db = LowLevelDatabase() db.get(a) db.complete() Modified: pypy/branch/translator-without-old-genc/c/test/test_genc.py ============================================================================== --- pypy/branch/translator-without-old-genc/c/test/test_genc.py (original) +++ pypy/branch/translator-without-old-genc/c/test/test_genc.py Thu Jun 9 22:19:15 2005 @@ -1,5 +1,6 @@ import autopath, sys, os, py from pypy.rpython.lltype import * +from pypy.annotation import model as annmodel from pypy.translator.translator import Translator from pypy.translator.c.database import LowLevelDatabase from pypy.translator.c.genc import gen_source @@ -118,3 +119,26 @@ assert f1(-5) == -42 mallocs, frees = module.malloc_counters() assert mallocs == frees + + +def test_rptr_array(): + A = GcArray(Ptr(PyObject)) + def f(i, x): + p = malloc(A, i) + p[1] = x + return p[1] + t = Translator(f) + t.annotate([int, annmodel.SomePtr(Ptr(PyObject))]) + t.specialize() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(f)) + db.complete() + #t.view() + module = compile_db(db) + + f1 = getattr(module, entrypoint) + assert f1(5, 123) == 123 + assert f1(12, "hello") == "hello" + mallocs, frees = module.malloc_counters() + assert mallocs == frees Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Thu Jun 9 22:19:15 2005 @@ -55,10 +55,23 @@ class __extend__(pairtype(PtrRepr, IntegerRepr)): def rtype_getitem((r_ptr, r_int), hop): + ARRAY = r_ptr.lowleveltype.TO + ITEM_TYPE = ARRAY.OF + if isinstance(ITEM_TYPE, ContainerType): + newopname = 'getarraysubstruct' + else: + newopname = 'getarrayitem' vlist = hop.inputargs(r_ptr, Signed) - return hop.genop('getarrayitem', vlist, + return hop.genop(newopname, vlist, resulttype = hop.r_result.lowleveltype) + def rtype_setitem((r_ptr, r_int), hop): + ARRAY = r_ptr.lowleveltype.TO + ITEM_TYPE = ARRAY.OF + assert not isinstance(ITEM_TYPE, ContainerType) + vlist = hop.inputargs(r_ptr, Signed, hop.args_r[2]) + hop.genop('setarrayitem', vlist) + # ____________________________________________________________ # # Null Pointers Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 9 22:19:15 2005 @@ -142,7 +142,7 @@ v_size = llops.genop('getarraysize', [v_chars], resulttype=Signed) czero = inputconst(Signed, 0) - v_char0ptr = llops.genop('getarrayitem', [v_chars, czero], + v_char0ptr = llops.genop('getarraysubstruct', [v_chars, czero], resulttype=Ptr(STR.chars.OF)) return llops.gencapicall('PyString_FromStringAndSize_Hack', [v_char0ptr, v_size], From arigo at codespeak.net Thu Jun 9 22:22:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:22:45 +0200 (CEST) Subject: [pypy-svn] r13243 - pypy/branch/translator-without-old-genc/llvm Message-ID: <20050609202245.DF9BF27B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:22:44 2005 New Revision: 13243 Removed: pypy/branch/translator-without-old-genc/llvm/ Log: Branch merging fun starts here.... From arigo at codespeak.net Thu Jun 9 22:23:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:23:31 +0200 (CEST) Subject: [pypy-svn] r13244 - pypy/branch/translator-without-old-genc/llvm Message-ID: <20050609202331.EBD0B27B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:23:30 2005 New Revision: 13244 Added: pypy/branch/translator-without-old-genc/llvm/ - copied from r13243, pypy/dist/pypy/translator/llvm/ Log: Copied from the head. From arigo at codespeak.net Thu Jun 9 22:24:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:24:54 +0200 (CEST) Subject: [pypy-svn] r13245 - pypy/dist/pypy/translator Message-ID: <20050609202454.9DA9B27B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:24:53 2005 New Revision: 13245 Removed: pypy/dist/pypy/translator/ Log: ... From arigo at codespeak.net Thu Jun 9 22:26:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:26:05 +0200 (CEST) Subject: [pypy-svn] r13246 - in pypy: branch/translator-without-old-genc dist/pypy/translator Message-ID: <20050609202605.085A227B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:26:01 2005 New Revision: 13246 Added: pypy/dist/pypy/translator/ - copied from r13245, pypy/branch/translator-without-old-genc/ Removed: pypy/branch/translator-without-old-genc/ Log: Moved the branch back to the head. From arigo at codespeak.net Thu Jun 9 22:36:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:36:46 +0200 (CEST) Subject: [pypy-svn] r13247 - in pypy/dist/pypy: bin translator/genc/test translator/test Message-ID: <20050609203646.56D6727B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:36:42 2005 New Revision: 13247 Added: pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py - copied unchanged from r13246, pypy/dist/pypy/translator/genc/test/test_typed.py Removed: pypy/dist/pypy/translator/genc/test/test_typed.py Modified: pypy/dist/pypy/bin/translator.py pypy/dist/pypy/translator/test/test_backends.py Log: Final adjustements and end of the merge. The Translator class uses now the new 'c' translator. To run the rtyper, use the method 'specialize()' of the Translator (which used to be defined on the annotator.) Renamed test file while in progress. Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Thu Jun 9 22:36:42 2005 @@ -24,7 +24,7 @@ t.call(arg) # call original function t.dis() # bytecode disassemble - a.specialize() # use low level operations (for C only) + t.specialize() # use low level operations (for C only) f = t.ccompile() # C compilation f = t.llvmcompile() # LLVM compilation assert f(arg) == t.call(arg) # sanity check Deleted: /pypy/dist/pypy/translator/genc/test/test_typed.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/test_typed.py Thu Jun 9 22:36:42 2005 +++ (empty file) @@ -1,91 +0,0 @@ -import autopath -import sys -import py.test -from pypy.translator.translator import Translator -from pypy.translator.test import snippet -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler - -from pypy.translator.genc.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase - - -class TestTypedTestCase(_TestAnnotatedTestCase): - - def getcompiled(self, func): - t = Translator(func, simplifying=True) - # builds starting-types from func_defs - argstypelist = [] - if func.func_defaults: - for spec in func.func_defaults: - if isinstance(spec, tuple): - spec = spec[0] # use the first type only for the tests - argstypelist.append(spec) - a = t.annotate(argstypelist) - a.simplify() - t.specialize() - t.checkgraphs() - return skip_missing_compiler(t.ccompile) - - def test_call_five(self): - # -- the result of call_five() isn't a real list, but an rlist - # that can't be converted to a PyListObject - def wrapper(): - lst = snippet.call_five() - return len(lst), lst[0] - call_five = self.getcompiled(snippet.call_five) - result = call_five() - assert result == (1, 5) - - def test_get_set_del_slice(self): - def get_set_del_nonneg_slice(l=list): # no neg slices for now! - del l[:1] - del l[len(l)-1:] - del l[2:4] - l[:1] = [3] - l[len(l)-1:] = [9] - l[2:4] = [8,11] - return l[:2], l[5:], l[3:5] - fn = self.getcompiled(get_set_del_nonneg_slice) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - - def test_slice_long(self): - "the parent's test_slice_long() makes no sense here" - - def test_int_overflow(self): - fn = self.getcompiled(snippet.add_func) - raises(OverflowError, fn, sys_maxint()) - - def test_int_div_ovf_zer(self): # - py.test.skip("right now aborting python with Floating Point Error!") - fn = self.getcompiled(snippet.div_func) - raises(OverflowError, fn, -1) - raises(ZeroDivisionError, fn, 0) - - def test_int_mod_ovf_zer(self): - py.test.skip("right now aborting python with Floating Point Error!") - fn = self.getcompiled(snippet.mod_func) - raises(OverflowError, fn, -1) - raises(ZeroDivisionError, fn, 0) - - def test_int_rshift_val(self): - fn = self.getcompiled(snippet.rshift_func) - raises(ValueError, fn, -1) - - def test_int_lshift_ovf_val(self): - fn = self.getcompiled(snippet.lshift_func) - raises(ValueError, fn, -1) - raises(OverflowError, fn, 1) - - def test_int_unary_ovf(self): - fn = self.getcompiled(snippet.unary_func) - for i in range(-3,3): - assert fn(i) == (-(i), abs(i-1)) - raises (OverflowError, fn, -sys_maxint()-1) - raises (OverflowError, fn, -sys_maxint()) - -def sys_maxint(): - if sys.maxint != 2147483647: - py.test.skip("genc ovf incomplete: int might differ from long") - return sys.maxint Modified: pypy/dist/pypy/translator/test/test_backends.py ============================================================================== --- pypy/dist/pypy/translator/test/test_backends.py (original) +++ pypy/dist/pypy/translator/test/test_backends.py Thu Jun 9 22:36:42 2005 @@ -10,6 +10,7 @@ backends = 'source c cl llvm pyrex'.split() +deterministic_backends = 'source cl llvm pyrex'.split() functions = 'forty_two'.split() #XXX add more functions here when RPythonTyper can handle them regenerate_code = '''def test_regenerate_%(function)s_%(backend)s(): @@ -17,15 +18,15 @@ t.simplify() a = t.annotate([]) a.simplify() - typer = RPythonTyper(t.annotator) - typer.specialize() + t.specialize() first = t.%(backend)s() second = t.%(backend)s() - if first != second: - print '\\n' + first + '\\n\\n' - print '\\n' + second + '\\n\\n' - #t.view() - assert first == second''' + if %(backend)r in deterministic_backends: + if first != second: + print '\\n' + first + '\\n\\n' + print '\\n' + second + '\\n\\n' + #t.view() + assert first == second''' for backend in backends: for function in functions: From arigo at codespeak.net Thu Jun 9 22:38:12 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 9 Jun 2005 22:38:12 +0200 (CEST) Subject: [pypy-svn] r13248 - pypy/dist/pypy/documentation Message-ID: <20050609203812.29FCF27B4E@code1.codespeak.net> Author: arigo Date: Thu Jun 9 22:38:10 2005 New Revision: 13248 Modified: pypy/dist/pypy/documentation/getting_started.txt Log: Doc fix. Modified: pypy/dist/pypy/documentation/getting_started.txt ============================================================================== --- pypy/dist/pypy/documentation/getting_started.txt (original) +++ pypy/dist/pypy/documentation/getting_started.txt Thu Jun 9 22:38:10 2005 @@ -342,7 +342,7 @@ The graph can be turned into C code:: - >>> a.specialize() + >>> t.specialize() >>> f = t.ccompile() The first command replaces operations with variables of types that are From ericvrp at codespeak.net Fri Jun 10 09:37:47 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 10 Jun 2005 09:37:47 +0200 (CEST) Subject: [pypy-svn] r13259 - pypy/dist/pypy/bin Message-ID: <20050610073747.AED2627B5A@code1.codespeak.net> Author: ericvrp Date: Fri Jun 10 09:37:46 2005 New Revision: 13259 Modified: pypy/dist/pypy/bin/translator.py Log: Fixed: printed wrong docstring with -h option Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Fri Jun 10 09:37:46 2005 @@ -98,7 +98,7 @@ self.test_compiled = True else: - print __doc__ + print extra_help sys.exit(0) else: From hpk at codespeak.net Fri Jun 10 14:09:58 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 10 Jun 2005 14:09:58 +0200 (CEST) Subject: [pypy-svn] r13261 - pypy/extradoc/sprintinfo Message-ID: <20050610120958.992F927B61@code1.codespeak.net> Author: hpk Date: Fri Jun 10 14:09:57 2005 New Revision: 13261 Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt Log: incorporated and edited logistic infos that Samuele forwarded me from Jacob. Next time, please just check things in yourself, there is no need to route this through my mailbox. I think we should try to send out this announcement real soon now, it has been dragging on some weeks to long, if you ask me, considering that we knew the time and basic place of the sprint since early May if not earlier. So please review the announcement and correct/fix/comment it so we can send things out on the weekend. Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-announcement.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-announcement.txt Fri Jun 10 14:09:57 2005 @@ -52,7 +52,59 @@ before the sprint! feel free to start such a discussion, though.) -Accomodation, Location and meeting points ------------------------------------------- +Location & Accomodation +------------------------ + +The sprint will be held in the former Math Center building +near the crossing of Gibraltargatan and Eklandagatan. Entrance +is on the middle of the side facing Gibraltargatan. The doors +to the building are normally locked, so you need the phone number +of somebody inside to get in. Instructions on whom to call will be +posted on the door. + +The sprint will be co-located with several other sprints. See the +`EuroPython Wiki`_, to find out what other sprints will be running. + +Nearest, and probably cheapest is to book accomodation at SGS Veckobost?der +through the Europython website. This option will be available until about +20 June. + +.. _`EuroPython Wiki`: http://www.europython.org/sections/sprints_and_wiki + +Exact times +----------- + +The public Pypy sprint is held Friday 1st July - Thursday 7 July 2005. +Hours will be from 09:00 until people have had enough. It's a good +idea to arrive a day before the sprint starts. + +(There is a sprint for people who are familiar with the Pypy codebase +before Europython as well. This will be held at Jacob & Laura's home +on G?tabergsgatan 22.) + + +Network, Food, currency +------------------------ + +Sweden is not part of the Euro zone. One SEK (krona in singular, kronor +in plural) is roughly 1/10th of a Euro (9.15 SEK to 1 Euro). + +There are some pizzerias, kebab places and the like close to the venue. +Their food is edible and cheap, but not very good. For good food, you need to +go downtown. + +You need a wirless network card to access the network. You will be +issued a login to the Chalmers NOMAD network. This will allow you to +use access points all over Chalmers. However, we can likely provide +a wireless/ethernet bridge. + +Sweden uses the same kind of plugs as Germany. 230V AC. + +Registration etc.pp. +-------------------- + +Please subscribe to the `PyPy sprint mailing list`_ and introduce +yourself and post a note that you want to come and ask any questions! + +.. _`PyPy sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint -XXX From arigo at codespeak.net Fri Jun 10 15:45:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 10 Jun 2005 15:45:53 +0200 (CEST) Subject: [pypy-svn] r13262 - pypy/extradoc/sprintinfo Message-ID: <20050610134553.596E827B5E@code1.codespeak.net> Author: arigo Date: Fri Jun 10 15:45:51 2005 New Revision: 13262 Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt Log: - reworded the paragraph about the summer of code. It suggested that the sprint would be a good time to come up with and polish off a proposal. - drop in two URLs. Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-announcement.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-announcement.txt Fri Jun 10 15:45:51 2005 @@ -2,7 +2,7 @@ ====================================================== The next PyPy sprint is scheduled right after EuroPython 2005 -in Gothenborg, Sweden. It's main focus is translation to +in Gothenborg, Sweden. Its main focus is translation to lower level backends but there are also other possible topics. We'll give newcomer-friendly introductions. To learn more about the new PyPy Python-in-Python implementation look here: @@ -10,11 +10,12 @@ http://codespeak.net/pypy On a side note, there are a number of sub projects that may be -interesting for participating in google's summer-of-code -event. Apart from refining and discussing tasks, the sprint -could possibly serve as a good meeting and kick-off point with -mentors from the PyPy group. Further down you'll find some -first areas, but there are certainly more and bigger ones :-) +interesting for participating in google's summer-of-code event +(deadline the 14th!). The PyPy group is willing to mentor +projects that have some link with PyPy, so if you are accepted +in such a project, the sprint could also serve as a good +meeting and kick-off point. Further down you'll find some +examples, but there are certainly more and bigger ones :-) Goals and topics of the sprint ------------------------------ @@ -31,9 +32,12 @@ - polish off the GenC and GenLLVM back-ends, responsible for turning the low-level C-like flow graphs into real C or LLVM source code. + +See http://codespeak.net/pipermail/pypy-dev/2005q2/002136.html for more +information (10th of June status). Non-translation-related topics are welcome too. Here are some suggestions -from the issue tracker: +from the issue tracker (https://codespeak.net/issue/pypy-dev/): - integrate the parser module, possibly making it RPython conformant; From hpk at codespeak.net Fri Jun 10 15:57:01 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 10 Jun 2005 15:57:01 +0200 (CEST) Subject: [pypy-svn] r13263 - pypy/extradoc/sprintinfo Message-ID: <20050610135701.2F44427B66@code1.codespeak.net> Author: hpk Date: Fri Jun 10 15:56:59 2005 New Revision: 13263 Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt Log: small adjustments and clarifications Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-announcement.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-announcement.txt Fri Jun 10 15:56:59 2005 @@ -11,7 +11,7 @@ On a side note, there are a number of sub projects that may be interesting for participating in google's summer-of-code event -(deadline the 14th!). The PyPy group is willing to mentor +(deadline June 14th!). The PyPy group is willing to mentor projects that have some link with PyPy, so if you are accepted in such a project, the sprint could also serve as a good meeting and kick-off point. Further down you'll find some @@ -107,8 +107,9 @@ Registration etc.pp. -------------------- -Please subscribe to the `PyPy sprint mailing list`_ and introduce -yourself and post a note that you want to come and ask any questions! +Please subscribe to the `PyPy sprint mailing list`_, introduce +yourself and post a note that you want to come. Feel free +to ask any questions there! .. _`PyPy sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint From tismer at codespeak.net Fri Jun 10 16:02:25 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 10 Jun 2005 16:02:25 +0200 (CEST) Subject: [pypy-svn] r13265 - pypy/dist/pypy/translator/goal Message-ID: <20050610140225.09B2B27B68@code1.codespeak.net> Author: tismer Date: Fri Jun 10 16:02:24 2005 New Revision: 13265 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: just a few comments which ask why I cannot enable this and that Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jun 10 16:02:24 2005 @@ -15,6 +15,10 @@ def entry_point(argv): w_argv = space.newlist([space.wrap(s) for s in argv]) w_exitcode = space.call(w_entry_point, w_argv) + # try to pull it all in +## from pypy.interpreter import main, interactive, error +## con = interactive.PyPyConsole(space) +## con.interact() return space.int_w(w_exitcode) # _____ Define and setup target ___ @@ -25,6 +29,7 @@ StdObjSpace.setup_old_style_classes = lambda self: None # disable geninterp for now -- we have faaar toooo much interp-level code # for the poor translator already + # XXX why can't I enable this? crashes the annotator! gateway.ApplevelClass.use_geninterp = False space = StdObjSpace() From tismer at codespeak.net Fri Jun 10 16:03:24 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 10 Jun 2005 16:03:24 +0200 (CEST) Subject: [pypy-svn] r13266 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050610140324.7615C27B68@code1.codespeak.net> Author: tismer Date: Fri Jun 10 16:03:23 2005 New Revision: 13266 Modified: pypy/branch/pypy-translation-snapshot/interpreter/interactive.py Log: replaced forbidden usage of space.exec_ Modified: pypy/branch/pypy-translation-snapshot/interpreter/interactive.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/interactive.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/interactive.py Fri Jun 10 16:03:23 2005 @@ -99,7 +99,9 @@ if completer: self.enable_command_line_completer() - space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals) + # forbidden: + #space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals) + space.setitem(self.w_globals, space.wrap('__pytrace__'),space.wrap(0)) self.tracelevel = 0 def enable_command_line_completer(self): From tismer at codespeak.net Fri Jun 10 16:03:46 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 10 Jun 2005 16:03:46 +0200 (CEST) Subject: [pypy-svn] r13267 - pypy/dist/pypy/interpreter Message-ID: <20050610140346.333FF27B68@code1.codespeak.net> Author: tismer Date: Fri Jun 10 16:03:44 2005 New Revision: 13267 Modified: pypy/dist/pypy/interpreter/interactive.py Log: replaced forbidden usage of space.exec_ Modified: pypy/dist/pypy/interpreter/interactive.py ============================================================================== --- pypy/dist/pypy/interpreter/interactive.py (original) +++ pypy/dist/pypy/interpreter/interactive.py Fri Jun 10 16:03:44 2005 @@ -99,7 +99,9 @@ if completer: self.enable_command_line_completer() - space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals) + # forbidden: + #space.exec_("__pytrace__ = 0", self.w_globals, self.w_globals) + space.setitem(self.w_globals, space.wrap('__pytrace__'),space.wrap(0)) self.tracelevel = 0 def enable_command_line_completer(self): From tismer at codespeak.net Fri Jun 10 16:31:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 10 Jun 2005 16:31:16 +0200 (CEST) Subject: [pypy-svn] r13270 - pypy/dist/pypy/objspace/flow Message-ID: <20050610143116.BB77B27B5F@code1.codespeak.net> Author: tismer Date: Fri Jun 10 16:31:15 2005 New Revision: 13270 Modified: pypy/dist/pypy/objspace/flow/model.py Log: folding the opcode strings by interning (they are few) Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Fri Jun 10 16:31:15 2005 @@ -273,7 +273,7 @@ __slots__ = "opname args result offset".split() def __init__(self, opname, args, result, offset=-1): - self.opname = opname # operation name + self.opname = intern(opname) # operation name self.args = list(args) # mixed list of var/const self.result = result # either Variable or Constant instance self.offset = offset # offset in code string From tismer at codespeak.net Fri Jun 10 16:57:25 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 10 Jun 2005 16:57:25 +0200 (CEST) Subject: [pypy-svn] r13272 - pypy/dist/pypy/translator Message-ID: <20050610145725.1BCBD27B68@code1.codespeak.net> Author: tismer Date: Fri Jun 10 16:57:23 2005 New Revision: 13272 Modified: pypy/dist/pypy/translator/annrpython.py Log: __gestate__ had a missing argument Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Fri Jun 10 16:57:23 2005 @@ -60,12 +60,13 @@ def __getstate__(self): attrs = """translator pendingblocks bindings annotated links_followed - notify bookkeeper policy""".split() + notify bookkeeper frozen policy""".split() ret = self.__dict__.copy() for key, value in ret.items(): if key not in attrs: - assert type(value) is dict, ("please update %s.__getstate__" % - self.__class__.__name__) + assert type(value) is dict, ( + "%r is not dict. please update %s.__getstate__" % + (key, self.__class__.__name__)) ret[key] = {} return ret From cfbolz at codespeak.net Fri Jun 10 20:48:19 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 10 Jun 2005 20:48:19 +0200 (CEST) Subject: [pypy-svn] r13275 - pypy/dist/pypy/tool Message-ID: <20050610184819.D074D27B4E@code1.codespeak.net> Author: cfbolz Date: Fri Jun 10 20:48:18 2005 New Revision: 13275 Added: pypy/dist/pypy/tool/import_graph.py Log: added simple tool that creates a module import dependency graph as a .dot file. At the moment the result is not usable (too many edges), I'm working on it. Added: pypy/dist/pypy/tool/import_graph.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/import_graph.py Fri Jun 10 20:48:18 2005 @@ -0,0 +1,215 @@ +from __future__ import division +import autopath +import py + +import math +import random +import sets + +exclude_files = ["__init__.py", "autopath.py", "conftest.py"] + +def include_file(path): + if ("test" in str(path) or "tool" in str(path) or + "documentation" in str(path) or "pyrex" in str(path) or + "_cache" in str(path)): + return False + if path.basename in exclude_files: + return False + return True + +def get_mod_from_path(path): + dirs = path.get("dirname")[0].split("/") + pypyindex = dirs.index("pypy") + return ".".join(dirs[pypyindex:] + path.get("purebasename")) + + +def find_references(path): + refs = [] + for line in path.open("r"): + if line.startswith(" "): # ignore local imports to reduce graph size + continue + if "\\" in line: #ignore line continuations + continue + line = line.strip() + line = line.split("#")[0].strip() + if line.startswith("import pypy."): # import pypy.bla.whatever + if " as " not in line: + refs.append((line[7:].strip(), None)) + else: # import pypy.bla.whatever as somethingelse + assert line.count(" as ") == 1 + line = line.split(" as ") + refs.append((line[0][7:].strip(), line[1].strip())) + elif line.startswith("from ") and "pypy" in line: #from pypy.b import a + line = line[5:] + if " as " not in line: + line = line.split(" import ") + what = line[1].split(",") + for w in what: + refs.append((line[0].strip() + "." + w.strip(), None)) + else: # prom pypy.b import a as c + if line.count(" as ") != 1 or "," in line: + print"can't handle this: " + line + continue + line = line.split(" as ") + what = line[0].replace(" import ", ".").replace(" ", "") + refs.append((what, line[1].strip())) + return refs + +def get_module(ref, imports): + ref = ref.split(".") + i = len(ref) + while i: + possible_mod = ".".join(ref[:i]) + if possible_mod in imports: + return possible_mod + i -= 1 + return None + +def casteljeau(points, t): + points = points[:] + while len(points) > 1: + for i in range(len(points) - 1): + points[i] = points[i] * (1 - t) + points[i + 1] * t + del points[-1] + return points[0] + +def color(t): + points = [0, 0, 1, 0, 0] + casteljeau([0, 0, 1, 0, 0], t) / 0.375 + +class ModuleGraph(object): + def __init__(self, path): + self.imports = {} + self.clusters = {} + self.mod_to_cluster = {} + for f in path.visit("*.py"): + if include_file(f): + self.imports[get_mod_from_path(f)] = find_references(f) + self.remove_object_refs() + self.remove_double_refs() + self.incoming = {} + for mod in self.imports: + self.incoming[mod] = sets.Set() + for mod, refs in self.imports.iteritems(): + for ref in refs: + if ref[0] in self.incoming: + self.incoming[ref[0]].add(mod) + self.remove_single_nodes() + self.topgraph_properties = ["rankdir=LR"] + + def remove_object_refs(self): + # reduces cases like import pypy.translator.genc.basetype.CType to + # import pypy.translator.genc.basetype + for mod, refs in self.imports.iteritems(): + i = 0 + while i < len(refs): + if refs[i][0] in self.imports: + i += 1 + else: + nref = get_module(refs[i][0], self.imports) + if nref is None: + print "removing", repr(refs[i]) + del refs[i] + else: + refs[i] = (nref, None) + i += 1 + + def remove_double_refs(self): + # remove several references to the same module + for mod, refs in self.imports.iteritems(): + i = 0 + seen_refs = sets.Set() + while i < len(refs): + if refs[i] not in seen_refs: + seen_refs.add(refs[i]) + i += 1 + else: + del refs[i] + + def remove_single_nodes(self): + # remove nodes that have no attached edges + rem = [] + for mod, refs in self.imports.iteritems(): + if len(refs) == 0 and len(self.incoming[mod]) == 0: + rem.append(mod) + for m in rem: + del self.incoming[m] + del self.imports[m] + + def create_clusters(self): + self.topgraph_properties.append("compound=true;") + self.clustered = True + hierarchy = [sets.Set() for i in range(6)] + for mod in self.imports: + for i, d in enumerate(mod.split(".")): + hierarchy[i].add(d) + for i in range(6): + if len(hierarchy[i]) != 1: + break + for mod in self.imports: + cluster = mod.split(".")[i] + if i == len(mod.split(".")) - 1: + continue + if cluster not in self.clusters: + self.clusters[cluster] = sets.Set() + self.clusters[cluster].add(mod) + self.mod_to_cluster[mod] = cluster + + def remove_tangling_randomly(self): + # remove edges to nodes that have a lot incoming edges randomly + tangled = [] + for mod, incoming in self.incoming.iteritems(): + if len(incoming) > 10: + tangled.append(mod) + for mod in tangled: + remove = sets.Set() + incoming = self.incoming[mod] + while len(remove) < len(incoming) * 0.80: + remove.add(random.choice(list(incoming))) + for rem in remove: + for i in range(len(self.imports[rem])): + if self.imports[rem][i][1] == mod: + break + del self.imports[rem][i] + incoming.remove(rem) + print "removing", mod, "<-", rem + self.remove_single_nodes() + + def dotfile(self, dot): + f = dot.open("w") + f.write("digraph G {\n") + for prop in self.topgraph_properties: + f.write("\t%s\n" % prop) + #write clusters and inter-cluster edges + for cluster, nodes in self.clusters.iteritems(): + f.write("\tsubgraph cluster_%s {\n" % cluster) + f.write("\t\tstyle=filled;\n\t\tcolor=lightgrey\n") + for node in nodes: + f.write('\t\t"%s";\n' % node[5:]) + for mod, refs in self.imports.iteritems(): + for ref in refs: + if mod in nodes and ref[0] in nodes: + f.write('\t\t"%s" -> "%s";\n' % (mod[5:], ref[0][5:])) + f.write("\t}\n") + #write edges between clusters + for mod, refs in self.imports.iteritems(): + try: + nodes = self.clusters[self.mod_to_cluster[mod]] + except KeyError: + nodes = sets.Set() + for ref in refs: + if ref[0] not in nodes: + f.write('\t"%s" -> "%s";\n' % (mod[5:], ref[0][5:])) + f.write("}") + f.close() + +if __name__ == "__main__": + import sys + if len(sys.argv) > 1: + path = py.path.local(sys.argv[1]) + else: + path = py.path.local(".") + gr = ModuleGraph(path) + gr.create_clusters() + dot = path.join("import_graph.dot") + gr.dotfile(dot) From ericvrp at codespeak.net Fri Jun 10 21:05:34 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 10 Jun 2005 21:05:34 +0200 (CEST) Subject: [pypy-svn] r13276 - pypy/extradoc/sprintinfo Message-ID: <20050610190534.6568227B4B@code1.codespeak.net> Author: ericvrp Date: Fri Jun 10 21:05:33 2005 New Revision: 13276 Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt Log: Added link to EuroPython special accomodation page Fixed typo Modified: pypy/extradoc/sprintinfo/EP2005-announcement.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-announcement.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-announcement.txt Fri Jun 10 21:05:33 2005 @@ -73,6 +73,7 @@ through the Europython website. This option will be available until about 20 June. +.. _`EuroPython special accomodation`: http://www.europython.org/sections/accomodation/special_accomodation .. _`EuroPython Wiki`: http://www.europython.org/sections/sprints_and_wiki Exact times @@ -97,7 +98,7 @@ Their food is edible and cheap, but not very good. For good food, you need to go downtown. -You need a wirless network card to access the network. You will be +You need a wireless network card to access the network. You will be issued a login to the Chalmers NOMAD network. This will allow you to use access points all over Chalmers. However, we can likely provide a wireless/ethernet bridge. From arigo at codespeak.net Fri Jun 10 22:35:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 10 Jun 2005 22:35:39 +0200 (CEST) Subject: [pypy-svn] r13277 - in pypy/dist/pypy/rpython: . test Message-ID: <20050610203539.1E93327B52@code1.codespeak.net> Author: arigo Date: Fri Jun 10 22:35:36 2005 New Revision: 13277 Added: pypy/dist/pypy/rpython/test/test_robject.py (contents, props changed) Modified: pypy/dist/pypy/rpython/robject.py Log: Support for all operations involving PyObjects -- basically just by deferring the problem to the code generator. GenC already knows what to do. Modified: pypy/dist/pypy/rpython/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Fri Jun 10 22:35:36 2005 @@ -3,6 +3,7 @@ from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass +from pypy.tool.sourcetools import func_with_new_name class __extend__(annmodel.SomeObject): @@ -23,15 +24,35 @@ class PyObjRepr(Repr): - lowleveltype = Ptr(PyObject) - def convert_const(self, value): return pyobjectptr(value) pyobj_repr = PyObjRepr() - - -class ConstPyObjRepr(Repr): - lowleveltype = Void - -constpyobj_repr = ConstPyObjRepr() +pyobj_repr.lowleveltype = Ptr(PyObject) +constpyobj_repr = PyObjRepr() +constpyobj_repr.lowleveltype = Void + +# ____________________________________________________________ +# +# All operations involving a PyObjRepr are "replaced" by themselves, +# after converting all other arguments to PyObjRepr as well. This +# basically defers the operations to the care of the code generator. + +def make_operation(opname, cls=PyObjRepr): + def rtype_op(_, hop): + vlist = hop.inputargs(*([pyobj_repr]*hop.nb_args)) + v = hop.genop(opname, vlist, resulttype = pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, hop.r_result) + + funcname = 'rtype_' + opname + func = func_with_new_name(rtype_op, funcname) + assert funcname not in cls.__dict__ # can be in Repr; overriden then. + setattr(cls, funcname, func) + + +for opname in annmodel.UNARY_OPERATIONS: + make_operation(opname) + +for opname in annmodel.BINARY_OPERATIONS: + make_operation(opname, pairtype(PyObjRepr, Repr)) + make_operation(opname, pairtype(Repr, PyObjRepr)) Added: pypy/dist/pypy/rpython/test/test_robject.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_robject.py Fri Jun 10 22:35:36 2005 @@ -0,0 +1,16 @@ +from pypy.translator.translator import Translator +from pypy.rpython.lltype import * + + +def rtype(fn, argtypes=[]): + t = Translator(fn) + t.annotate(argtypes) + t.specialize() + t.checkgraphs() + return t + + +def test_set_del_item(): + def dummyfn(obj): + return obj + 1 + rtype(dummyfn, [object]) From arigo at codespeak.net Fri Jun 10 22:44:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 10 Jun 2005 22:44:25 +0200 (CEST) Subject: [pypy-svn] r13278 - pypy/dist/pypy/translator/genc/test Message-ID: <20050610204425.7D9AC27B57@code1.codespeak.net> Author: arigo Date: Fri Jun 10 22:44:23 2005 New Revision: 13278 Modified: pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Log: Yuck! Typo. Modified: pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py (original) +++ pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Fri Jun 10 22:44:23 2005 @@ -31,7 +31,7 @@ def wrapper(): lst = snippet.call_five() return len(lst), lst[0] - call_five = self.getcompiled(snippet.call_five) + call_five = self.getcompiled(wrapper) result = call_five() assert result == (1, 5) From arigo at codespeak.net Fri Jun 10 23:48:28 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 10 Jun 2005 23:48:28 +0200 (CEST) Subject: [pypy-svn] r13280 - in pypy/dist/pypy: annotation translator translator/test Message-ID: <20050610214828.01A9627B4E@code1.codespeak.net> Author: arigo Date: Fri Jun 10 23:48:26 2005 New Revision: 13280 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/test/test_annrpython.py Log: Teach the annotator to deduce nonneg flags from code like "if i >= 0:...". Exposed a bug in the two oldest tests we have for the annotator, which build a graph by hand, reusing the same variable multiple times :-( Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Fri Jun 10 23:48:26 2005 @@ -2,6 +2,7 @@ Binary operations between SomeValues. """ +import operator from pypy.annotation.pairtype import pair, pairtype from pypy.annotation.model import SomeObject, SomeInteger, SomeBool from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict @@ -13,7 +14,7 @@ from pypy.annotation.model import add_knowntypedata, merge_knowntypedata from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation.classdef import isclassdef -from pypy.objspace.flow.model import Constant +from pypy.objspace.flow.model import Constant, Variable # convenience only! def immutablevalue(x): @@ -235,6 +236,38 @@ pow.can_only_throw = [ZeroDivisionError] pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError]) + def _compare_helper((int1, int2), opname, operation): + if int1.is_constant() and int2.is_constant(): + r = immutablevalue(operation(int1.const, int2.const)) + else: + r = SomeBool() + knowntypedata = {} + # XXX HACK HACK HACK + # propagate nonneg information between the two arguments + fn, block, i = getbookkeeper().position_key + op = block.operations[i] + assert op.opname == opname + assert len(op.args) == 2 + if int1.nonneg and isinstance(op.args[1], Variable): + case = opname in ('lt', 'le', 'eq') + add_knowntypedata(knowntypedata, case, [op.args[1]], + SomeInteger(nonneg=True)) + if int2.nonneg and isinstance(op.args[0], Variable): + case = opname in ('gt', 'ge', 'eq') + add_knowntypedata(knowntypedata, case, [op.args[0]], + SomeInteger(nonneg=True)) + if knowntypedata: + r.knowntypedata = knowntypedata + return r + + def lt(intint): return intint._compare_helper('lt', operator.lt) + def le(intint): return intint._compare_helper('le', operator.le) + def eq(intint): return intint._compare_helper('eq', operator.eq) + def ne(intint): return intint._compare_helper('ne', operator.ne) + def gt(intint): return intint._compare_helper('gt', operator.gt) + def ge(intint): return intint._compare_helper('ge', operator.ge) + + class __extend__(pairtype(SomeBool, SomeBool)): def union((boo1, boo2)): Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Fri Jun 10 23:48:26 2005 @@ -7,7 +7,7 @@ from pypy.annotation.bookkeeper import Bookkeeper from pypy.objspace.flow.model import Variable, Constant from pypy.objspace.flow.model import SpaceOperation, FunctionGraph -from pypy.objspace.flow.model import last_exception +from pypy.objspace.flow.model import last_exception, checkgraph class AnnotatorError(Exception): pass @@ -86,6 +86,7 @@ """Recursively build annotations about the specific entry point.""" if isinstance(func_or_flowgraph, FunctionGraph): flowgraph = func_or_flowgraph + checkgraph(flowgraph) self._register_returnvar(flowgraph, func) else: func = func_or_flowgraph Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Fri Jun 10 23:48:26 2005 @@ -80,20 +80,22 @@ i = i - 1 return i """ - i = Variable("i") + i1 = Variable("i1") + i2 = Variable("i2") + i3 = Variable("i3") conditionres = Variable("conditionres") - conditionop = SpaceOperation("gt", [i, Constant(0)], conditionres) - decop = SpaceOperation("add", [i, Constant(-1)], i) - headerblock = Block([i]) - whileblock = Block([i]) + conditionop = SpaceOperation("gt", [i1, Constant(0)], conditionres) + decop = SpaceOperation("add", [i2, Constant(-1)], i3) + headerblock = Block([i1]) + whileblock = Block([i2]) fun = FunctionGraph("f", headerblock) headerblock.operations.append(conditionop) headerblock.exitswitch = conditionres - headerblock.closeblock(Link([i], fun.returnblock, False), - Link([i], whileblock, True)) + headerblock.closeblock(Link([i1], fun.returnblock, False), + Link([i1], whileblock, True)) whileblock.operations.append(decop) - whileblock.closeblock(Link([i], headerblock)) + whileblock.closeblock(Link([i3], headerblock)) a = self.RPythonAnnotator() a.build_types(fun, [int]) @@ -109,26 +111,31 @@ i = i - 1 return sum """ - i = Variable("i") - sum = Variable("sum") + i1 = Variable("i1") + i2 = Variable("i2") + i3 = Variable("i3") + i4 = Variable("i4") + sum2 = Variable("sum2") + sum3 = Variable("sum3") + sum4 = Variable("sum4") conditionres = Variable("conditionres") - conditionop = SpaceOperation("gt", [i, Constant(0)], conditionres) - decop = SpaceOperation("add", [i, Constant(-1)], i) - addop = SpaceOperation("add", [i, sum], sum) - startblock = Block([i]) - headerblock = Block([i, sum]) - whileblock = Block([i, sum]) + conditionop = SpaceOperation("gt", [i2, Constant(0)], conditionres) + decop = SpaceOperation("add", [i3, Constant(-1)], i4) + addop = SpaceOperation("add", [i3, sum3], sum4) + startblock = Block([i1]) + headerblock = Block([i2, sum2]) + whileblock = Block([i3, sum3]) fun = FunctionGraph("f", startblock) - startblock.closeblock(Link([i, Constant(0)], headerblock)) + startblock.closeblock(Link([i1, Constant(0)], headerblock)) headerblock.operations.append(conditionop) headerblock.exitswitch = conditionres - headerblock.closeblock(Link([sum], fun.returnblock, False), - Link([i, sum], whileblock, True)) + headerblock.closeblock(Link([sum2], fun.returnblock, False), + Link([i2, sum2], whileblock, True)) whileblock.operations.append(addop) whileblock.operations.append(decop) - whileblock.closeblock(Link([i, sum], headerblock)) + whileblock.closeblock(Link([i4, sum4], headerblock)) a = self.RPythonAnnotator() a.build_types(fun, [int]) @@ -1177,7 +1184,7 @@ def test_prime(self): a = self.RPythonAnnotator() s = a.build_types(snippet.prime, [int]) - assert s == annmodel.SomeBool() + assert s.knowntype == bool def test_and_is_true_coalesce(self): def f(a,b,c,d,e): @@ -1238,8 +1245,25 @@ a = self.RPythonAnnotator() s = a.build_types(f, [bool]) assert not s.is_constant() - - + + def test_nonneg_cleverness(self): + def f(a, b, c, d, e, f, g, h): + if a < 0: a = 0 + if b <= 0: b = 0 + if c >= 0: + pass + else: + c = 0 + if d < a: d = a + if e <= b: e = 1 + if c > f: f = 2 + if d >= g: g = 3 + if h != a: h = 0 + return a, b, c, d, e, f, g, h + a = self.RPythonAnnotator() + s = a.build_types(f, [int]*8) + assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 8) + def g(n): return [0,1,2,n] From ericvrp at codespeak.net Fri Jun 10 23:57:34 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 10 Jun 2005 23:57:34 +0200 (CEST) Subject: [pypy-svn] r13281 - pypy/dist/pypy/bin Message-ID: <20050610215734.8975C27B4E@code1.codespeak.net> Author: ericvrp Date: Fri Jun 10 23:57:33 2005 New Revision: 13281 Modified: pypy/dist/pypy/bin/translator.py Log: Fixed problems caused by the fact that some backends call the RTyper when generating source or compiling. The RTyper is not happy with getting woken twice. Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Fri Jun 10 23:57:33 2005 @@ -173,13 +173,18 @@ elif options.backend == 'llvm': print t.llvm() + #note: this is a workaround because genllvm calls the RPythonTyper which is not smart enough right now to leave already lltyped blocks alone + t = Translator(entry_function) + t.simplify() + a = t.annotate(argumentTypes) + a.simplify() elif options.backend == 'pyrex': print t.pyrex() if options.compile: if options.backend == 'c': - a.specialize() # use low level operations (for C only) + #a.specialize() # use low level operations (for C only) f = t.ccompile() elif options.backend == 'llvm': From ericvrp at codespeak.net Sat Jun 11 00:01:57 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 11 Jun 2005 00:01:57 +0200 (CEST) Subject: [pypy-svn] r13282 - pypy/dist/pypy/translator/llvm Message-ID: <20050610220157.9707727B4F@code1.codespeak.net> Author: ericvrp Date: Sat Jun 11 00:01:56 2005 New Revision: 13282 Modified: pypy/dist/pypy/translator/llvm/funcrepr.py pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/llvm/lazyattribute.py pypy/dist/pypy/translator/llvm/llvmbc.py pypy/dist/pypy/translator/llvm/pointerrepr.py pypy/dist/pypy/translator/llvm/representation.py pypy/dist/pypy/translator/llvm/seqrepr.py pypy/dist/pypy/translator/llvm/typerepr.py Log: Added casts, same_as and ..._is_true for all lltypes by using casts for all of then. This raises the question whether the rtyper should really generate same_as and ..._is_true instructions. Perhaps the rtyper could also stick to casts to same type (same_as) or to bool (..._is_true)? XXX some instructions fail silently (for instance pow(...)) in t_op(...) methods. This should be fixed! Modified: pypy/dist/pypy/translator/llvm/funcrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/funcrepr.py (original) +++ pypy/dist/pypy/translator/llvm/funcrepr.py Sat Jun 11 00:01:56 2005 @@ -21,8 +21,8 @@ from pypy.translator.llvm.representation import SimpleRepr from pypy.translator.llvm.typerepr import TypeRepr, PointerTypeRepr -debug = True -lazy_debug = True +debug = False +lazy_debug = False INTRINSIC_OPS = ["lt", "le", "eq", "ne", "gt", "ge", "is_", "is_true", "len", "neg", "pos", "invert", "add", "sub", "mul", "truediv", @@ -31,7 +31,7 @@ "inplace_truediv", "inplace_floordiv", "inplace_div", "inplace_mod", "inplace_pow", "inplace_lshift", "inplace_rshift", "inplace_and", "inplace_or", "inplace_xor", - "contains", "alloc_and_set", "issubtype", "type", "ord"] + "contains", "alloc_and_set", "issubtype", "type", "ord" ] C_SIMPLE_TYPES = {annmodel.SomeChar: "char", annmodel.SomeString: "char*", @@ -82,9 +82,7 @@ l_functions = {} def get(obj, gen): if isinstance(obj, lltype._func): - print "1a)" if obj._callable not in FunctionRepr.l_functions: - print "1b)" FunctionRepr.l_functions[obj._callable] = FunctionRepr(obj, gen) return FunctionRepr.l_functions[obj._callable] return None @@ -115,36 +113,29 @@ self.gen = gen self.func = function self.translator = gen.translator - if debug: print "init 1a)" - #if debug: print 'QQQ',function.name,'QQQ' - #if debug: print "init 1b)" - print function, function.__class__ + if debug: + print function, function.__class__ self.name = gen.get_global_tmp(function._name) - if debug: print "init 2)" self.graph = function.graph self.annotator = gen.translator.annotator self.blocknum = {} self.allblocks = [] self.pyrex_source = "" self.dependencies = sets.Set() - if debug: print "init 3)" self.type = self.gen.get_repr(function._TYPE) - if debug: print "init 4)" self.l_args = [self.gen.get_repr(ar) for ar in self.graph.startblock.inputargs] self.dependencies.add(self.type) self.dependencies.update(self.l_args) - if debug: print "init 8)" self.l_default_args = None remove_double_links(self.translator, self.graph) - print "init 9)" self.get_bbs() - print "init done" lazy_attributes = ['llvm_func', 'lblocks'] def setup(self): - print "setup" + if debug: + print "setup" self.se = True self.lblocks = [] self.build_bbs() @@ -197,10 +188,11 @@ l_args = [self.gen.get_repr(arg) for arg in args] if len(l_args) - 1 < len(self.l_args): if self.func.func_defaults is None: - for l_a in l_args: - print l_a, l_a.llvmname(), - for l_a in self.l_args: - print l_a, l_a.llvmname(), + if debug: + for l_a in l_args: + print l_a, l_a.llvmname(), + for l_a in self.l_args: + print l_a, l_a.llvmname(), assert self.func.func_defaults is not None if self.l_default_args is None: self.l_default_args = [self.gen.get_repr(Constant(de)) @@ -271,6 +263,9 @@ return l_arg0 = self.gen.get_repr(op.args[0]) self.l_func.dependencies.add(l_arg0) + if op.opname.startswith("cast_") or op.opname.startswith("same_as") or op.opname.endswith("_is_true"): + self.lblock.cast(l_target, l_arg0) + return l_op = getattr(l_arg0, "op_" + op.opname, None) if l_op is not None: l_op(l_target, op.args, self.lblock, self.l_func) @@ -486,7 +481,8 @@ def setup(self): f = self.gen.rtyper.getfunctionptr(self.function)._obj - print "EntryFunctionRepr", f + if debug: + print "EntryFunctionRepr", f self.l_function = self.gen.get_repr(f) self.dependencies.add(self.l_function) #XXX clean this up @@ -544,7 +540,8 @@ return fd def llvmfuncdef(self): - print self.l_function.l_args + if debug: + print self.l_function.l_args s = "%s %s(" % (self.l_function.type.l_returntype.typename(), self.name) s += ", ".join([a.typed_name() for a in self.l_function.l_args]) + ")" return s Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Sat Jun 11 00:01:56 2005 @@ -33,7 +33,7 @@ from pypy.translator.llvm import reprmap -debug = True +debug = False def llvmcompile(transl, optimize=False): @@ -75,11 +75,7 @@ for mod in [representation, funcrepr, typerepr, pointerrepr]: self.repr_classes += [getattr(mod, s) for s in dir(mod) if "Repr" in s] - #if debug: - # print 'LLVMGenerator before repr_classes=', len(self.repr_classes), self.repr_classes self.repr_classes = [c for c in self.repr_classes if hasattr(c, "get")] - #if debug: - # print 'LLVMGenerator after repr_classes=', len(self.repr_classes), self.repr_classes self.llvm_reprs = {} self.depth = 0 self.entryname = self.translator.functions[0].__name__ @@ -94,6 +90,8 @@ from pypy.tool.udir import udir name = self.entryname llvmfile = udir.join('%s.ll' % name) + if debug: + print "llvmfile:", llvmfile f = llvmfile.open('w') self.write(f) f.close() @@ -159,22 +157,16 @@ except AttributeError: pass for cl in self.repr_classes: - if 0: #debug: + if debug and 0: print 'try cl.get(obj, self) where cl=', cl try: g = cl.get(obj, self) - #if debug: - # print 'A) g=', g except AttributeError: continue - #if debug: - # print 'B) g=', g if g is not None: self.llvm_reprs[key] = g self.local_counts[g] = 0 self.depth -= 1 - #if debug: - # print 'C) should return here' return g raise CompileError, "Can't get repr of %s, %s" % (obj, obj.__class__) Modified: pypy/dist/pypy/translator/llvm/lazyattribute.py ============================================================================== --- pypy/dist/pypy/translator/llvm/lazyattribute.py (original) +++ pypy/dist/pypy/translator/llvm/lazyattribute.py Sat Jun 11 00:01:56 2005 @@ -2,7 +2,7 @@ import sets -debug = True +debug = False def create_property(cls, la, name): def get(self): Modified: pypy/dist/pypy/translator/llvm/llvmbc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/llvmbc.py (original) +++ pypy/dist/pypy/translator/llvm/llvmbc.py Sat Jun 11 00:01:56 2005 @@ -94,6 +94,15 @@ l_a.typed_name(), l_b.llvmname()) self.instructions.append(s) + #Shift instructions + def shift_instruction(self, instr, l_target, l_a, l_b): + self.phi_done = True + assert l_target.llvmtype() == l_a.llvmtype() + #assert l_b.llvmtype() == 'ubyte' #or cast to ubyte or assuma nothing goes wrong + s = "%s = %s %s, ubyte %s" % (l_target.llvmname(), instr, + l_a.typed_name(), l_b.llvmname()) + self.instructions.append(s) + #Memory access instructions def load(self, l_target, l_pter): self.phi_done = True Modified: pypy/dist/pypy/translator/llvm/pointerrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/pointerrepr.py (original) +++ pypy/dist/pypy/translator/llvm/pointerrepr.py Sat Jun 11 00:01:56 2005 @@ -11,7 +11,7 @@ from pypy.translator.llvm import representation from pypy.translator.llvm import typerepr -debug = True +debug = False class PointerRepr(representation.LLVMRepr): def __init__(self, ptr, gen): @@ -56,4 +56,4 @@ def typename(self): return self.l_to.typename() - \ No newline at end of file + Modified: pypy/dist/pypy/translator/llvm/representation.py ============================================================================== --- pypy/dist/pypy/translator/llvm/representation.py (original) +++ pypy/dist/pypy/translator/llvm/representation.py Sat Jun 11 00:01:56 2005 @@ -253,18 +253,18 @@ def llvmname(self): return repr(self.value) - def cast_to_unsigned(self, l_val, lblock, l_function): - if self.type.annotation.unsigned: - return self - else: - return IntRepr(annmodel.SomeInteger(True, True), - self.value, self.gen) - - def cast_to_signed(self, l_val, lblock, l_function): - if not self.type.annotation.unsigned: - return self - else: - return IntRepr(annmodel.SomeInteger(), self.value, self.gen) + #def cast_to_unsigned(self, l_val, lblock, l_function): + # if self.type.annotation.unsigned: + # return self + # else: + # return IntRepr(annmodel.SomeInteger(True, True), + # self.value, self.gen) + # + #def cast_to_signed(self, l_val, lblock, l_function): + # if not self.type.annotation.unsigned: + # return self + # else: + # return IntRepr(annmodel.SomeInteger(), self.value, self.gen) class VariableRepr(LLVMRepr): def get(obj, gen): @@ -290,11 +290,10 @@ return "%" + self.var.name def __getattr__(self, name): - print "getattr called", name, self.type.typename() + if debug: + print "getattr called", name, self.type.typename() if name.startswith("op_"): return getattr(self.type, "t_" + name, None) - elif name.startswith("cast_"): - return getattr(self.type, name, None) else: raise AttributeError, ("VariableRepr instance has no attribute %s" % repr(name)) @@ -363,6 +362,6 @@ if name.startswith("op_"): return getattr(self.type, "t_" + name, None) else: - raise AttributeError, ("VariableRepr instance has no attribute %s" + raise AttributeError, ("StringRepr instance has no attribute %s" % repr(name)) Modified: pypy/dist/pypy/translator/llvm/seqrepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/seqrepr.py (original) +++ pypy/dist/pypy/translator/llvm/seqrepr.py Sat Jun 11 00:01:56 2005 @@ -272,7 +272,7 @@ l_func.dependencies.update(l_args) l_tmp = self.gen.get_local_tmp(PointerTypeRepr(l_target.llvmtype(), self.gen), l_func) - cast = getattr(l_args[1], "cast_to_unsigned", None) + cast = getattr(l_args[1], "cast_to_unsigned", None) #XXX that method is gone now, need to change this too! if cast is not None: l_unsigned = cast(l_args[1], lblock, l_func) else: Modified: pypy/dist/pypy/translator/llvm/typerepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/typerepr.py (original) +++ pypy/dist/pypy/translator/llvm/typerepr.py Sat Jun 11 00:01:56 2005 @@ -24,8 +24,8 @@ else: BYTES_IN_INT = 8 -lazy_debug = True -debug = True +lazy_debug = False +debug = False class TypeRepr(LLVMRepr): def get(obj, gen): @@ -77,39 +77,64 @@ class SignedTypeRepr(TypeRepr): - directly_supported_ops = { + directly_supported_binary_ops = { "int_add": "add", "int_sub": "sub", "int_mul": "mul", "int_div": "div", "int_mod": "rem", "int_xor": "xor", - "int_and_": "and", + "int_and": "and", + "int_lshift": "shl", + "int_rshift": "shr", + "int_or": "or", "int_eq": "seteq", "int_ne": "setne", "int_gt": "setgt", "int_ge": "setge", "int_lt": "setlt", "int_le": "setle"} - + def __init__(self, gen): if debug: print "SignedTypeRepr" self.gen = gen def t_op(self, opname, l_target, args, lblock, l_func): - if opname in SignedTypeRepr.directly_supported_ops: + if opname in SignedTypeRepr.directly_supported_binary_ops: assert len(args) == 2 l_args = [self.gen.get_repr(arg) for arg in args] l_func.dependencies.update(l_args) - lblock.binary_instruction( - SignedTypeRepr.directly_supported_ops[opname], l_target, - l_args[0], l_args[1]) + l_op = SignedTypeRepr.directly_supported_binary_ops[opname] + if l_op in ('shl', 'shr'): #feel free to refactor this + lblock.shift_instruction( + l_op, l_target, + l_args[0], l_args[1]) + else: + lblock.binary_instruction( + l_op, l_target, + l_args[0], l_args[1]) + + def t_op_int_pos(self, l_target, args, lblock, l_func): + pass + + def t_op_int_neg(self, l_target, args, lblock, l_func): + l_arg = self.gen.get_repr(args[0]) + l_func.dependencies.add(l_arg) + lblock.instruction("%s = sub int 0, %s" % (l_target.llvmname(), + l_arg.llvmname())) + + def t_op_int_invert(self, l_target, args, lblock, l_func): + l_arg = self.gen.get_repr(args[0]) + l_func.dependencies.add(l_arg) + lblock.instruction("%s = xor int -1, %s" % (l_target.llvmname(), + l_arg.llvmname())) - def t_op_int_is_true(self, l_target, args, lblock, l_func): + def t_op_int_abs(self, l_target, args, lblock, l_func): l_arg = self.gen.get_repr(args[0]) l_func.dependencies.add(l_arg) - lblock.cast(l_target, l_arg) + lblock.instruction("%s = and int 2147483647, %s" % (l_target.llvmname(), + l_arg.llvmname())) def typename(self): return "int" @@ -138,18 +163,12 @@ def typename(self): return "bool" - def t_op_same_as(self, l_target, args, lblock, l_func): - l_arg0 = self.gen.get_repr(args[0]) - l_func.dependencies.add(l_arg0) - lblock.instruction("%s = or %s, false" % (l_target.llvmname(), - l_arg0.typed_name())) - def llvmsize(self): return 1 class FloatTypeRepr(TypeRepr): - directly_supported_ops = { + directly_supported_binary_ops = { "float_add": "add", "float_sub": "sub", "float_mul": "mul", @@ -173,12 +192,12 @@ return "double" def t_op(self, opname, l_target, args, lblock, l_func): - if opname in FloatTypeRepr.directly_supported_ops: + if opname in FloatTypeRepr.directly_supported_binary_ops: assert len(args) == 2 l_args = [self.gen.get_repr(arg) for arg in args] l_func.dependencies.update(l_args) lblock.binary_instruction( - FloatTypeRepr.directly_supported_ops[opname], l_target, + FloatTypeRepr.directly_supported_binary_ops[opname], l_target, l_args[0], l_args[1]) def llvmsize(self): @@ -268,25 +287,25 @@ def typename(self): return self.name - def cast_to_signed(self, l_val, lblock, l_function): - if not self.annotation.unsigned: - return l_val - ann = annmodel.SomeInteger() - l_type = self.gen.get_repr(ann) - l_tmp = self.gen.get_local_tmp(l_type, l_function) - l_function.dependencies.update([l_type, l_tmp]) - lblock.cast(l_tmp, l_val, l_type) - return l_tmp - - def cast_to_unsigned(self, l_val, lblock, l_function): - if self.annotation.unsigned: - return l_val - ann = annmodel.SomeInteger(True, True) - l_type = self.gen.get_repr(ann) - l_tmp = self.gen.get_local_tmp(l_type, l_function) - l_function.dependencies.update([l_type, l_tmp]) - lblock.cast(l_tmp, l_val, l_type) - return l_tmp + #def cast_to_signed(self, l_val, lblock, l_function): + # if not self.annotation.unsigned: + # return l_val + # ann = annmodel.SomeInteger() + # l_type = self.gen.get_repr(ann) + # l_tmp = self.gen.get_local_tmp(l_type, l_function) + # l_function.dependencies.update([l_type, l_tmp]) + # lblock.cast(l_tmp, l_val, l_type) + # return l_tmp + # + #def cast_to_unsigned(self, l_val, lblock, l_function): + # if self.annotation.unsigned: + # return l_val + # ann = annmodel.SomeInteger(True, True) + # l_type = self.gen.get_repr(ann) + # l_tmp = self.gen.get_local_tmp(l_type, l_function) + # l_function.dependencies.update([l_type, l_tmp]) + # lblock.cast(l_tmp, l_val, l_type) + # return l_tmp class SimpleTypeRepr(TypeRepr): def get(obj, gen): From arigo at codespeak.net Sat Jun 11 00:11:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 11 Jun 2005 00:11:13 +0200 (CEST) Subject: [pypy-svn] r13283 - in pypy/dist/pypy: rpython translator/genc/test Message-ID: <20050610221113.1311B27B4F@code1.codespeak.net> Author: arigo Date: Sat Jun 11 00:11:09 2005 New Revision: 13283 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Log: Bug fix in rtyper. Simplified test. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sat Jun 11 00:11:09 2005 @@ -280,6 +280,8 @@ self.s_result = rtyper.binding(spaceop.result) self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] self.r_result = rtyper.getrepr(self.s_result) + for r in self.args_r + [self.r_result]: + r.setup() def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, Modified: pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py (original) +++ pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Sat Jun 11 00:11:09 2005 @@ -36,19 +36,33 @@ assert result == (1, 5) def test_get_set_del_slice(self): - def get_set_del_nonneg_slice(l=list): # no neg slices for now! + def get_set_del_nonneg_slice(): # no neg slices for now! + l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] del l[:1] - del l[len(l)-1:] + bound = len(l)-1 + if bound >= 0: + del l[bound:] del l[2:4] - l[:1] = [3] - l[len(l)-1:] = [9] - l[2:4] = [8,11] - return l[:2], l[5:], l[3:5] + #l[:1] = [3] + #bound = len(l)-1 + #assert bound >= 0 + #l[bound:] = [9] no setting slice into lists for now + #l[2:4] = [8,11] + l[0], l[-1], l[2], l[3] = 3, 9, 8, 11 + + list_3_c = l[:2] + list_9 = l[5:] + list_11_h = l[3:5] + return (len(l), l[0], l[1], l[2], l[3], l[4], l[5], + len(list_3_c), list_3_c[0], list_3_c[1], + len(list_9), list_9[0], + len(list_11_h), list_11_h[0], list_11_h[1]) fn = self.getcompiled(get_set_del_nonneg_slice) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) + result = fn() + assert result == (6, 3, 'c', 8, 11, 'h', 9, + 2, 3, 'c', + 1, 9, + 2, 11, 'h') def test_slice_long(self): "the parent's test_slice_long() makes no sense here" From hpk at codespeak.net Sat Jun 11 15:31:07 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 11 Jun 2005 15:31:07 +0200 (CEST) Subject: [pypy-svn] r13297 - pypy/dist/pypy/documentation Message-ID: <20050611133107.7CEFA27B4A@code1.codespeak.net> Author: hpk Date: Sat Jun 11 15:31:06 2005 New Revision: 13297 Added: pypy/dist/pypy/documentation/faq.txt Log: issue76 chatting starting the FAQ but mostly for testing if the issue-commit integration mails still work. Added: pypy/dist/pypy/documentation/faq.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/documentation/faq.txt Sat Jun 11 15:31:06 2005 @@ -0,0 +1,13 @@ + +Frequently Asked Questions +========================== + +How fast is PyPy? + + As of June 2005, PyPy still runs on top of CPython and thus + is slower by a factor of 2000 compared to CPython. We don't + know yet how fast it will be once we complete our translation + efforts, aimed at a first static self-contained low-level + translated version. + + From pedronis at codespeak.net Sat Jun 11 23:08:40 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 11 Jun 2005 23:08:40 +0200 (CEST) Subject: [pypy-svn] r13307 - in pypy/dist/pypy: rpython translator Message-ID: <20050611210840.327E627B88@code1.codespeak.net> Author: pedronis Date: Sat Jun 11 23:08:39 2005 New Revision: 13307 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/transform.py Log: always annotator simplify before specializing, made transform_dead_code idempotent Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sat Jun 11 23:08:39 2005 @@ -61,6 +61,8 @@ def specialize(self): """Main entry point: specialize all annotated blocks of the program.""" + # specialize depends on annotator simplifications + self.annotator.simplify() # first make sure that all functions called in a group have exactly # the same signature, by hacking their flow graphs if needed perform_normalizations(self.annotator) Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Sat Jun 11 23:08:39 2005 @@ -303,6 +303,8 @@ c2 = Constant(AssertionError(msg)) errlink = Link([c1, c2], graph.exceptblock) block.recloseblock(errlink, *block.exits) + # record new link to make the transformation idempotent + self.links_followed[errlink] = True # fix the annotation of the exceptblock.inputargs etype, evalue = graph.exceptblock.inputargs s_type = annmodel.SomeObject() From pedronis at codespeak.net Sun Jun 12 00:34:59 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 12 Jun 2005 00:34:59 +0200 (CEST) Subject: [pypy-svn] r13308 - in pypy/dist/pypy: annotation translator Message-ID: <20050611223459.A4FFB27B4C@code1.codespeak.net> Author: pedronis Date: Sun Jun 12 00:34:56 2005 New Revision: 13308 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/annotation/specialize.py pypy/dist/pypy/translator/annrpython.py Log: make override a special case of specialization, fix bug uncovered by this in query_spaceop_callable that was not appending a s_self argument when classdef was present renaming _annspecialcase_ to _specialize_ again will happen later Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sun Jun 12 00:34:56 2005 @@ -327,8 +327,8 @@ else: implicit_init = None - pbc, dontcarememo = self.query_spaceop_callable(spaceop, - implicit_init=implicit_init) + pbc, dontcaresc = self.query_spaceop_callable(spaceop, + implicit_init=implicit_init) nonnullcallables = [] for func, classdef in pbc.prebuiltinstances.items(): @@ -387,10 +387,10 @@ return unionof(*results) # decide_callable(position, func, args, mono) -> callb, key - # query_spaceop_callable(spaceop) -> pbc, memo + # query_spaceop_callable(spaceop) -> pbc, isspecialcase # get_s_init(decided_cls) -> classdef, s_undecided_init - def query_spaceop_callable(self, spaceop, implicit_init=None): # -> s_pbc, memo + def query_spaceop_callable(self, spaceop, implicit_init=None): # -> s_pbc, specialcase self.enter(None) try: if implicit_init is None: @@ -408,10 +408,15 @@ argsvars = spaceop.args[1:] args_s = [self.annotator.binding(v) for v in argsvars] args = self.build_args(spaceop.opname, args_s) - if init_classdef: - args = args.prepend(SomeInstance(init_classdef)) func, classdef = s_obj.prebuiltinstances.items()[0] + + if init_classdef: + args = args.prepend(SomeInstance(init_classdef)) + elif isclassdef(classdef): + s_self = SomeInstance(classdef) + args = args.prepend(s_self) + func, key = decide_callable(self, spaceop, func, args, mono=True) if key is None: @@ -444,6 +449,21 @@ else: return classdef, None + def get_inputcells(self, func, args): + # parse the arguments according to the function we are calling + signature = cpython_code_signature(func.func_code) + defs_s = [] + if func.func_defaults: + for x in func.func_defaults: + defs_s.append(self.immutablevalue(x)) + try: + inputcells = args.match_signature(signature, defs_s) + except ArgErr, e: + raise TypeError, "signature mismatch: %s" % e.getmsg(args, func.__name__) + + return inputcells + + def pycall(self, func, args, mono): if func is None: # consider None as a NULL function pointer return SomeImpossibleValue() @@ -474,17 +494,7 @@ assert isinstance(func, FunctionType), "[%s] expected function, got %r" % (self.whereami(), func) - # parse the arguments according to the function we are calling - signature = cpython_code_signature(func.func_code) - defs_s = [] - if func.func_defaults: - for x in func.func_defaults: - defs_s.append(self.immutablevalue(x)) - try: - inputcells = args.match_signature(signature, defs_s) - except ArgErr, e: - assert False, 'ABOUT TO IGNORE %r' % e # we should take care that we don't end up here anymore - return SomeImpossibleValue() + inputcells = self.get_inputcells(func, args) r = self.annotator.recursivecall(func, self.position_key, inputcells) Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Sun Jun 12 00:34:56 2005 @@ -7,38 +7,41 @@ Possibly subclass and pass an instance to the annotator to control special casing during annotation """ - def getspecialcase(pol, kind, obj): - if hasattr(obj, '_annspecialcase_'): - sc = obj._annspecialcase_.split(':') - assert len(sc) ==2, "_annspecialcase_ should have the form kind:tag" - if sc[0] == kind: - return sc[1] - assert sc[0] in ('override', 'specialize'), "_annspecialcase_ kinds are only 'override', 'specialize'" - return None - - def override(pol, func, inputcells): - tag = pol.getspecialcase('override', func) - if tag is None: - return None - try: - override = getattr(pol, 'override__%s' % tag) - except AttributeError: - raise AttributeError, "%s override tag found in user program but not defined in annotation policy %s" % (tag, pol) - - return override(*inputcells) - def specialize(pol, bookkeeper, spaceop, func, args, mono): - tag = pol.getspecialcase('specialize', func) - if tag is None: - return pol.default_specialize(bookkeeper, spaceop, func, args, mono) + if hasattr(func, '_annspecialcase_'): + directive = func._annspecialcase_ + if directive.startswith('specialize:'): + directive = directive[len('specialize:'):] + tag_mod = directive.split(':', 1) + if len(tag_mod) == 1: + tag, = tag_mod + mod = None + else: + tag, mod = tag_mod + else: + return pol.default_specialize(bookkeeper, None, spaceop, func, args, mono) try: specialize = getattr(pol, 'specialize__%s' % tag) except AttributeError: raise AttributeError, "%s specialize tag found in user program but not defined in annotation policy %s" % (tag, pol) - return specialize(bookkeeper, spaceop, func, args, mono) - + return specialize(bookkeeper, mod, spaceop, func, args, mono) + + def specialize__override(pol, bookkeeper, mod, spaceop, func, args, mono): + from pypy.annotation.model import SomeObject + override_tag = mod + + try: + override = getattr(pol, 'override__%s' % override_tag) + except AttributeError: + raise AttributeError, "'override:%s' found in user program but not defined in annotation policy %s" % (override_tag, pol) + + inputcells = bookkeeper.get_inputcells(func, args) + r = override(*inputcells) + + assert isinstance(r, SomeObject) + return r # common specializations Modified: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- pypy/dist/pypy/annotation/specialize.py (original) +++ pypy/dist/pypy/annotation/specialize.py Sun Jun 12 00:34:56 2005 @@ -19,10 +19,10 @@ key = bookkeeper.annotator.policy.specialize(bookkeeper, spaceop, func, args, mono) if key is not None: - assert mono, "not-static call to specialized %s" % func if isinstance(key, SomeObject): # direct computation return None, key + assert mono, "not-static call to specialized %s" % func if isinstance(key, tuple): # cache specialization try: @@ -47,7 +47,7 @@ return func, key -def default_specialize(bookkeeper, spaceop, func, args, mono): +def default_specialize(bookkeeper, dontcare, spaceop, func, args, mono): from pypy.interpreter.pycode import CO_VARARGS if isinstance(func, types.FunctionType) and func.func_code.co_flags & CO_VARARGS: # calls to *arg functions: create one version per number of args @@ -121,8 +121,9 @@ # ____________________________________________________________________________ # specializations -def memo(bookkeeper, spaceop, func, args, mono): +def memo(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" + assert mono, "not-static call to memoized %s" % func from pypy.annotation.model import unionof # call the function now, and collect possible results arglist_s, kwds_s = args.unpack() @@ -171,7 +172,7 @@ # l.append(name) # return func, "__".join(l) -def ctr_location(bookkeeper, spaceop, orig_cls, args, mono): +def ctr_location(bookkeeper, mod, spaceop, orig_cls, args, mono): """NOT_RPYTHON""" from pypy.annotation.model import SomeInstance v = spaceop.result @@ -185,14 +186,14 @@ return cls def argvalue(i): - def specialize_argvalue(bookkeeper, spaceop, func, args, mono): + def specialize_argvalue(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" ignore, args_w = args.flatten() return func, args_w[i].const return specialize_argvalue def argtype(i): - def specialize_argtype(bookkeeper, spaceop, func, args, mono): + def specialize_argtype(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" ignore, args_w = args.flatten() return func, args_w[i].knowntype Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sun Jun 12 00:34:56 2005 @@ -13,8 +13,6 @@ pass class BasicAnnotatorPolicy: - def override(pol, func, inputcells): - return None def specialize(pol, bookkeeper, spaceop, func, args, mono): return None @@ -251,9 +249,6 @@ #___ interface for annotator.bookkeeper _______ def recursivecall(self, func, position_key, inputcells): - overriden = self.policy.override(func, inputcells) - if overriden is not None: - return overriden parent_fn, parent_block, parent_index = position_key graph = self.getflowgraph(func, parent_fn, position_key) # self.notify[graph.returnblock] is a dictionary of call From pedronis at codespeak.net Sun Jun 12 01:56:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 12 Jun 2005 01:56:07 +0200 (CEST) Subject: [pypy-svn] r13309 - in pypy/dist/pypy: annotation translator translator/test Message-ID: <20050611235607.B54C127B45@code1.codespeak.net> Author: pedronis Date: Sun Jun 12 01:56:05 2005 New Revision: 13309 Added: pypy/dist/pypy/translator/test/test_annsimplify2.py (contents, props changed) Modified: pypy/dist/pypy/annotation/specialize.py pypy/dist/pypy/translator/transform.py Log: added annotation transformation that substitute specialzed callables with the specialized version at call sites, and substitutes special case calls with 'specialcase' operations... reworked specialization caching for idempotence of the transformation Modified: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- pypy/dist/pypy/annotation/specialize.py (original) +++ pypy/dist/pypy/annotation/specialize.py Sun Jun 12 01:56:05 2005 @@ -28,10 +28,14 @@ try: func = bookkeeper.cachespecializations[key] except KeyError: - postfix = key - if postfix[0] is func: - postfix = postfix[1:] - func = bookkeeper.cachespecializations[key] = clone(func, postfix) + if key[0] is func: + postfix = key[1:] + else: + postfix = key + newfunc = clone(func, postfix) + if key[0] is func: + bookkeeper.cachespecializations[(newfunc,) + postfix] = newfunc + func = bookkeeper.cachespecializations[key] = newfunc elif isinstance(key, str): # specialization explicit in operation annotation postfix = key Added: pypy/dist/pypy/translator/test/test_annsimplify2.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/test/test_annsimplify2.py Sun Jun 12 01:56:05 2005 @@ -0,0 +1,29 @@ +from pypy.annotation.policy import AnnotatorPolicy +from pypy.translator.annrpython import RPythonAnnotator +from pypy.objspace.flow import model as flowmodel + +def test_simplify_spec(): + def g(*args): + pass + def f(): + g(1,2) + g(1,2,3) + g() + a = RPythonAnnotator(policy=AnnotatorPolicy()) + s = a.build_types(f,[]) + calls = [] + for block in a.annotated: + for op in block.operations: + if op.opname == 'simple_call' and op.args[0] == flowmodel.Constant(g): + calls.append(op) + assert len(calls) == 3 + a.simplify() + spec_gs = [op.args[0].value for op in calls] + assert len(spec_gs) == 3 + assert g not in spec_gs + assert spec_gs[0] != spec_gs[1] + assert spec_gs[0] != spec_gs[2] + assert spec_gs[1] != spec_gs[2] + a.simplify() + assert spec_gs == [op.args[0].value for op in calls] # idempotent + Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Sun Jun 12 01:56:05 2005 @@ -316,7 +316,25 @@ # make sure the bookkeeper knows about AssertionError self.bookkeeper.getclassdef(AssertionError) +def transform_specialization(self): + for block in fully_annotated_blocks(self): + for op in block.operations: + if op.opname in ('simple_call', 'call_args'): + callb = self.binding(op.args[0], extquery=True) + if isinstance(callb, annmodel.SomePBC): + if len(callb.prebuiltinstances) == 1: + specialized_callb, specialcase = self.bookkeeper.query_spaceop_callable(op) + if specialcase or callb != specialized_callb: + if not specialcase: + op.args[0] = Constant(specialized_callb.prebuiltinstances.keys()[0]) + else: + if op.opname == 'simple_call': + op.opname = intern('simple_specialcase') + else: + op.opname = intern('specialcase_args') + default_extra_passes = [ + transform_specialization, transform_allocate, ] From pedronis at codespeak.net Sun Jun 12 02:38:25 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 12 Jun 2005 02:38:25 +0200 (CEST) Subject: [pypy-svn] r13310 - in pypy/dist/pypy: rpython rpython/test translator Message-ID: <20050612003825.1F97427B4A@code1.codespeak.net> Author: pedronis Date: Sun Jun 12 02:38:23 2005 New Revision: 13310 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/transform.py Log: let annotation simplify a subset of blocks use this to guarantee that block low-level helpers blocks created and annotated during rtyping are simplified too in annotate_lowlevel_helper. Use the latter in test_llann Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Sun Jun 12 02:38:23 2005 @@ -15,6 +15,11 @@ ## saved = annotator.policy ## annotator.policy = LowLevelAnnotatorPolicy() ## try: - annotator.build_types(ll_function, args_s) + oldblocks = annotator.annotated.keys() + s = annotator.build_types(ll_function, args_s) + newblocks = [block for block in annotator.annotated.iterkeys() if block not in oldblocks] + # invoke annotation simplifcations for the new blocks + annotator.simplify(block_subset=newblocks) ## finally: ## annotator.policy = saved + return s Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Sun Jun 12 02:38:23 2005 @@ -1,6 +1,6 @@ from pypy.rpython.lltype import * from pypy.annotation import model as annmodel - +from pypy.rpython.annlowlevel import annotate_lowlevel_helper class TestLowLevelAnnotateTestCase: objspacename = 'flow' @@ -13,7 +13,7 @@ s = malloc(S) return s.v a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_simple2(self): @@ -23,7 +23,7 @@ s = malloc(S2) return s.a.v+s.b.v a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_array(self): @@ -32,7 +32,7 @@ a = malloc(A, 1) return a[0].v a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_prim_array(self): @@ -41,7 +41,7 @@ a = malloc(A, 1) return a[0] a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_prim_array_setitem(self): @@ -51,7 +51,7 @@ a[0] = 3 return a[0] a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_cast_parent(self): @@ -64,7 +64,7 @@ p3 = cast_parent(PS1, p2) return p3 a = self.RPythonAnnotator() - s = a.build_types(llf, [annmodel.SomePtr(PS1)]) + s = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PS1)]) assert isinstance(s, annmodel.SomePtr) assert s.ll_ptrtype == PS1 @@ -78,7 +78,7 @@ p3 = cast_parent(PS1, p2) return p3 a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert isinstance(s, annmodel.SomePtr) assert s.ll_ptrtype == PS1 @@ -88,7 +88,7 @@ a = malloc(A, 1) return len(a) a = self.RPythonAnnotator() - s = a.build_types(llf, []) + s = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_funcptr(self): @@ -97,6 +97,6 @@ def llf(p): return p(0) a = self.RPythonAnnotator() - s = a.build_types(llf, [annmodel.SomePtr(PF)]) + s = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PF)]) assert s.knowntype == int Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sun Jun 12 02:38:23 2005 @@ -301,10 +301,10 @@ else: raise CannotSimplify - def simplify(self): + def simplify(self, block_subset=None): # Generic simplifications from pypy.translator import transform - transform.transform_graph(self) + transform.transform_graph(self, block_subset=block_subset) from pypy.translator import simplify for graph in self.translator.flowgraphs.values(): simplify.eliminate_empty_blocks(graph) Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Sun Jun 12 02:38:23 2005 @@ -29,9 +29,9 @@ # --> # d = alloc_and_set(b, a) -def transform_allocate(self): +def transform_allocate(self, block_subset): """Transforms [a] * b to alloc_and_set(b, a) where b is int.""" - for block in fully_annotated_blocks(self): + for block in block_subset: operations = block.operations[:] n_op = len(operations) for i in range(0, n_op-1): @@ -54,9 +54,9 @@ # --> # e = getslice(a, b, c) -def transform_slice(self): +def transform_slice(self, block_subset): """Transforms a[b:c] to getslice(a, b, c).""" - for block in fully_annotated_blocks(self): + for block in block_subset: operations = block.operations[:] n_op = len(operations) for i in range(0, n_op-1): @@ -71,193 +71,18 @@ op2.result) block.operations[i+1:i+2] = [new_op] -# a(*b) -# --> -# c = newtuple(*b) -# d = newdict() -# e = call(function a, c, d) -# --> -# e = simple_call(a, *b) - -# ---------------------------------------------------------------------- -# The 'call_args' operation is the strangest one. The meaning of its -# arguments is as follows: -# -# call_args(, , , , ...) -# -# The shape must be a constant object, which describes how the remaining -# arguments are regrouped. The class pypy.interpreter.argument.Arguments -# has a method 'fromshape(shape, list-of-args)' that reconstructs a complete -# Arguments instance from this information. Don't try to interpret the -# shape anywhere else, but for reference, it is a 3-tuple: -# (number-of-pos-arg, tuple-of-keyword-names, flag-presence-of-*-arg) -# ---------------------------------------------------------------------- - -## REMOVED: now FlowObjSpace produces 'call_args' operations only -##def transform_simple_call(self): -## """Transforms call(a, (...), {}) to simple_call(a, ...)""" -## for block in self.annotated: -## known_vars = block.inputargs[:] -## operations = [] -## for op in block.operations: -## try: -## if op.opname != 'call': -## raise CannotSimplify -## varargs_cell = self.binding(op.args[1]) -## varkwds_cell = self.binding(op.args[2]) -## arg_cells = self.decode_simple_call(varargs_cell, -## varkwds_cell) -## if arg_cells is None: -## raise CannotSimplify - -## args = [self.reverse_binding(known_vars, c) for c in arg_cells] -## args.insert(0, op.args[0]) -## new_ops = [SpaceOperation('simple_call', args, op.result)] - -## except CannotSimplify: -## new_ops = [op] - -## for op in new_ops: -## operations.append(op) -## known_vars.append(op.result) - -## block.operations = operations - -def transform_dead_op_vars(self): +def transform_dead_op_vars(self, block_subset): # we redo the same simplification from simplify.py, # to kill dead (never-followed) links, # which can possibly remove more variables. from pypy.translator.simplify import transform_dead_op_vars_in_blocks - transform_dead_op_vars_in_blocks(self.annotated) - -# expands the += operation between lists into a basic block loop. -# a = inplace_add(b, c) -# becomes the following graph: -# -# clen = len(c) -# growlist(b, clen) # ensure there is enough space for clen new items -# | -# | (pass all variables to next block, plus i=0) -# V -# ,--> z = lt(i, clen) -# | exitswitch(z): -# | | | False -# | | True `------------------> ...sequel... -# | V -# | x = getitem(c, i) -# | fastappend(b, x) -# | i1 = add(i, 1) -# | | -# `-----' (pass all variables, with i=i1) -# -##def transform_listextend(self): -## allblocks = list(self.annotated) -## for block in allblocks: -## for j in range(len(block.operations)): -## op = block.operations[j] -## if op.opname != 'inplace_add': -## continue -## a = op.result -## b, c = op.args -## s_list = self.bindings.get(b) -## if not isinstance(s_list, annmodel.SomeList): -## continue - -## # new variables -## clen = Variable() -## i = Variable() -## i1 = Variable() -## z = Variable() -## x = Variable() -## dummy = Variable() -## self.setbinding(clen, annmodel.SomeInteger(nonneg=True)) -## self.setbinding(i, annmodel.SomeInteger(nonneg=True)) -## self.setbinding(i1, annmodel.SomeInteger(nonneg=True)) -## self.setbinding(z, annmodel.SomeBool()) -## self.setbinding(x, s_list.s_item) -## self.setbinding(dummy, annmodel.SomeImpossibleValue()) - -## sequel_operations = block.operations[j+1:] -## sequel_exitswitch = block.exitswitch -## sequel_exits = block.exits - -## del block.operations[j:] -## block.operations += [ -## SpaceOperation('len', [c], clen), -## SpaceOperation('growlist', [b, clen], dummy), -## ] -## block.exitswitch = None -## allvars = block.getvariables() - -## condition_block = Block(allvars+[i]) -## condition_block.operations += [ -## SpaceOperation('lt', [i, clen], z), -## ] -## condition_block.exitswitch = z - -## loopbody_block = Block(allvars+[i]) -## loopbody_block.operations += [ -## SpaceOperation('getitem', [c, i], x), -## SpaceOperation('fastappend', [b, x], dummy), -## SpaceOperation('add', [i, Constant(1)], i1), -## ] - -## sequel_block = Block(allvars+[a]) -## sequel_block.operations = sequel_operations -## sequel_block.exitswitch = sequel_exitswitch - -## # link the blocks together -## block.recloseblock( -## Link(allvars+[Constant(0)], condition_block), -## ) -## condition_block.closeblock( -## Link(allvars+[i], loopbody_block, exitcase=True), -## Link(allvars+[b], sequel_block, exitcase=False), -## ) -## loopbody_block.closeblock( -## Link(allvars+[i1], condition_block), -## ) -## sequel_block.closeblock(*sequel_exits) - -## # now rename the variables -- so far all blocks use the -## # same variables, which is forbidden -## renamevariables(self, condition_block) -## renamevariables(self, loopbody_block) -## renamevariables(self, sequel_block) - -## allblocks.append(sequel_block) -## break - -##def renamevariables(self, block): -## """Utility to rename the variables in a block to fresh variables. -## The annotations are carried over from the old to the new vars.""" -## varmap = {} -## block.inputargs = [varmap.setdefault(a, Variable()) -## for a in block.inputargs] -## operations = [] -## for op in block.operations: -## result = varmap.setdefault(op.result, Variable()) -## args = [varmap.get(a, a) for a in op.args] -## op = SpaceOperation(op.opname, args, result) -## operations.append(op) -## block.operations = operations -## block.exitswitch = varmap.get(block.exitswitch, block.exitswitch) -## exits = [] -## for exit in block.exits: -## args = [varmap.get(a, a) for a in exit.args] -## exits.append(Link(args, exit.target, exit.exitcase)) -## block.recloseblock(*exits) -## # carry over the annotations -## for a1, a2 in varmap.items(): -## if a1 in self.bindings: -## self.setbinding(a2, self.bindings[a1]) -## self.annotated[block] = True + transform_dead_op_vars_in_blocks(block_subset) -def transform_dead_code(self): +def transform_dead_code(self, block_subset): """Remove dead code: these are the blocks that are not annotated at all because the annotation considered that no conditional jump could reach them.""" - for block in fully_annotated_blocks(self): + for block in block_subset: for link in block.exits: if link not in self.links_followed: lst = list(block.exits) @@ -316,8 +141,8 @@ # make sure the bookkeeper knows about AssertionError self.bookkeeper.getclassdef(AssertionError) -def transform_specialization(self): - for block in fully_annotated_blocks(self): +def transform_specialization(self, block_subset): + for block in block_subset: for op in block.operations: if op.opname in ('simple_call', 'call_args'): callb = self.binding(op.args[0], extquery=True) @@ -338,18 +163,20 @@ transform_allocate, ] -def transform_graph(ann, extra_passes=default_extra_passes): +def transform_graph(ann, extra_passes=default_extra_passes, block_subset=None): """Apply set of transformations available.""" # WARNING: this produces incorrect results if the graph has been # modified by t.simplify() after it had been annotated. if ann.translator: ann.translator.checkgraphs() - transform_dead_code(ann) + if block_subset is None: + block_subset = list(fully_annotated_blocks(ann)) + print block_subset + transform_dead_code(ann, block_subset) for pass_ in extra_passes: - pass_(ann) - ##transform_listextend(ann) + pass_(ann, block_subset) # do this last, after the previous transformations had a # chance to remove dependency on certain variables - transform_dead_op_vars(ann) + transform_dead_op_vars(ann, block_subset) if ann.translator: ann.translator.checkgraphs() From pedronis at codespeak.net Sun Jun 12 04:44:13 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 12 Jun 2005 04:44:13 +0200 (CEST) Subject: [pypy-svn] r13311 - pypy/dist/pypy/translator Message-ID: <20050612024413.BD36D27B4A@code1.codespeak.net> Author: pedronis Date: Sun Jun 12 04:44:11 2005 New Revision: 13311 Modified: pypy/dist/pypy/translator/transform.py Log: oops, debug print Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Sun Jun 12 04:44:11 2005 @@ -171,7 +171,6 @@ ann.translator.checkgraphs() if block_subset is None: block_subset = list(fully_annotated_blocks(ann)) - print block_subset transform_dead_code(ann, block_subset) for pass_ in extra_passes: pass_(ann, block_subset) From pedronis at codespeak.net Sun Jun 12 04:45:46 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 12 Jun 2005 04:45:46 +0200 (CEST) Subject: [pypy-svn] r13312 - in pypy/dist/pypy: annotation rpython rpython/test translator Message-ID: <20050612024546.A4F8F27B4A@code1.codespeak.net> Author: pedronis Date: Sun Jun 12 04:45:44 2005 New Revision: 13312 Modified: pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/annotation/specialize.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/rpython/test/test_rtyper.py pypy/dist/pypy/translator/annrpython.py Log: - specializations can modify the arguments to pass allong - support for low-level helpers reformulated as specialization, low-level helpers should be able to call each others Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Sun Jun 12 04:45:44 2005 @@ -41,7 +41,7 @@ r = override(*inputcells) assert isinstance(r, SomeObject) - return r + return r, None # common specializations Modified: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- pypy/dist/pypy/annotation/specialize.py (original) +++ pypy/dist/pypy/annotation/specialize.py Sun Jun 12 04:45:44 2005 @@ -17,12 +17,13 @@ fn, block, i = position spaceop = block.operations[i] - key = bookkeeper.annotator.policy.specialize(bookkeeper, spaceop, func, args, mono) + key, new_args = bookkeeper.annotator.policy.specialize(bookkeeper, spaceop, func, args, mono) if key is not None: if isinstance(key, SomeObject): # direct computation return None, key assert mono, "not-static call to specialized %s" % func + args = new_args if isinstance(key, tuple): # cache specialization try: @@ -63,8 +64,8 @@ s_len = args.w_stararg.len() assert s_len.is_constant(), "calls require known number of args" nbargs += s_len.const - return (func, nbargs) - return None # no specialization + return (func, nbargs), args + return None, None # no specialization # helpers @@ -137,7 +138,7 @@ for arglist in possible_arguments(arglist_s): result = func(*arglist) possible_results.append(bookkeeper.immutablevalue(result)) - return unionof(*possible_results) + return unionof(*possible_results), args def possible_arguments(args): from pypy.annotation.model import SomeBool, SomePBC @@ -182,23 +183,23 @@ v = spaceop.result s_ins = bookkeeper.annotator.binding(v, extquery=True) if s_ins is None: - return "Giving_"+v.name + return "Giving_"+v.name, args else: assert isinstance(s_ins, SomeInstance) cls = s_ins.classdef.cls assert issubclass(cls, orig_cls) - return cls + return cls, args def argvalue(i): def specialize_argvalue(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" ignore, args_w = args.flatten() - return func, args_w[i].const + return (func, args_w[i].const), args return specialize_argvalue def argtype(i): def specialize_argtype(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" ignore, args_w = args.flatten() - return func, args_w[i].knowntype + return (func, args_w[i].knowntype), args return specialize_argtype Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Sun Jun 12 04:45:44 2005 @@ -2,24 +2,65 @@ The code needed to flow and annotate low-level helpers -- the ll_*() functions """ -##from pypy.translator.annrpython import BasicAnnotatorPolicy - - -##class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy): - -## def compute_at_fixpoint(self, annotator): -## pass - +from pypy.annotation import model as annmodel +from pypy.annotation.specialize import decide_callable +from pypy.translator.annrpython import BasicAnnotatorPolicy + +def not_const(s_obj): # xxx move it somewhere else + if s_obj.is_constant(): + new_s_obj = annmodel.SomeObject() + new_s_obj.__class__ = s_obj.__class__ + new_s_obj.__dict__ = s_obj.__dict__ + del new_s_obj.const + s_obj = new_s_obj + return s_obj + + +class KeyComp(object): + def __init__(self, val): + self.val = val + def __eq__(self, other): + return self.__class__ == other.__class__ and self.val == other.val + def __ne__(self, other): + return not (self == other) + def __hash__(self): + return hash(self.val) + def __str__(self): + return getattr(self.val, '__name__', self.val) + 'Const' + +class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy): + + def specialize(pol, bookkeeper, spaceop, func, args, mono): + args_s, kwds_s = args.unpack() + assert not kwds_s + if not args_s: + return None, None + key = [func] + new_args_s = [] + for s_obj in args_s: + if isinstance(s_obj, annmodel.SomePBC): + assert s_obj.is_constant(), "ambiguous low-level helper specialization" + key.append(KeyComp(s_obj.const)) + new_args_s.append(s_obj) + else: + new_args_s.append(not_const(s_obj)) + key.append(annmodel.annotation_to_lltype(s_obj)) + return tuple(key), bookkeeper.build_args('simple_call', new_args_s) + def annotate_lowlevel_helper(annotator, ll_function, args_s): -## saved = annotator.policy -## annotator.policy = LowLevelAnnotatorPolicy() -## try: - oldblocks = annotator.annotated.keys() - s = annotator.build_types(ll_function, args_s) - newblocks = [block for block in annotator.annotated.iterkeys() if block not in oldblocks] - # invoke annotation simplifcations for the new blocks - annotator.simplify(block_subset=newblocks) -## finally: -## annotator.policy = saved - return s + saved = annotator.policy + annotator.policy = LowLevelAnnotatorPolicy() + try: + args = annotator.bookkeeper.build_args('simple_call', args_s) + (ll_function, args), key = decide_callable(annotator.bookkeeper, None, ll_function, args, mono=True, unpacked=True) + args_s, kwds_s = args.unpack() + assert not kwds_s + oldblocks = annotator.annotated.keys() + s = annotator.build_types(ll_function, args_s) + newblocks = [block for block in annotator.annotated.iterkeys() if block not in oldblocks] + # invoke annotation simplifications for the new blocks + annotator.simplify(block_subset=newblocks) + finally: + annotator.policy = saved + return s, ll_function Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun Jun 12 04:45:44 2005 @@ -365,36 +365,19 @@ def gendirectcall(self, ll_function, *args_v): rtyper = self.rtyper - spec_key = [ll_function] - spec_name = [ll_function.func_name] args_s = [] for v in args_v: if v.concretetype == Void: s_value = rtyper.binding(v) if not s_value.is_constant(): raise TyperError("non-constant variable of type Void") - key = s_value.const # specialize by constant value args_s.append(s_value) assert isinstance(s_value, annmodel.SomePBC) - suffix = 'Const' else: - key = v.concretetype # specialize by low-level type - args_s.append(annmodel.lltype_to_annotation(key)) - suffix = '' - spec_key.append(key) - spec_name.append(valid_identifier(getattr(key, '__name__', key)) - + suffix) - spec_key = tuple(spec_key) - try: - spec_function = self.rtyper.specialized_ll_functions[spec_key] - except KeyError: - name = '_'.join(spec_name) - spec_function = func_with_new_name(ll_function, name) - # flow and annotate (the copy of) the low-level function - self.rtyper.call_all_setups() # compute ForwardReferences now - annotate_lowlevel_helper(rtyper.annotator, spec_function, args_s) - # cache the result - self.rtyper.specialized_ll_functions[spec_key] = spec_function + args_s.append(annmodel.lltype_to_annotation(v.concretetype)) + + self.rtyper.call_all_setups() # compute ForwardReferences now + dontcare, spec_function = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s) # build the 'direct_call' operation f = self.rtyper.getfunctionptr(spec_function) Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Sun Jun 12 04:45:44 2005 @@ -13,7 +13,7 @@ s = malloc(S) return s.v a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_simple2(self): @@ -23,7 +23,7 @@ s = malloc(S2) return s.a.v+s.b.v a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_array(self): @@ -32,7 +32,7 @@ a = malloc(A, 1) return a[0].v a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_prim_array(self): @@ -41,7 +41,7 @@ a = malloc(A, 1) return a[0] a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_prim_array_setitem(self): @@ -51,7 +51,7 @@ a[0] = 3 return a[0] a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_cast_parent(self): @@ -64,7 +64,7 @@ p3 = cast_parent(PS1, p2) return p3 a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PS1)]) + s, dontcare = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PS1)]) assert isinstance(s, annmodel.SomePtr) assert s.ll_ptrtype == PS1 @@ -78,7 +78,7 @@ p3 = cast_parent(PS1, p2) return p3 a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert isinstance(s, annmodel.SomePtr) assert s.ll_ptrtype == PS1 @@ -88,7 +88,7 @@ a = malloc(A, 1) return len(a) a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, []) + s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int def test_funcptr(self): @@ -97,6 +97,58 @@ def llf(p): return p(0) a = self.RPythonAnnotator() - s = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PF)]) + s, dontcare = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PF)]) assert s.knowntype == int + + def test_ll_calling_ll(self): + A = GcArray(Float) + B = GcArray(Signed) + def ll_make(T, n): + x = malloc(T, n) + return x + def ll_get(T, x, i): + return x[i] + def llf(): + a = ll_make(A, 3) + b = ll_make(B, 2) + a[0] = 1.0 + b[1] = 3 + y0 = ll_get(A, a, 1) + y1 = ll_get(B, b, 1) + # + a2 = ll_make(A, 4) + a2[0] = 2.0 + return ll_get(A, a2, 1) + a = self.RPythonAnnotator() + s, llf2 = annotate_lowlevel_helper(a, llf, []) + assert llf2 is llf + assert s == annmodel.SomeFloat() + g = a.translator.getflowgraph(llf) + for_ = {} + for block in a.annotated: + for op in block.operations: + if op.opname == 'simple_call' and op.args[0].value.__name__.startswith("ll_"): + for_[tuple([x.value for x in op.args[0:2]])] = True + assert len(for_) == 4 + vTs = [] + for func, T in for_.keys(): + g = a.translator.getflowgraph(func) + args = g.getargs() + rv = g.getreturnvar() + if len(args) == 2: + vT, vn = args + vTs.append(vT) + assert a.binding(vT) == annmodel.SomePBC({T: True}) + assert a.binding(vn).knowntype == int + assert a.binding(rv).ll_ptrtype.TO == T + else: + vT, vp, vi = args + vTs.append(vT) + assert a.binding(vT) == annmodel.SomePBC({T: True}) + assert a.binding(vi).knowntype == int + assert a.binding(vp).ll_ptrtype.TO == T + assert a.binding(rv) == annmodel.lltype_to_annotation(T.OF) + return a, vTs + + Modified: pypy/dist/pypy/rpython/test/test_rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtyper.py (original) +++ pypy/dist/pypy/rpython/test/test_rtyper.py Sun Jun 12 04:45:44 2005 @@ -55,3 +55,11 @@ graph = t.getflowgraph(f) assert graph.getreturnvar().concretetype == Void assert graph.startblock.exits[0].args[0].concretetype == Void + +def test_ll_calling_ll(): + import test_llann + tst = test_llann.TestLowLevelAnnotateTestCase() + a, vTs = tst.test_ll_calling_ll() + a.translator.specialize() + assert [vT.concretetype for vT in vTs] == [Void] * 4 + Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sun Jun 12 04:45:44 2005 @@ -15,7 +15,7 @@ class BasicAnnotatorPolicy: def specialize(pol, bookkeeper, spaceop, func, args, mono): - return None + return None, None def compute_at_fixpoint(pol, annotator): annotator.bookkeeper.compute_at_fixpoint() From pedronis at codespeak.net Sun Jun 12 05:12:29 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 12 Jun 2005 05:12:29 +0200 (CEST) Subject: [pypy-svn] r13313 - pypy/dist/pypy/rpython/test Message-ID: <20050612031229.DEFE927B4A@code1.codespeak.net> Author: pedronis Date: Sun Jun 12 05:12:28 2005 New Revision: 13313 Modified: pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/rpython/test/test_rtyper.py Log: some more testing Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Sun Jun 12 05:12:28 2005 @@ -151,4 +151,68 @@ assert a.binding(rv) == annmodel.lltype_to_annotation(T.OF) return a, vTs - + def test_ll_calling_ll2(self): + A = GcArray(Float) + B = GcArray(Signed) + def ll_make(T, n): + x = malloc(T, n) + return x + def ll_get(x, i): + return x[i] + def makelen4(T): + return ll_make(T, 4) + def llf(): + a = ll_make(A, 3) + b = ll_make(B, 2) + a[0] = 1.0 + b[1] = 3 + y0 = ll_get(a, 1) + y1 = ll_get(b, 1) + # + a2 = makelen4(A) + a2[0] = 2.0 + return ll_get(a2, 1) + a = self.RPythonAnnotator() + s, llf2 = annotate_lowlevel_helper(a, llf, []) + assert llf2 is llf + assert s == annmodel.SomeFloat() + g = a.translator.getflowgraph(llf) + for_ = {} + def q(v): + s = a.binding(v) + if s.is_constant(): + return s.const + else: + return s.ll_ptrtype + + for block in a.annotated: + for op in block.operations: + if op.opname == 'simple_call': + if op.args[0].value.__name__.startswith("ll_"): + for_[tuple([q(x) for x in op.args[0:2]])] = True + elif op.args[0].value.__name__.startswith("makelen4"): + for_[tuple([q(x) for x in op.args[0:2]])] = True + assert len(for_) == 5 + vTs = [] + for func, T in for_.keys(): + g = a.translator.getflowgraph(func) + args = g.getargs() + rv = g.getreturnvar() + if isinstance(T, ContainerType): + if len(args) == 2: + vT, vn = args + vTs.append(vT) + assert a.binding(vT) == annmodel.SomePBC({T: True}) + assert a.binding(vn).knowntype == int + assert a.binding(rv).ll_ptrtype.TO == T + else: + vT, = args + vTs.append(vT) + assert a.binding(vT) == annmodel.SomePBC({T: True}) + assert a.binding(rv).ll_ptrtype.TO == T + else: + vp, vi = args + assert a.binding(vi).knowntype == int + assert a.binding(vp).ll_ptrtype == T + assert a.binding(rv) == annmodel.lltype_to_annotation(T.TO.OF) + return a, vTs Modified: pypy/dist/pypy/rpython/test/test_rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtyper.py (original) +++ pypy/dist/pypy/rpython/test/test_rtyper.py Sun Jun 12 05:12:28 2005 @@ -62,4 +62,11 @@ a, vTs = tst.test_ll_calling_ll() a.translator.specialize() assert [vT.concretetype for vT in vTs] == [Void] * 4 + +def test_ll_calling_ll2(): + import test_llann + tst = test_llann.TestLowLevelAnnotateTestCase() + a, vTs = tst.test_ll_calling_ll2() + a.translator.specialize() + assert [vT.concretetype for vT in vTs] == [Void] * 3 From arigo at codespeak.net Sun Jun 12 14:28:52 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 12 Jun 2005 14:28:52 +0200 (CEST) Subject: [pypy-svn] r13320 - pypy/dist/pypy/rpython Message-ID: <20050612122852.9AD3C27B4F@code1.codespeak.net> Author: arigo Date: Sun Jun 12 14:28:51 2005 New Revision: 13320 Modified: pypy/dist/pypy/rpython/lltype.py Log: Cannot hash ForwardReferences. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sun Jun 12 14:28:51 2005 @@ -222,6 +222,9 @@ self.__class__ = realcontainertype.__class__ self.__dict__ = realcontainertype.__dict__ + def __hash__(self): + raise TypeError("%r object is not hashable" % self.__class__.__name__) + class GcForwardReference(ForwardReference): def become(self, realcontainertype): if not isinstance(realcontainertype, GC_CONTAINER): From arigo at codespeak.net Sun Jun 12 23:09:50 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 12 Jun 2005 23:09:50 +0200 (CEST) Subject: [pypy-svn] r13322 - pypy/dist/pypy/documentation/website Message-ID: <20050612210950.8500927B4F@code1.codespeak.net> Author: arigo Date: Sun Jun 12 23:09:50 2005 New Revision: 13322 Added: pypy/dist/pypy/documentation/website/EP2005-announcement.txt - copied unchanged from r13321, pypy/extradoc/sprintinfo/EP2005-announcement.txt Modified: pypy/dist/pypy/documentation/website/news.txt Log: issue60 chatting * announced the sprint in the news.txt and on mailing lists. * removed old news items from the news page. (Do we want to keep them publicly available somewhere?) Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Sun Jun 12 23:09:50 2005 @@ -9,6 +9,21 @@ .. _Python: http://www.python.org/doc/current/ref/ref.html .. _`more...`: ../architecture.html#mission-statement +Next Sprint after EuroPython 2005 1st-7th July +====================================================== + +The next sprint is scheduled right after EuroPython_ 2005 in G?teborg, Sweden. +We take a day of break after the conference and start sprinting from 1st-7th +of July 2005. See the `sprint announcement`_. The sprint theme is related +strongly to `translation`_ and working towards getting a first self-contained +PyPy version. Additionally there will be a four day Pre-EuroPython sprint for +people who already are familiar with the PyPy code base. *(05/04/2005, +12/06/2005)* + +.. _EuroPython: http://europython.org +.. _`translation`: ../translation.html +.. _`sprint announcement`: EP2005-announcement.html + First PyPy release! =================== @@ -22,30 +37,3 @@ .. _`release announcement`: http://codespeak.net/pypy/index.cgi?doc/release-0.6.html .. _`getting started`: http://codespeak.net/pypy/index.cgi?getting-started -Next Sprint after EuroPython 2005 1st-7th July -====================================================== - -The next sprint is scheduled right after EuroPython_ 2005 in G?teborg, Sweden. -We take a day of break after the conference and start sprinting from 1st-7th -of July 2005. The sprint theme is likely to be related strongly to -`translation`_ and working towards getting a first self-contained PyPy -version. Additionally there will be a four day Pre-EuroPython sprint -for people who already are familiar with the PyPy code base. -*(05/04/2005)* - -.. _EuroPython: http://europython.org -.. _`translation`: ../translation.html - -Pycon 2005 Sprint in Washington finished -========================================================== - -Our `Pycon 2005 Sprint`_ finished and was a good success. In our new -`revision report`_ we track information on compliancy with CPython. During the -conferences we made good contacts with other Python implementors and look -forward to closer cooperation. -*(03/28/2005)* - -.. _`revision report`: http://codespeak.net/pypy/rev/current/ -.. _`Pycon 2005 Sprint`: http://codespeak.net/svn/pypy/extradoc/sprintinfo/pycon2005-announcement.txt - - From arigo at codespeak.net Mon Jun 13 01:27:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 13 Jun 2005 01:27:21 +0200 (CEST) Subject: [pypy-svn] r13325 - pypy/dist/pypy/translator Message-ID: <20050612232721.DA22827B50@code1.codespeak.net> Author: arigo Date: Mon Jun 13 01:27:20 2005 New Revision: 13325 Modified: pypy/dist/pypy/translator/annrpython.py Log: Performance improvement if this is called repeatedly. Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Mon Jun 13 01:27:20 2005 @@ -306,7 +306,15 @@ from pypy.translator import transform transform.transform_graph(self, block_subset=block_subset) from pypy.translator import simplify - for graph in self.translator.flowgraphs.values(): + if block_subset is None: + graphs = self.translator.flowgraphs.values() + else: + graphs = {} + for block in block_subset: + fn = self.annotated.get(block) + if fn in self.translator.flowgraphs: + graphs[self.translator.flowgraphs[fn]] = True + for graph in graphs: simplify.eliminate_empty_blocks(graph) From arigo at codespeak.net Mon Jun 13 01:28:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 13 Jun 2005 01:28:20 +0200 (CEST) Subject: [pypy-svn] r13326 - pypy/dist/pypy/annotation Message-ID: <20050612232820.5C1CA27B50@code1.codespeak.net> Author: arigo Date: Mon Jun 13 01:28:18 2005 New Revision: 13326 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py Log: - Bug fix. - Support for constant low-level pointers in the annotator. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Mon Jun 13 01:28:18 2005 @@ -15,6 +15,7 @@ from pypy.interpreter.argument import Arguments, ArgErr from pypy.rpython.rarithmetic import r_uint from pypy.tool.unionfind import UnionFind +from pypy.rpython import lltype from pypy.annotation.specialize import decide_callable @@ -193,6 +194,8 @@ self.immutable_cache[id(x)] = result elif ishashable(x) and x in BUILTIN_ANALYZERS: result = SomeBuiltin(BUILTIN_ANALYZERS[x]) + elif isinstance(x, lltype._ptr): + result = SomePtr(lltype.typeOf(x)) elif callable(x) or isinstance(x, staticmethod): # XXX # maybe 'x' is a method bound to a not-yet-frozen cache? # fun fun fun. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Mon Jun 13 01:28:18 2005 @@ -445,7 +445,7 @@ v_lltype._defl()) def simple_call(p, *args_s): - llargs = [annotation_to_lltype(arg_s)._example() for arg_s in args_s] + llargs = [annotation_to_lltype(arg_s)._defl() for arg_s in args_s] v = p.ll_ptrtype._example()(*llargs) return ll_to_annotation(v) From arigo at codespeak.net Mon Jun 13 01:33:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 13 Jun 2005 01:33:24 +0200 (CEST) Subject: [pypy-svn] r13327 - in pypy/dist/pypy: objspace/flow rpython rpython/test Message-ID: <20050612233324.C66BC27B50@code1.codespeak.net> Author: arigo Date: Mon Jun 13 01:33:20 2005 New Revision: 13327 Added: pypy/dist/pypy/rpython/exceptiondata.py (contents, props changed) Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rptr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_exception.py Log: Bordering on the insane, here is the start of rtyper support for exceptions, including converting from an exception set by CPython to an instance of the corresponding RPython class. More general fun with strange code all around the place. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Mon Jun 13 01:33:20 2005 @@ -75,7 +75,7 @@ class Link(object): - __slots__ = """args target exitcase prevblock + __slots__ = """args target exitcase llexitcase prevblock last_exception last_exc_value""".split() def __init__(self, args, target, exitcase=None): Added: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/exceptiondata.py Mon Jun 13 01:33:20 2005 @@ -0,0 +1,108 @@ +from pypy.annotation import model as annmodel +from pypy.rpython import rclass +from pypy.rpython.annlowlevel import annotate_lowlevel_helper +from pypy.rpython.lltype import * + + +class ExceptionData: + """Public information for the code generators to help with exceptions.""" + + def __init__(self, rtyper): + # (NB. rclass identifies 'Exception' and 'object') + r_type = rclass.getclassrepr(rtyper, None) + r_instance = rclass.getinstancerepr(rtyper, None) + r_type.setup() + r_instance.setup() + self.lltype_of_exception_type = r_type.lowleveltype + self.lltype_of_exception_value = r_instance.lowleveltype + + # create helper functions + self.ll_exception_match = self.make_exception_matcher(rtyper) + self.ll_type_of_exc_inst = self.make_type_of_exc_inst(rtyper) + self.ll_pyexcclass2exc = self.make_pyexcclass2exc(rtyper) + + + def make_exception_matcher(self, rtyper): + # ll_exception_matcher(real_exception_vtable, match_exception_vtable) + s_typeptr = annmodel.SomePtr(self.lltype_of_exception_type) + dontcare, spec_function = annotate_lowlevel_helper( + rtyper.annotator, rclass.ll_issubclass, [s_typeptr, s_typeptr]) + return spec_function + + + def make_type_of_exc_inst(self, rtyper): + # ll_type_of_exc_inst(exception_instance) -> exception_vtable + s_excinst = annmodel.SomePtr(self.lltype_of_exception_value) + dontcare, spec_function = annotate_lowlevel_helper( + rtyper.annotator, rclass.ll_type, [s_excinst]) + return spec_function + + + def make_pyexcclass2exc(self, rtyper): + # ll_pyexcclass2exc(python_exception_class) -> exception_instance + table = {} + for clsdef in rtyper.class_reprs: + if (clsdef and clsdef.cls is not Exception + and issubclass(clsdef.cls, Exception)): + cls = clsdef.cls + if not clsdef.attrs: + r_inst = rclass.getinstancerepr(rtyper, clsdef) + r_inst.setup() + example = malloc(r_inst.lowleveltype.TO, immortal=True) + example = rclass.ll_cast_to_object(example) + example.typeptr = r_inst.rclass.getvtable() + table[cls] = example + else: + assert cls.__module__ != 'exceptions', ( + "built-in exceptions should not grow attributes") + r_inst = rclass.getinstancerepr(rtyper, None) + r_inst.setup() + default_excinst = malloc(self.lltype_of_exception_value.TO, + immortal=True) + default_excinst.typeptr = r_inst.rclass.getvtable() + + # build the table in order base classes first, subclasses last + sortedtable = [] + def add_class(cls): + if cls in table: + for base in cls.__bases__: + add_class(base) + sortedtable.append((cls, table[cls])) + del table[cls] + for cls in table.keys(): + add_class(cls) + assert table == {} + print sortedtable + + A = Array(('pycls', Ptr(PyObject)), + ('excinst', self.lltype_of_exception_value)) + pycls2excinst = malloc(A, len(sortedtable), immortal=True) + for i in range(len(sortedtable)): + cls, example = sortedtable[i] + pycls2excinst[i].pycls = pyobjectptr(cls) + pycls2excinst[i].excinst = example + + FUNCTYPE = FuncType([Ptr(PyObject), Ptr(PyObject)], Signed) + PyErr_GivenExceptionMatches = functionptr( + FUNCTYPE, "PyErr_GivenExceptionMatches", external="C", + _callable=lambda pyobj1, pyobj2: + int(issubclass(pyobj1._obj.value, pyobj2._obj.value))) + + initial_value_of_i = len(pycls2excinst)-1 + + def ll_pyexcclass2exc(python_exception_class): + """Return an RPython instance of the best approximation of the + Python exception identified by its Python class. + """ + i = initial_value_of_i + while i >= 0: + if PyErr_GivenExceptionMatches(python_exception_class, + pycls2excinst[i].pycls): + return pycls2excinst[i].excinst + i -= 1 + return default_excinst + + s_pyobj = annmodel.SomePtr(Ptr(PyObject)) + dontcare, spec_function = annotate_lowlevel_helper( + rtyper.annotator, ll_pyexcclass2exc, [s_pyobj]) + return spec_function Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jun 13 01:33:20 2005 @@ -37,20 +37,36 @@ OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR))) OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) - +OBJECTPTR = Ptr(OBJECT) def getclassrepr(rtyper, classdef): try: result = rtyper.class_reprs[classdef] except KeyError: - result = rtyper.class_reprs[classdef] = ClassRepr(rtyper, classdef) + if classdef and classdef.cls is Exception: + # skip Exception as a base class and go directly to 'object'. + # the goal is to allow any class anywhere in the hierarchy + # to have Exception as a second base class. It should be an + # empty class anyway. + if classdef.attrs: + raise TyperError("the Exception class should not " + "have any attribute attached to it") + result = getclassrepr(rtyper, None) + else: + result = ClassRepr(rtyper, classdef) + rtyper.class_reprs[classdef] = result return result def getinstancerepr(rtyper, classdef): try: result = rtyper.instance_reprs[classdef] except KeyError: - result = rtyper.instance_reprs[classdef] = InstanceRepr(rtyper,classdef) + if classdef and classdef.cls is Exception: + # see getclassrepr() + result = getinstancerepr(rtyper, None) + else: + result = InstanceRepr(rtyper,classdef) + rtyper.instance_reprs[classdef] = result return result class MissingRTypeAttribute(TyperError): @@ -467,3 +483,25 @@ classdef = hop.rtyper.annotator.getuserclasses()[cls] rinstance = getinstancerepr(hop.rtyper, classdef) return rinstance.new_instance(hop.llops) + +# ____________________________________________________________ +# +# Low-level implementation of operations on classes and instances + +def ll_cast_to_object(obj): + # This strange recursive version is type-safe :-) + # Each ll_cast_to_object() call below is done with a different type. + if typeOf(obj) == OBJECTPTR: + return obj + else: + return ll_cast_to_object(obj.super) + +def ll_type(obj): + return ll_cast_to_object(obj).typeptr + +def ll_issubclass(subcls, cls): + while subcls != cls: + if not subcls: + return False + subcls = subcls.parenttypeptr + return True Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Mon Jun 13 01:33:20 2005 @@ -1,18 +1,18 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.lltype import Ptr, _ptr -from pypy.rpython.lltype import ContainerType, Void, Signed, Bool +from pypy.rpython.lltype import ContainerType, Void, Signed, Bool, FuncType from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst class __extend__(annmodel.SomePtr): def rtyper_makerepr(self, rtyper): - if self.is_constant(): # constant NULL + if self.is_constant() and not self.const: # constant NULL return nullptr_repr else: return PtrRepr(self.ll_ptrtype) def rtyper_makekey(self): - if self.is_constant(): + if self.is_constant() and not self.const: return None else: return self.ll_ptrtype @@ -51,6 +51,13 @@ vlist = hop.inputargs(self) return hop.genop('ptr_nonzero', vlist, resulttype=Bool) + def rtype_simple_call(self, hop): + if not isinstance(self.lowleveltype.TO, FuncType): + raise TyperError("calling a non-function %r", self.lowleveltype.TO) + vlist = hop.inputargs(*hop.args_r) + return hop.genop('direct_call', vlist, + resulttype = self.lowleveltype.TO.RESULT) + class __extend__(pairtype(PtrRepr, IntegerRepr)): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Mon Jun 13 01:33:20 2005 @@ -2,7 +2,7 @@ from pypy.annotation.pairtype import pair from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Variable, Constant, Block, Link -from pypy.objspace.flow.model import SpaceOperation +from pypy.objspace.flow.model import SpaceOperation, last_exception from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void from pypy.rpython.lltype import LowLevelType, Ptr, ContainerType from pypy.rpython.lltype import FuncType, functionptr, typeOf @@ -11,6 +11,7 @@ from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr from pypy.rpython.normalizecalls import perform_normalizations from pypy.rpython.annlowlevel import annotate_lowlevel_helper +from pypy.rpython.exceptiondata import ExceptionData debug = False @@ -36,6 +37,9 @@ r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r + def getexceptiondata(self): + return self.exceptiondata # built at the end of specialize() + def getrepr(self, s_obj): # s_objs are not hashable... try hard to find a unique key anyway key = s_obj.__class__, s_obj.rtyper_makekey() @@ -69,17 +73,25 @@ # 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: - # specialize all blocks in the 'pending' list - for block in pending: - self.specialize_block(block) - already_seen[block] = True - # make sure all reprs so far have had their setup() called - self.call_all_setups() - # look for newly created blocks - pending = [block for block in self.annotator.annotated - if block not in already_seen] + + def specialize_more_blocks(): + while True: + # look for blocks not specialized yet + pending = [block for block in self.annotator.annotated + if block not in already_seen] + if not pending: + break + # specialize all blocks in the 'pending' list + for block in pending: + self.specialize_block(block) + already_seen[block] = True + # make sure all reprs so far have had their setup() called + self.call_all_setups() + + specialize_more_blocks() + self.exceptiondata = ExceptionData(self) + specialize_more_blocks() + if self.typererror: exc, value, tb = self.typererror self.typererror = None @@ -128,6 +140,13 @@ # insert the needed conversions on the links can_insert_here = block.exitswitch is None and len(block.exits) == 1 for link in block.exits: + if block.exitswitch is not None and link.exitcase is not None: + if isinstance(block.exitswitch, Variable): + r_case = self.bindingrepr(block.exitswitch) + else: + assert block.exitswitch == Constant(last_exception) + r_case = rclass.get_type_repr(self) + link.llexitcase = r_case.convert_const(link.exitcase) for a in [link.last_exception, link.last_exc_value]: if isinstance(a, Variable): self.setconcretetype(a) @@ -282,8 +301,7 @@ self.s_result = rtyper.binding(spaceop.result) self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] self.r_result = rtyper.getrepr(self.s_result) - for r in self.args_r + [self.r_result]: - r.setup() + rtyper.call_all_setups() # compute ForwardReferences now def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, @@ -402,5 +420,5 @@ from pypy.rpython import rint, rbool, rfloat from pypy.rpython import rslice from pypy.rpython import rlist, rstr, rtuple -from pypy.rpython import rbuiltin, rpbc +from pypy.rpython import rclass, rbuiltin, rpbc from pypy.rpython import rptr Modified: pypy/dist/pypy/rpython/test/test_exception.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_exception.py (original) +++ pypy/dist/pypy/rpython/test/test_exception.py Mon Jun 13 01:33:20 2005 @@ -6,6 +6,9 @@ class MyException(Exception): pass +class MyStrangeException: # no (Exception) here + pass + def test_simple(): def g(): @@ -23,3 +26,27 @@ typer.specialize() #t.view() t.checkgraphs() + + +def test_exception_data(): + def f(n): + raise OverflowError() + + t = Translator(f) + a = t.annotate([int]) + t.specialize() + data = t.rtyper.getexceptiondata() + #t.view() + ovferr_inst = data.ll_pyexcclass2exc(pyobjectptr(OverflowError)) + classdef = a.bookkeeper.getclassdef(OverflowError) + assert ovferr_inst.typeptr == t.rtyper.class_reprs[classdef].getvtable() + + keyerr_inst = data.ll_pyexcclass2exc(pyobjectptr(KeyError)) + classdef = a.bookkeeper.getclassdef(StandardError) # most precise class seen + assert keyerr_inst.typeptr == t.rtyper.class_reprs[classdef].getvtable() + + myerr_inst = data.ll_pyexcclass2exc(pyobjectptr(MyException)) + assert myerr_inst.typeptr == t.rtyper.class_reprs[None].getvtable() + + strgerr_inst = data.ll_pyexcclass2exc(pyobjectptr(MyStrangeException)) + assert strgerr_inst.typeptr == t.rtyper.class_reprs[None].getvtable() From arigo at codespeak.net Mon Jun 13 01:50:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 13 Jun 2005 01:50:24 +0200 (CEST) Subject: [pypy-svn] r13328 - pypy/dist/pypy/translator/test Message-ID: <20050612235024.A473327B50@code1.codespeak.net> Author: arigo Date: Mon Jun 13 01:50:24 2005 New Revision: 13328 Modified: pypy/dist/pypy/translator/test/test_backends.py Log: test_backends is difficult to write generically at the moment. (See explanations in the file itself) Modified: pypy/dist/pypy/translator/test/test_backends.py ============================================================================== --- pypy/dist/pypy/translator/test/test_backends.py (original) +++ pypy/dist/pypy/translator/test/test_backends.py Mon Jun 13 01:50:24 2005 @@ -9,6 +9,16 @@ from pypy.translator.test.snippet import * +py.test.skip("the Translator and back-ends depend on too many conditions " + "to test the back-ends generically") +# e.g. some back-ends require annotation and/or specialization to be done +# while some require it *not* to be done. GenCL for example has no +# chance to understand a specialized graph. (That's why the test still +# used to pass: forty_two is basically an empty function, so +# specializing it makes no difference. Now the RTyper produces a few +# helper functions in all cases.) + + backends = 'source c cl llvm pyrex'.split() deterministic_backends = 'source cl llvm pyrex'.split() functions = 'forty_two'.split() #XXX add more functions here when RPythonTyper can handle them From pedronis at codespeak.net Mon Jun 13 03:58:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 03:58:57 +0200 (CEST) Subject: [pypy-svn] r13330 - in pypy/dist/pypy/rpython: . test Message-ID: <20050613015857.CF55927B5A@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 03:58:56 2005 New Revision: 13330 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py Log: - introduced a generic cast_pointer with tests (needs annotation support etc) - found bug in cast_parent (which could maybe go away or layered on cast_pointer/castable) Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Mon Jun 13 03:58:56 2005 @@ -110,6 +110,14 @@ self._flds = frozendict(flds) self._names = tuple(names) + def _first_struct(self): + if self._names: + first = self._names[0] + FIRSTTYPE = self._flds[first] + if isinstance(FIRSTTYPE, Struct) and self._gcstatus() == FIRSTTYPE._gcstatus(): + return first, FIRSTTYPE + return None, None + def _inline_is_varsize(self, last): if self._arrayfld: raise TypeError("cannot inline a var-sized struct " @@ -316,6 +324,8 @@ if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, Ptr): raise TypeError, "can only cast pointers to other pointers" CURTYPE = ptr._TYPE + if castable(PTRTYPE, CURTYPE) != -1: # xxx makes some of the rest superfluous + raise InvalidCast(CURTYPE, PTRTYPE) if CURTYPE._needsgc() != PTRTYPE._needsgc(): raise TypeError("cast_parent() cannot change the gc status: %s to %s" % (CURTYPE, PTRTYPE)) @@ -332,8 +342,69 @@ PARENTTYPE = ptr._obj._parent_type if getattr(parent, PARENTTYPE._names[0]) is not ptr._obj: raise InvalidCast(CURTYPE, PTRTYPE) + if PARENTTYPE != PTRTYPE.TO: + raise TypeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO)) return _ptr(PTRTYPE, parent) + +def _castdepth(OUTSIDE, INSIDE): + if OUTSIDE == INSIDE: + return 0 + dwn = 0 + while True: + first, FIRSTTYPE = OUTSIDE._first_struct() + if first is None: + return -1 + dwn += 1 + if FIRSTTYPE == INSIDE: + return dwn + OUTSIDE = getattr(OUTSIDE, first) + +def castable(PTRTYPE, CURTYPE): + if CURTYPE._needsgc() != PTRTYPE._needsgc(): + raise TypeError("cast_pointer() cannot change the gc status: %s to %s" + % (CURTYPE, PTRTYPE)) + if (not isinstance(CURTYPE.TO, Struct) or + not isinstance(PTRTYPE.TO, Struct)): + raise InvalidCast(CURTYPE, PTRTYPE) + CURSTRUC = CURTYPE.TO + PTRSTRUC = PTRTYPE.TO + d = _castdepth(CURSTRUC, PTRSTRUC) + if d >= 0: + return d + u = _castdepth(PTRSTRUC, CURSTRUC) + if u == -1: + raise InvalidCast(CURTYPE, PTRTYPE) + return -u + +def cast_pointer(PTRTYPE, ptr): + if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, Ptr): + raise TypeError, "can only cast pointers to other pointers" + CURTYPE = ptr._TYPE + down_or_up = castable(PTRTYPE, CURTYPE) + if down_or_up == 0: + return ptr + elif down_or_up > 0: + p = ptr + while down_or_up: + p = getattr(p, typeOf(p).TO._names[0]) + down_or_up -= 1 + return _ptr(PTRTYPE, p._obj) + u = -down_or_up + struc = ptr._obj + while u: + parent = struc._parentstructure() + if parent is None: + raise RuntimeError("widening to trash: %r" % ptr) + PARENTTYPE = struc._parent_type + if getattr(parent, PARENTTYPE._names[0]) is not struc: + raise InvalidCast(CURTYPE, PTRTYPE) # xxx different exception perhaps? + struc = parent + u -= 1 + if PARENTTYPE != PTRTYPE.TO: + raise TypeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO)) + return _ptr(PTRTYPE, struc) + def _expose(val): """XXX A nice docstring here""" T = typeOf(val) @@ -642,5 +713,5 @@ def pyobjectptr(obj): o = _pyobject(obj) - return _ptr(Ptr(PyObject), o) # xxx was non-gc + return _ptr(Ptr(PyObject), o) Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Mon Jun 13 03:58:56 2005 @@ -146,6 +146,10 @@ py.test.raises(TypeError, "cast_parent(Ptr(S2), p3)") SUnrelated = Struct("unrelated") py.test.raises(TypeError, "cast_parent(Ptr(SUnrelated), p3)") + S1bis = Struct("s1b", ('sub1', S2)) + p1b = malloc(S1bis, immortal=True) + p2 = p1b.sub1 + py.test.raises(TypeError, "cast_parent(Ptr(S1), p2)") def test_cast_parent2(): S2 = GcStruct("s2", ('a', Signed)) @@ -158,6 +162,46 @@ p2 = malloc(S2) py.test.raises(RuntimeError, "cast_parent(Ptr(S1), p2)") +def test_cast_pointer(): + S3 = GcStruct("s3", ('a', Signed)) + S2 = GcStruct("s3", ('sub', S3)) + S1 = GcStruct("s1", ('sub', S2)) + p1 = malloc(S1) + p2 = p1.sub + p3 = p2.sub + assert typeOf(p3) == Ptr(S3) + assert typeOf(p2) == Ptr(S2) + p12 = cast_pointer(Ptr(S1), p2) + assert p12 == p1 + p13 = cast_pointer(Ptr(S1), p3) + assert p13 == p1 + p21 = cast_pointer(Ptr(S2), p1) + assert p21 == p2 + p23 = cast_pointer(Ptr(S2), p3) + assert p23 == p2 + p31 = cast_pointer(Ptr(S3), p1) + assert p31 == p3 + p32 = cast_pointer(Ptr(S3), p2) + assert p32 == p3 + p3 = malloc(S3) + p2 = malloc(S2) + py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p3)") + py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p2)") + py.test.raises(RuntimeError, "cast_pointer(Ptr(S2), p3)") + S0 = GcStruct("s0", ('sub', S1)) + p0 = malloc(S0) + assert p0 == cast_pointer(Ptr(S0), p0) + p3 = cast_pointer(Ptr(S3), p0) + p03 = cast_pointer(Ptr(S0), p3) + assert p0 == p03 + S1bis = GcStruct("s1b", ('sub', S2)) + assert S1bis != S1 + p1b = malloc(S1bis) + p3 = p1b.sub.sub + assert typeOf(p3) == Ptr(S3) + assert p1b == cast_pointer(Ptr(S1bis), p3) + py.test.raises(TypeError, "cast_pointer(Ptr(S1), p3)") + def test_best_effort_gced_parent_detection(): S2 = Struct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('sub2', S2), ('tail', Array(('e', Signed)))) From pedronis at codespeak.net Mon Jun 13 13:52:46 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 13:52:46 +0200 (CEST) Subject: [pypy-svn] r13343 - in pypy/dist/pypy/rpython: . test Message-ID: <20050613115246.A228F27B54@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 13:52:45 2005 New Revision: 13343 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py Log: let freely cast null-pointers if the types are ok Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Mon Jun 13 13:52:45 2005 @@ -384,7 +384,9 @@ down_or_up = castable(PTRTYPE, CURTYPE) if down_or_up == 0: return ptr - elif down_or_up > 0: + if not ptr: # null pointer cast + return PTRTYPE._defl() + if down_or_up > 0: p = ptr while down_or_up: p = getattr(p, typeOf(p).TO._names[0]) @@ -709,7 +711,7 @@ return _ptr(Ptr(TYPE), o) def nullptr(T): - return _ptr(Ptr(T), None) + return Ptr(T)._defl() def pyobjectptr(obj): o = _pyobject(obj) Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Mon Jun 13 13:52:45 2005 @@ -285,6 +285,18 @@ S = Struct('s') p0 = nullptr(S) assert not p0 + assert typeOf(p0) == Ptr(S) + + +def test_nullptr_cast(): + S = Struct('s') + p0 = nullptr(S) + assert not p0 + S1 = Struct("s1", ('s', S)) + p10 = cast_pointer(Ptr(S1), p0) + assert typeOf(p10) == Ptr(S1) + assert not p10 + def test_hash(): S = ForwardReference() From pedronis at codespeak.net Mon Jun 13 14:31:13 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 14:31:13 +0200 (CEST) Subject: [pypy-svn] r13344 - in pypy/dist/pypy: annotation rpython/test Message-ID: <20050613123113.4C58227B50@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 14:31:08 2005 New Revision: 13344 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/test/test_llann.py Log: annotation for cast_pointer (given that null pointers are accepted is slightly saner), refactored a bit the code in test_llann Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Mon Jun 13 14:31:08 2005 @@ -319,8 +319,16 @@ r.const = p return r +def cast_pointer(PtrT, s_p): + assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p + assert PtrT.is_constant() + cast_p = lltype.cast_pointer(PtrT.const, s_p.ll_ptrtype._defl()) + return SomePtr(ll_ptrtype=lltype.typeOf(cast_p)) + + BUILTIN_ANALYZERS[lltype.malloc] = malloc BUILTIN_ANALYZERS[lltype.cast_parent] = cast_parent BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.nullptr] = nullptr +BUILTIN_ANALYZERS[lltype.cast_pointer] = cast_pointer Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Mon Jun 13 14:31:08 2005 @@ -2,6 +2,20 @@ from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import annotate_lowlevel_helper +# helpers + +def annotated_calls(ann, ops=('simple_call,')): + for block in ann.annotated: + for op in block.operations: + if op.opname in ops: + yield op + +def derived(op, orig): + if op.args[0].value.__name__.startswith(orig): + return op.args[0].value + else: + return None + class TestLowLevelAnnotateTestCase: objspacename = 'flow' @@ -82,6 +96,38 @@ assert isinstance(s, annmodel.SomePtr) assert s.ll_ptrtype == PS1 + def test_cast_pointer(self): + S3 = GcStruct("s3", ('a', Signed)) + S2 = GcStruct("s3", ('sub', S3)) + S1 = GcStruct("s1", ('sub', S2)) + PS1 = Ptr(S1) + PS2 = Ptr(S2) + PS3 = Ptr(S3) + def llwitness(p12, p13, p21, p23, p31, p32): + pass + def llf(): + p1 = malloc(S1) + p2 = p1.sub + p3 = p2.sub + p12 = cast_pointer(PS1, p2) + p13 = cast_pointer(PS1, p3) + p21 = cast_pointer(PS2, p1) + p23 = cast_pointer(PS2, p3) + p31 = cast_pointer(PS3, p1) + p32 = cast_pointer(PS3, p2) + llwitness(p12, p13, p21, p23, p31, p32) + a = self.RPythonAnnotator() + s, dontcare = annotate_lowlevel_helper(a, llf, []) + + spec_llwitness = None + for call in annotated_calls(a): + spec_llwitness = derived(call, 'llwitness') + + g = a.translator.flowgraphs[spec_llwitness] + bindings = [a.binding(v) for v in g.getargs()] + assert [x.ll_ptrtype for x in bindings] == [PS1, PS1, PS2, PS2, PS3, PS3] + + def test_array_length(self): A = GcArray(('v', Signed)) def llf(): @@ -126,10 +172,9 @@ assert s == annmodel.SomeFloat() g = a.translator.getflowgraph(llf) for_ = {} - for block in a.annotated: - for op in block.operations: - if op.opname == 'simple_call' and op.args[0].value.__name__.startswith("ll_"): - for_[tuple([x.value for x in op.args[0:2]])] = True + for call in annotated_calls(a): + if derived(call, "ll_"): + for_[tuple([x.value for x in call.args[0:2]])] = True assert len(for_) == 4 vTs = [] for func, T in for_.keys(): @@ -184,14 +229,11 @@ return s.const else: return s.ll_ptrtype + + for call in annotated_calls(a): + if derived(call, "ll_") or derived(call, "makelen4"): + for_[tuple([q(x) for x in call.args[0:2]])] = True - for block in a.annotated: - for op in block.operations: - if op.opname == 'simple_call': - if op.args[0].value.__name__.startswith("ll_"): - for_[tuple([q(x) for x in op.args[0:2]])] = True - elif op.args[0].value.__name__.startswith("makelen4"): - for_[tuple([q(x) for x in op.args[0:2]])] = True assert len(for_) == 5 vTs = [] for func, T in for_.keys(): From pedronis at codespeak.net Mon Jun 13 14:58:08 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 14:58:08 +0200 (CEST) Subject: [pypy-svn] r13345 - in pypy/dist/pypy/rpython: . test Message-ID: <20050613125808.D18DD27B46@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 14:58:01 2005 New Revision: 13345 Added: pypy/dist/pypy/rpython/test/test_rptr.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rbuiltin.py Log: added support for cast_pointer in the rtyper (with some testing) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jun 13 14:58:01 2005 @@ -127,9 +127,17 @@ return hop.genop('cast_parent', [v_input], # v_type implicit in r_result resulttype = hop.r_result.lowleveltype) +def rtype_cast_pointer(hop): + assert hop.args_s[0].is_constant() + assert isinstance(hop.args_r[1], rptr.PtrRepr) + v_type, v_input = hop.inputargs(Void, hop.args_r[1]) + return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result + resulttype = hop.r_result.lowleveltype) + BUILTIN_TYPER[lltype.malloc] = rtype_malloc BUILTIN_TYPER[lltype.cast_parent] = rtype_cast_parent +BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask Added: pypy/dist/pypy/rpython/test/test_rptr.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rptr.py Mon Jun 13 14:58:01 2005 @@ -0,0 +1,33 @@ +from pypy.translator.annrpython import RPythonAnnotator +from pypy.rpython.annlowlevel import annotate_lowlevel_helper +from pypy.rpython.lltype import * +from pypy.rpython.rtyper import RPythonTyper +from pypy.annotation import model as annmodel + + +# ____________________________________________________________ + +def ll_rtype(llfn, argtypes=[]): + a = RPythonAnnotator() + s, dontcare = annotate_lowlevel_helper(a, llfn, argtypes) + t = a.translator + typer = RPythonTyper(a) + typer.specialize() + #t.view() + t.checkgraphs() + return s, t + +def test_cast_pointer(): + S = GcStruct('s', ('x', Signed)) + S1 = GcStruct('s1', ('sub', S)) + S2 = GcStruct('s2', ('sub', S1)) + PS = Ptr(S) + PS2 = Ptr(S2) + def lldown(p): + return cast_pointer(PS, p) + s, t = ll_rtype(lldown, [annmodel.SomePtr(PS2)]) + assert s.ll_ptrtype == PS + def llup(p): + return cast_pointer(PS2, p) + s, t = ll_rtype(llup, [annmodel.SomePtr(PS)]) + assert s.ll_ptrtype == PS2 From pedronis at codespeak.net Mon Jun 13 15:18:44 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 15:18:44 +0200 (CEST) Subject: [pypy-svn] r13346 - pypy/dist/pypy/translator/c Message-ID: <20050613131844.08ADF27B50@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 15:18:39 2005 New Revision: 13346 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: genc support for cast_pointer (identical to the old cast_parent at this level) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Mon Jun 13 15:18:39 2005 @@ -445,6 +445,13 @@ cdecl(typename, ''), self.expr(op.args[0])) + def OP_CAST_POINTER(self, op, err): + TYPE = self.lltypemap[op.result] + typename = self.db.gettype(TYPE) + return '%s = (%s)%s;' % (self.expr(op.result), + cdecl(typename, ''), + self.expr(op.args[0])) + def OP_SAME_AS(self, op, err): result = [] assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] From pedronis at codespeak.net Mon Jun 13 16:09:29 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 16:09:29 +0200 (CEST) Subject: [pypy-svn] r13348 - pypy/dist/pypy/translator/c Message-ID: <20050613140929.4109327B54@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 16:09:26 2005 New Revision: 13348 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: cast_pointer need a potential incref as same_as Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Mon Jun 13 16:09:26 2005 @@ -438,19 +438,19 @@ ] return '\t'.join(result) - def OP_CAST_PARENT(self, op, err): - TYPE = self.lltypemap[op.result] - typename = self.db.gettype(TYPE) - return '%s = (%s)%s;' % (self.expr(op.result), - cdecl(typename, ''), - self.expr(op.args[0])) - def OP_CAST_POINTER(self, op, err): TYPE = self.lltypemap[op.result] typename = self.db.gettype(TYPE) - return '%s = (%s)%s;' % (self.expr(op.result), - cdecl(typename, ''), - self.expr(op.args[0])) + result = [] + result.append('%s = (%s)%s;' % (self.expr(op.result), + cdecl(typename, ''), + self.expr(op.args[0]))) + line = self.cincref(op.result) + if line: + result.append(line) + return '\t'.join(result) + + OP_CAST_PARENT = OP_CAST_POINTER def OP_SAME_AS(self, op, err): result = [] From pedronis at codespeak.net Mon Jun 13 16:29:24 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 13 Jun 2005 16:29:24 +0200 (CEST) Subject: [pypy-svn] r13349 - pypy/dist/pypy/rpython Message-ID: <20050613142924.3FC8927B7A@code1.codespeak.net> Author: pedronis Date: Mon Jun 13 16:29:20 2005 New Revision: 13349 Modified: pypy/dist/pypy/rpython/rclass.py Log: use cast_pointer instead of cast_parent and pointer chasing in rclass inst and classes impls Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Mon Jun 13 16:29:20 2005 @@ -214,19 +214,15 @@ # then initialize the 'super' portion of the vtable self.rbase.setup_vtable(vtable.super, rsubcls) - def fromparentpart(self, v_vtableptr, llops): - """Return the vtable pointer cast from the parent vtable's type - to self's vtable type.""" - return llops.genop('cast_parent', [v_vtableptr], - resulttype=self.lowleveltype) + #def fromparentpart(self, v_vtableptr, llops): + # """Return the vtable pointer cast from the parent vtable's type + # to self's vtable type.""" def fromtypeptr(self, vcls, llops): """Return the type pointer cast to self's vtable type.""" - if self.classdef is None: - return vcls - else: - v_vtableptr = self.rbase.fromtypeptr(vcls, llops) - return self.fromparentpart(v_vtableptr, llops) + castable(self.lowleveltype, vcls.concretetype) # sanity check + return llops.genop('cast_pointer', [vcls], + resulttype=self.lowleveltype) def getclsfieldrepr(self, attr): """Return the repr used for the given attribute.""" @@ -360,11 +356,11 @@ setattr(targetptr, mangled_name, llattrvalue) return targetptr - def parentpart(self, vinst, llops): - """Return the pointer 'vinst' cast to the parent type.""" - cname = inputconst(Void, 'super') - return llops.genop('getsubstruct', [vinst, cname], - resulttype=self.rbase.lowleveltype) + #def parentpart(self, vinst, llops): + # """Return the pointer 'vinst' cast to the parent type.""" + # cname = inputconst(Void, 'super') + # return llops.genop('getsubstruct', [vinst, cname], + # resulttype=self.rbase.lowleveltype) def getfieldrepr(self, attr): """Return the repr used for the given attribute.""" @@ -376,29 +372,33 @@ raise MissingRTypeAttribute(attr) return self.rbase.getfieldrepr(attr) - def getfield(self, vinst, attr, llops): + def getfield(self, vinst, attr, llops, start_repr=None): """Read the given attribute (or __class__ for the type) of 'vinst'.""" + if start_repr is None: + start_repr = self if attr in self.fields: mangled_name, r = self.fields[attr] cname = inputconst(Void, mangled_name) + vinst = llops.convertvar(vinst, start_repr, self) return llops.genop('getfield', [vinst, cname], resulttype=r) else: if self.classdef is None: raise MissingRTypeAttribute(attr) - vsuper = self.parentpart(vinst, llops) - return self.rbase.getfield(vsuper, attr, llops) + return self.rbase.getfield(vinst, attr, llops, start_repr=start_repr) - def setfield(self, vinst, attr, vvalue, llops): + def setfield(self, vinst, attr, vvalue, llops, start_repr=None): """Write the given attribute (or __class__ for the type) of 'vinst'.""" + if start_repr is None: + start_repr = self if attr in self.fields: mangled_name, r = self.fields[attr] cname = inputconst(Void, mangled_name) + vinst = llops.convertvar(vinst, start_repr, self) llops.genop('setfield', [vinst, cname, vvalue]) else: if self.classdef is None: raise MissingRTypeAttribute(attr) - vsuper = self.parentpart(vinst, llops) - self.rbase.setfield(vsuper, attr, vvalue, llops) + self.rbase.setfield(vinst, attr, vvalue, llops, start_repr=start_repr) def new_instance(self, llops): """Build a new instance, without calling __init__.""" @@ -453,26 +453,20 @@ def convert_from_to((r_ins1, r_ins2), v, llops): # which is a subclass of which? if r_ins1.classdef is None or r_ins2.classdef is None: - return NotImplemented - basedef = r_ins1.classdef.commonbase(r_ins2.classdef) + basedef = None + else: + basedef = r_ins1.classdef.commonbase(r_ins2.classdef) if basedef == r_ins2.classdef: # r_ins1 is an instance of the subclass: converting to parent - while r_ins1 != r_ins2: - v = r_ins1.parentpart(v, llops) - r_ins1 = r_ins1.rbase + v = llops.genop('cast_pointer', [v], + resulttype = r_ins2.lowleveltype) return v elif basedef == r_ins1.classdef: # r_ins2 is an instance of the subclass: potentially unsafe # casting, but we do it anyway (e.g. the annotator produces # such casts after a successful isinstance() check) - cast_chain = [] - while r_ins2 != r_ins1: - cast_chain.append(r_ins2) - r_ins2 = r_ins2.rbase - cast_chain.reverse() - for r in cast_chain: - v = llops.genop('cast_parent', [v], - resulttype = r.lowleveltype) + v = llops.genop('cast_pointer', [v], + resulttype = r_ins2.lowleveltype) return v else: return NotImplemented From adim at codespeak.net Mon Jun 13 16:43:41 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 13 Jun 2005 16:43:41 +0200 (CEST) Subject: [pypy-svn] r13351 - pypy/branch/pycompiler/module/recparser Message-ID: <20050613144341.AE14527B72@code1.codespeak.net> Author: adim Date: Mon Jun 13 16:43:39 2005 New Revision: 13351 Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py Log: generate_tokens is now translatable Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonlexer.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonlexer.py Mon Jun 13 16:43:39 2005 @@ -310,6 +310,7 @@ import token as tokenmod from pypy.module.parser.pytokenize import generate_tokens, tabsize, \ whiteSpaceDFA, triple_quoted, endDFAs, single_quoted, pseudoDFA +from pypy.module.parser import automata # adopt pytokenize notations / values tokenmod.COMMENT = tokenmod.N_TOKENS @@ -323,7 +324,7 @@ self.token_stack = token_stack -def generate_tokens(readline): +def generate_tokens(lines): """ This is a rewrite of pypy.module.parser.pytokenize.generate_tokens since the original function is not RPYTHON (uses yield) @@ -355,8 +356,10 @@ encoding = None strstart = (0, 0) - while 1: # loop over lines in stream - line = readline() + lines.append('') # XXX HACK probably not needed + endDFA = automata.DFA([]) # XXX Make the translator happy + line = '' # XXX Make the translator happy + for line in lines: lnum = lnum + 1 pos, max = 0, len(line) @@ -542,7 +545,8 @@ """This source uses Jonathan's tokenizer""" def __init__(self, inpstring): TokenSource.__init__(self) - tokens, encoding = generate_tokens(StringAsFile(inpstring).readline) + # tokens, encoding = generate_tokens(StringAsFile(inpstring).readline) + tokens, encoding = generate_tokens(inpstring.splitlines(True)) self.token_stack = tokens self.encoding = encoding self._current_line = '' # the current line (as a string) @@ -613,7 +617,7 @@ f = file(filename).read() src = Source(f) token = src.next() - while token!=("ENDMARKER",None) and token!=(None,None): + while token != ("ENDMARKER", None) and token != (None, None): print token token = src.next() From adim at codespeak.net Mon Jun 13 16:46:08 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 13 Jun 2005 16:46:08 +0200 (CEST) Subject: [pypy-svn] r13352 - pypy/branch/pycompiler/module/parser Message-ID: <20050613144608.9825B27B72@code1.codespeak.net> Author: adim Date: Mon Jun 13 16:46:05 2005 New Revision: 13352 Modified: pypy/branch/pycompiler/module/parser/automata.py Log: Made small changes to make each function translatable. (This breaks for now the parser module) Modified: pypy/branch/pycompiler/module/parser/automata.py ============================================================================== --- pypy/branch/pycompiler/module/parser/automata.py (original) +++ pypy/branch/pycompiler/module/parser/automata.py Mon Jun 13 16:46:05 2005 @@ -26,7 +26,7 @@ # ______________________________________________________________________ -def chain (states, *stateIndexPairs): +def chain (states, stateIndexPairs): if len(stateIndexPairs) > 1: start, lastFinish = stateIndexPairs[0] for nStart, nFinish in stateIndexPairs[1:]: @@ -38,8 +38,8 @@ # ______________________________________________________________________ -def chainStr (states, str): - return chain(states, *map(lambda x : newArcPair(states, x), str)) +def chainStr(states, str): + return chain(states, [newArcPair(states, x) for x in str]) # ______________________________________________________________________ @@ -62,7 +62,7 @@ # ______________________________________________________________________ -def group (states, *stateIndexPairs): +def group(states, stateIndexPairs): if len(stateIndexPairs) > 1: start = len(states) finish = start + 1 @@ -78,38 +78,38 @@ # ______________________________________________________________________ -def groupStr (states, str): - return group(states, *map(lambda x : newArcPair(states, x), str)) +def groupStr(states, str): + return group(states, [newArcPair(states, x) for x in str]) # ______________________________________________________________________ -def any (states, *stateIndexPairs): - start, finish = group(states, *stateIndexPairs) +def any (states, stateIndexPairs): + start, finish = group(states, stateIndexPairs) states[finish].append((EMPTY, start)) return start, start # ______________________________________________________________________ -def maybe (states, *stateIndexPairs): - start, finish = group(states, *stateIndexPairs) +def maybe (states, stateIndexPairs): + start, finish = group(states, stateIndexPairs) states[start].append((EMPTY, finish)) return start, finish # ______________________________________________________________________ -def atleastonce (states, *stateIndexPairs): - start, finish = group(states, *stateIndexPairs) +def atleastonce (states, stateIndexPairs): + start, finish = group(states, stateIndexPairs) states[finish].append((EMPTY, start)) return start, finish # ______________________________________________________________________ -def notGroup (states, *stateIndexPairs): +def notGroup (states, stateIndexPairs): """Like group, but will add a DEFAULT transition to a new end state, causing anything in the group to not match by going to a dead state. XXX I think this is right... """ - start, dead = group(states, *stateIndexPairs) + start, dead = group(states, stateIndexPairs) finish = len(states) states.append([]) states[start].append((DEFAULT, finish)) @@ -118,7 +118,7 @@ # ______________________________________________________________________ def notGroupStr (states, str): - return notGroup(states, *map(lambda x : newArcPair(states, x), str)) + return notGroup(states, [newArcPair(states, x) for x in str]) # ______________________________________________________________________ From adim at codespeak.net Mon Jun 13 17:28:25 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 13 Jun 2005 17:28:25 +0200 (CEST) Subject: [pypy-svn] r13356 - pypy/branch/pycompiler/module/recparser Message-ID: <20050613152825.E59AE27B80@code1.codespeak.net> Author: adim Date: Mon Jun 13 17:28:24 2005 New Revision: 13356 Modified: pypy/branch/pycompiler/module/recparser/codegen.py Log: updated codegen draft Modified: pypy/branch/pycompiler/module/recparser/codegen.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/codegen.py (original) +++ pypy/branch/pycompiler/module/recparser/codegen.py Mon Jun 13 17:28:24 2005 @@ -1,3 +1,10 @@ +# Copyright (c) 2000-2003 LOGILAB S.A. (Paris, FRANCE). +# http://www.logilab.fr/ -- mailto:contact at logilab.fr +""" + +""" + +__revision__ = "$Id: $" import pythonutil from compiler.visitor import ASTVisitor @@ -27,7 +34,7 @@ def __init__(self): self.lineno = 0 - def emit(self, insn ): + def emit(self, insn): print "% 5d %s" % (self.lineno, insn) def emit_arg(self, insn, arg ): @@ -54,15 +61,26 @@ def set_start_pos(self, pos ): self.start_pos = pos +########################### +### XXX MUST FIX SET_LINENO +########################### class CompilerVisitor(ASTVisitor): """Basic code generator for Python Bytecode""" + + LOOP = 1 + EXCEPT = 2 + TRY_FINALLY = 3 + END_FINALLY = 4 + def __init__(self, filename, flags, dont_inherit ): self.scopes = [] self.blocks = [] + self.setups = [] # for loops and try/finally self.code = None self.current_block = None + self.ctx = PrintContext() ### Visitor functions @@ -87,18 +105,100 @@ if is_constant_false(test): continue test.visit(self) # emit test code in current block - self.a nextTest = Block() + self.emit(CondJump('IF_FALSE', nextTest)) + self.nextBlock() + self.emit(PopTop()) + suite.visit(self) + self.emit(CondJump('FWD', end)) + self.startBlock(nextTest) + self.emit(PopTop()) + if node.else_: + node.else_.visit(self) + self.nextBlock(end) + + def visitWhile(self, node): + # XXX emit LINENO here ? + loop = self.newBlock() + else_ = self.newBlock() + after = self.newBlock() + + self.emit(SetupLoop(after)) + + self.nextBlock(loop) + self.setups.append((self.LOOP, loop)) + + node.test.visit(self) + self.emit(CondJump('IF_FALSE', else_or after)) + self.nextBlock() + self.emit(PopTop()) + node.body.visit(self) + self.emit(CondJump('ABOSLUTE', loop)) + + self.startBlock(else_) # or just the POPs if not else clause + self.emit(PopTop()) + self.emit(PopBlock()) + self.setups.pop() + if node.else_: + node.else_.visit(self) + self.nextBlock(after) + + + def visitFor(self, node): + start = self.newBlock() + anchor = self.newBlock() + after = self.newBlock() + + self.setups.append((self.LOOP, start)) + + self.emit(SetupLoop(after)) + node.list.visit(self) + self.emit(GetIter()) + + self.nextBlock(start) + self.set_lineno(node, force=1) + self.emit(ForIter(anchor)) + node.assign.visit(self) + node.body.visit(self) + self.emit(CondJump('ABSOLUTE', start)) + self.nextBlock(anchor) + self.emit(PopBlock()) + self.setups.pop() + if node.else_: + node.else_.visist(self) + self.nextBlock(after) + + def visitBreak(self, node): + if not self.setups: + raise SyntaxError("'break' outside loop (%s, %d)" % \ + (node.filename, node.lineno)) + # self.set_lineno(node) + self.emit(BreakLoop()) + + + ## Shortcut methods + def emit(self, bytecode): + bytecode.emit(self.ctx) + ### Block handling functions def newBlock(self): """Create a new block and make it current""" b = Block() self.blocks.append(b) - self.current_block = b + # self.current_block = b return b + def nextBlock(self, block=None): + """goto next block in the flow graph""" + if block is None: + block = self.newBlock() + self.blocks.append(block) + self.startBlock(block) + + def startBlock(self, block): + self.current_block = block if __name__ == "__main__": testf = file("pycodegen2.py").read() From adim at codespeak.net Mon Jun 13 18:29:29 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 13 Jun 2005 18:29:29 +0200 (CEST) Subject: [pypy-svn] r13358 - pypy/branch/pycompiler/module/recparser Message-ID: <20050613162929.8E0EE27B71@code1.codespeak.net> Author: adim Date: Mon Jun 13 18:29:28 2005 New Revision: 13358 Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py Log: - removed the regexp-based parser (the automata-based one is fully compatible and is now translatable) - provided a dummy implementation for enconding decl recognition (don't use regexp anymore) - tidy up Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonlexer.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonlexer.py Mon Jun 13 18:29:28 2005 @@ -4,47 +4,44 @@ """ from grammar import TokenSource, Token +# Don't import string for that ... +NAMECHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' +NUMCHARS = '0123456789' +ALNUMCHARS = NAMECHARS + NUMCHARS +EXTENDED_ALNUMCHARS = ALNUMCHARS + '-.' +WHITESPACES = ' \t\n\r\v\f' + +def match_encoding_declaration(comment): + """returns the declared encoding or None + + This function is a replacement for : + >>> py_encoding = re.compile(r"coding[:=]\s*([-\w.]+)") + >>> py_encoding.search(comment) + """ + index = comment.find('coding') + if index == -1: + return None + next_char = comment[index + 6] + if next_char not in ':=': + return None + end_of_decl = comment[index + 7:] + index = 0 + for char in end_of_decl: + if char not in WHITESPACES: + break + index += 1 + else: + return None + encoding = '' + for char in end_of_decl[index:]: + if char in EXTENDED_ALNUMCHARS: + encoding += char + else: + break + if encoding != '': + return encoding + return None -DEBUG = False -import re - -KEYWORDS = [ - 'and', 'assert', 'break', 'class', 'continue', 'def', 'del', - 'elif', 'if', 'import', 'in', 'is', 'finally', 'for', 'from', - 'global', 'else', 'except', 'exec', 'lambda', 'not', 'or', - 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield' - ] - -py_keywords = re.compile(r'(%s)$' % ('|'.join(KEYWORDS)), re.M | re.X) - -py_punct = re.compile(r""" -<>|!=|==|~| -<=|<<=|<<|<| ->=|>>=|>>|>| -\*=|\*\*=|\*\*|\*| -//=|/=|//|/| -%=|\^=|\|=|\+=|=|&=|-=| -,|\^|&|\+|-|\.|%|\|| -\)|\(|;|:|@|\[|\]|`|\{|\} -""", re.M | re.X) - -g_symdef = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*:", re.M) -g_string = re.compile(r"'[^']+'", re.M) -py_name = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*", re.M) -py_comment = re.compile(r"#.*$|[ \t\014]*$", re.M) -py_ws = re.compile(r" *", re.M) -py_skip = re.compile(r"[ \t\014]*(#.*$)?", re.M) -py_encoding = re.compile(r"coding[:=]\s*([-\w.]+)") -# py_number = re.compile(r"0x[0-9a-z]+|[0-9]+l|([0-9]+\.[0-9]*|\.[0-9]+|[0-9]+)(e[+-]?[0-9]+)?j?||[0-9]+", re.I) - -# 0x[\da-f]+l matches hexadecimal numbers, possibly defined as long -# \d+l matches and only matches long integers -# (\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?j? matches simple integers, -# exponential notations and complex -py_number = re.compile(r"""0x[\da-f]+l?| -\d+l| -(\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?j? -""", re.I | re.X) def _normalize_encoding(encoding): """returns normalized name for @@ -64,251 +61,9 @@ return 'iso-8859-1' return encoding -class PythonSource(TokenSource): - """The Python tokenizer""" - def __init__(self, inpstring): - TokenSource.__init__(self) - self.input = inpstring - self.pos = 0 - self.indent = 0 - self.indentstack = [ 0 ] - self.atbol = True - self.line = 1 - self._current_line = 1 - self.pendin = 0 # indentation change waiting to be reported - self.level = 0 - self.linestart = 0 - self.stack = [] - self.stack_pos = 0 - self.comment = '' - self.encoding = None - - - def current_line(self): - return self._current_line - - def context(self): - return self.stack_pos - - def restore(self, ctx): - self.stack_pos = ctx - - def offset(self, ctx=None): - if ctx is None: - return self.stack_pos - else: - assert type(ctx)==int - return ctx - - def _next(self): - """returns the next token from source""" - inp = self.input - pos = self.pos - input_length = len(inp) - if pos >= input_length: - return self.end_of_file() - # Beginning of line - if self.atbol: - self.linestart = pos - col = 0 - m = py_ws.match(inp, pos) - pos = m.end() - col = pos - self.linestart - self.atbol = False - # skip blanklines - m = py_comment.match(inp, pos) - if m: - if not self.comment: - self.comment = m.group(0) - # XXX FIXME: encoding management - if self.line <= 2: - # self.comment can be the previous comment, so don't use it - comment = m.group(0)[1:] - m_enc = py_encoding.search(comment) - if m_enc is not None: - self.encoding = _normalize_encoding(m_enc.group(1)) - # - self.pos = m.end() + 1 - self.line += 1 - self.atbol = True - return self._next() - # the current block is more indented than the previous one - if col > self.indentstack[-1]: - self.indentstack.append(col) - return "INDENT", None - # the current block is less indented than the previous one - while col < self.indentstack[-1]: - self.pendin += 1 - self.indentstack.pop(-1) - if col != self.indentstack[-1]: - raise SyntaxError("Indentation Error") - if self.pendin > 0: - self.pendin -= 1 - return "DEDENT", None - m = py_skip.match(inp, pos) - if m.group(0)[-1:] == '\n': - self.line += 1 - self.comment = m.group(1) or '' - pos = m.end() # always match - if pos >= input_length: - return self.end_of_file() - self.pos = pos - - # STRING - c = inp[pos] - if c in ('r','R'): - if pos < input_length-1 and inp[pos+1] in ("'",'"'): - return self.next_string(raw=1) - elif c in ('u','U'): - if pos < input_length-1: - if inp[pos+1] in ("r",'R'): - if pos 0: - return self._next() - else: - self.atbol = True - comment = self.comment - self.comment = '' - return "NEWLINE", comment - - if c == '\\': - if pos < input_length-1 and inp[pos+1] == '\n': - self.pos += 2 - return self._next() - - m = py_punct.match(inp, pos) - if m: - punct = m.group(0) - if punct in ( '(', '{', '[' ): - self.level += 1 - if punct in ( ')', '}', ']' ): - self.level -= 1 - self.pos = m.end() - return punct, None - raise SyntaxError("Unrecognized token '%s'" % inp[pos:pos+20] ) - - def next(self): - if self.stack_pos >= len(self.stack): - pos0 = self.pos - tok, val = self._next() - token = Token( tok, val ) - self.stack.append( ( token, self.line, pos0) ) - self._current_line = self.line - else: - token, line, pos0 = self.stack[self.stack_pos] - self._current_line = line - self.stack_pos += 1 - if DEBUG: - print "%d/%d: %s, %s" % (self.stack_pos, len(self.stack), tok, val) - return token - - def get_pos(self): - if self.stack_pos >= len(self.stack): - return self.pos - else: - token, line, pos = self.stack[self.stack_pos] - return pos - - def get_source_text(self, pos0, pos1 ): - return self.input[pos0:pos1] - - def peek(self): - """returns next token without consuming it""" - ctx = self.context() - token = self.next() - self.restore(ctx) - return token - - - def end_of_file(self): - """return DEDENT and ENDMARKER""" - if len(self.indentstack) == 1: - self.indentstack.pop(-1) - return "NEWLINE", '' #self.comment - elif len(self.indentstack) > 1: - self.indentstack.pop(-1) - return "DEDENT", None - return "ENDMARKER", None - - - def next_string(self, raw=0, uni=0): - pos = self.pos + raw + uni - inp = self.input - quote = inp[pos] - qsize = 1 - if inp[pos:pos+3] == 3*quote: - pos += 3 - quote = 3*quote - qsize = 3 - else: - pos += 1 - while True: - if inp[pos:pos+qsize] == quote: - s = inp[self.pos:pos+qsize] - self.pos = pos+qsize - return "STRING", s - # FIXME : shouldn't it be inp[pos] == os.linesep ? - if inp[pos:pos+2] == "\n" and qsize == 1: - return None, None - if inp[pos] == "\\": - pos += 1 - pos += 1 - - def debug(self): - """return context for debug information""" - if not hasattr(self, '_lines'): - # split lines only once - self._lines = self.input.splitlines() - if self.line > len(self._lines): - lineno = len(self._lines) - else: - lineno = self.line - return 'line %s : %s' % (lineno, self._lines[lineno-1]) - - ################################################################################ -class StringAsFile(object): - """XXX: Is StringIO RPython ?""" - - def __init__(self, inpstring): - self.lines = inpstring.splitlines(True) - self.lineno = 0 - - def readline(self): - if self.lineno < len(self.lines): - line = self.lines[self.lineno] - self.lineno += 1 - return line - return '' - - import token as tokenmod -from pypy.module.parser.pytokenize import generate_tokens, tabsize, \ +from pypy.module.parser.pytokenize import tabsize, \ whiteSpaceDFA, triple_quoted, endDFAs, single_quoted, pseudoDFA from pypy.module.parser import automata @@ -347,8 +102,8 @@ """ token_list = [] lnum = parenlev = continued = 0 - namechars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_' - numchars = '0123456789' + namechars = NAMECHARS + numchars = NUMCHARS contstr, needcont = '', 0 contline = None indents = [0] @@ -405,10 +160,10 @@ if line[pos] == '#': tok = token_from_values(tokenmod.COMMENT, line[pos:]) last_comment = line[pos:] - if lnum <= 2: - m_enc = py_encoding.search(last_comment) - if m_enc is not None: - encoding = _normalize_encoding(m_enc.group(1)) + if lnum <= 2 and encoding is None: + encoding = match_encoding_declaration(last_comment) + if encoding is not None: + encoding = _normalize_encoding(encoding) else: tok = token_from_values(tokenmod.NL, line[pos:]) last_comment = '' @@ -468,10 +223,10 @@ elif initial == '#': tok = token_from_values(tokenmod.COMMENT, token) last_comment = token - if lnum <= 2: - m_enc = py_encoding.search(last_comment) - if m_enc is not None: - encoding = _normalize_encoding(m_enc.group(1)) + if lnum <= 2 and encoding is None: + encoding = match_encoding_declaration(last_comment) + if encoding is not None: + encoding = _normalize_encoding(encoding) # XXX Skip # token_list.append((tok, line)) # token_list.append((COMMENT, token, spos, epos, line)) elif token in triple_quoted: @@ -540,12 +295,10 @@ # token_list.append((ENDMARKER, '', (lnum, 0), (lnum, 0), '')) return token_list, encoding - -class PythonSource2(TokenSource): +class PythonSource(TokenSource): """This source uses Jonathan's tokenizer""" def __init__(self, inpstring): TokenSource.__init__(self) - # tokens, encoding = generate_tokens(StringAsFile(inpstring).readline) tokens, encoding = generate_tokens(inpstring.splitlines(True)) self.token_stack = tokens self.encoding = encoding @@ -611,7 +364,7 @@ return Token('NEWLINE', '') # XXX pending comment ? return Token(tokenmod.tok_name[tok_type], tok_string) -Source = PythonSource2 +Source = PythonSource def tokenize_file(filename): f = file(filename).read() From adim at codespeak.net Mon Jun 13 18:30:22 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Mon, 13 Jun 2005 18:30:22 +0200 (CEST) Subject: [pypy-svn] r13359 - pypy/branch/pycompiler/module/recparser/test Message-ID: <20050613163022.239F427B71@code1.codespeak.net> Author: adim Date: Mon Jun 13 18:30:20 2005 New Revision: 13359 Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py pypy/branch/pycompiler/module/recparser/test/test_samples.py Log: - added tests for encoding decl recognition - fixed imports to use the new Lexer Modified: pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_pytokenizer.py Mon Jun 13 18:30:20 2005 @@ -1,5 +1,5 @@ -from pypy.module.recparser.pythonlexer import Source, py_number, \ - g_symdef, g_string, py_name, py_punct, TokenError +from pypy.module.recparser.pythonlexer import Source, TokenError, \ + match_encoding_declaration from pypy.module.recparser.grammar import Token def parse_source(source): @@ -40,17 +40,6 @@ 'j', '0xg', '0xj', '0xJ', ] -def test_empty_string(): - """make sure defined regexps don't match empty string""" - rgxes = {'numbers' : py_number, - 'defsym' : g_symdef, - 'strings' : g_string, - 'names' : py_name, - 'punct' : py_punct, - } - for label, rgx in rgxes.items(): - assert rgx.match('') is None, '%s matches empty string' % label - def test_several_lines_list(): """tests list definition on several lines""" s = """['a' @@ -77,8 +66,6 @@ Token('NUMBER', '0x12L'), Token('NEWLINE', ''), Token('ENDMARKER', None)] -import sys - def test_punct(): """make sure each punctuation is correctly parsed""" for pstr in PUNCTS: @@ -88,3 +75,19 @@ tokens = [tok for tok, line in error.token_stack] assert tokens[0].name == pstr + +def test_encoding_declarations_match(): + checks = [ + ('# -*- coding: ISO-8859-1 -*-', 'ISO-8859-1'), + ('# -*- coding: ISO-8859-1 -*-\n', 'ISO-8859-1'), + ('# -*- coding: ISO-8859-1', 'ISO-8859-1'), + ('# -*- coding= UTF-8', 'UTF-8'), + ('# coding= UTF-8', 'UTF-8'), + ('# coding= UTF-8 hello', 'UTF-8'), + ('# -*- coding: ISO_8859-1', 'ISO_8859-1'), + ('# -*- coding ISO_8859-1', None), + ('# coding ISO_8859-1', None), + ] + for comment, encoding in checks: + res = match_encoding_declaration(comment) + assert res == encoding, "Failed on (%s), %s != %s" % (comment, res, encoding) Modified: pypy/branch/pycompiler/module/recparser/test/test_samples.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/test/test_samples.py (original) +++ pypy/branch/pycompiler/module/recparser/test/test_samples.py Mon Jun 13 18:30:20 2005 @@ -51,7 +51,6 @@ for fname in os.listdir(samples_dir): if not fname.endswith('.py'): continue - # if fname != 'snippet_encoding_declaration.py': abspath = osp.join(samples_dir, fname) yield check_parse, abspath From pedronis at codespeak.net Tue Jun 14 01:24:01 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 14 Jun 2005 01:24:01 +0200 (CEST) Subject: [pypy-svn] r13368 - in pypy/dist/pypy: annotation rpython rpython/test translator/c Message-ID: <20050613232401.7F8C727B84@code1.codespeak.net> Author: pedronis Date: Tue Jun 14 01:23:59 2005 New Revision: 13368 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_llann.py pypy/dist/pypy/rpython/test/test_lltype.py pypy/dist/pypy/translator/c/funcgen.py Log: - cast_parent isn't anymore - converted tests to test cast_pointer instead Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue Jun 14 01:23:59 2005 @@ -299,15 +299,6 @@ #print "MALLOC", r return r -def cast_parent(PtrT, s_p): - assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p - assert PtrT.is_constant() - PtrT = PtrT.const - parent_p = PtrT._example() - candidate_p = s_p.ll_ptrtype._example() - parent_p._setfirst(candidate_p) - return SomePtr(ll_ptrtype=lltype.typeOf(lltype.cast_parent(PtrT, candidate_p))) - def typeOf(s_val): lltype = annotation_to_lltype(s_val, info="in typeOf(): ") return immutablevalue(lltype) @@ -327,7 +318,6 @@ BUILTIN_ANALYZERS[lltype.malloc] = malloc -BUILTIN_ANALYZERS[lltype.cast_parent] = cast_parent BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.nullptr] = nullptr BUILTIN_ANALYZERS[lltype.cast_pointer] = cast_pointer Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 14 01:23:59 2005 @@ -320,33 +320,6 @@ class InvalidCast(TypeError): pass -def cast_parent(PTRTYPE, ptr): - if not isinstance(ptr, _ptr) or not isinstance(PTRTYPE, Ptr): - raise TypeError, "can only cast pointers to other pointers" - CURTYPE = ptr._TYPE - if castable(PTRTYPE, CURTYPE) != -1: # xxx makes some of the rest superfluous - raise InvalidCast(CURTYPE, PTRTYPE) - if CURTYPE._needsgc() != PTRTYPE._needsgc(): - raise TypeError("cast_parent() cannot change the gc status: %s to %s" - % (CURTYPE, PTRTYPE)) - # * converting from TO-structure to a parent TO-structure whose first - # field is the original structure - if (not isinstance(CURTYPE.TO, Struct) or - not isinstance(PTRTYPE.TO, Struct) or - len(PTRTYPE.TO._names) == 0 or - PTRTYPE.TO._flds[PTRTYPE.TO._names[0]] != CURTYPE.TO): - raise InvalidCast(CURTYPE, PTRTYPE) - parent = ptr._obj._parentstructure() - if parent is None: - raise RuntimeError("widening to trash: %r" % ptr) - PARENTTYPE = ptr._obj._parent_type - if getattr(parent, PARENTTYPE._names[0]) is not ptr._obj: - raise InvalidCast(CURTYPE, PTRTYPE) - if PARENTTYPE != PTRTYPE.TO: - raise TypeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO)) - return _ptr(PTRTYPE, parent) - - def _castdepth(OUTSIDE, INSIDE): if OUTSIDE == INSIDE: return 0 @@ -486,19 +459,19 @@ raise AttributeError("%r instance has no field %r" % (self._T, field_name)) - def _setfirst(self, p): - if isinstance(self._T, Struct) and self._T._names: - if not isinstance(p, _ptr) or not isinstance(p._obj, _struct): - raise InvalidCast(typeOf(p), typeOf(self)) - field_name = self._T._names[0] - T1 = self._T._flds[field_name] - T2 = typeOf(p._obj) - if T1 != T2: - raise InvalidCast(typeOf(p), typeOf(self)) - setattr(self._obj, field_name, p._obj) - p._obj._setparentstructure(self._obj, 0) - return - raise TypeError("%r instance has no first field" % (self._T,)) + #def _setfirst(self, p): + # if isinstance(self._T, Struct) and self._T._names: + # if not isinstance(p, _ptr) or not isinstance(p._obj, _struct): + # raise InvalidCast(typeOf(p), typeOf(self)) + # field_name = self._T._names[0] + # T1 = self._T._flds[field_name] + # T2 = typeOf(p._obj) + # if T1 != T2: + # raise InvalidCast(typeOf(p), typeOf(self)) + # setattr(self._obj, field_name, p._obj) + # p._obj._setparentstructure(self._obj, 0) + # return + # raise TypeError("%r instance has no first field" % (self._T,)) def __setattr__(self, field_name, val): if isinstance(self._T, Struct): Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jun 14 01:23:59 2005 @@ -120,13 +120,6 @@ def rtype_const_result(hop): return hop.inputconst(Void, hop.s_result.const) -def rtype_cast_parent(hop): - assert hop.args_s[0].is_constant() - assert isinstance(hop.args_r[1], rptr.PtrRepr) - v_type, v_input = hop.inputargs(Void, hop.args_r[1]) - return hop.genop('cast_parent', [v_input], # v_type implicit in r_result - resulttype = hop.r_result.lowleveltype) - def rtype_cast_pointer(hop): assert hop.args_s[0].is_constant() assert isinstance(hop.args_r[1], rptr.PtrRepr) @@ -136,7 +129,6 @@ BUILTIN_TYPER[lltype.malloc] = rtype_malloc -BUILTIN_TYPER[lltype.cast_parent] = rtype_cast_parent BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Tue Jun 14 01:23:59 2005 @@ -68,28 +68,28 @@ s, dontcare = annotate_lowlevel_helper(a, llf, []) assert s.knowntype == int - def test_cast_parent(self): + def test_cast_simple_widening(self): S2 = Struct("s2", ('a', Signed)) S1 = Struct("s1", ('sub1', S2), ('sub2', S2)) PS1 = Ptr(S1) PS2 = Ptr(S2) def llf(p1): p2 = p1.sub1 - p3 = cast_parent(PS1, p2) + p3 = cast_pointer(PS1, p2) return p3 a = self.RPythonAnnotator() s, dontcare = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(PS1)]) assert isinstance(s, annmodel.SomePtr) assert s.ll_ptrtype == PS1 - def test_cast_parent_from_gc(self): + def test_cast_simple_widening_from_gc(self): S2 = GcStruct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2), ('x', Signed)) PS1 = Ptr(S1) def llf(): p1 = malloc(S1) p2 = p1.sub1 - p3 = cast_parent(PS1, p2) + p3 = cast_pointer(PS1, p2) return p3 a = self.RPythonAnnotator() s, dontcare = annotate_lowlevel_helper(a, llf, []) Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Tue Jun 14 01:23:59 2005 @@ -132,35 +132,34 @@ assert typeOf(p1.sub1) == Ptr(S1) assert isweak(p1.sub2, S2) -def test_cast_parent(): +def test_cast_simple_widening(): S2 = Struct("s2", ('a', Signed)) S1 = Struct("s1", ('sub1', S2), ('sub2', S2)) p1 = malloc(S1, immortal=True) p2 = p1.sub1 p3 = p2 assert typeOf(p3) == Ptr(S2) - p4 = cast_parent(Ptr(S1), p3) + p4 = cast_pointer(Ptr(S1), p3) assert typeOf(p4) == Ptr(S1) assert p4 == p1 - py.test.raises(TypeError, "cast_parent(Ptr(S1), p1.sub2)") - py.test.raises(TypeError, "cast_parent(Ptr(S2), p3)") + py.test.raises(TypeError, "cast_pointer(Ptr(S1), p1.sub2)") SUnrelated = Struct("unrelated") - py.test.raises(TypeError, "cast_parent(Ptr(SUnrelated), p3)") + py.test.raises(TypeError, "cast_pointer(Ptr(SUnrelated), p3)") S1bis = Struct("s1b", ('sub1', S2)) p1b = malloc(S1bis, immortal=True) p2 = p1b.sub1 - py.test.raises(TypeError, "cast_parent(Ptr(S1), p2)") + py.test.raises(TypeError, "cast_pointer(Ptr(S1), p2)") -def test_cast_parent2(): +def test_cast_simple_widening2(): S2 = GcStruct("s2", ('a', Signed)) S1 = GcStruct("s1", ('sub1', S2)) p1 = malloc(S1) p2 = p1.sub1 assert typeOf(p2) == Ptr(S2) - p3 = cast_parent(Ptr(S1), p2) + p3 = cast_pointer(Ptr(S1), p2) assert p3 == p1 p2 = malloc(S2) - py.test.raises(RuntimeError, "cast_parent(Ptr(S1), p2)") + py.test.raises(RuntimeError, "cast_pointer(Ptr(S1), p2)") def test_cast_pointer(): S3 = GcStruct("s3", ('a', Signed)) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Tue Jun 14 01:23:59 2005 @@ -450,8 +450,6 @@ result.append(line) return '\t'.join(result) - OP_CAST_PARENT = OP_CAST_POINTER - def OP_SAME_AS(self, op, err): result = [] assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] From pedronis at codespeak.net Tue Jun 14 03:15:03 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 14 Jun 2005 03:15:03 +0200 (CEST) Subject: [pypy-svn] r13369 - pypy/dist/pypy/annotation Message-ID: <20050614011503.ECE1827B7D@code1.codespeak.net> Author: pedronis Date: Tue Jun 14 03:15:01 2005 New Revision: 13369 Modified: pypy/dist/pypy/annotation/classdef.py Log: adding assert for assumption that seems intermittently not valid Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Tue Jun 14 03:15:01 2005 @@ -203,6 +203,7 @@ break else: self._generalize_attr(attr, s_value) + assert attr in self.attrs def about_attribute(self, name): """This is the interface for the code generators to ask about From adim at codespeak.net Tue Jun 14 11:12:15 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Tue, 14 Jun 2005 11:12:15 +0200 (CEST) Subject: [pypy-svn] r13371 - pypy/branch/pycompiler/bin Message-ID: <20050614091215.E18C127B83@code1.codespeak.net> Author: adim Date: Tue Jun 14 11:12:14 2005 New Revision: 13371 Modified: pypy/branch/pycompiler/bin/translator.py Log: added readline / history / tab support for translator shell (fed up with always retyping the same things ... ) this will probably reamain local to the pycompiler branch Modified: pypy/branch/pycompiler/bin/translator.py ============================================================================== --- pypy/branch/pycompiler/bin/translator.py (original) +++ pypy/branch/pycompiler/bin/translator.py Tue Jun 14 11:12:14 2005 @@ -36,7 +36,25 @@ from pypy.translator.translator import Translator +def setup_readline(): + import readline + import rlcompleter + readline.parse_and_bind("tab: complete") + import os + histfile = os.path.join(os.environ["HOME"], ".pypytrhist") + print "reading history file ..." + try: + readline.read_history_file(histfile) + except IOError: + pass + print "done" + import atexit + atexit.register(readline.write_history_file, histfile) + del os, histfile + + if __name__ == '__main__': + setup_readline() from pypy.translator.test import snippet as test if (os.getcwd() not in sys.path and os.path.curdir not in sys.path): From adim at codespeak.net Tue Jun 14 11:33:42 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Tue, 14 Jun 2005 11:33:42 +0200 (CEST) Subject: [pypy-svn] r13376 - pypy/branch/pycompiler/annotation Message-ID: <20050614093342.08C0327B85@code1.codespeak.net> Author: adim Date: Tue Jun 14 11:33:41 2005 New Revision: 13376 Modified: pypy/branch/pycompiler/annotation/unaryop.py Log: added str.find() annotation capability to be able to translate / annotate pythonlexer.match_encoding_declaration Modified: pypy/branch/pycompiler/annotation/unaryop.py ============================================================================== --- pypy/branch/pycompiler/annotation/unaryop.py (original) +++ pypy/branch/pycompiler/annotation/unaryop.py Tue Jun 14 11:33:41 2005 @@ -274,6 +274,9 @@ def method_join(str, s_list): return SomeString() + def method_find(str, frag): + return SomeInteger() + def iter(str): return SomeIterator(SomeChar()) From adim at codespeak.net Tue Jun 14 12:11:47 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Tue, 14 Jun 2005 12:11:47 +0200 (CEST) Subject: [pypy-svn] r13378 - pypy/dist/pypy/bin Message-ID: <20050614101147.CA60227B85@code1.codespeak.net> Author: adim Date: Tue Jun 14 12:11:46 2005 New Revision: 13378 Modified: pypy/dist/pypy/bin/translator.py Log: added readline / history / tab support for translator shell (fed up with always retyping the same things ... ) History file is $HOME/.pypytrhist Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Tue Jun 14 12:11:46 2005 @@ -209,11 +209,28 @@ print 'Backend', options.backend, 'compiled code returns (%s)' % backendReturn, '[use -t to perform a sanity check]' +def setup_readline(): + import readline + import rlcompleter + readline.parse_and_bind("tab: complete") + import os + histfile = os.path.join(os.environ["HOME"], ".pypytrhist") + try: + readline.read_history_file(histfile) + except IOError: + pass + import atexit + atexit.register(readline.write_history_file, histfile) + if __name__ == '__main__': from pypy.translator.test import snippet as test from pypy.translator.llvm.test import llvmsnippet as test2 from pypy.rpython.rtyper import RPythonTyper + try: + setup_readline() + except ImportError, err: + print "Disabling readline support (%s)" % err if (os.getcwd() not in sys.path and os.path.curdir not in sys.path): sys.path.insert(0, os.getcwd()) From arigo at codespeak.net Tue Jun 14 12:40:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 12:40:26 +0200 (CEST) Subject: [pypy-svn] r13379 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614104026.29D3B27B85@code1.codespeak.net> Author: arigo Date: Tue Jun 14 12:40:23 2005 New Revision: 13379 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_lltype.py Log: - sanitize rclass.ll_cast_to_object(). - bug fix with test in the parent structure reference code. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Tue Jun 14 12:40:23 2005 @@ -544,7 +544,9 @@ self._wrparent = weakref.ref(parent) self._parent_type = typeOf(parent) self._parent_index = parentindex - if parentindex == 0 and self._TYPE._gcstatus() == typeOf(parent)._gcstatus(): + if (isinstance(self._parent_type, Struct) + and parentindex == self._parent_type._names[0] + and self._TYPE._gcstatus() == typeOf(parent)._gcstatus()): # keep strong reference to parent, we share the same allocation self._keepparent = parent Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jun 14 12:40:23 2005 @@ -483,15 +483,10 @@ # Low-level implementation of operations on classes and instances def ll_cast_to_object(obj): - # This strange recursive version is type-safe :-) - # Each ll_cast_to_object() call below is done with a different type. - if typeOf(obj) == OBJECTPTR: - return obj - else: - return ll_cast_to_object(obj.super) + return cast_pointer(OBJECTPTR, obj) def ll_type(obj): - return ll_cast_to_object(obj).typeptr + return cast_pointer(OBJECTPTR, obj).typeptr def ll_issubclass(subcls, cls): while subcls != cls: Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Tue Jun 14 12:40:23 2005 @@ -328,5 +328,13 @@ py.test.raises(TypeError, "a[0] = s") S = Struct('s', ('last', Array(S))) py.test.raises(TypeError, "Array(S)") - - + +def test_immortal_parent(): + S1 = GcStruct('substruct', ('x', Signed)) + S = GcStruct('parentstruct', ('s1', S1)) + p = malloc(S, immortal=True) + p1 = p.s1 + p1.x = 5 + del p + p = cast_pointer(Ptr(S), p1) + assert p.s1.x == 5 From arigo at codespeak.net Tue Jun 14 15:03:35 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 15:03:35 +0200 (CEST) Subject: [pypy-svn] r13380 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050614130335.2F10627B85@code1.codespeak.net> Author: arigo Date: Tue Jun 14 15:03:28 2005 New Revision: 13380 Added: pypy/dist/pypy/translator/c/external.py (contents, props changed) pypy/dist/pypy/translator/c/g_exception.h (contents, props changed) pypy/dist/pypy/translator/c/test/test_exception.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/g_module.h pypy/dist/pypy/translator/c/g_support.h pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/ll_include.h pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/pyobj_include.h pypy/dist/pypy/translator/c/test/test_genc.py pypy/dist/pypy/translator/c/wrapper.py Log: Support for real RPython exceptions in genc. Exceptions are regular RPython instances, set in a pair of global variables (for now), rpython_exc_type and rpython_exc_value. Standard exceptions (ValueError, OverflowError, etc.) have no 'args' field; the message is ignored right now. Moreover, the part about exchanging these exceptions with CPython exceptions at the correct point is quite messy, and looses almost all information. So if any rpython exception is raised by the code and not caught, the module throws you a completely useless "RPythonError". Needs to be improved... Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Tue Jun 14 15:03:28 2005 @@ -1,6 +1,7 @@ from pypy.rpython.lltype import Primitive, Ptr, typeOf from pypy.rpython.lltype import Struct, Array, FuncType, PyObject, Void -from pypy.rpython.lltype import ContainerType +from pypy.rpython.lltype import ContainerType, pyobjectptr +from pypy.rpython.rmodel import getfunctionptr from pypy.objspace.flow.model import Constant from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue @@ -14,6 +15,7 @@ class LowLevelDatabase: def __init__(self, translator=None): + self.translator = translator self.structdefnodes = {} self.structdeflist = [] self.containernodes = {} @@ -144,3 +146,45 @@ for node in self.containerlist: if node.globalcontainer: yield node + + def pre_include_code_lines(self): + # generate some #defines that go before the #include to control + # what g_exception.h does + if self.translator is not None and self.translator.rtyper is not None: + exceptiondata = self.translator.rtyper.getexceptiondata() + + TYPE = exceptiondata.lltype_of_exception_type + assert isinstance(TYPE, Ptr) + typename = self.gettype(TYPE) + yield '#define RPYTHON_EXCEPTION_VTABLE %s' % cdecl(typename, '') + + TYPE = exceptiondata.lltype_of_exception_value + assert isinstance(TYPE, Ptr) + typename = self.gettype(TYPE) + yield '#define RPYTHON_EXCEPTION %s' % cdecl(typename, '') + + fnptr = getfunctionptr(self.translator, + exceptiondata.ll_exception_match) + fnname = self.get(fnptr) + yield '#define RPYTHON_EXCEPTION_MATCH %s' % (fnname,) + + fnptr = getfunctionptr(self.translator, + exceptiondata.ll_type_of_exc_inst) + fnname = self.get(fnptr) + yield '#define RPYTHON_TYPE_OF_EXC_INST %s' % (fnname,) + + fnptr = getfunctionptr(self.translator, + exceptiondata.ll_pyexcclass2exc) + fnname = self.get(fnptr) + yield '#define RPYTHON_PYEXCCLASS2EXC %s' % (fnname,) + + for pyexccls in [TypeError, OverflowError, ValueError, + ZeroDivisionError, MemoryError]: + exc_llvalue = exceptiondata.ll_pyexcclass2exc( + pyobjectptr(pyexccls)) + # strange naming here because the macro name must be + # a substring of PyExc_%s + yield '#define Exc_%s\t%s' % ( + pyexccls.__name__, self.get(exc_llvalue)) + + self.complete() # because of the get() and gettype() above Added: pypy/dist/pypy/translator/c/external.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/external.py Tue Jun 14 15:03:28 2005 @@ -0,0 +1,35 @@ +from __future__ import generators +from pypy.rpython.lltype import typeOf, Void +from pypy.translator.c.support import cdecl, ErrorValue, somelettersfrom + + +class CExternalFunctionCodeGenerator: + + def __init__(self, fnptr, db): + self.fnptr = fnptr + self.db = db + self.FUNCTYPE = typeOf(fnptr) + assert Void not in self.FUNCTYPE.ARGS + self.argtypenames = [db.gettype(T) for T in self.FUNCTYPE.ARGS] + self.resulttypename = db.gettype(self.FUNCTYPE.RESULT) + + def argnames(self): + return ['%s%d' % (somelettersfrom(self.argtypenames[i]), i) + for i in range(len(self.argtypenames))] + + def allconstantvalues(self): + return [] + + def cfunction_declarations(self): + if self.FUNCTYPE.RESULT != Void: + yield '%s;' % cdecl(self.resulttypename, 'result') + + def cfunction_body(self): + call = '%s(%s)' % (self.fnptr._name, ', '.join(self.argnames())) + if self.FUNCTYPE.RESULT != Void: + yield 'result = %s;' % call + yield 'if (PyErr_Occurred()) ConvertExceptionFromCPython();' + yield 'return result;' + else: + yield '%s;' % call + yield 'if (PyErr_Occurred()) ConvertExceptionFromCPython();' Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Tue Jun 14 15:03:28 2005 @@ -2,7 +2,7 @@ from pypy.translator.c.support import cdecl, ErrorValue from pypy.translator.c.support import llvalue_from_constant from pypy.objspace.flow.model import Variable, Constant, Block -from pypy.objspace.flow.model import traverse, uniqueitems, last_exception +from pypy.objspace.flow.model import traverse, last_exception from pypy.rpython.lltype import Ptr, PyObject, Void, Bool from pypy.rpython.lltype import pyobjectptr, Struct, Array from pypy.translator.unsimplify import remove_direct_loops @@ -16,55 +16,72 @@ from a flow graph. """ - def __init__(self, graph, db): + def __init__(self, graph, db, cpython_exc=False): self.graph = graph remove_direct_loops(None, graph) self.db = db - self.lltypemap = self.collecttypes() - self.typemap = {} - for v, T in self.lltypemap.items(): - self.typemap[v] = db.gettype(T) - - def collecttypes(self): + self.cpython_exc = cpython_exc + # # collect all variables and constants used in the body, # and get their types now - result = [] + # + # NOTE: cannot use dictionaries with Constants has keys, because + # Constants may hash and compare equal but have different lltypes + mix = [] + self.more_ll_values = {} def visit(block): if isinstance(block, Block): - result.extend(block.inputargs) + mix.extend(block.inputargs) for op in block.operations: - result.extend(op.args) - result.append(op.result) + mix.extend(op.args) + mix.append(op.result) for link in block.exits: - result.extend(link.getextravars()) - result.extend(link.args) - result.append(Constant(link.exitcase)) - traverse(visit, self.graph) - resultvar = self.graph.getreturnvar() - lltypemap = {resultvar: Void} # default value, normally overridden - for v in uniqueitems(result): - # xxx what kind of pointer for constants? - T = getattr(v, 'concretetype', PyObjPtr) - lltypemap[v] = T - return lltypemap + mix.extend(link.getextravars()) + mix.extend(link.args) + mix.append(Constant(link.exitcase)) + if hasattr(link, 'llexitcase'): + self.more_ll_values[link.llexitcase] = True + traverse(visit, graph) + resultvar = graph.getreturnvar() + + self.lltypes = { + # default, normally overridden: + id(resultvar): (resultvar, Void, db.gettype(Void)), + } + for v in mix: + T = getattr(v, 'concretetype', PyObjPtr) + typename = db.gettype(T) + self.lltypes[id(v)] = v, T, typename def argnames(self): return [v.name for v in self.graph.getargs()] def allvariables(self): - return [v for v in self.typemap if isinstance(v, Variable)] + return [v for v, T, typename in self.lltypes.values() + if isinstance(v, Variable)] def allconstants(self): - return [v for v in self.typemap if isinstance(v, Constant)] + return [c for c, T, typename in self.lltypes.values() + if isinstance(c, Constant)] def allconstantvalues(self): - for v in self.typemap: - if isinstance(v, Constant): - yield llvalue_from_constant(v) + for c, T, typename in self.lltypes.values(): + if isinstance(c, Constant): + yield llvalue_from_constant(c) + for llvalue in self.more_ll_values: + yield llvalue + + def lltypemap(self, v): + v, T, typename = self.lltypes[id(v)] + return T + + def lltypename(self, v): + v, T, typename = self.lltypes[id(v)] + return typename def expr(self, v): if isinstance(v, Variable): - if self.lltypemap[v] == Void: + if self.lltypemap(v) == Void: return '/* nothing */' else: return v.name @@ -74,8 +91,12 @@ raise TypeError, "expr(%r)" % (v,) def error_return_value(self): - returnlltype = self.lltypemap[self.graph.getreturnvar()] - return self.db.get(ErrorValue(returnlltype)) + if self.cpython_exc: + assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr + return 'ConvertExceptionToCPython()' + else: + returnlltype = self.lltypemap(self.graph.getreturnvar()) + return self.db.get(ErrorValue(returnlltype)) # ____________________________________________________________ @@ -88,8 +109,8 @@ result_by_name = [] for v in self.allvariables(): if v not in inputargset: - result = cdecl(self.typemap[v], v.name) + ';' - if self.lltypemap[v] == Void: + result = cdecl(self.lltypename(v), v.name) + ';' + if self.lltypemap(v) == Void: result = '/*%s*/' % result result_by_name.append((v._name, result)) result_by_name.sort() @@ -117,7 +138,7 @@ linklocalvars[v] = self.expr(v) has_ref = linklocalvars.copy() for a1, a2 in zip(link.args, link.target.inputargs): - if self.lltypemap[a2] == Void: + if self.lltypemap(a2) == Void: continue if a1 in linklocalvars: src = linklocalvars[a1] @@ -127,7 +148,7 @@ if a1 in has_ref: del has_ref[a1] else: - assert self.lltypemap[a1] == self.lltypemap[a2] + assert self.lltypemap(a1) == self.lltypemap(a2) line += '\t' + self.cincref(a2) yield line for v in has_ref: @@ -169,7 +190,7 @@ # exceptional return block exc_cls = self.expr(block.inputargs[0]) exc_value = self.expr(block.inputargs[1]) - yield 'PyErr_Restore(%s, %s, NULL);' % (exc_cls, exc_value) + yield 'RaiseException(%s, %s);' % (exc_cls, exc_value) yield 'return %s;' % self.error_return_value() else: # regular return block @@ -197,31 +218,40 @@ yield '' for link in block.exits[1:]: assert issubclass(link.exitcase, Exception) - yield 'if (PyErr_ExceptionMatches(%s)) {' % ( - self.db.get(pyobjectptr(link.exitcase)),) - yield '\tPyObject *exc_cls, *exc_value, *exc_tb;' - yield '\tPyErr_Fetch(&exc_cls, &exc_value, &exc_tb);' - yield '\tif (exc_value == NULL) {' - yield '\t\texc_value = Py_None;' - yield '\t\tPy_INCREF(Py_None);' - yield '\t}' - yield '\tPy_XDECREF(exc_tb);' + try: + etype = link.llexitcase + except AttributeError: + etype = pyobjectptr(link.exitcase) + T1 = PyObjPtr + T2 = PyObjPtr + else: + assert hasattr(link.last_exception, 'concretetype') + assert hasattr(link.last_exc_value, 'concretetype') + T1 = link.last_exception.concretetype + T2 = link.last_exc_value.concretetype + typ1 = self.db.gettype(T1) + typ2 = self.db.gettype(T2) + yield 'if (MatchException(%s)) {' % (self.db.get(etype),) + yield '\t%s;' % cdecl(typ1, 'exc_cls') + yield '\t%s;' % cdecl(typ2, 'exc_value') + yield '\tFetchException(exc_cls, exc_value, %s);' % ( + cdecl(typ2, '')) d = {} if isinstance(link.last_exception, Variable): d[link.last_exception] = 'exc_cls' else: - yield '\tPy_XDECREF(exc_cls);' + yield '\t' + self.db.cdecrefstmt('exc_cls', T1) if isinstance(link.last_exc_value, Variable): d[link.last_exc_value] = 'exc_value' else: - yield '\tPy_XDECREF(exc_value);' + yield '\t' + self.db.cdecrefstmt('exc_value', T2) for op in gen_link(link, d): yield '\t' + op yield '}' err_reachable = True else: # block ending in a switch on a value - TYPE = self.lltypemap[block.exitswitch] + TYPE = self.lltypemap(block.exitswitch) for link in block.exits[:-1]: assert link.exitcase in (False, True) expr = self.expr(block.exitswitch) @@ -302,14 +332,14 @@ def OP_DIRECT_CALL(self, op, err): # skip 'void' arguments - args = [self.expr(v) for v in op.args if self.lltypemap[v] != Void] - if self.lltypemap[op.result] == Void: + args = [self.expr(v) for v in op.args if self.lltypemap(v) != Void] + if self.lltypemap(op.result) == Void: # skip assignment of 'void' return value - return '%s(%s); if (PyErr_Occurred()) FAIL(%s)' % ( + return '%s(%s); if (ExceptionOccurred()) FAIL(%s)' % ( args[0], ', '.join(args[1:]), err) else: r = self.expr(op.result) - return '%s = %s(%s); if (PyErr_Occurred()) FAIL(%s)' % ( + return '%s = %s(%s); if (ExceptionOccurred()) FAIL(%s)' % ( r, args[0], ', '.join(args[1:]), err) # low-level operations @@ -317,7 +347,7 @@ newvalue = self.expr(op.result) result = ['%s = %s;' % (newvalue, sourceexpr)] # need to adjust the refcount of the result - T = self.lltypemap[op.result] + T = self.lltypemap(op.result) increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: result.append(increfstmt) @@ -330,14 +360,14 @@ newvalue = self.expr(op.args[2]) result = ['%s = %s;' % (targetexpr, newvalue)] # need to adjust some refcounts - T = self.lltypemap[op.args[2]] + T = self.lltypemap(op.args[2]) decrefstmt = self.db.cdecrefstmt('prev', T) increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: result.append(increfstmt) if decrefstmt: result.insert(0, '{ %s = %s;' % ( - cdecl(self.typemap[op.args[2]], 'prev'), + cdecl(self.lltypename(op.args[2]), 'prev'), targetexpr)) result.append(decrefstmt) result.append('}') @@ -348,7 +378,7 @@ def OP_GETFIELD(self, op, err, ampersand=''): assert isinstance(op.args[1], Constant) - STRUCT = self.lltypemap[op.args[0]].TO + STRUCT = self.lltypemap(op.args[0]).TO structdef = self.db.gettypedefnode(STRUCT) fieldname = structdef.c_struct_field_name(op.args[1].value) return self.generic_get(op, '%s%s->%s' % (ampersand, @@ -357,7 +387,7 @@ def OP_SETFIELD(self, op, err): assert isinstance(op.args[1], Constant) - STRUCT = self.lltypemap[op.args[0]].TO + STRUCT = self.lltypemap(op.args[0]).TO structdef = self.db.gettypedefnode(STRUCT) fieldname = structdef.c_struct_field_name(op.args[1].value) return self.generic_set(op, '%s->%s' % (self.expr(op.args[0]), @@ -398,7 +428,7 @@ self.expr(op.args[1])) def OP_MALLOC(self, op, err): - TYPE = self.lltypemap[op.result].TO + TYPE = self.lltypemap(op.result).TO typename = self.db.gettype(TYPE) eresult = self.expr(op.result) result = ['OP_ZERO_MALLOC(sizeof(%s), %s, %s)' % (cdecl(typename, ''), @@ -410,7 +440,7 @@ return '\t'.join(result) def OP_MALLOC_VARSIZE(self, op, err): - TYPE = self.lltypemap[op.result].TO + TYPE = self.lltypemap(op.result).TO typename = self.db.gettype(TYPE) lenfld = 'length' nodedef = self.db.gettypedefnode(TYPE) @@ -439,7 +469,7 @@ return '\t'.join(result) def OP_CAST_POINTER(self, op, err): - TYPE = self.lltypemap[op.result] + TYPE = self.lltypemap(op.result) typename = self.db.gettype(TYPE) result = [] result.append('%s = (%s)%s;' % (self.expr(op.result), @@ -452,8 +482,8 @@ def OP_SAME_AS(self, op, err): result = [] - assert self.lltypemap[op.args[0]] == self.lltypemap[op.result] - if self.lltypemap[op.result] != Void: + assert self.lltypemap(op.args[0]) == self.lltypemap(op.result) + if self.lltypemap(op.result) != Void: result.append('%s = %s;' % (self.expr(op.result), self.expr(op.args[0]))) line = self.cincref(op.result) @@ -462,9 +492,9 @@ return '\t'.join(result) def cincref(self, v): - T = self.lltypemap[v] + T = self.lltypemap(v) return self.db.cincrefstmt(v.name, T) def cdecref(self, v, expr=None): - T = self.lltypemap[v] + T = self.lltypemap(v) return self.db.cdecrefstmt(expr or v.name, T) Added: pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/g_exception.h Tue Jun 14 15:03:28 2005 @@ -0,0 +1,84 @@ + +/************************************************************/ + /*** C header subsection: exceptions ***/ + +static PyObject *RPythonError; + + +/******************************************************************/ +#ifdef RPYTHON_EXCEPTION_VTABLE /* RPython version of exceptions */ +/******************************************************************/ + +static RPYTHON_EXCEPTION_VTABLE rpython_exc_type = NULL; +static RPYTHON_EXCEPTION rpython_exc_value = NULL; + +#define ExceptionOccurred() (rpython_exc_type != NULL) + +#define RaiseException(etype, evalue) \ + assert(!ExceptionOccurred()); \ + rpython_exc_type = (RPYTHON_EXCEPTION_VTABLE)(etype); \ + rpython_exc_value = (RPYTHON_EXCEPTION)(evalue) + +#define FetchException(etypevar, evaluevar, type_of_evaluevar) \ + etypevar = rpython_exc_type; \ + evaluevar = (type_of_evaluevar) rpython_exc_value; \ + rpython_exc_type = NULL; \ + rpython_exc_value = NULL + +#define MatchException(etype) RPYTHON_EXCEPTION_MATCH(rpython_exc_type, \ + (RPYTHON_EXCEPTION_VTABLE) etype) + +static void ConvertExceptionFromCPython(void) +{ + /* convert the CPython exception to an RPython one */ + PyObject *exc_type, *exc_value, *exc_tb; + assert(PyErr_Occurred()); + assert(!ExceptionOccurred()); + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + /* XXX loosing the error message here */ + rpython_exc_value = RPYTHON_PYEXCCLASS2EXC(exc_type); + rpython_exc_type = RPYTHON_TYPE_OF_EXC_INST(rpython_exc_value); +} + +static PyObject *ConvertExceptionToCPython(void) +{ + assert(ExceptionOccurred()); + assert(!PyErr_Occurred()); + rpython_exc_type = NULL; /* XXX leaks! */ + rpython_exc_value = NULL; + PyErr_SetNone(RPythonError); + return NULL; +} + +#define RaiseSimpleException(exc, msg) \ + /* XXX 1. uses officially bad fishing */ \ + /* XXX 2. msg is ignored */ \ + rpython_exc_type = (exc)->o_typeptr; \ + rpython_exc_value = (exc); \ + rpython_exc_value->refcount++ + +/******************************************************************/ +#else /* non-RPython version of exceptions, using CPython only */ +/******************************************************************/ + +#define ExceptionOccurred() PyErr_Occurred() +#define RaiseException(etype, evalue) PyErr_Restore(etype, evalue, NULL) +#define FetchException(etypevar, evaluevar, ignored) { \ + PyObject *__tb; \ + PyErr_Fetch(&etypevar, &evaluevar, &__tb); \ + if (evaluevar == NULL) { \ + evaluevar = Py_None; \ + Py_INCREF(Py_None); \ + } \ + Py_XDECREF(__tb); \ + } +#define MatchException(etype) PyErr_ExceptionMatches(etype) +#define ConvertExceptionFromCPython() /* nothing */ +#define ConvertExceptionToCPython() NULL + +#define RaiseSimpleException(exc, msg) \ + PyErr_SetString(Py##exc, msg) /* pun */ + +/******************************************************************/ +#endif /* RPYTHON_EXCEPTION_VTABLE */ +/******************************************************************/ Modified: pypy/dist/pypy/translator/c/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/g_include.h (original) +++ pypy/dist/pypy/translator/c/g_include.h Tue Jun 14 15:03:28 2005 @@ -10,6 +10,7 @@ #include "marshal.h" #include "eval.h" +#include "g_exception.h" #include "g_trace.h" #include "g_support.h" #include "g_module.h" Modified: pypy/dist/pypy/translator/c/g_module.h ============================================================================== --- pypy/dist/pypy/translator/c/g_module.h (original) +++ pypy/dist/pypy/translator/c/g_module.h Tue Jun 14 15:03:28 2005 @@ -15,12 +15,17 @@ PyMODINIT_FUNC init##modname(void) #endif -#define SETUP_MODULE(modname) \ +#define SETUP_MODULE(modname) \ PyObject *m = Py_InitModule(#modname, my_methods); \ PyModule_AddStringConstant(m, "__sourcefile__", __FILE__); \ this_module_globals = PyModule_GetDict(m); \ PyGenCFunction_Type.tp_base = &PyCFunction_Type; \ PyType_Ready(&PyGenCFunction_Type); \ + RPythonError = PyErr_NewException(#modname ".RPythonError", \ + NULL, NULL); \ + if (RPythonError == NULL) \ + return; \ + PyModule_AddObject(m, "RPythonError", RPythonError); \ if (setup_globalfunctions(globalfunctiondefs) < 0) \ return; \ if (setup_initcode(frozen_initcode, FROZEN_INITCODE_SIZE) < 0) \ Modified: pypy/dist/pypy/translator/c/g_support.h ============================================================================== --- pypy/dist/pypy/translator/c/g_support.h (original) +++ pypy/dist/pypy/translator/c/g_support.h Tue Jun 14 15:03:28 2005 @@ -11,12 +11,13 @@ #define FAIL_EXCEPTION(err, exc, msg) \ { \ - PyErr_SetString(exc, msg); \ + RaiseSimpleException(exc, msg); \ FAIL(err) \ } -#define FAIL_OVF(err, msg) FAIL_EXCEPTION(err, PyExc_OverflowError, msg) -#define FAIL_VAL(err, msg) FAIL_EXCEPTION(err, PyExc_ValueError, msg) -#define FAIL_ZER(err, msg) FAIL_EXCEPTION(err, PyExc_ZeroDivisionError, msg) +#define FAIL_OVF(err, msg) FAIL_EXCEPTION(err, Exc_OverflowError, msg) +#define FAIL_VAL(err, msg) FAIL_EXCEPTION(err, Exc_ValueError, msg) +#define FAIL_ZER(err, msg) FAIL_EXCEPTION(err, Exc_ZeroDivisionError, msg) +#define CFAIL(err) { ConvertExceptionFromCPython(); FAIL(err) } /* we need a subclass of 'builtin_function_or_method' which can be used as methods: builtin function objects that can be bound on instances */ Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Tue Jun 14 15:03:28 2005 @@ -43,6 +43,7 @@ # ____________________________________________________________ def gen_readable_parts_of_main_c_file(f, database): + lines = list(database.pre_include_code_lines()) # # All declarations # @@ -53,9 +54,6 @@ for node in database.structdeflist: for line in node.definition(phase=1): print >> f, line - for node in database.structdeflist: - for line in node.definition(phase=2): - print >> f, line print >> f print >> f, '/***********************************************************/' print >> f, '/*** Forward declarations ***/' @@ -63,13 +61,23 @@ for node in database.globalcontainers(): for line in node.forward_declaration(): print >> f, line + # # Implementation of functions and global structures and arrays # print >> f print >> f, '/***********************************************************/' print >> f, '/*** Implementations ***/' - blank = True + print >> f + for line in lines: + print >> f, line + print >> f, '#include "g_include.h"' + print >> f + blank = False + for node in database.structdeflist: + for line in node.definition(phase=2): + print >> f, line + blank = True for node in database.globalcontainers(): if blank: print >> f @@ -90,7 +98,7 @@ # for key, value in defines.items(): print >> f, '#define %s %s' % (key, value) - print >> f, '#include "g_include.h"' + print >> f, '#include "Python.h"' # # 1) All declarations Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Tue Jun 14 15:03:28 2005 @@ -4,11 +4,6 @@ /*** unary operations ***/ -#define OP_INCREF_int(x) /* nothing */ -#define OP_DECREF_int(x) /* nothing */ -#define CONV_TO_OBJ_int PyInt_FromLong -#define CONV_FROM_OBJ_int PyInt_AS_LONG - #define OP_INT_IS_TRUE(x,r,err) OP_INT_NE(x,0,r,err) #define OP_INT_INVERT(x,r,err) r = ~((long)(x)); @@ -197,4 +192,4 @@ if (p_rem) *p_rem = xmody; return xdivy; -} \ No newline at end of file +} Modified: pypy/dist/pypy/translator/c/ll_include.h ============================================================================== --- pypy/dist/pypy/translator/c/ll_include.h (original) +++ pypy/dist/pypy/translator/c/ll_include.h Tue Jun 14 15:03:28 2005 @@ -3,11 +3,11 @@ /*** C header subsection: operations on LowLevelTypes ***/ -#define OP_ZERO_MALLOC(size, r, err) { \ - r = (void*) PyObject_Malloc(size); \ - if (r == NULL) { PyErr_NoMemory(); FAIL(err) } \ - memset((void*) r, 0, size); \ - COUNT_MALLOC \ +#define OP_ZERO_MALLOC(size, r, err) { \ + r = (void*) PyObject_Malloc(size); \ + if (r == NULL) FAIL_EXCEPTION(err, Exc_MemoryError, "out of memory")\ + memset((void*) r, 0, size); \ + COUNT_MALLOC \ } #define OP_FREE(p) { PyObject_Free(p); COUNT_FREE } Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue Jun 14 15:03:28 2005 @@ -3,6 +3,7 @@ from pypy.rpython.lltype import GcStruct, GcArray, GC_CONTAINER, ContainerType from pypy.rpython.lltype import parentlink, Ptr, PyObject, Void from pypy.translator.c.funcgen import FunctionCodeGenerator +from pypy.translator.c.external import CExternalFunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom from pypy.translator.c.primitive import PrimitiveType @@ -318,8 +319,7 @@ globalcontainer = True def __init__(self, db, T, obj): - graph = obj.graph # only user-defined functions with graphs for now - self.funcgen = FunctionCodeGenerator(graph, db) + self.funcgen = select_function_code_generator(obj, db) self.db = db self.T = T self.obj = obj @@ -380,39 +380,14 @@ yield '}' -class CExternalFuncNode(ContainerNode): - globalcontainer = True - - def __init__(self, db, T, obj): - self.db = db - self.T = T - self.obj = obj - #self.dependencies = {} - self.typename = db.gettype(T) #, who_asks=self) - self.name = obj._name - self.ptrname = self.name - - def enum_dependencies(self): - return [] - - def implementation(self): - return [] - - def forward_declaration(self): - return [] - - def implementation(self): - return [] - - -def funcnodemaker(db, T, obj): - if hasattr(obj, 'graph'): - cls = FuncNode - elif getattr(obj, 'external', None) == 'C': - cls = CExternalFuncNode +def select_function_code_generator(fnptr, db): + if hasattr(fnptr, 'graph'): + cpython_exc = getattr(fnptr, 'exception_policy', None) == "CPython" + return FunctionCodeGenerator(fnptr.graph, db, cpython_exc) + elif getattr(fnptr, 'external', None) == 'C': + return CExternalFunctionCodeGenerator(fnptr, db) else: - raise ValueError, "don't know about %r" % (obj,) - return cls(db, T, obj) + raise ValueError, "don't know how to generate code for %r" % (fnptr,) class PyObjectNode(ContainerNode): @@ -446,6 +421,6 @@ GcStruct: StructNode, Array: ArrayNode, GcArray: ArrayNode, - FuncType: funcnodemaker, + FuncType: FuncNode, PyObjectType: PyObjectNode, } Modified: pypy/dist/pypy/translator/c/pyobj_include.h ============================================================================== --- pypy/dist/pypy/translator/c/pyobj_include.h (original) +++ pypy/dist/pypy/translator/c/pyobj_include.h Tue Jun 14 15:03:28 2005 @@ -7,13 +7,13 @@ #define op_bool(r,err,what) { \ int _retval = what; \ if (_retval < 0) { \ - FAIL(err) \ + CFAIL(err) \ } \ r = PyBool_FromLong(_retval); \ } #define op_richcmp(x,y,r,err,dir) \ - if (!(r=PyObject_RichCompare(x,y,dir))) FAIL(err) + if (!(r=PyObject_RichCompare(x,y,dir))) CFAIL(err) #define OP_LT(x,y,r,err) op_richcmp(x,y,r,err, Py_LT) #define OP_LE(x,y,r,err) op_richcmp(x,y,r,err, Py_LE) #define OP_EQ(x,y,r,err) op_richcmp(x,y,r,err, Py_EQ) @@ -29,71 +29,71 @@ #define OP_LEN(x,r,err) { \ int _retval = PyObject_Size(x); \ if (_retval < 0) { \ - FAIL(err) \ + CFAIL(err) \ } \ r = PyInt_FromLong(_retval); \ } -#define OP_NEG(x,r,err) if (!(r=PyNumber_Negative(x))) FAIL(err) -#define OP_POS(x,r,err) if (!(r=PyNumber_Positive(x))) FAIL(err) -#define OP_INVERT(x,r,err) if (!(r=PyNumber_Invert(x))) FAIL(err) -#define OP_ABS(x,r,err) if (!(r=PyNumber_Absolute(x))) FAIL(err) - -#define OP_ADD(x,y,r,err) if (!(r=PyNumber_Add(x,y))) FAIL(err) -#define OP_SUB(x,y,r,err) if (!(r=PyNumber_Subtract(x,y))) FAIL(err) -#define OP_MUL(x,y,r,err) if (!(r=PyNumber_Multiply(x,y))) FAIL(err) -#define OP_TRUEDIV(x,y,r,err) if (!(r=PyNumber_TrueDivide(x,y))) FAIL(err) -#define OP_FLOORDIV(x,y,r,err) if (!(r=PyNumber_FloorDivide(x,y)))FAIL(err) -#define OP_DIV(x,y,r,err) if (!(r=PyNumber_Divide(x,y))) FAIL(err) -#define OP_MOD(x,y,r,err) if (!(r=PyNumber_Remainder(x,y))) FAIL(err) -#define OP_DIVMOD(x,y,r,err) if (!(r=PyNumber_Divmod(x,y))) FAIL(err) -#define OP_POW(x,y,z,r,err) if (!(r=PyNumber_Power(x,y,z))) FAIL(err) -#define OP_LSHIFT(x,y,r,err) if (!(r=PyNumber_Lshift(x,y))) FAIL(err) -#define OP_RSHIFT(x,y,r,err) if (!(r=PyNumber_Rshift(x,y))) FAIL(err) -#define OP_AND_(x,y,r,err) if (!(r=PyNumber_And(x,y))) FAIL(err) -#define OP_OR_(x,y,r,err) if (!(r=PyNumber_Or(x,y))) FAIL(err) -#define OP_XOR(x,y,r,err) if (!(r=PyNumber_Xor(x,y))) FAIL(err) +#define OP_NEG(x,r,err) if (!(r=PyNumber_Negative(x))) CFAIL(err) +#define OP_POS(x,r,err) if (!(r=PyNumber_Positive(x))) CFAIL(err) +#define OP_INVERT(x,r,err) if (!(r=PyNumber_Invert(x))) CFAIL(err) +#define OP_ABS(x,r,err) if (!(r=PyNumber_Absolute(x))) CFAIL(err) + +#define OP_ADD(x,y,r,err) if (!(r=PyNumber_Add(x,y))) CFAIL(err) +#define OP_SUB(x,y,r,err) if (!(r=PyNumber_Subtract(x,y))) CFAIL(err) +#define OP_MUL(x,y,r,err) if (!(r=PyNumber_Multiply(x,y))) CFAIL(err) +#define OP_TRUEDIV(x,y,r,err) if (!(r=PyNumber_TrueDivide(x,y))) CFAIL(err) +#define OP_FLOORDIV(x,y,r,err) if (!(r=PyNumber_FloorDivide(x,y)))CFAIL(err) +#define OP_DIV(x,y,r,err) if (!(r=PyNumber_Divide(x,y))) CFAIL(err) +#define OP_MOD(x,y,r,err) if (!(r=PyNumber_Remainder(x,y))) CFAIL(err) +#define OP_DIVMOD(x,y,r,err) if (!(r=PyNumber_Divmod(x,y))) CFAIL(err) +#define OP_POW(x,y,z,r,err) if (!(r=PyNumber_Power(x,y,z))) CFAIL(err) +#define OP_LSHIFT(x,y,r,err) if (!(r=PyNumber_Lshift(x,y))) CFAIL(err) +#define OP_RSHIFT(x,y,r,err) if (!(r=PyNumber_Rshift(x,y))) CFAIL(err) +#define OP_AND_(x,y,r,err) if (!(r=PyNumber_And(x,y))) CFAIL(err) +#define OP_OR_(x,y,r,err) if (!(r=PyNumber_Or(x,y))) CFAIL(err) +#define OP_XOR(x,y,r,err) if (!(r=PyNumber_Xor(x,y))) CFAIL(err) #define OP_INPLACE_ADD(x,y,r,err) if (!(r=PyNumber_InPlaceAdd(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_SUB(x,y,r,err) if (!(r=PyNumber_InPlaceSubtract(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_MUL(x,y,r,err) if (!(r=PyNumber_InPlaceMultiply(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_TRUEDIV(x,y,r,err) if (!(r=PyNumber_InPlaceTrueDivide(x,y)))\ - FAIL(err) + CFAIL(err) #define OP_INPLACE_FLOORDIV(x,y,r,err)if(!(r=PyNumber_InPlaceFloorDivide(x,y)))\ - FAIL(err) + CFAIL(err) #define OP_INPLACE_DIV(x,y,r,err) if (!(r=PyNumber_InPlaceDivide(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_MOD(x,y,r,err) if (!(r=PyNumber_InPlaceRemainder(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_POW(x,y,r,err) if (!(r=PyNumber_InPlacePower(x,y,Py_None))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_LSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceLshift(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_RSHIFT(x,y,r,err) if (!(r=PyNumber_InPlaceRshift(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_AND(x,y,r,err) if (!(r=PyNumber_InPlaceAnd(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_OR(x,y,r,err) if (!(r=PyNumber_InPlaceOr(x,y))) \ - FAIL(err) + CFAIL(err) #define OP_INPLACE_XOR(x,y,r,err) if (!(r=PyNumber_InPlaceXor(x,y))) \ - FAIL(err) + CFAIL(err) -#define OP_GETITEM(x,y,r,err) if (!(r=PyObject_GetItem1(x,y))) FAIL(err) -#define OP_SETITEM(x,y,z,r,err) if ((PyObject_SetItem1(x,y,z))<0) FAIL(err) \ +#define OP_GETITEM(x,y,r,err) if (!(r=PyObject_GetItem1(x,y))) CFAIL(err) +#define OP_SETITEM(x,y,z,r,err) if ((PyObject_SetItem1(x,y,z))<0) CFAIL(err) \ r=Py_None; Py_INCREF(r); -#define OP_DELITEM(x,y,r,err) if ((PyObject_DelItem(x,y))<0) FAIL(err) \ +#define OP_DELITEM(x,y,r,err) if ((PyObject_DelItem(x,y))<0) CFAIL(err) \ r=Py_None; Py_INCREF(r); #define OP_CONTAINS(x,y,r,err) op_bool(r,err,(PySequence_Contains(x,y))) -#define OP_GETATTR(x,y,r,err) if (!(r=PyObject_GetAttr(x,y))) FAIL(err) -#define OP_SETATTR(x,y,z,r,err) if ((PyObject_SetAttr(x,y,z))<0) FAIL(err) \ +#define OP_GETATTR(x,y,r,err) if (!(r=PyObject_GetAttr(x,y))) CFAIL(err) +#define OP_SETATTR(x,y,z,r,err) if ((PyObject_SetAttr(x,y,z))<0) CFAIL(err) \ r=Py_None; Py_INCREF(r); -#define OP_DELATTR(x,y,r,err) if ((PyObject_SetAttr(x,y,NULL))<0)FAIL(err) \ +#define OP_DELATTR(x,y,r,err) if ((PyObject_SetAttr(x,y,NULL))<0)CFAIL(err) \ r=Py_None; Py_INCREF(r); -#define OP_NEWSLICE(x,y,z,r,err) if (!(r=PySlice_New(x,y,z))) FAIL(err) +#define OP_NEWSLICE(x,y,z,r,err) if (!(r=PySlice_New(x,y,z))) CFAIL(err) #define OP_GETSLICE(x,y,z,r,err) { \ PyObject *__yo = y, *__zo = z; \ @@ -102,46 +102,46 @@ if (__zo == Py_None) __zo = NULL; \ if (!_PyEval_SliceIndex(__yo, &__y) || \ !_PyEval_SliceIndex(__zo, &__z) || \ - !(r=PySequence_GetSlice(x, __y, __z))) FAIL(err) \ + !(r=PySequence_GetSlice(x, __y, __z))) CFAIL(err) \ } #define OP_ALLOC_AND_SET(x,y,r,err) { \ /* XXX check for long/int overflow */ \ int __i, __x = PyInt_AsLong(x); \ - if (PyErr_Occurred()) FAIL(err) \ - if (!(r = PyList_New(__x))) FAIL(err) \ + if (PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyList_New(__x))) CFAIL(err) \ for (__i=0; __i<__x; __i++) { \ Py_INCREF(y); \ PyList_SET_ITEM(r, __i, y); \ } \ } -#define OP_ITER(x,r,err) if (!(r=PyObject_GetIter(x))) FAIL(err) +#define OP_ITER(x,r,err) if (!(r=PyObject_GetIter(x))) CFAIL(err) #define OP_NEXT(x,r,err) if (!(r=PyIter_Next(x))) { \ if (!PyErr_Occurred()) PyErr_SetNone(PyExc_StopIteration); \ - FAIL(err) \ + CFAIL(err) \ } -#define OP_STR(x,r,err) if (!(r=PyObject_Str(x))) FAIL(err) -#define OP_REPR(x,r,err) if (!(r=PyObject_Repr(x))) FAIL(err) +#define OP_STR(x,r,err) if (!(r=PyObject_Str(x))) CFAIL(err) +#define OP_REPR(x,r,err) if (!(r=PyObject_Repr(x))) CFAIL(err) #define OP_ORD(s,r,err) { \ char *__c = PyString_AsString(s); \ int __len; \ - if ( !__c) FAIL(err) \ + if ( !__c) CFAIL(err) \ if ((__len = PyString_GET_SIZE(s)) != 1) { \ PyErr_Format(PyExc_TypeError, \ "ord() expected a character, but string of length %d found", \ __len); \ - FAIL(err) \ + CFAIL(err) \ } \ if (!(r = PyInt_FromLong((unsigned char)(__c[0])))) \ - FAIL(err) \ + CFAIL(err) \ } -#define OP_ID(x,r,err) if (!(r=PyLong_FromVoidPtr(x))) FAIL(err) +#define OP_ID(x,r,err) if (!(r=PyLong_FromVoidPtr(x))) CFAIL(err) #define OP_HASH(x,r,err) { \ long __hash = PyObject_Hash(x); \ - if (__hash == -1 && PyErr_Occurred()) FAIL(err) \ - if (!(r = PyInt_FromLong(__hash))) FAIL(err) \ + if (__hash == -1 && PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyInt_FromLong(__hash))) CFAIL(err) \ } #define OP_HEX(x,r,err) { \ @@ -150,9 +150,9 @@ __nb->nb_hex == NULL) { \ PyErr_SetString(PyExc_TypeError, \ "hex() argument can't be converted to hex"); \ - FAIL(err) \ + CFAIL(err) \ } \ - if (!(r = (*__nb->nb_hex)(x))) FAIL(err) \ + if (!(r = (*__nb->nb_hex)(x))) CFAIL(err) \ } #define OP_OCT(x,r,err) { \ PyNumberMethods *__nb; \ @@ -160,32 +160,32 @@ __nb->nb_oct == NULL) { \ PyErr_SetString(PyExc_TypeError, \ "oct() argument can't be converted to oct"); \ - FAIL(err) \ + CFAIL(err) \ } \ - if (!(r = (*__nb->nb_oct)(x))) FAIL(err) \ + if (!(r = (*__nb->nb_oct)(x))) CFAIL(err) \ } #define OP_INT(x,r,err) { \ long __val = PyInt_AsLong(x); \ - if (__val == -1 && PyErr_Occurred()) FAIL(err) \ - if (!(r = PyInt_FromLong(__val))) FAIL (err) \ + if (__val == -1 && PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyInt_FromLong(__val))) CFAIL (err) \ } #define OP_FLOAT(x,r,err) { \ double __val = PyFloat_AsDouble(x); \ - if (PyErr_Occurred()) FAIL(err) \ - if (!(r = PyFloat_FromDouble(__val))) FAIL (err) \ + if (PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyFloat_FromDouble(__val))) CFAIL (err) \ } #define OP_CMP(x,y,r,err) { \ int __val = PyObject_Compare(x, y); \ - if (PyErr_Occurred()) FAIL(err) \ - if (!(r = PyInt_FromLong(__val))) FAIL (err) \ + if (PyErr_Occurred()) CFAIL(err) \ + if (!(r = PyInt_FromLong(__val))) CFAIL (err) \ } #define OP_SIMPLE_CALL(args,r,err) if (!(r=PyObject_CallFunctionObjArgs args)) \ - FAIL(err) -#define OP_CALL_ARGS(args,r,err) if (!(r=CallWithShape args)) FAIL(err) + CFAIL(err) +#define OP_CALL_ARGS(args,r,err) if (!(r=CallWithShape args)) CFAIL(err) /* Needs to act like getattr(x, '__class__', type(x)) */ #define OP_TYPE(x,r,err) { \ @@ -205,27 +205,17 @@ /*** operations with a variable number of arguments ***/ -#define OP_NEWLIST0(r,err) if (!(r=PyList_New(0))) FAIL(err) -#define OP_NEWLIST(args,r,err) if (!(r=PyList_Pack args)) FAIL(err) -#define OP_NEWDICT0(r,err) if (!(r=PyDict_New())) FAIL(err) -#define OP_NEWDICT(args,r,err) if (!(r=PyDict_Pack args)) FAIL(err) -#define OP_NEWTUPLE(args,r,err) if (!(r=PyTuple_Pack args)) FAIL(err) +#define OP_NEWLIST0(r,err) if (!(r=PyList_New(0))) CFAIL(err) +#define OP_NEWLIST(args,r,err) if (!(r=PyList_Pack args)) CFAIL(err) +#define OP_NEWDICT0(r,err) if (!(r=PyDict_New())) CFAIL(err) +#define OP_NEWDICT(args,r,err) if (!(r=PyDict_Pack args)) CFAIL(err) +#define OP_NEWTUPLE(args,r,err) if (!(r=PyTuple_Pack args)) CFAIL(err) /*** argument parsing ***/ #define OP_DECODE_ARG(fname, pos, name, vargs, vkwds, r, err) \ - if (!(r=decode_arg(fname, pos, name, vargs, vkwds, NULL))) FAIL(err) + if (!(r=decode_arg(fname, pos, name, vargs, vkwds, NULL))) CFAIL(err) #define OP_DECODE_ARG_DEF(fname, pos, name, vargs, vkwds, def, r, err) \ - if (!(r=decode_arg(fname, pos, name, vargs, vkwds, def))) FAIL(err) + if (!(r=decode_arg(fname, pos, name, vargs, vkwds, def))) CFAIL(err) #define OP_CHECK_NO_MORE_ARG(fname, n, vargs, r, err) \ - if (check_no_more_arg(fname, n, vargs) < 0) FAIL(err) - -/*** conversions, reference counting ***/ - -#define OP_INCREF_pyobj(o) Py_INCREF(o); -#define OP_DECREF_pyobj(o) Py_DECREF(o); -#define CONV_TO_OBJ_pyobj(o) ((void)Py_INCREF(o), o) -#define CONV_FROM_OBJ_pyobj(o) ((void)Py_INCREF(o), o) - -#define OP_INCREF_borrowedpyobj(o) /* nothing */ -#define OP_DECREF_borrowedpyobj(o) /* nothing */ + if (check_no_more_arg(fname, n, vargs) < 0) CFAIL(err) Added: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/test_exception.py Tue Jun 14 15:03:28 2005 @@ -0,0 +1,23 @@ +from pypy.translator.translator import Translator + + +class MyException(Exception): + pass + +def test_myexception(): + def g(): + raise MyException + def f(): + try: + g() + except MyException: + return 5 + else: + return 2 + + t = Translator(f) + t.annotate([]).simplify() + t.specialize() + #t.view() + f1 = t.ccompile() + assert f1() == 5 Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Tue Jun 14 15:03:28 2005 @@ -58,12 +58,12 @@ assert f1(5) == 10 assert f1(x=5) == 10 assert f1(-123) == -246 - py.test.raises(TypeError, f1, "world") # check that it's really typed - py.test.raises(TypeError, f1) - py.test.raises(TypeError, f1, 2, 3) - py.test.raises(TypeError, f1, 2, x=2) - #py.test.raises(TypeError, f1, 2, y=2) XXX missing a check at the moment assert module.malloc_counters() == (0, 0) + py.test.raises(Exception, f1, "world") # check that it's really typed + py.test.raises(Exception, f1) + py.test.raises(Exception, f1, 2, 3) + py.test.raises(Exception, f1, 2, x=2) + #py.test.raises(Exception, f1, 2, y=2) XXX missing a check at the moment def test_rlist(): Modified: pypy/dist/pypy/translator/c/wrapper.py ============================================================================== --- pypy/dist/pypy/translator/c/wrapper.py (original) +++ pypy/dist/pypy/translator/c/wrapper.py Tue Jun 14 15:03:28 2005 @@ -118,4 +118,5 @@ PyObjPtr], PyObjPtr), wgraph.name, - graph = wgraph) + graph = wgraph, + exception_policy = "CPython") From arigo at codespeak.net Tue Jun 14 15:18:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 15:18:23 +0200 (CEST) Subject: [pypy-svn] r13383 - in pypy/dist/pypy/translator: genc/test test Message-ID: <20050614131823.BB5F927B83@code1.codespeak.net> Author: arigo Date: Tue Jun 14 15:18:21 2005 New Revision: 13383 Modified: pypy/dist/pypy/translator/genc/test/test_annotated.py pypy/dist/pypy/translator/test/snippet.py Log: Fix one more test. Modified: pypy/dist/pypy/translator/genc/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/genc/test/test_annotated.py Tue Jun 14 15:18:21 2005 @@ -123,6 +123,8 @@ assert abs(fn(7) + 0.8584) < 1E-5 def test_do_try_raise_choose(self): - fn = self.getcompiled(snippet.do_try_raise_choose) - result = fn() + fn = self.getcompiled(snippet.try_raise_choose) + result = [] + for n in [-1,0,1,2]: + result.append(fn(n)) assert result == [-1,0,1,2] Modified: pypy/dist/pypy/translator/test/snippet.py ============================================================================== --- pypy/dist/pypy/translator/test/snippet.py (original) +++ pypy/dist/pypy/translator/test/snippet.py Tue Jun 14 15:18:21 2005 @@ -363,7 +363,7 @@ raise Exception return 0 -def try_raise_choose(n): +def try_raise_choose(n=int): try: raise_choose(n) except E1: From arigo at codespeak.net Tue Jun 14 17:00:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 17:00:24 +0200 (CEST) Subject: [pypy-svn] r13387 - pypy/dist/pypy/rpython Message-ID: <20050614150024.B36F427B84@code1.codespeak.net> Author: arigo Date: Tue Jun 14 17:00:23 2005 New Revision: 13387 Modified: pypy/dist/pypy/rpython/rclass.py Log: rtype_new_instance fixed to allow creation of instances of 'object'. This is needed because object == Exception in our model. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jun 14 17:00:23 2005 @@ -408,21 +408,22 @@ ctypeptr = inputconst(TYPEPTR, self.rclass.getvtable()) self.setfield(vptr, '__class__', ctypeptr, llops) # initialize instance attributes from their defaults from the class - flds = self.allinstancefields.keys() - flds.sort() - mro = list(self.classdef.getmro()) - for fldname in flds: - if fldname == '__class__': - continue - mangled_name, r = self.allinstancefields[fldname] - if r.lowleveltype == Void: - continue - for clsdef in mro: - if fldname in clsdef.cls.__dict__: - value = clsdef.cls.__dict__[fldname] - cvalue = inputconst(r, value) - self.setfield(vptr, fldname, cvalue, llops) - break + if self.classdef is not None: + flds = self.allinstancefields.keys() + flds.sort() + mro = list(self.classdef.getmro()) + for fldname in flds: + if fldname == '__class__': + continue + mangled_name, r = self.allinstancefields[fldname] + if r.lowleveltype == Void: + continue + for clsdef in mro: + if fldname in clsdef.cls.__dict__: + value = clsdef.cls.__dict__[fldname] + cvalue = inputconst(r, value) + self.setfield(vptr, fldname, cvalue, llops) + break return vptr def rtype_type(self, hop): From cfbolz at codespeak.net Tue Jun 14 18:05:53 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 14 Jun 2005 18:05:53 +0200 (CEST) Subject: [pypy-svn] r13388 - in pypy/dist/pypy/translator/llvm: . test Message-ID: <20050614160553.D617727B9C@code1.codespeak.net> Author: cfbolz Date: Tue Jun 14 18:05:53 2005 New Revision: 13388 Modified: pypy/dist/pypy/translator/llvm/build_llvm_module.py pypy/dist/pypy/translator/llvm/llvmbc.py pypy/dist/pypy/translator/llvm/test/llvmsnippet.py pypy/dist/pypy/translator/llvm/test/test_genllvm.py pypy/dist/pypy/translator/llvm/typerepr.py Log: fix the handling of shifts. there is a fundamental problem at the moment: since LLVM bytecode strives to be platform independent, int is always 32 bit, genllvm has to use long on 64 bit machines. Modified: pypy/dist/pypy/translator/llvm/build_llvm_module.py ============================================================================== --- pypy/dist/pypy/translator/llvm/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm/build_llvm_module.py Tue Jun 14 18:05:53 2005 @@ -14,7 +14,7 @@ from pypy.translator.tool.buildpyxmodule import make_c_from_pyxfile from pypy.translator.tool import stdoutcapture -debug = False +debug = True class CompileError(exceptions.Exception): pass Modified: pypy/dist/pypy/translator/llvm/llvmbc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/llvmbc.py (original) +++ pypy/dist/pypy/translator/llvm/llvmbc.py Tue Jun 14 18:05:53 2005 @@ -97,8 +97,7 @@ #Shift instructions def shift_instruction(self, instr, l_target, l_a, l_b): self.phi_done = True - assert l_target.llvmtype() == l_a.llvmtype() - #assert l_b.llvmtype() == 'ubyte' #or cast to ubyte or assuma nothing goes wrong + # XXX hack: just assume that l_b is of the appropriate type s = "%s = %s %s, ubyte %s" % (l_target.llvmname(), instr, l_a.typed_name(), l_b.llvmname()) self.instructions.append(s) Modified: pypy/dist/pypy/translator/llvm/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm/test/llvmsnippet.py Tue Jun 14 18:05:53 2005 @@ -62,6 +62,13 @@ def return_none(): pass +def shiftleft(i, j): + return i << j + +def shiftright(i, j): + return i << j + + #float snippets def float_f1(x): Modified: pypy/dist/pypy/translator/llvm/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_genllvm.py Tue Jun 14 18:05:53 2005 @@ -1,5 +1,7 @@ from __future__ import division import autopath +import sys + import py from pypy.translator.translator import Translator @@ -97,6 +99,14 @@ f = compile_function(llvmsnippet.return_none, []) assert f() is None + def test_shift(self): + shl = compile_function(llvmsnippet.shiftleft, [int, int]) + shr = compile_function(llvmsnippet.shiftright, [int, int]) + for i in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: + for j in [1, 2, 3, 100000, 2000000, sys.maxint - 1]: + assert shl(i, j) == i << j + assert shr(i, j) == i >> j + class TestFloat(object): def setup_method(self, method): if not llvm_found: Modified: pypy/dist/pypy/translator/llvm/typerepr.py ============================================================================== --- pypy/dist/pypy/translator/llvm/typerepr.py (original) +++ pypy/dist/pypy/translator/llvm/typerepr.py Tue Jun 14 18:05:53 2005 @@ -85,8 +85,6 @@ "int_mod": "rem", "int_xor": "xor", "int_and": "and", - "int_lshift": "shl", - "int_rshift": "shr", "int_or": "or", "int_eq": "seteq", "int_ne": "setne", @@ -105,15 +103,51 @@ assert len(args) == 2 l_args = [self.gen.get_repr(arg) for arg in args] l_func.dependencies.update(l_args) - l_op = SignedTypeRepr.directly_supported_binary_ops[opname] - if l_op in ('shl', 'shr'): #feel free to refactor this - lblock.shift_instruction( - l_op, l_target, - l_args[0], l_args[1]) - else: - lblock.binary_instruction( - l_op, l_target, - l_args[0], l_args[1]) + lblock.binary_instruction( + SignedTypeRepr.directly_supported_binary_ops[opname], l_target, + l_args[0], l_args[1]) + + def t_op_int_lshift(self, l_target, args, lblock, l_func): + # XXX hack: llvm only supports shifts by ubyte args + # so we have to jump through some loops + # someone on the LLVM list said this would change in the future + assert len(args) == 2 + l_tmp1 = self.gen.get_local_tmp(None, l_func) #using only the name + l_tmp2 = self.gen.get_local_tmp(None, l_func) + l_tmp3 = self.gen.get_local_tmp(None, l_func) + l_args = [self.gen.get_repr(arg) for arg in args] + l_func.dependencies.update(l_args) + lblock.instruction("%s = setge %s, %s" % (l_tmp1.llvmname(), + l_args[1].typed_name(), + 8 * BYTES_IN_INT)) + lblock.instruction("%s = cast int %s to ubyte" % + (l_tmp2.llvmname(), l_args[1].llvmname())) + lblock.shift_instruction("shl", l_tmp3, l_args[0], l_tmp2) + lblock.instruction("%s = select bool %s, int 0, int %s" % + (l_target.llvmname(), l_tmp1.llvmname(), + l_tmp3.llvmname())) + lblock.phi_done = True + + def t_op_int_rshift(self, l_target, args, lblock, l_func): + # XXX hack: llvm only supports shifts by ubyte args + # so we have to jump through some loops + # someone on the LLVM list said this would change in the future + assert len(args) == 2 + l_tmp1 = self.gen.get_local_tmp(None, l_func) #using only the name + l_tmp2 = self.gen.get_local_tmp(None, l_func) + l_tmp3 = self.gen.get_local_tmp(None, l_func) + l_args = [self.gen.get_repr(arg) for arg in args] + l_func.dependencies.update(l_args) + lblock.instruction("%s = setge %s, %s" % (l_tmp1.llvmname(), + l_args[1].typed_name(), + 8 * BYTES_IN_INT)) + lblock.instruction("%s = cast int %s to ubyte" % (l_tmp2.llvmname(), + l_args[1].llvmname())) + lblock.shift_instruction("shr", l_tmp3, l_args[0], l_tmp2) + lblock.instruction("%s = select bool %s, int 0, int %s" % + (l_target.llvmname(), l_tmp1.llvmname(), + l_tmp3.llvmname())) + lblock.phi_done = True def t_op_int_pos(self, l_target, args, lblock, l_func): pass @@ -133,8 +167,9 @@ def t_op_int_abs(self, l_target, args, lblock, l_func): l_arg = self.gen.get_repr(args[0]) l_func.dependencies.add(l_arg) - lblock.instruction("%s = and int 2147483647, %s" % (l_target.llvmname(), - l_arg.llvmname())) + lblock.instruction("%s = and int %s, %s" % (l_target.llvmname(), + sys.maxint - 1, + l_arg.llvmname())) def typename(self): return "int" From cfbolz at codespeak.net Tue Jun 14 18:08:51 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 14 Jun 2005 18:08:51 +0200 (CEST) Subject: [pypy-svn] r13389 - pypy/dist/pypy/translator/llvm/test Message-ID: <20050614160851.1346727B9C@code1.codespeak.net> Author: cfbolz Date: Tue Jun 14 18:08:50 2005 New Revision: 13389 Modified: pypy/dist/pypy/translator/llvm/test/llvmsnippet.py Log: fix test Modified: pypy/dist/pypy/translator/llvm/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm/test/llvmsnippet.py Tue Jun 14 18:08:50 2005 @@ -66,7 +66,7 @@ return i << j def shiftright(i, j): - return i << j + return i >> j #float snippets From arigo at codespeak.net Tue Jun 14 18:18:56 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 18:18:56 +0200 (CEST) Subject: [pypy-svn] r13390 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050614161856.D977B27B96@code1.codespeak.net> Author: arigo Date: Tue Jun 14 18:18:53 2005 New Revision: 13390 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/robject.py pypy/dist/pypy/translator/c/g_exception.h pypy/dist/pypy/translator/c/test/test_exception.py Log: Trying to map rpython exceptions back to CPython exceptions at the exit of a call to compiled generated code. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Tue Jun 14 18:18:53 2005 @@ -11,6 +11,7 @@ # # struct object_vtable { # struct object_vtable* parenttypeptr; +# array { char } * name; # } # # Every other class X, with parent Y, has the structure: @@ -34,7 +35,9 @@ OBJECT_VTABLE = ForwardReference() TYPEPTR = Ptr(OBJECT_VTABLE) -OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR))) +OBJECT_VTABLE.become(Struct('object_vtable', + ('parenttypeptr', TYPEPTR), + ('name', Ptr(Array(Char))))) OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) OBJECTPTR = Ptr(OBJECT) @@ -195,8 +198,16 @@ """Initialize the 'self' portion of the 'vtable' belonging to the given subclass.""" if self.classdef is None: - # initialize the 'parenttypeptr' field + # initialize the 'parenttypeptr' and 'name' fields vtable.parenttypeptr = rsubcls.rbase.getvtable() + if rsubcls.classdef is None: + name = 'object' + else: + name = rsubcls.classdef.cls.__name__ + vtable.name = malloc(Array(Char), len(name)+1, immortal=True) + for i in range(len(name)): + vtable.name[i] = name[i] + vtable.name[len(name)] = '\x00' 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/robject.py ============================================================================== --- pypy/dist/pypy/rpython/robject.py (original) +++ pypy/dist/pypy/rpython/robject.py Tue Jun 14 18:18:53 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pair, pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr -from pypy.rpython.rmodel import Repr, TyperError +from pypy.rpython.lltype import PyObject, Ptr, Void, Bool, pyobjectptr, nullptr +from pypy.rpython.rmodel import Repr, TyperError, VoidRepr, inputconst from pypy.rpython import rclass from pypy.tool.sourcetools import func_with_new_name @@ -32,6 +32,14 @@ constpyobj_repr = PyObjRepr() constpyobj_repr.lowleveltype = Void + +class __extend__(pairtype(VoidRepr, PyObjRepr)): + # conversion used to return a PyObject* when a function can really only + # raise an exception, in which case the return value is a VoidRepr + def convert_from_to(_, v, llops): + return inputconst(Ptr(PyObject), nullptr(PyObject)) + + # ____________________________________________________________ # # All operations involving a PyObjRepr are "replaced" by themselves, @@ -46,7 +54,7 @@ funcname = 'rtype_' + opname func = func_with_new_name(rtype_op, funcname) - assert funcname not in cls.__dict__ # can be in Repr; overriden then. + assert funcname not in cls.__dict__ # can be in Repr; overridden then. setattr(cls, funcname, func) Modified: pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- pypy/dist/pypy/translator/c/g_exception.h (original) +++ pypy/dist/pypy/translator/c/g_exception.h Tue Jun 14 18:18:53 2005 @@ -42,11 +42,23 @@ static PyObject *ConvertExceptionToCPython(void) { + /* XXX 1. uses officially bad fishing */ + /* XXX 2. looks for exception classes by name, fragile */ + char* clsname; + PyObject* pycls; assert(ExceptionOccurred()); assert(!PyErr_Occurred()); + clsname = rpython_exc_type->ov_name->items; + pycls = PyDict_GetItemString(PyEval_GetBuiltins(), clsname); + if (pycls != NULL && PyClass_Check(pycls) && + PyClass_IsSubclass(pycls, PyExc_Exception)) { + PyErr_SetNone(pycls); + } + else { + PyErr_SetString(RPythonError, clsname); + } rpython_exc_type = NULL; /* XXX leaks! */ rpython_exc_value = NULL; - PyErr_SetNone(RPythonError); return NULL; } Modified: pypy/dist/pypy/translator/c/test/test_exception.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_exception.py (original) +++ pypy/dist/pypy/translator/c/test/test_exception.py Tue Jun 14 18:18:53 2005 @@ -1,3 +1,4 @@ +import py from pypy.translator.translator import Translator @@ -21,3 +22,22 @@ #t.view() f1 = t.ccompile() assert f1() == 5 + +def test_raise_outside_testfn(): + def testfn(n): + if n < 0: + raise ValueError("hello") + else: + raise MyException("world") + + t = Translator(testfn) + t.annotate([int]).simplify() + t.specialize() + f1 = t.ccompile() + assert py.test.raises(ValueError, f1, -1) + try: + f1(1) + except Exception, e: + assert str(e) == 'MyException' # which is genc's best effort + else: + py.test.fail("f1(1) did not raise anything") From cfbolz at codespeak.net Tue Jun 14 18:21:35 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 14 Jun 2005 18:21:35 +0200 (CEST) Subject: [pypy-svn] r13392 - pypy/dist/pypy/bin Message-ID: <20050614162135.CAAED27BA6@code1.codespeak.net> Author: cfbolz Date: Tue Jun 14 18:21:35 2005 New Revision: 13392 Modified: pypy/dist/pypy/bin/translator.py Log: using rlcompleter2, if available Modified: pypy/dist/pypy/bin/translator.py ============================================================================== --- pypy/dist/pypy/bin/translator.py (original) +++ pypy/dist/pypy/bin/translator.py Tue Jun 14 18:21:35 2005 @@ -211,8 +211,12 @@ def setup_readline(): import readline - import rlcompleter - readline.parse_and_bind("tab: complete") + try: + import rlcompleter2 + rlcompleter2.setup() + except ImportError: + import rlcompleter + readline.parse_and_bind("tab: complete") import os histfile = os.path.join(os.environ["HOME"], ".pypytrhist") try: From arigo at codespeak.net Tue Jun 14 18:26:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 18:26:11 +0200 (CEST) Subject: [pypy-svn] r13393 - in pypy/dist/pypy: rpython translator/c Message-ID: <20050614162611.98C2A27B9C@code1.codespeak.net> Author: arigo Date: Tue Jun 14 18:26:09 2005 New Revision: 13393 Modified: pypy/dist/pypy/rpython/exceptiondata.py pypy/dist/pypy/translator/c/database.py Log: Force some standard exceptions to exist and be translated. Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Tue Jun 14 18:26:09 2005 @@ -7,7 +7,12 @@ class ExceptionData: """Public information for the code generators to help with exceptions.""" + # the exceptions that can be implicitely raised by some operations + standardexceptions = [TypeError, OverflowError, ValueError, + ZeroDivisionError, MemoryError] + def __init__(self, rtyper): + self.make_standard_exceptions(rtyper) # (NB. rclass identifies 'Exception' and 'object') r_type = rclass.getclassrepr(rtyper, None) r_instance = rclass.getinstancerepr(rtyper, None) @@ -22,6 +27,13 @@ self.ll_pyexcclass2exc = self.make_pyexcclass2exc(rtyper) + def make_standard_exceptions(self, rtyper): + bk = rtyper.annotator.bookkeeper + for cls in self.standardexceptions: + classdef = bk.getclassdef(cls) + rclass.getclassrepr(rtyper, classdef).setup() + + def make_exception_matcher(self, rtyper): # ll_exception_matcher(real_exception_vtable, match_exception_vtable) s_typeptr = annmodel.SomePtr(self.lltype_of_exception_type) Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Tue Jun 14 18:26:09 2005 @@ -178,8 +178,7 @@ fnname = self.get(fnptr) yield '#define RPYTHON_PYEXCCLASS2EXC %s' % (fnname,) - for pyexccls in [TypeError, OverflowError, ValueError, - ZeroDivisionError, MemoryError]: + for pyexccls in exceptiondata.standardexceptions: exc_llvalue = exceptiondata.ll_pyexcclass2exc( pyobjectptr(pyexccls)) # strange naming here because the macro name must be From hpk at codespeak.net Tue Jun 14 19:10:59 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 14 Jun 2005 19:10:59 +0200 (CEST) Subject: [pypy-svn] r13394 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614171059.110FC27BAB@code1.codespeak.net> Author: hpk Date: Tue Jun 14 19:10:58 2005 New Revision: 13394 Added: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: simplistic start at a lowlevel flow interpreter Added: pypy/dist/pypy/rpython/interp.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/interp.py Tue Jun 14 19:10:58 2005 @@ -0,0 +1,77 @@ +from pypy.rpython.lltype import * + + +class LLInterpreter(object): + """ low level interpreter working with concrete values. """ + def __init__(self, flowgraphs): + self.flowgraphs = flowgraphs + self.bindings = {} + + # _______________________________________________________ + # variable setters/getters helpers + + def fillvars(self, block, values): + vars = block.inputargs + assert len(vars) == len(values), ( + "block %s received %d args, expected %d" % ( + block, len(values), len(vars))) + for var, val in zip(vars, values): + self.setvar(var, val) + + def setvar(self, var, val): + # XXX assert that val "matches" lowlevel type + assert var not in self.bindings + self.bindings[var] = val + + def getval(self, varorconst): + try: + return varorconst.value + except AttributeError: + return self.bindings[varorconst] + + # _______________________________________________________ + # evaling functions + + def eval_function(self, func, args=()): + graph = self.flowgraphs[func] + # inputargs + self.fillvars(graph.startblock, args) + # run startblock + nextblock = graph.startblock + while 1: + nextblock, values = self.eval_block(nextblock) + if nextblock is None: + return values + self.fillvars(nextblock, values) + + def eval_block(self, block): + for op in block.operations: + self.eval_operation(op) + + # determine nextblock and/or return value + if len(block.exits) == 0: + # return block + resvar, = block.getvariables() + return None, self.getval(resvar) + elif len(block.exits) == 1: + index = 0 + else: + index = self.getval(block.exitswitch) + link = block.exits[index] + return link.target, [self.getval(x) for x in link.args] + + def eval_operation(self, operation): + g = globals() + opname = operation.opname + assert opname in g, ( + "cannot handle operation %r yet" %(opname,)) + ophandler = g[opname] + vals = [self.getval(x) for x in operation.args] + retval = ophandler(*vals) + self.setvar(operation.result, retval) + +############################## +# int operations + +def int_add(x, y): + return x + y Added: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_interp.py Tue Jun 14 19:10:58 2005 @@ -0,0 +1,51 @@ + +import py +py.magic.autopath() +from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.interp import LLInterpreter +from pypy.translator.translator import Translator + +def gengraph(func, argtypes=[]): + t = Translator(func) + t.annotate(argtypes) + typer = RPythonTyper(t.annotator) + typer.specialize() + #t.view() + t.checkgraphs() + return t + +def test_int_adding(): + t = gengraph(int_adding, [int]) + interp = LLInterpreter(t.flowgraphs) + res = interp.eval_function(int_adding, [3]) + assert res == 6 + +#__________________________________________________________________ +# example functions for testing the LLInterpreter +_snap = globals().copy() + +def int_adding(i): + j = i + 2 + return j + 1 + + + +#__________________________________________________________________ +# interactive playing + +if __name__ == '__main__': + try: + import rlcompleter2 as _rl2 + _rl2.setup() + except ImportError: + pass + + t = gengraph(int_adding, [int]) + interp = LLInterpreter(t.flowgraphs) + res = interp.eval_function(int_adding, [3]) + assert res == 6 + for name, value in globals().items(): + if name not in _snap and name[0] != '_': + print "%20s: %s" %(name, value) + + From arigo at codespeak.net Tue Jun 14 19:13:49 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 19:13:49 +0200 (CEST) Subject: [pypy-svn] r13395 - in pypy/dist/pypy: rpython translator/c Message-ID: <20050614171349.E19E927BAC@code1.codespeak.net> Author: arigo Date: Tue Jun 14 19:13:47 2005 New Revision: 13395 Modified: pypy/dist/pypy/rpython/exceptiondata.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/g_exception.h Log: Force the except blocks to receive a standardized exception type and value. This allows the code generators to assume they know the low-level type of the data coming in, to do the 'raise'. Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Tue Jun 14 19:13:47 2005 @@ -18,9 +18,13 @@ r_instance = rclass.getinstancerepr(rtyper, None) r_type.setup() r_instance.setup() + self.r_exception_type = r_type + self.r_exception_value = r_instance self.lltype_of_exception_type = r_type.lowleveltype self.lltype_of_exception_value = r_instance.lowleveltype + + def make_helpers(self, rtyper): # create helper functions self.ll_exception_match = self.make_exception_matcher(rtyper) self.ll_type_of_exc_inst = self.make_type_of_exc_inst(rtyper) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jun 14 19:13:47 2005 @@ -36,6 +36,7 @@ for s_primitive, lltype in annmodel.annotation_to_ll_map: r = self.getrepr(s_primitive) self.primitive_to_repr[r.lowleveltype] = r + self.exceptiondata = ExceptionData(self) def getexceptiondata(self): return self.exceptiondata # built at the end of specialize() @@ -89,8 +90,8 @@ self.call_all_setups() specialize_more_blocks() - self.exceptiondata = ExceptionData(self) - specialize_more_blocks() + self.exceptiondata.make_helpers(self) + specialize_more_blocks() # for the helpers just made if self.typererror: exc, value, tb = self.typererror @@ -111,10 +112,39 @@ assert isinstance(v, Variable) v.concretetype = self.bindingrepr(v).lowleveltype + def typedconstant(self, c, using_repr=None): + """Make a copy of the Constant 'c' and give it a concretetype.""" + assert isinstance(c, Constant) + if using_repr is None: + using_repr = self.bindingrepr(c) + if not hasattr(c, 'concretetype'): + c = inputconst(using_repr, c.value) + else: + if c.concretetype != Void: + assert typeOf(c.value) == using_repr.lowleveltype + return c + + def setup_block_entry(self, block): + if block.operations == () and len(block.inputargs) == 2: + # special case for exception blocks: force them to return an + # exception type and value in a standardized format + v1, v2 = block.inputargs + v1.concretetype = self.exceptiondata.lltype_of_exception_type + v2.concretetype = self.exceptiondata.lltype_of_exception_value + return [self.exceptiondata.r_exception_type, + self.exceptiondata.r_exception_value] + else: + # normal path + result = [] + for a in block.inputargs: + r = self.bindingrepr(a) + a.concretetype = r.lowleveltype + result.append(r) + return result + def specialize_block(self, block): # give the best possible types to the input args - for a in block.inputargs: - self.setconcretetype(a) + self.setup_block_entry(block) # specialize all the operations, as far as possible if block.operations == (): # return or except block @@ -147,15 +177,20 @@ assert block.exitswitch == Constant(last_exception) r_case = rclass.get_type_repr(self) link.llexitcase = r_case.convert_const(link.exitcase) - for a in [link.last_exception, link.last_exc_value]: + + for attr in ('last_exception', 'last_exc_value'): + a = getattr(link, attr) if isinstance(a, Variable): self.setconcretetype(a) + elif isinstance(a, Constant): + setattr(link, attr, self.typedconstant(a)) + + inputargs_reprs = self.setup_block_entry(link.target) for i in range(len(link.args)): a1 = link.args[i] - a2 = link.target.inputargs[i] - r_a2 = self.bindingrepr(a2) + r_a2 = inputargs_reprs[i] if isinstance(a1, Constant): - link.args[i] = inputconst(r_a2, a1.value) + link.args[i] = self.typedconstant(a1, using_repr=r_a2) continue # the Constant was typed, done r_a1 = self.bindingrepr(a1) if r_a1 == r_a2: Modified: pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- pypy/dist/pypy/translator/c/g_exception.h (original) +++ pypy/dist/pypy/translator/c/g_exception.h Tue Jun 14 19:13:47 2005 @@ -14,10 +14,10 @@ #define ExceptionOccurred() (rpython_exc_type != NULL) -#define RaiseException(etype, evalue) \ - assert(!ExceptionOccurred()); \ - rpython_exc_type = (RPYTHON_EXCEPTION_VTABLE)(etype); \ - rpython_exc_value = (RPYTHON_EXCEPTION)(evalue) +#define RaiseException(etype, evalue) \ + assert(!ExceptionOccurred()); \ + rpython_exc_type = etype; \ + rpython_exc_value = evalue #define FetchException(etypevar, evaluevar, type_of_evaluevar) \ etypevar = rpython_exc_type; \ From hpk at codespeak.net Tue Jun 14 19:14:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 14 Jun 2005 19:14:43 +0200 (CEST) Subject: [pypy-svn] r13396 - pypy/dist/pypy/rpython Message-ID: <20050614171443.802BD27BB7@code1.codespeak.net> Author: hpk Date: Tue Jun 14 19:14:42 2005 New Revision: 13396 Modified: pypy/dist/pypy/rpython/interp.py Log: cosmetics Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Tue Jun 14 19:14:42 2005 @@ -34,17 +34,17 @@ def eval_function(self, func, args=()): graph = self.flowgraphs[func] - # inputargs - self.fillvars(graph.startblock, args) - # run startblock nextblock = graph.startblock while 1: - nextblock, values = self.eval_block(nextblock) + self.fillvars(nextblock, args) + nextblock, args = self.eval_block(nextblock) if nextblock is None: - return values - self.fillvars(nextblock, values) + return args def eval_block(self, block): + """ return (nextblock, values) tuple. If nextblock + is None, values is the concrete return value. + """ for op in block.operations: self.eval_operation(op) From arigo at codespeak.net Tue Jun 14 19:58:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 19:58:45 +0200 (CEST) Subject: [pypy-svn] r13399 - pypy/dist/pypy/objspace/flow Message-ID: <20050614175845.4130A27BBE@code1.codespeak.net> Author: arigo Date: Tue Jun 14 19:58:43 2005 New Revision: 13399 Modified: pypy/dist/pypy/objspace/flow/operation.py Log: made Table internal. Modified: pypy/dist/pypy/objspace/flow/operation.py ============================================================================== --- pypy/dist/pypy/objspace/flow/operation.py (original) +++ pypy/dist/pypy/objspace/flow/operation.py Tue Jun 14 19:58:43 2005 @@ -106,6 +106,8 @@ # if multiple built-in functions correspond to it. The first one should # be picked, though, as the best built-in for the given operation name. # Lines ('name', operator.name) are added automatically. + +# INTERNAL ONLY, use the dicts declared at the top of the file. Table = [ ('id', id), ('type', new_style_type), @@ -172,3 +174,4 @@ Arity[name] = line[2] assert name in FunctionByName setup() +del Table # INTERNAL ONLY, use the dicts declared at the top of the file From arigo at codespeak.net Tue Jun 14 19:59:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 19:59:45 +0200 (CEST) Subject: [pypy-svn] r13400 - pypy/dist/pypy/rpython Message-ID: <20050614175945.6EA0027BC0@code1.codespeak.net> Author: arigo Date: Tue Jun 14 19:59:43 2005 New Revision: 13400 Modified: pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rtyper.py Log: Completed rint.py with all _ovf version of the operations and with the exceptional low-level operations (xxx_zer, xxx_val) that are used if we see the corresponding ZeroDivisionError or ValueError caught. Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Tue Jun 14 19:59:43 2005 @@ -54,18 +54,42 @@ return _rtype_template(hop, 'mul') rtype_inplace_mul = rtype_mul + def rtype_mul_ovf(_, hop): + return _rtype_template(hop, 'mul_ovf') + rtype_inplace_mul_ovf = rtype_mul_ovf + def rtype_div(_, hop): - return _rtype_template(hop, 'div') + return _rtype_template(hop, 'div', [ZeroDivisionError]) rtype_inplace_div = rtype_div + def rtype_div_ovf(_, hop): + return _rtype_template(hop, 'div_ovf', [ZeroDivisionError]) + rtype_inplace_div_ovf = rtype_div_ovf + def rtype_floordiv(_, hop): - return _rtype_template(hop, 'floordiv') + return _rtype_template(hop, 'floordiv', [ZeroDivisionError]) rtype_inplace_floordiv = rtype_floordiv + def rtype_floordiv_ovf(_, hop): + return _rtype_template(hop, 'floordiv_ovf', [ZeroDivisionError]) + rtype_inplace_floordiv_ovf = rtype_floordiv_ovf + + def rtype_truediv(_, hop): + return _rtype_template(hop, 'truediv', [ZeroDivisionError]) + rtype_inplace_truediv = rtype_truediv + + def rtype_truediv_ovf(_, hop): + return _rtype_template(hop, 'truediv_ovf', [ZeroDivisionError]) + rtype_inplace_truediv_ovf = rtype_truediv_ovf + def rtype_mod(_, hop): - return _rtype_template(hop, 'mod') + return _rtype_template(hop, 'mod', [ZeroDivisionError]) rtype_inplace_mod = rtype_mod + def rtype_mod_ovf(_, hop): + return _rtype_template(hop, 'mod_ovf', [ZeroDivisionError]) + rtype_inplace_mod_ovf = rtype_mod_ovf + def rtype_xor(_, hop): return _rtype_template(hop, 'xor') rtype_inplace_xor = rtype_xor @@ -79,38 +103,44 @@ rtype_inplace_or = rtype_or_ def rtype_lshift(_, hop): - return _rtype_template(hop, 'lshift') + return _rtype_template(hop, 'lshift', [ValueError]) rtype_inplace_lshift = rtype_lshift def rtype_lshift_ovf(_, hop): - return _rtype_template(hop, 'lshift_ovf') + return _rtype_template(hop, 'lshift_ovf', [ValueError]) rtype_inplace_lshift_ovf = rtype_lshift_ovf def rtype_rshift(_, hop): - return _rtype_template(hop, 'rshift') + return _rtype_template(hop, 'rshift', [ValueError]) rtype_inplace_rshift = rtype_rshift - def rtype_rshift_ovf(_, hop): - return _rtype_template(hop, 'rshift_ovf') - rtype_inplace_rshift_ovf = rtype_rshift_ovf - - def rtype_pow(_, hop): + def rtype_pow(_, hop, suffix=''): + if hop.has_implicit_exception(ZeroDivisionError): + suffix += '_zer' s_int3 = hop.args_s[2] if hop.s_result.unsigned: if s_int3.is_constant() and s_int3.const is None: vlist = hop.inputargs(Unsigned, Unsigned, Void)[:2] else: vlist = hop.inputargs(Unsigned, Unsigned, Unsigned) - return hop.genop('uint_pow', vlist, resulttype=Unsigned) + return hop.genop('uint_pow' + suffix, vlist, resulttype=Unsigned) else: if s_int3.is_constant() and s_int3.const is None: vlist = hop.inputargs(Signed, Signed, Void)[:2] else: vlist = hop.inputargs(Signed, Signed, Signed) - return hop.genop('int_pow', vlist, resulttype=Signed) + return hop.genop('int_pow' + suffix, vlist, resulttype=Signed) + + def rtype_pow_ovf(_, hop): + if hop.s_result.unsigned: + raise TyperError("forbidden uint_pow_ovf") + return self.rtype_pow(_, hop, suffix='_ovf') def rtype_inplace_pow(_, hop): - return _rtype_template(hop, 'pow') + return _rtype_template(hop, 'pow', [ZeroDivisionError]) + + def rtype_inplace_pow_ovf(_, hop): + return _rtype_template(hop, 'pow_ovf', [ZeroDivisionError]) #comparisons: eq is_ ne lt le gt ge @@ -136,8 +166,14 @@ #Helper functions -def _rtype_template(hop, func): +def _rtype_template(hop, func, implicit_excs=[]): + func1 = func + for implicit_exc in implicit_excs: + if hop.has_implicit_exception(implicit_exc): + func += '_' + implicit_exc.__name__[:3].lower() if hop.s_result.unsigned: + if func1.endswith('_ovf'): + raise TyperError("forbidden uint_" + func) vlist = hop.inputargs(Unsigned, Unsigned) return hop.genop('uint_'+func, vlist, resulttype=Unsigned) else: @@ -191,8 +227,7 @@ def rtype_abs_ovf(_, hop): if hop.s_result.unsigned: - vlist = hop.inputargs(Unsigned) - return vlist[0] + raise TyperError("forbidden uint_abs_ovf") else: vlist = hop.inputargs(Signed) return hop.genop('int_abs_ovf', vlist, resulttype=Signed) @@ -213,6 +248,13 @@ vlist = hop.inputargs(Signed) return hop.genop('int_neg', vlist, resulttype=Signed) + def rtype_neg_ovf(_, hop): + if hop.s_result.unsigned: + raise TyperError("forbidden uint_neg_ovf") + else: + vlist = hop.inputargs(Signed) + return hop.genop('int_neg_ovf', vlist, resulttype=Signed) + def rtype_pos(_, hop): if hop.s_result.unsigned: vlist = hop.inputargs(Unsigned) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jun 14 19:59:43 2005 @@ -1,3 +1,4 @@ +from __future__ import generators import sys from pypy.annotation.pairtype import pair from pypy.annotation import model as annmodel @@ -154,12 +155,11 @@ for v in block.getvariables(): varmapping[v] = v # records existing Variables - for op in block.operations: + for hop in self.highlevelops(block, newops): try: - hop = HighLevelOp(self, op, newops) self.translate_hl_to_ll(hop, varmapping) except TyperError, e: - self.gottypererror(e, block, op, newops) + self.gottypererror(e, block, hop.spaceop, newops) return # cannot continue this block: no op.result.concretetype block.operations[:] = newops @@ -214,6 +214,18 @@ block.operations.extend(newops) link.args[i] = a1 + def highlevelops(self, block, llops): + # enumerate the HighLevelOps in a block. + if block.operations: + for op in block.operations[:-1]: + yield HighLevelOp(self, op, [], llops) + # look for exception links for the last operation + if block.exitswitch == Constant(last_exception): + exclinks = block.exits[1:] + else: + exclinks = [] + yield HighLevelOp(self, block.operations[-1], exclinks, llops) + def translate_hl_to_ll(self, hop, varmapping): if debug: print hop.spaceop.opname, hop.args_s @@ -327,7 +339,7 @@ class HighLevelOp: nb_popped = 0 - def __init__(self, rtyper, spaceop, llops): + def __init__(self, rtyper, spaceop, exceptionlinks, llops): self.rtyper = rtyper self.spaceop = spaceop self.nb_args = len(spaceop.args) @@ -337,6 +349,7 @@ self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] self.r_result = rtyper.getrepr(self.s_result) rtyper.call_all_setups() # compute ForwardReferences now + self.exceptionlinks = exceptionlinks def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, @@ -381,6 +394,12 @@ self.nb_args -= 1 return self.args_r.pop(0), self.args_s.pop(0) + def has_implicit_exception(self, exc_cls): + for link in self.exceptionlinks: + if issubclass(exc_cls, link.exitcase): + return True + return False + # ____________________________________________________________ class LowLevelOpList(list): From hpk at codespeak.net Tue Jun 14 20:05:47 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 14 Jun 2005 20:05:47 +0200 (CEST) Subject: [pypy-svn] r13401 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614180547.3992927BC2@code1.codespeak.net> Author: hpk Date: Tue Jun 14 20:05:46 2005 New Revision: 13401 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: use operator module and tests ints and floats Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Tue Jun 14 20:05:46 2005 @@ -71,7 +71,16 @@ self.setvar(operation.result, retval) ############################## -# int operations +# primitive operations +import operator -def int_add(x, y): - return x + y +for typ in (float, int): + typname = typ.__name__ + for opname in 'add', 'sub', 'mul', 'div': + assert hasattr(operator, opname) + exec py.code.Source(""" + def %(typname)s_%(opname)s(x,y): + assert isinstance(x, %(typname)s) + assert isinstance(y, %(typname)s) + return operator.%(opname)s(x, y) + """ % locals()).compile() Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Tue Jun 14 20:05:46 2005 @@ -14,21 +14,28 @@ t.checkgraphs() return t -def test_int_adding(): - t = gengraph(int_adding, [int]) +def test_int_ops(): + t = gengraph(number_ops, [int]) interp = LLInterpreter(t.flowgraphs) - res = interp.eval_function(int_adding, [3]) - assert res == 6 + res = interp.eval_function(number_ops, [3]) + assert res == 4 + +def test_float_ops(): + t = gengraph(number_ops, [float]) + interp = LLInterpreter(t.flowgraphs) + res = interp.eval_function(number_ops, [3.5]) + assert res == 4.5 + #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() -def int_adding(i): +def number_ops(i): j = i + 2 - return j + 1 - - + k = j * 2 + m = k / 2 + return m - 1 #__________________________________________________________________ # interactive playing @@ -40,9 +47,9 @@ except ImportError: pass - t = gengraph(int_adding, [int]) + t = gengraph(number_ops, [int]) interp = LLInterpreter(t.flowgraphs) - res = interp.eval_function(int_adding, [3]) + res = interp.eval_function(number_ops, [3]) assert res == 6 for name, value in globals().items(): if name not in _snap and name[0] != '_': From arigo at codespeak.net Tue Jun 14 20:24:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 20:24:39 +0200 (CEST) Subject: [pypy-svn] r13402 - in pypy/dist/pypy: rpython translator/c translator/genc/test Message-ID: <20050614182439.A987127BC6@code1.codespeak.net> Author: arigo Date: Tue Jun 14 20:24:34 2005 New Revision: 13402 Added: pypy/dist/pypy/translator/c/float_include.h (contents, props changed) Modified: pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/genc/test/test_annotated.py Log: Started the support for floats in genc. Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Tue Jun 14 20:24:34 2005 @@ -3,6 +3,7 @@ from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void from pypy.rpython.rmodel import Repr, TyperError, FloatRepr from pypy.rpython.rmodel import IntegerRepr, BoolRepr +from pypy.rpython.robject import PyObjRepr, pyobj_repr debug = False @@ -131,3 +132,17 @@ if debug: print 'explicit cast_bool_to_float' return llops.genop('cast_bool_to_float', [v], resulttype=Float) return NotImplemented + +class __extend__(pairtype(PyObjRepr, FloatRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Float: + return llops.gencapicall('PyFloat_AsDouble', [v], + resulttype=Float) + return NotImplemented + +class __extend__(pairtype(FloatRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Float: + return llops.gencapicall('PyFloat_FromDouble', [v], + resulttype=pyobj_repr) + return NotImplemented Added: pypy/dist/pypy/translator/c/float_include.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/float_include.h Tue Jun 14 20:24:34 2005 @@ -0,0 +1,39 @@ + +/************************************************************/ + /*** C header subsection: operations between floats ***/ + + +/* XXX INCOMPLETE */ + + +/*** unary operations ***/ + +#define OP_FLOAT_IS_TRUE(x,r,err) OP_FLOAT_NE(x,0.0,r,err) + + +/*** binary operations ***/ + +#define OP_FLOAT_EQ(x,y,r,err) r = (x == y); +#define OP_FLOAT_NE(x,y,r,err) r = (x != y); +#define OP_FLOAT_LE(x,y,r,err) r = (x <= y); +#define OP_FLOAT_GT(x,y,r,err) r = (x > y); +#define OP_FLOAT_LT(x,y,r,err) r = (x < y); +#define OP_FLOAT_GE(x,y,r,err) r = (x >= y); + +#define OP_FLOAT_CMP(x,y,r,err) \ + r = ((x > y) - (x < y)) + +/* addition, subtraction */ + +#define OP_FLOAT_ADD(x,y,r,err) r = x + y; +#define OP_FLOAT_SUB(x,y,r,err) r = x - y; +#define OP_FLOAT_MUL(x,y,r,err) r = x * y; + + +/*** conversions ***/ + +#define OP_CAST_FLOAT_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_FLOAT_TO_UINT(x,r,err) r = (unsigned long)(x); +#define OP_CAST_INT_TO_FLOAT(x,r,err) r = (double)(x); +#define OP_CAST_UINT_TO_FLOAT(x,r,err) r = (double)(x); +#define OP_CAST_BOOL_TO_FLOAT(x,r,err) r = (double)(x); Modified: pypy/dist/pypy/translator/c/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/g_include.h (original) +++ pypy/dist/pypy/translator/c/g_include.h Tue Jun 14 20:24:34 2005 @@ -16,5 +16,6 @@ #include "g_module.h" #include "int_include.h" +#include "float_include.h" #include "ll_include.h" #include "pyobj_include.h" Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Tue Jun 14 20:24:34 2005 @@ -135,6 +135,15 @@ if ((long)(y)) { OP_INT_MOD_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") +/*** conversions ***/ + +#define OP_CAST_BOOL_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_BOOL_TO_UINT(x,r,err) r = (unsigned long)(x); +#define OP_CAST_UINT_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_INT_TO_UINT(x,r,err) r = (unsigned long)(x); +#define OP_CAST_CHAR_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); + /* _________________ certain implementations __________________ */ #ifndef HAVE_LONG_LONG Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Tue Jun 14 20:24:34 2005 @@ -11,6 +11,9 @@ assert value >= 0 return '%d' % value +def name_float(value): + return repr(value) + def name_char(value): value = value assert type(value) is str and len(value) == 1 @@ -28,6 +31,7 @@ PrimitiveName = { Signed: name_signed, Unsigned: name_unsigned, + Float: name_float, Char: name_char, Bool: name_bool, Void: name_void, @@ -36,6 +40,7 @@ PrimitiveType = { Signed: 'long @', Unsigned: 'unsigned long @', + Float: 'double @', Char: 'char @', Bool: 'char @', Void: 'void @', @@ -44,6 +49,7 @@ PrimitiveErrorValue = { Signed: '-1', Unsigned: '((unsigned) -1)', + Float: '-1.0', Char: '((char) -1)', Bool: '((char) -1)', Void: '/* error */', Modified: pypy/dist/pypy/translator/genc/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/genc/test/test_annotated.py Tue Jun 14 20:24:34 2005 @@ -110,7 +110,7 @@ def test_type_conversion(self): # obfuscated test case specially for typer.insert_link_conversions() - def type_conversion(n): + def type_conversion(n=int): if n > 3: while n > 0: n = n-1 From arigo at codespeak.net Tue Jun 14 20:31:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 20:31:08 +0200 (CEST) Subject: [pypy-svn] r13403 - pypy/dist/pypy/translator/genc/test Message-ID: <20050614183108.5022C27BC9@code1.codespeak.net> Author: arigo Date: Tue Jun 14 20:31:05 2005 New Revision: 13403 Added: pypy/dist/pypy/translator/genc/test/test_typed.py - copied, changed from r13387, pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Removed: pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Log: All tests pass! :-) Deleted: /pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py Tue Jun 14 20:31:05 2005 +++ (empty file) @@ -1,105 +0,0 @@ -import autopath -import sys -import py.test -from pypy.translator.translator import Translator -from pypy.translator.test import snippet -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler - -from pypy.translator.genc.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase - - -class TestTypedTestCase(_TestAnnotatedTestCase): - - def getcompiled(self, func): - t = Translator(func, simplifying=True) - # builds starting-types from func_defs - argstypelist = [] - if func.func_defaults: - for spec in func.func_defaults: - if isinstance(spec, tuple): - spec = spec[0] # use the first type only for the tests - argstypelist.append(spec) - a = t.annotate(argstypelist) - a.simplify() - t.specialize() - t.checkgraphs() - return skip_missing_compiler(t.ccompile) - - def test_call_five(self): - # -- the result of call_five() isn't a real list, but an rlist - # that can't be converted to a PyListObject - def wrapper(): - lst = snippet.call_five() - return len(lst), lst[0] - call_five = self.getcompiled(wrapper) - result = call_five() - assert result == (1, 5) - - def test_get_set_del_slice(self): - def get_set_del_nonneg_slice(): # no neg slices for now! - l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] - del l[:1] - bound = len(l)-1 - if bound >= 0: - del l[bound:] - del l[2:4] - #l[:1] = [3] - #bound = len(l)-1 - #assert bound >= 0 - #l[bound:] = [9] no setting slice into lists for now - #l[2:4] = [8,11] - l[0], l[-1], l[2], l[3] = 3, 9, 8, 11 - - list_3_c = l[:2] - list_9 = l[5:] - list_11_h = l[3:5] - return (len(l), l[0], l[1], l[2], l[3], l[4], l[5], - len(list_3_c), list_3_c[0], list_3_c[1], - len(list_9), list_9[0], - len(list_11_h), list_11_h[0], list_11_h[1]) - fn = self.getcompiled(get_set_del_nonneg_slice) - result = fn() - assert result == (6, 3, 'c', 8, 11, 'h', 9, - 2, 3, 'c', - 1, 9, - 2, 11, 'h') - - def test_slice_long(self): - "the parent's test_slice_long() makes no sense here" - - def test_int_overflow(self): - fn = self.getcompiled(snippet.add_func) - raises(OverflowError, fn, sys_maxint()) - - def test_int_div_ovf_zer(self): # - py.test.skip("right now aborting python with Floating Point Error!") - fn = self.getcompiled(snippet.div_func) - raises(OverflowError, fn, -1) - raises(ZeroDivisionError, fn, 0) - - def test_int_mod_ovf_zer(self): - py.test.skip("right now aborting python with Floating Point Error!") - fn = self.getcompiled(snippet.mod_func) - raises(OverflowError, fn, -1) - raises(ZeroDivisionError, fn, 0) - - def test_int_rshift_val(self): - fn = self.getcompiled(snippet.rshift_func) - raises(ValueError, fn, -1) - - def test_int_lshift_ovf_val(self): - fn = self.getcompiled(snippet.lshift_func) - raises(ValueError, fn, -1) - raises(OverflowError, fn, 1) - - def test_int_unary_ovf(self): - fn = self.getcompiled(snippet.unary_func) - for i in range(-3,3): - assert fn(i) == (-(i), abs(i-1)) - raises (OverflowError, fn, -sys_maxint()-1) - raises (OverflowError, fn, -sys_maxint()) - -def sys_maxint(): - if sys.maxint != 2147483647: - py.test.skip("genc ovf incomplete: int might differ from long") - return sys.maxint Copied: pypy/dist/pypy/translator/genc/test/test_typed.py (from r13387, pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py) ============================================================================== --- pypy/dist/pypy/translator/genc/test/inprogress_test_typed.py (original) +++ pypy/dist/pypy/translator/genc/test/test_typed.py Tue Jun 14 20:31:05 2005 @@ -72,13 +72,11 @@ raises(OverflowError, fn, sys_maxint()) def test_int_div_ovf_zer(self): # - py.test.skip("right now aborting python with Floating Point Error!") fn = self.getcompiled(snippet.div_func) raises(OverflowError, fn, -1) raises(ZeroDivisionError, fn, 0) def test_int_mod_ovf_zer(self): - py.test.skip("right now aborting python with Floating Point Error!") fn = self.getcompiled(snippet.mod_func) raises(OverflowError, fn, -1) raises(ZeroDivisionError, fn, 0) From hpk at codespeak.net Tue Jun 14 20:38:13 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 14 Jun 2005 20:38:13 +0200 (CEST) Subject: [pypy-svn] r13404 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614183813.4B79927BCC@code1.codespeak.net> Author: hpk Date: Tue Jun 14 20:38:12 2005 New Revision: 13404 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: add branching and some more operations to the ll-interpreter (now using pypy.objspace.flow.operation although i am still not sure it's really worth it) Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Tue Jun 14 20:38:12 2005 @@ -20,7 +20,6 @@ def setvar(self, var, val): # XXX assert that val "matches" lowlevel type - assert var not in self.bindings self.bindings[var] = val def getval(self, varorconst): @@ -63,6 +62,7 @@ def eval_operation(self, operation): g = globals() opname = operation.opname + print "considering", operation assert opname in g, ( "cannot handle operation %r yet" %(opname,)) ophandler = g[opname] @@ -72,15 +72,29 @@ ############################## # primitive operations -import operator +from pypy.objspace.flow.operation import FunctionByName +opimpls = FunctionByName.copy() +opimpls['is_true'] = bool + +def same_as(x): + return x for typ in (float, int): typname = typ.__name__ - for opname in 'add', 'sub', 'mul', 'div': - assert hasattr(operator, opname) + for opname in 'add', 'sub', 'mul', 'div', 'gt', 'lt': + assert opname in opimpls exec py.code.Source(""" - def %(typname)s_%(opname)s(x,y): + def %(typname)s_%(opname)s(x, y): assert isinstance(x, %(typname)s) assert isinstance(y, %(typname)s) - return operator.%(opname)s(x, y) + func = opimpls[%(opname)r] + return func(x, y) + """ % locals()).compile() + for opname in 'is_true',: + assert opname in opimpls + exec py.code.Source(""" + def %(typname)s_%(opname)s(x): + assert isinstance(x, %(typname)s) + func = opimpls[%(opname)r] + return func(x) """ % locals()).compile() Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Tue Jun 14 20:38:12 2005 @@ -13,6 +13,9 @@ #t.view() t.checkgraphs() return t + +#__________________________________________________________________ +# tests def test_int_ops(): t = gengraph(number_ops, [int]) @@ -26,7 +29,23 @@ res = interp.eval_function(number_ops, [3.5]) assert res == 4.5 +def interpret(func, values): + t = gengraph(func, [type(x) for x in values]) + interp = LLInterpreter(t.flowgraphs) + res = interp.eval_function(func, values) + return res +def test_ifs(): + res = interpret(simple_ifs, [0]) + assert res == 43 + res = interpret(simple_ifs, [1]) + assert res == 42 + +def test_while_simple(): + res = interpret(while_simple, [3]) + assert res == 6 + + #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() @@ -37,6 +56,19 @@ m = k / 2 return m - 1 +def simple_ifs(i): + if i: + return 42 + else: + return 43 + +def while_simple(i): + sum = 0 + while i > 0: + sum += i + i -= 1 + return sum + #__________________________________________________________________ # interactive playing From arigo at codespeak.net Tue Jun 14 21:05:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 21:05:24 +0200 (CEST) Subject: [pypy-svn] r13405 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614190524.A72E127BCF@code1.codespeak.net> Author: arigo Date: Tue Jun 14 21:05:21 2005 New Revision: 13405 Modified: pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: rtuple fix, with test. First bug found by Holger's in-progress low-level interpreter :-) Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Tue Jun 14 21:05:21 2005 @@ -61,7 +61,7 @@ # Irregular operations. def newtuple(llops, r_tuple, items_v): - c1 = inputconst(Void, r_tuple.lowleveltype) + c1 = inputconst(Void, r_tuple.lowleveltype.TO) v_result = llops.genop('malloc', [c1], resulttype = r_tuple.lowleveltype) for i in range(len(r_tuple.items_r)): cname = inputconst(Void, r_tuple.fieldnames[i]) Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Tue Jun 14 21:05:21 2005 @@ -44,3 +44,8 @@ ## total += x ## return total ## rtype(dummyfn) + +def test_return_tuple(): + def dummyfn(x, y): + return (xy) + rtype(dummyfn, [int, int]).view() From arigo at codespeak.net Tue Jun 14 21:10:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 21:10:39 +0200 (CEST) Subject: [pypy-svn] r13406 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050614191039.0AA1C27BD2@code1.codespeak.net> Author: arigo Date: Tue Jun 14 21:10:36 2005 New Revision: 13406 Modified: pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/test/test_database.py Log: Fixed the representation of C constants for longs, unsigned longs, and chars. Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Tue Jun 14 21:10:36 2005 @@ -1,3 +1,4 @@ +import sys from pypy.rpython.lltype import * # ____________________________________________________________ @@ -5,20 +6,22 @@ # Primitives def name_signed(value): - return '%d' % value + if value == -sys.maxint-1: # blame C + return '(-%dL-1L)' % sys.maxint + else: + return '%dL' % value def name_unsigned(value): assert value >= 0 - return '%d' % value + return '%dUL' % value def name_float(value): return repr(value) def name_char(value): - value = value assert type(value) is str and len(value) == 1 if ' ' <= value < '\x7f': - return "'%s'" % (value.replace("'", r"\'"),) + return "'%s'" % (value.replace("'", r"\'").replace("\\", r"\\"),) else: return '%d' % ord(value) Modified: pypy/dist/pypy/translator/c/test/test_database.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_database.py (original) +++ pypy/dist/pypy/translator/c/test/test_database.py Tue Jun 14 21:10:36 2005 @@ -27,7 +27,7 @@ def test_primitive(): db = LowLevelDatabase() - assert db.get(5) == '5' + assert db.get(5) == '5L' assert db.get(True) == '1' def test_struct(): From arigo at codespeak.net Tue Jun 14 21:22:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 21:22:45 +0200 (CEST) Subject: [pypy-svn] r13407 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614192245.DE8E527BD9@code1.codespeak.net> Author: arigo Date: Tue Jun 14 21:22:37 2005 New Revision: 13407 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: Normalized the type of the exception-related data when catching it, in the same way as we normalized it when raising it. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jun 14 21:22:37 2005 @@ -178,12 +178,19 @@ r_case = rclass.get_type_repr(self) link.llexitcase = r_case.convert_const(link.exitcase) - for attr in ('last_exception', 'last_exc_value'): - a = getattr(link, attr) - if isinstance(a, Variable): - self.setconcretetype(a) - elif isinstance(a, Constant): - setattr(link, attr, self.typedconstant(a)) + a = link.last_exception + if isinstance(a, Variable): + a.concretetype = self.exceptiondata.lltype_of_exception_type + elif isinstance(a, Constant): + link.last_exception = self.typedconstant( + a, using_repr=self.exceptiondata.r_exception_type) + + a = link.last_exc_value + if isinstance(a, Variable): + a.concretetype = self.exceptiondata.lltype_of_exception_value + elif isinstance(a, Constant): + link.last_exc_value = self.typedconstant( + a, using_repr=self.exceptiondata.r_exception_value) inputargs_reprs = self.setup_block_entry(link.target) for i in range(len(link.args)): Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Tue Jun 14 21:22:37 2005 @@ -48,4 +48,4 @@ def test_return_tuple(): def dummyfn(x, y): return (xy) - rtype(dummyfn, [int, int]).view() + rtype(dummyfn, [int, int]) From arigo at codespeak.net Tue Jun 14 21:40:03 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 21:40:03 +0200 (CEST) Subject: [pypy-svn] r13408 - in pypy/dist/pypy/translator: c genc/test Message-ID: <20050614194003.86FCD27BD9@code1.codespeak.net> Author: arigo Date: Tue Jun 14 21:40:03 2005 New Revision: 13408 Modified: pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/genc/test/test_typed.py Log: Re-enabled old skipped tests, which work with the new genc. Shut up gcc warnings in case constant numbers are passed in OP_INT_FLOORDIV_OVF or OP_INT_MOD_OVF. Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Tue Jun 14 21:40:03 2005 @@ -106,7 +106,7 @@ #define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); #define OP_INT_FLOORDIV_OVF(x,y,r,err) \ - if ((long)(y) == -1 && (long)(x) < 0 && (long)(x) == -(long)(x)) \ + if ((long)(y) == -1 && (long)(x) < 0 && ((unsigned long)(x) << 1) == 0) \ FAIL_OVF(err, "integer division") \ OP_INT_FLOORDIV(x,y,r,err) @@ -123,7 +123,7 @@ #define OP_INT_MOD(x,y,r,err) op_divmod_adj(x, y, &r); #define OP_INT_MOD_OVF(x,y,r,err) \ - if ((long)(y) == -1 && (long)(x) < 0 && (long)x == -(long)(x)) \ + if ((long)(y) == -1 && (long)(x) < 0 && ((unsigned long)(x) << 1) == 0) \ FAIL_OVF(err, "integer modulo") \ OP_INT_MOD(x,y,r,err); Modified: pypy/dist/pypy/translator/genc/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/genc/test/test_typed.py (original) +++ pypy/dist/pypy/translator/genc/test/test_typed.py Tue Jun 14 21:40:03 2005 @@ -69,7 +69,7 @@ def test_int_overflow(self): fn = self.getcompiled(snippet.add_func) - raises(OverflowError, fn, sys_maxint()) + raises(OverflowError, fn, sys.maxint) def test_int_div_ovf_zer(self): # fn = self.getcompiled(snippet.div_func) @@ -94,10 +94,5 @@ fn = self.getcompiled(snippet.unary_func) for i in range(-3,3): assert fn(i) == (-(i), abs(i-1)) - raises (OverflowError, fn, -sys_maxint()-1) - raises (OverflowError, fn, -sys_maxint()) - -def sys_maxint(): - if sys.maxint != 2147483647: - py.test.skip("genc ovf incomplete: int might differ from long") - return sys.maxint + raises (OverflowError, fn, -sys.maxint-1) + raises (OverflowError, fn, -sys.maxint) From arigo at codespeak.net Tue Jun 14 21:44:15 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 21:44:15 +0200 (CEST) Subject: [pypy-svn] r13409 - in pypy/dist/pypy/translator: c/test genc/test Message-ID: <20050614194415.D685427BDA@code1.codespeak.net> Author: arigo Date: Tue Jun 14 21:44:09 2005 New Revision: 13409 Added: pypy/dist/pypy/translator/c/test/test_annotated.py - copied unchanged from r13408, pypy/dist/pypy/translator/genc/test/test_annotated.py pypy/dist/pypy/translator/c/test/test_lltyped.py - copied unchanged from r13408, pypy/dist/pypy/translator/genc/test/test_lltyped.py pypy/dist/pypy/translator/c/test/test_notype.py - copied unchanged from r13408, pypy/dist/pypy/translator/genc/test/test_notype.py pypy/dist/pypy/translator/c/test/test_operation.py - copied unchanged from r13408, pypy/dist/pypy/translator/genc/test/test_operation.py pypy/dist/pypy/translator/c/test/test_typed.py - copied unchanged from r13408, pypy/dist/pypy/translator/genc/test/test_typed.py Removed: pypy/dist/pypy/translator/genc/test/test_annotated.py pypy/dist/pypy/translator/genc/test/test_lltyped.py pypy/dist/pypy/translator/genc/test/test_notype.py pypy/dist/pypy/translator/genc/test/test_operation.py pypy/dist/pypy/translator/genc/test/test_typed.py Log: Moved the old genc tests into the new genc directory, now that they all pass with the new genc. Deleted: /pypy/dist/pypy/translator/genc/test/test_annotated.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/test_annotated.py Tue Jun 14 21:44:09 2005 +++ (empty file) @@ -1,130 +0,0 @@ -import autopath -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler -from pypy.translator.translator import Translator - -from pypy.translator.test import snippet - -# XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() - -class TestAnnotatedTestCase: - - def getcompiled(self, func): - t = Translator(func, simplifying=True) - # builds starting-types from func_defs - argstypelist = [] - if func.func_defaults: - for spec in func.func_defaults: - if isinstance(spec, tuple): - spec = spec[0] # use the first type only for the tests - argstypelist.append(spec) - a = t.annotate(argstypelist) - a.simplify() - return skip_missing_compiler(t.ccompile) - - def test_set_attr(self): - set_attr = self.getcompiled(snippet.set_attr) - assert set_attr() == 2 - - def test_inheritance2(self): - inheritance2 = self.getcompiled(snippet.inheritance2) - assert inheritance2() == ((-12, -12), (3, "world")) - - def test_factorial2(self): - factorial2 = self.getcompiled(snippet.factorial2) - assert factorial2(5) == 120 - - def test_factorial(self): - factorial = self.getcompiled(snippet.factorial) - assert factorial(5) == 120 - - def test_simple_method(self): - simple_method = self.getcompiled(snippet.simple_method) - assert simple_method(55) == 55 - - def test_sieve_of_eratosthenes(self): - sieve_of_eratosthenes = self.getcompiled(snippet.sieve_of_eratosthenes) - assert sieve_of_eratosthenes() == 1028 - - def test_nested_whiles(self): - nested_whiles = self.getcompiled(snippet.nested_whiles) - assert nested_whiles(5,3) == '!!!!!' - - def test_call_five(self): - call_five = self.getcompiled(snippet.call_five) - result = call_five() - assert result == [5] - # -- currently result isn't a real list, but a pseudo-array - # that can't be inspected from Python. - #self.assertEquals(result.__class__.__name__[:8], "list of ") - - def test_call_unpack_56(self): - call_unpack_56 = self.getcompiled(snippet.call_unpack_56) - result = call_unpack_56() - assert result == (2, 5, 6) - - def test_class_defaultattr(self): - class K: - n = "hello" - def class_defaultattr(): - k = K() - k.n += " world" - return k.n - fn = self.getcompiled(class_defaultattr) - assert fn() == "hello world" - - def test_tuple_repr(self): - def tuple_repr(x=int, y=object): - z = x, y - while x: - x = x-1 - return z - fn = self.getcompiled(tuple_repr) - assert fn(6,'a') == (6,'a') - - def test_classattribute(self): - fn = self.getcompiled(snippet.classattribute) - assert fn(1) == 123 - assert fn(2) == 456 - assert fn(3) == 789 - assert fn(4) == 789 - assert fn(5) == 101112 - - def test_get_set_del_slice(self): - fn = self.getcompiled(snippet.get_set_del_slice) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - - def test_slice_long(self): - def slice_long(l=list, n=long): - return l[:n] - fn = self.getcompiled(slice_long) - l = list('abc') - result = fn(l, 2**32) - assert result == list('abc') - result = fn(l, 2**64) - assert result == list('abc') - - def test_type_conversion(self): - # obfuscated test case specially for typer.insert_link_conversions() - def type_conversion(n=int): - if n > 3: - while n > 0: - n = n-1 - if n == 5: - n += 3.1416 - return n - fn = self.getcompiled(type_conversion) - assert fn(3) == 3 - assert fn(5) == 0 - assert abs(fn(7) + 0.8584) < 1E-5 - - def test_do_try_raise_choose(self): - fn = self.getcompiled(snippet.try_raise_choose) - result = [] - for n in [-1,0,1,2]: - result.append(fn(n)) - assert result == [-1,0,1,2] Deleted: /pypy/dist/pypy/translator/genc/test/test_lltyped.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/test_lltyped.py Tue Jun 14 21:44:09 2005 +++ (empty file) @@ -1,36 +0,0 @@ -from pypy.rpython.lltype import * -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler -from pypy.translator.translator import Translator - - -class TestLowLevelType: - objspacename = 'flow' - - def getcompiled(self, func, argstypelist=[]): - t = Translator(func, simplifying=True) - # builds starting-types from func_defs - a = t.annotate(argstypelist) - a.simplify() - t.specialize() - t.checkgraphs() - #t.view() - return skip_missing_compiler(t.ccompile) - - def test_simple(self): - S = GcStruct("s", ('v', Signed)) - def llf(): - s = malloc(S) - return s.v - fn = self.getcompiled(llf) - assert fn() == 0 - - def test_simple2(self): - S = Struct("s", ('v', Signed)) - S2 = GcStruct("s2", ('a',S), ('b',S)) - def llf(): - s = malloc(S2) - s.a.v = 6 - s.b.v = 12 - return s.a.v+s.b.v - fn = self.getcompiled(llf) - assert fn() == 18 Deleted: /pypy/dist/pypy/translator/genc/test/test_notype.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/test_notype.py Tue Jun 14 21:44:09 2005 +++ (empty file) @@ -1,216 +0,0 @@ -import autopath -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler -from pypy.translator.translator import Translator - -from pypy.translator.test import snippet - -# XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() - -class TestNoTypeCGenTestCase: - objspacename = 'flow' - - def build_cfunc(self, func, *morefuncs): - try: func = func.im_func - except AttributeError: pass - t = Translator(func) - for fn in morefuncs: - t.getflowgraph(fn) - t.simplify() - return skip_missing_compiler(t.ccompile) - - def test_simple_func(self): - cfunc = self.build_cfunc(snippet.simple_func) - assert cfunc(1) == 2 - - def test_while_func(self): - while_func = self.build_cfunc(snippet.while_func) - assert while_func(10) == 55 - - def test_nested_whiles(self): - nested_whiles = self.build_cfunc(snippet.nested_whiles) - assert nested_whiles(111, 114) == ( - '...!...!...!...!...!') - - def test_poor_man_range(self): - poor_man_range = self.build_cfunc(snippet.poor_man_range) - assert poor_man_range(10) == range(10) - - def poor_man_rev_range(self): - poor_man_rev_range = self.build_cfunc(snippet.poor_man_rev_range) - assert poor_man_rev_range(10) == range(9,-1,-1) - - def test_simple_id(self): - #we just want to see, if renaming of parameter works correctly - #if the first branch is the end branch - simple_id = self.build_cfunc(snippet.simple_id) - assert simple_id(9) == 9 - - def test_branch_id(self): - branch_id = self.build_cfunc(snippet.branch_id) - assert branch_id(1, 2, 3) == 2 - assert branch_id(0, 2, 3) == 3 - - def test_int_id(self): - int_id = self.build_cfunc(snippet.int_id) - assert int_id(3) == 3 - - def dont_test_attrs(self): - attrs = self.build_cfunc(snippet.attrs) - assert attrs() == 9 - - def test_builtinusage(self): - fun = self.build_cfunc(snippet.builtinusage) - assert fun() == 4 - - def test_sieve(self): - sieve = self.build_cfunc(snippet.sieve_of_eratosthenes) - assert sieve() == 1028 - - def test_slice(self): - half = self.build_cfunc(snippet.half_of_n) - assert half(10) == 5 - - def test_poly_branch(self): - poly_branch = self.build_cfunc(snippet.poly_branch) - assert poly_branch(10) == [1,2,3]*2 - assert poly_branch(0) == ['a','b','c']*2 - - def test_and(self): - sand = self.build_cfunc(snippet.s_and) - assert sand(5, 6) == "yes" - assert sand(5, 0) == "no" - assert sand(0, 6) == "no" - assert sand(0, 0) == "no" - - def test_yast(self): - yast = self.build_cfunc(snippet.yast) - assert yast([1000,100,10,1]) == 1111 - assert yast(range(100)) == (99*100)/2 - - def test_with_init(self): - with_init = self.build_cfunc(snippet.with_init) - assert with_init(0) == 0 - assert with_init(-100) == -100 - - def test_with_more_init(self): - with_more_init = self.build_cfunc(snippet.with_more_init) - assert with_more_init(10, False) == -10 - assert with_more_init(20, True) == 20 - - def test_global_instance(self): - global_instance = self.build_cfunc(snippet.global_instance) - assert global_instance() == 42 - - def test_global_newstyle_instance(self): - global_newstyle_instance = self.build_cfunc(snippet.global_newstyle_instance) - assert global_newstyle_instance().a == 1 - - def test_global_recursive_list(self): - global_recursive_list = self.build_cfunc(snippet.global_recursive_list) - lst = global_recursive_list() - assert len(lst) == 1 - assert lst[0] is lst - -## def test_global_badinit(self): -## global_badinit = self.build_cfunc(snippet.global_badinit) -## self.assertEquals(global_badinit(), 1) - - def test_multiple_inheritance(self): - multiple_inheritance = self.build_cfunc(snippet.multiple_inheritance) - assert multiple_inheritance() == 1+2+3+4 - - def test_call_star_args(self): - call_star_args = self.build_cfunc(snippet.call_star_args) - assert call_star_args(42) == 52 - - def test_call_default_args(self): - call_default_args = self.build_cfunc(snippet.call_default_args) - assert call_default_args(42) == 111+42+3 - - def test_call_default_and_star_args(self): - call_default_and_star_args = self.build_cfunc( - snippet.call_default_and_star_args) - assert call_default_and_star_args(42) == ( - (111+42+3+0, -1000-2000-3000+2)) - - def test_call_with_star(self): - call_with_star = self.build_cfunc(snippet.call_with_star) - assert call_with_star(()) == -15L - assert call_with_star((4,)) == -13L - assert call_with_star((4,7)) == -9L - assert call_with_star([]) == -15L - assert call_with_star([4]) == -13L - assert call_with_star([4,7]) == -9L - raises(TypeError, call_with_star, (4,7,12)) - raises(TypeError, call_with_star, [4,7,12,63]) - raises(TypeError, call_with_star, 521) - - def test_call_with_keyword(self): - call_with_keyword = self.build_cfunc(snippet.call_with_keyword) - assert call_with_keyword(100) == 82 - - def test_call_very_complex(self): - call_very_complex = self.build_cfunc(snippet.call_very_complex, - snippet.default_args) - assert call_very_complex(5, (3,), {}) == -12 - assert call_very_complex(5, (), {'y': 3}) == -12 - raises(TypeError, call_very_complex, 5, (3,), {'y': 4}) - - def test_finallys(self): - finallys = self.build_cfunc(snippet.finallys) - assert finallys(['hello']) == 8 - assert finallys('X') == 8 - assert finallys([]) == 6 - assert finallys('XY') == 6 - - def test_finally2(self): - finally2 = self.build_cfunc(snippet.finally2) - lst = range(10) - finally2(lst, 5) - assert lst == [0,1,2,3,4, 6, 6,7,8, 'done'] - dic = {} - raises(KeyError, finally2, dic, "won't find this key") - assert dic == {-1: 'done'} - - def test_bare_raise(self): - bare_raise = self.build_cfunc(snippet.bare_raise) - assert bare_raise(range(0, 100, 10), False) == 50 - assert bare_raise(range(0, 100, 10), True) == 50 - raises(IndexError, bare_raise, range(0, 30, 10), False) - assert bare_raise(range(0, 30, 10), True) == None - - def test_get_set_del_slice(self): - fn = self.build_cfunc(snippet.get_set_del_slice) - l = list('abcdefghij') - result = fn(l) - assert l == [3, 'c', 8, 11, 'h', 9] - assert result == ([3, 'c'], [9], [11, 'h']) - - def test_global_const_w_init(self): - fn = self.build_cfunc(snippet.one_thing1) - assert fn().thingness == 1 - - def test_global_const_w_new(self): - fn = self.build_cfunc(snippet.one_thing2) - assert fn() == 4 - - def test_direct_loop(self): - # check that remove_direct_loops() does its job correctly - def direct_loop(n, m): - x = False - while 1: - o = n; n = m; m = o - n -= 10 - if n < 0: - return n, x - x = True - fn = self.build_cfunc(direct_loop) - assert fn(117, 114) == (-6, True) - assert fn(117, 124) == (-3, True) - - def test_do_try_raise_choose(self): - fn = self.build_cfunc(snippet.do_try_raise_choose) - result = fn() - assert result == [-1,0,1,2] Deleted: /pypy/dist/pypy/translator/genc/test/test_operation.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/test_operation.py Tue Jun 14 21:44:09 2005 +++ (empty file) @@ -1,131 +0,0 @@ -import autopath -from pypy.objspace.flow.model import * -from pypy.objspace.flow.operation import FunctionByName -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler -from pypy.translator.translator import Translator - -# XXX this tries to make compiling faster for full-scale testing -from pypy.translator.tool import buildpyxmodule -buildpyxmodule.enable_fast_compilation() - - -TESTCASES = [ - ('is_', [], []), - ('id', False), - ('id', True), - ('type', 42), - ('issubtype', bool, int), - ('issubtype', int, int), - ('issubtype', int, bool), - ('repr', 'hi'), - ('repr', 42), - ('str', 'hi'), - ('str', 42), - ('len', [1,3,5,7]), - ('len', 'hello world'), - ('hash', 'hello world'), - ('pos', 42), - ('neg', 42), - ('nonzero', 42), - ('abs' , -42), - ('hex', 42), - ('oct', 42), - ('ord', '*'), - ('invert', 42), - ('add', 40, 2), - ('add', 'hello ', 'world'), - ('add', [1,3,5], [2,4]), - ('sub', 40, 2), - ('mul', 6, 7), - ('mul', [5], 4), - ('mul', 5, [4]), - ('truediv', 7, 2), - ('floordiv', 7, 2), - ('div', 7, 2), - ('mod', 7, 2), - ('divmod', 7, 2), - ('pow', 5, 2, 7), - ('lshift', 21, 1), - ('rshift', 21, 1), - ('and_', 21, 7), - ('or_', 21, 7), - ('xor', 21, 7), - ('int', 42.5), - ('float', 42), - ('inplace_add', 'hello ', 'world'), - ('inplace_sub', 32, 49), - ('inplace_mul', 41, 12), - ('inplace_truediv', 965, 22), - ('inplace_floordiv',847, 31), - ('inplace_div', 984, 12), - ('inplace_mod', 148, 20), - ('inplace_pow', 10, 6), - ('inplace_lshift', 9148, 3), - ('inplace_rshift', 1029, 2), - ('inplace_and', 18711, 98172), - ('inplace_or', 8722, 19837), - ('inplace_xor', 91487, 18320), - ('lt', 5, 7), - ('lt', 5, 5), - ('lt', 'hello', 'world'), - ('le', 5, 7), - ('le', 5, 5), - ('le', 'hello', 'world'), - ('eq', 5, 7), - ('eq', 5, 5), - ('eq', 'hello', 'world'), - ('ne', 5, 7), - ('ne', 5, 5), - ('ne', 'hello', 'world'), - ('gt', 5, 7), - ('gt', 5, 5), - ('gt', 'hello', 'world'), - ('ge', 5, 7), - ('ge', 5, 5), - ('ge', 'hello', 'world'), - ('cmp', 5, 7), - ('cmp', 5, 5), - ('cmp', 'hello', 'world'), - ('contains', [1,3,5,7], 4), - ('contains', [1,3,5,7], 5), - ] - -def operationtestfn(): - pass - - -class TestOperations: - objspacename = 'flow' - - def build_cfunc(self, graph): - t = Translator() - t.entrypoint = operationtestfn - t.functions.append(operationtestfn) - t.flowgraphs[operationtestfn] = graph - return skip_missing_compiler(t.ccompile) - - def test_operations(self): - expected = [] - resvars = [] - block = Block([]) - for testcase in TESTCASES: - opname = testcase[0] - args = testcase[1:] - op = SpaceOperation(opname, [Constant(x) for x in args], Variable()) - block.operations.append(op) - expected.append(FunctionByName[opname](*args)) - resvars.append(op.result) - op = SpaceOperation('newtuple', resvars, Variable()) - block.operations.append(op) - graph = FunctionGraph('operationtestfn', block) - block.closeblock(Link([op.result], graph.returnblock)) - - fn = self.build_cfunc(graph) - results = fn() - - assert len(results) == len(TESTCASES) - for testcase, expected, result in zip(TESTCASES, expected, results): - assert (type(expected) == type(result) and expected == result), ( - "%s(%s) computed %r instead of %r" % ( - testcase[0], ', '.join([repr(x) for x in testcase[1:]]), - result, expected)) Deleted: /pypy/dist/pypy/translator/genc/test/test_typed.py ============================================================================== --- /pypy/dist/pypy/translator/genc/test/test_typed.py Tue Jun 14 21:44:09 2005 +++ (empty file) @@ -1,98 +0,0 @@ -import autopath -import sys -import py.test -from pypy.translator.translator import Translator -from pypy.translator.test import snippet -from pypy.translator.tool.buildpyxmodule import skip_missing_compiler - -from pypy.translator.genc.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase - - -class TestTypedTestCase(_TestAnnotatedTestCase): - - def getcompiled(self, func): - t = Translator(func, simplifying=True) - # builds starting-types from func_defs - argstypelist = [] - if func.func_defaults: - for spec in func.func_defaults: - if isinstance(spec, tuple): - spec = spec[0] # use the first type only for the tests - argstypelist.append(spec) - a = t.annotate(argstypelist) - a.simplify() - t.specialize() - t.checkgraphs() - return skip_missing_compiler(t.ccompile) - - def test_call_five(self): - # -- the result of call_five() isn't a real list, but an rlist - # that can't be converted to a PyListObject - def wrapper(): - lst = snippet.call_five() - return len(lst), lst[0] - call_five = self.getcompiled(wrapper) - result = call_five() - assert result == (1, 5) - - def test_get_set_del_slice(self): - def get_set_del_nonneg_slice(): # no neg slices for now! - l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'] - del l[:1] - bound = len(l)-1 - if bound >= 0: - del l[bound:] - del l[2:4] - #l[:1] = [3] - #bound = len(l)-1 - #assert bound >= 0 - #l[bound:] = [9] no setting slice into lists for now - #l[2:4] = [8,11] - l[0], l[-1], l[2], l[3] = 3, 9, 8, 11 - - list_3_c = l[:2] - list_9 = l[5:] - list_11_h = l[3:5] - return (len(l), l[0], l[1], l[2], l[3], l[4], l[5], - len(list_3_c), list_3_c[0], list_3_c[1], - len(list_9), list_9[0], - len(list_11_h), list_11_h[0], list_11_h[1]) - fn = self.getcompiled(get_set_del_nonneg_slice) - result = fn() - assert result == (6, 3, 'c', 8, 11, 'h', 9, - 2, 3, 'c', - 1, 9, - 2, 11, 'h') - - def test_slice_long(self): - "the parent's test_slice_long() makes no sense here" - - def test_int_overflow(self): - fn = self.getcompiled(snippet.add_func) - raises(OverflowError, fn, sys.maxint) - - def test_int_div_ovf_zer(self): # - fn = self.getcompiled(snippet.div_func) - raises(OverflowError, fn, -1) - raises(ZeroDivisionError, fn, 0) - - def test_int_mod_ovf_zer(self): - fn = self.getcompiled(snippet.mod_func) - raises(OverflowError, fn, -1) - raises(ZeroDivisionError, fn, 0) - - def test_int_rshift_val(self): - fn = self.getcompiled(snippet.rshift_func) - raises(ValueError, fn, -1) - - def test_int_lshift_ovf_val(self): - fn = self.getcompiled(snippet.lshift_func) - raises(ValueError, fn, -1) - raises(OverflowError, fn, 1) - - def test_int_unary_ovf(self): - fn = self.getcompiled(snippet.unary_func) - for i in range(-3,3): - assert fn(i) == (-(i), abs(i-1)) - raises (OverflowError, fn, -sys.maxint-1) - raises (OverflowError, fn, -sys.maxint) From arigo at codespeak.net Tue Jun 14 21:45:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 21:45:01 +0200 (CEST) Subject: [pypy-svn] r13410 - pypy/dist/pypy/translator/genc Message-ID: <20050614194501.2DEF627BDE@code1.codespeak.net> Author: arigo Date: Tue Jun 14 21:44:59 2005 New Revision: 13410 Removed: pypy/dist/pypy/translator/genc/ Log: So long, and thanks for all the fish From arigo at codespeak.net Tue Jun 14 22:10:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 22:10:05 +0200 (CEST) Subject: [pypy-svn] r13411 - in pypy/dist/pypy: annotation rpython translator Message-ID: <20050614201005.603B027BDD@code1.codespeak.net> Author: arigo Date: Tue Jun 14 22:10:02 2005 New Revision: 13411 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/translator/simplify.py Log: Santitization: the operations inplace_xxx_ovf cannot really be produced anyway, so let's remove them entierely. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Tue Jun 14 22:10:02 2005 @@ -32,14 +32,12 @@ 'inplace_lshift', 'inplace_rshift', 'inplace_and', 'inplace_or', 'inplace_xor', 'lt', 'le', 'eq', 'ne', 'gt', 'ge', 'is_', 'cmp', - 'union', 'coerce', + 'coerce', ] +[opname+'_ovf' for opname in """add sub mul truediv floordiv div mod divmod pow lshift - inplace_add inplace_sub inplace_mul inplace_truediv - inplace_floordiv inplace_div inplace_mod inplace_pow - inplace_lshift""".split() + """.split() ]) for opname in BINARY_OPERATIONS: Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Tue Jun 14 22:10:02 2005 @@ -1,5 +1,6 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel +from pypy.objspace.flow.objspace import op_appendices from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -40,7 +41,6 @@ def rtype_add_ovf(_, hop): return _rtype_template(hop, 'add_ovf') - rtype_inplace_add_ovf = rtype_add_ovf def rtype_sub(_, hop): return _rtype_template(hop, 'sub') @@ -48,7 +48,6 @@ def rtype_sub_ovf(_, hop): return _rtype_template(hop, 'sub_ovf') - rtype_inplace_sub_ovf = rtype_sub_ovf def rtype_mul(_, hop): return _rtype_template(hop, 'mul') @@ -56,7 +55,6 @@ def rtype_mul_ovf(_, hop): return _rtype_template(hop, 'mul_ovf') - rtype_inplace_mul_ovf = rtype_mul_ovf def rtype_div(_, hop): return _rtype_template(hop, 'div', [ZeroDivisionError]) @@ -64,7 +62,6 @@ def rtype_div_ovf(_, hop): return _rtype_template(hop, 'div_ovf', [ZeroDivisionError]) - rtype_inplace_div_ovf = rtype_div_ovf def rtype_floordiv(_, hop): return _rtype_template(hop, 'floordiv', [ZeroDivisionError]) @@ -72,7 +69,6 @@ def rtype_floordiv_ovf(_, hop): return _rtype_template(hop, 'floordiv_ovf', [ZeroDivisionError]) - rtype_inplace_floordiv_ovf = rtype_floordiv_ovf def rtype_truediv(_, hop): return _rtype_template(hop, 'truediv', [ZeroDivisionError]) @@ -80,7 +76,6 @@ def rtype_truediv_ovf(_, hop): return _rtype_template(hop, 'truediv_ovf', [ZeroDivisionError]) - rtype_inplace_truediv_ovf = rtype_truediv_ovf def rtype_mod(_, hop): return _rtype_template(hop, 'mod', [ZeroDivisionError]) @@ -88,7 +83,6 @@ def rtype_mod_ovf(_, hop): return _rtype_template(hop, 'mod_ovf', [ZeroDivisionError]) - rtype_inplace_mod_ovf = rtype_mod_ovf def rtype_xor(_, hop): return _rtype_template(hop, 'xor') @@ -108,7 +102,6 @@ def rtype_lshift_ovf(_, hop): return _rtype_template(hop, 'lshift_ovf', [ValueError]) - rtype_inplace_lshift_ovf = rtype_lshift_ovf def rtype_rshift(_, hop): return _rtype_template(hop, 'rshift', [ValueError]) @@ -139,9 +132,6 @@ def rtype_inplace_pow(_, hop): return _rtype_template(hop, 'pow', [ZeroDivisionError]) - def rtype_inplace_pow_ovf(_, hop): - return _rtype_template(hop, 'pow_ovf', [ZeroDivisionError]) - #comparisons: eq is_ ne lt le gt ge def rtype_eq(_, hop): @@ -170,7 +160,12 @@ func1 = func for implicit_exc in implicit_excs: if hop.has_implicit_exception(implicit_exc): - func += '_' + implicit_exc.__name__[:3].lower() + for appendix, klass in op_appendices.items(): + if klass is implicit_exc: + break + else: + raise ValueError("can't find implicit exc %r" % (implicit_exc,)) + func += '_' + appendix if hop.s_result.unsigned: if func1.endswith('_ovf'): raise TyperError("forbidden uint_" + func) Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Tue Jun 14 22:10:02 2005 @@ -52,7 +52,7 @@ Example: try: - ovfcheck(array1[idx-1] += array2[idx+1]) + array1[idx-1] = ovfcheck(array1[idx-1] + array2[idx+1]) except OverflowError: ... From arigo at codespeak.net Tue Jun 14 22:53:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 22:53:53 +0200 (CEST) Subject: [pypy-svn] r13412 - pypy/dist/pypy/translator/c/test Message-ID: <20050614205353.71D2D27BE0@code1.codespeak.net> Author: arigo Date: Tue Jun 14 22:53:43 2005 New Revision: 13412 Modified: pypy/dist/pypy/translator/c/test/test_typed.py Log: Oups. Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Tue Jun 14 22:53:43 2005 @@ -5,7 +5,7 @@ from pypy.translator.test import snippet from pypy.translator.tool.buildpyxmodule import skip_missing_compiler -from pypy.translator.genc.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase +from pypy.translator.c.test.test_annotated import TestAnnotatedTestCase as _TestAnnotatedTestCase class TestTypedTestCase(_TestAnnotatedTestCase): From arigo at codespeak.net Tue Jun 14 22:57:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 22:57:25 +0200 (CEST) Subject: [pypy-svn] r13413 - pypy/dist/pypy/rpython Message-ID: <20050614205725.9E47027BE2@code1.codespeak.net> Author: arigo Date: Tue Jun 14 22:57:25 2005 New Revision: 13413 Modified: pypy/dist/pypy/rpython/rint.py Log: Oups again: the op_appendices mapping goes in the other direction. Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Tue Jun 14 22:57:25 2005 @@ -160,11 +160,7 @@ func1 = func for implicit_exc in implicit_excs: if hop.has_implicit_exception(implicit_exc): - for appendix, klass in op_appendices.items(): - if klass is implicit_exc: - break - else: - raise ValueError("can't find implicit exc %r" % (implicit_exc,)) + appendix = op_appendices[implicit_exc] func += '_' + appendix if hop.s_result.unsigned: if func1.endswith('_ovf'): From arigo at codespeak.net Tue Jun 14 23:00:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 14 Jun 2005 23:00:36 +0200 (CEST) Subject: [pypy-svn] r13414 - in pypy/dist/pypy: annotation objspace/flow rpython Message-ID: <20050614210036.2014227BD0@code1.codespeak.net> Author: arigo Date: Tue Jun 14 23:00:32 2005 New Revision: 13414 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/objspace/flow/objspace.py pypy/dist/pypy/objspace/flow/operation.py pypy/dist/pypy/rpython/rint.py Log: Added is_true and xxx_ovf operations in the table of flow/operation.py. Some more simplifications about which _ovf operations can exist: indeed, it's not possible to use the ovfcheck(a b) syntax with the following operations: divmod inplace_* Moreover, 'invert' can never raise OverflowError in any case, and neither can 'truediv' with integer arguments. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Tue Jun 14 23:00:32 2005 @@ -35,8 +35,7 @@ 'coerce', ] +[opname+'_ovf' for opname in - """add sub mul truediv - floordiv div mod divmod pow lshift + """add sub mul floordiv div mod pow lshift """.split() ]) Modified: pypy/dist/pypy/objspace/flow/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/flow/objspace.py (original) +++ pypy/dist/pypy/objspace/flow/objspace.py Tue Jun 14 23:00:32 2005 @@ -465,11 +465,12 @@ inplace_add inplace_sub inplace_mul inplace_truediv inplace_floordiv inplace_div inplace_mod inplace_divmod inplace_pow""", FloatingPointError) -_add_except_ovf("""neg abs invert add sub mul truediv - floordiv div mod divmod pow lshift +_add_exceptions("""truediv divmod inplace_add inplace_sub inplace_mul inplace_truediv inplace_floordiv inplace_div inplace_mod inplace_pow - inplace_lshift""") + inplace_lshift""", OverflowError) # without a _ovf version +_add_except_ovf("""neg abs add sub mul + floordiv div mod pow lshift""") # with a _ovf version del _add_exceptions, _add_except_ovf def extract_cell_content(c): Modified: pypy/dist/pypy/objspace/flow/operation.py ============================================================================== --- pypy/dist/pypy/objspace/flow/operation.py (original) +++ pypy/dist/pypy/objspace/flow/operation.py Tue Jun 14 23:00:32 2005 @@ -5,6 +5,7 @@ from pypy.interpreter.baseobjspace import ObjSpace import operator, types, __future__ from pypy.tool.sourcetools import compile2 +from pypy.rpython.rarithmetic import ovfcheck, ovfcheck_lshift FunctionByName = {} # dict {"operation_name": } OperationName = {} # dict {: "operation_name"} @@ -100,6 +101,36 @@ def userdel(x): x.__del__() +def neg_ovf(x): + return ovfcheck(-x) + +def abs_ovf(x): + return ovfcheck(abs(x)) + +def add_ovf(x, y): + return ovfcheck(x + y) + +def sub_ovf(x, y): + return ovfcheck(x - y) + +def mul_ovf(x, y): + return ovfcheck(x * y) + +def floordiv_ovf(x, y): + return ovfcheck(operator.floordiv(x, y)) + +def div_ovf(x, y): + return ovfcheck(operator.div(x, y)) + +def mod_ovf(x, y): + return ovfcheck(x % y) + +def pow_ovf(*two_or_three_args): + return ovfcheck(pow(*two_or_three_args)) + +def lshift_ovf(x, y): + return ovfcheck_lshift(x, y) + # ____________________________________________________________ # The following table can list several times the same operation name, @@ -122,6 +153,8 @@ ('delattr', delattr), ('nonzero', bool), ('nonzero', operator.truth), + ('is_true', bool), + ('is_true', operator.truth), ('abs' , abs), ('hex', hex), ('oct', oct), @@ -152,6 +185,17 @@ ('set', set), ('delete', delete), ('userdel', userdel), + # --- operations added by graph transformations --- + ('neg_ovf', neg_ovf), + ('abs_ovf', abs_ovf), + ('add_ovf', add_ovf), + ('sub_ovf', sub_ovf), + ('mul_ovf', mul_ovf), + ('floordiv_ovf', floordiv_ovf), + ('div_ovf', div_ovf), + ('mod_ovf', mod_ovf), + ('pow_ovf', pow_ovf), + ('lshift_ovf', lshift_ovf), ] def setup(): @@ -166,8 +210,8 @@ for name, func in Table: if name not in FunctionByName: FunctionByName[name] = func - assert func not in OperationName - OperationName[func] = name + if func not in OperationName: + OperationName[func] = name # check that the result is complete for line in ObjSpace.MethodTable: name = line[0] Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Tue Jun 14 23:00:32 2005 @@ -74,9 +74,6 @@ return _rtype_template(hop, 'truediv', [ZeroDivisionError]) rtype_inplace_truediv = rtype_truediv - def rtype_truediv_ovf(_, hop): - return _rtype_template(hop, 'truediv_ovf', [ZeroDivisionError]) - def rtype_mod(_, hop): return _rtype_template(hop, 'mod', [ZeroDivisionError]) rtype_inplace_mod = rtype_mod From arigo at codespeak.net Wed Jun 15 00:20:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 00:20:16 +0200 (CEST) Subject: [pypy-svn] r13418 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050614222016.639B527BE9@code1.codespeak.net> Author: arigo Date: Wed Jun 15 00:20:14 2005 New Revision: 13418 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/translator/test/test_annrpython.py Log: A couple of bug fixes to the annotator. The exact bugs they fix are not easily described. See the two new tests, basically. Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Wed Jun 15 00:20:14 2005 @@ -28,9 +28,13 @@ def getvalue(self): while self.sources: - source, classdef = self.sources.popitem() + source, classdef = self.sources.iteritems().next() s_value = self.bookkeeper.immutablevalue( source.__dict__[self.name]) + # warning: 'source' should not be removed from the dict before + # immutablevalue() finished, because the latter can move attrdefs + # around and this would gets this source lost + del self.sources[source] if classdef: s_value = s_value.bindcallables(classdef) self.s_value = tracking_unionof(self, self.s_value, s_value) @@ -123,11 +127,13 @@ self.attr_mutated(homedef, attrdef) def locate_attribute(self, attr): - for cdef in self.getmro(): - if attr in cdef.attrs: - return cdef - self.generalize_attr(attr) - return self + while True: + for cdef in self.getmro(): + if attr in cdef.attrs: + return cdef + self.generalize_attr(attr) + # the return value will likely be 'self' now, but not always -- see + # test_annrpython.test_attr_moving_from_subclass_to_class_to_parent def find_attribute(self, attr): return self.locate_attribute(attr).attrs[attr] @@ -203,7 +209,6 @@ break else: self._generalize_attr(attr, s_value) - assert attr in self.attrs def about_attribute(self, name): """This is the interface for the code generators to ask about Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jun 15 00:20:14 2005 @@ -1264,6 +1264,39 @@ s = a.build_types(f, [int]*8) assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 8) + def test_attr_moving_into_parent(self): + class A: pass + class B(A): pass + a1 = A() + b1 = B() + b1.stuff = a1 + a1.stuff = None + def f(): + return b1.stuff + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInstance) + assert s.can_be_None + assert s.classdef.cls is A + + def test_attr_moving_from_subclass_to_class_to_parent(self): + class A: pass + class B(A): pass + class C(B): pass + a1 = A() + a1.stuff = None + c1 = C() + c1.stuff = a1 + def f(): + b = B() + b.consider_me = c1 + return b.stuff + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInstance) + assert s.can_be_None + assert s.classdef.cls is A + def g(n): return [0,1,2,n] From arigo at codespeak.net Wed Jun 15 01:01:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 01:01:23 +0200 (CEST) Subject: [pypy-svn] r13419 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050614230123.B4C3E27BED@code1.codespeak.net> Author: arigo Date: Wed Jun 15 01:01:21 2005 New Revision: 13419 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/translator/test/test_annrpython.py Log: Another bug fix: a 'del sources[key]' where the key might have been removed under our feet in the meantime. Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Wed Jun 15 01:01:21 2005 @@ -34,7 +34,10 @@ # warning: 'source' should not be removed from the dict before # immutablevalue() finished, because the latter can move attrdefs # around and this would gets this source lost - del self.sources[source] + try: + del self.sources[source] + except KeyError: + pass if classdef: s_value = s_value.bindcallables(classdef) self.s_value = tracking_unionof(self, self.s_value, s_value) Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jun 15 01:01:21 2005 @@ -1297,6 +1297,20 @@ assert s.can_be_None assert s.classdef.cls is A + def test_attr_recursive_getvalue(self): + class A: pass + a2 = A() + a2.stuff = None + a1 = A() + a1.stuff = a2 + def f(): + return a1.stuff + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeInstance) + assert s.can_be_None + assert s.classdef.cls is A + def g(n): return [0,1,2,n] From hpk at codespeak.net Wed Jun 15 01:09:34 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 15 Jun 2005 01:09:34 +0200 (CEST) Subject: [pypy-svn] r13420 - in pypy/dist/pypy/rpython: . test Message-ID: <20050614230934.79D1927BF3@code1.codespeak.net> Author: hpk Date: Wed Jun 15 01:09:33 2005 New Revision: 13420 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/rrange.py pypy/dist/pypy/rpython/test/test_interp.py Log: - some more number operations - start to use py.log functionality (don't use that at home though) - random fixes to rrange.py discovered while playing around with a yet disabled test Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Wed Jun 15 01:09:33 2005 @@ -1,8 +1,11 @@ from pypy.rpython.lltype import * +import py class LLInterpreter(object): """ low level interpreter working with concrete values. """ + log = py.log.Producer('llinterp') + def __init__(self, flowgraphs): self.flowgraphs = flowgraphs self.bindings = {} @@ -29,6 +32,18 @@ return self.bindings[varorconst] # _______________________________________________________ + # other helpers + def getoperationhandler(self, opname): + try: + return getattr(self, 'op_' + opname) + except AttributeError: + g = globals() + assert opname in g, ( + "cannot handle operation %r yet" %(opname,)) + ophandler = g[opname] + return ophandler + + # _______________________________________________________ # evaling functions def eval_function(self, func, args=()): @@ -50,8 +65,10 @@ # determine nextblock and/or return value if len(block.exits) == 0: # return block - resvar, = block.getvariables() - return None, self.getval(resvar) + resultvar, = block.getvariables() + result = self.getval(resultvar) + self.log.operation("returning", result) + return None, result elif len(block.exits) == 1: index = 0 else: @@ -60,28 +77,33 @@ return link.target, [self.getval(x) for x in link.args] def eval_operation(self, operation): - g = globals() - opname = operation.opname - print "considering", operation - assert opname in g, ( - "cannot handle operation %r yet" %(opname,)) - ophandler = g[opname] + self.log.operation("considering", operation) + ophandler = self.getoperationhandler(operation.opname) vals = [self.getval(x) for x in operation.args] retval = ophandler(*vals) self.setvar(operation.result, retval) -############################## + # __________________________________________________________ + # misc LL operation implementations + + def op_same_as(self, x): + return x + + def op_setfield(self, obj, fieldname, fieldvalue): + # obj should be pointer + setattr(obj, fieldname, fieldvalue) # is that right? + + +# __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName opimpls = FunctionByName.copy() opimpls['is_true'] = bool -def same_as(x): - return x - for typ in (float, int): typname = typ.__name__ - for opname in 'add', 'sub', 'mul', 'div', 'gt', 'lt': + for opname in ('add', 'sub', 'mul', 'div', 'gt', 'lt', + 'ge', 'ne', 'le', 'eq'): assert opname in opimpls exec py.code.Source(""" def %(typname)s_%(opname)s(x, y): @@ -98,3 +120,4 @@ func = opimpls[%(opname)r] return func(x) """ % locals()).compile() + Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Wed Jun 15 01:09:33 2005 @@ -33,8 +33,8 @@ class __extend__(pairtype(RangeRepr, IntegerRepr)): def rtype_getitem((r_rng, r_int), hop): - v_lst, v_index = hop.inputargs(r_lst, Signed) - cstep = hop.inputconst(Signed, self.step) + v_lst, v_index = hop.inputargs(r_rng, Signed) + cstep = hop.inputconst(Signed, r_rng.step) if hop.args_s[1].nonneg: llfn = ll_rangeitem_nonneg else: Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Wed Jun 15 01:09:33 2005 @@ -14,27 +14,23 @@ t.checkgraphs() return t +def interpret(func, values): + t = gengraph(func, [type(x) for x in values]) + interp = LLInterpreter(t.flowgraphs) + res = interp.eval_function(func, values) + return res + #__________________________________________________________________ # tests def test_int_ops(): - t = gengraph(number_ops, [int]) - interp = LLInterpreter(t.flowgraphs) - res = interp.eval_function(number_ops, [3]) + res = interpret(number_ops, [3]) assert res == 4 def test_float_ops(): - t = gengraph(number_ops, [float]) - interp = LLInterpreter(t.flowgraphs) - res = interp.eval_function(number_ops, [3.5]) + res = interpret(number_ops, [3.5]) assert res == 4.5 -def interpret(func, values): - t = gengraph(func, [type(x) for x in values]) - interp = LLInterpreter(t.flowgraphs) - res = interp.eval_function(func, values) - return res - def test_ifs(): res = interpret(simple_ifs, [0]) assert res == 43 @@ -44,7 +40,21 @@ def test_while_simple(): res = interpret(while_simple, [3]) assert res == 6 - + +def test_number_comparisons(): + for t in float, int: + val1 = t(3) + val2 = t(4) + gcres = interpret(comparisons, [val1, val2]) + res = [getattr(gcres._obj0, x) for x in gcres._obj0._TYPE._names] + assert res == [True, True, False, True, False, False] + +def XXXtest_some_builtin(): + def f(i, j): + x = range(i) + return x[j] + res = interpret(f, [10, 7]) + assert res == 6 #__________________________________________________________________ # example functions for testing the LLInterpreter @@ -56,6 +66,17 @@ m = k / 2 return m - 1 +def comparisons(x, y): + return (x < y, + x <= y, + x == y, + x != y, + #x is None, + #x is not None, + x >= y, + x > y, + ) + def simple_ifs(i): if i: return 42 From pedronis at codespeak.net Wed Jun 15 02:05:43 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 02:05:43 +0200 (CEST) Subject: [pypy-svn] r13421 - pypy/dist/pypy/annotation Message-ID: <20050615000543.AB67B27BBF@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 02:05:42 2005 New Revision: 13421 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: immutablevalue for lists and dicts was not guarding for recursion adequately Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Wed Jun 15 02:05:42 2005 @@ -180,18 +180,21 @@ try: return self.immutable_cache[id(x)] except KeyError: - items_s = [self.immutablevalue(e) for e in x] - result = SomeList(ListDef(self, unionof(*items_s))) + result = SomeList(ListDef(self, SomeImpossibleValue())) self.immutable_cache[id(x)] = result + for e in x: + result.listdef.generalize(self.immutablevalue(e)) elif tp is dict: # exactly a dict try: return self.immutable_cache[id(x)] except KeyError: - keys_s = [self.immutablevalue(e) for e in x.keys()] - values_s = [self.immutablevalue(e) for e in x.values()] - result = SomeDict(DictDef(self, unionof(*keys_s), - unionof(*values_s))) + result = SomeDict(DictDef(self, + SomeImpossibleValue(), + SomeImpossibleValue())) self.immutable_cache[id(x)] = result + for ek, ev in e.iteritems(): + result.dictdef.generalize_key(immutablevalue(ek)) + result.dictdef.generalize_key(immutablevalue(ek)) elif ishashable(x) and x in BUILTIN_ANALYZERS: result = SomeBuiltin(BUILTIN_ANALYZERS[x]) elif isinstance(x, lltype._ptr): From pedronis at codespeak.net Wed Jun 15 02:17:25 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 02:17:25 +0200 (CEST) Subject: [pypy-svn] r13422 - pypy/dist/pypy/annotation Message-ID: <20050615001725.684FC27BBF@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 02:17:23 2005 New Revision: 13422 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: oops Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Wed Jun 15 02:17:23 2005 @@ -192,9 +192,9 @@ SomeImpossibleValue(), SomeImpossibleValue())) self.immutable_cache[id(x)] = result - for ek, ev in e.iteritems(): - result.dictdef.generalize_key(immutablevalue(ek)) - result.dictdef.generalize_key(immutablevalue(ek)) + for ek, ev in x.iteritems(): + result.dictdef.generalize_key(self.immutablevalue(ek)) + result.dictdef.generalize_key(self.immutablevalue(ek)) elif ishashable(x) and x in BUILTIN_ANALYZERS: result = SomeBuiltin(BUILTIN_ANALYZERS[x]) elif isinstance(x, lltype._ptr): From arigo at codespeak.net Wed Jun 15 02:19:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 02:19:09 +0200 (CEST) Subject: [pypy-svn] r13423 - pypy/dist/pypy/translator/test Message-ID: <20050615001909.5F94E27B58@code1.codespeak.net> Author: arigo Date: Wed Jun 15 02:19:07 2005 New Revision: 13423 Modified: pypy/dist/pypy/translator/test/test_annrpython.py Log: A test for pedronis' last check-in. Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jun 15 02:19:07 2005 @@ -1311,6 +1311,22 @@ assert s.can_be_None assert s.classdef.cls is A + def test_long_list_recursive_getvalue(self): + class A: pass + lst = [] + for i in range(500): + a1 = A() + a1.stuff = lst + lst.append(a1) + def f(): + A().stuff = None + return (A().stuff, lst)[1] + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeList) + s_item = s.listdef.listitem.s_value + assert isinstance(s_item, annmodel.SomeInstance) + def g(n): return [0,1,2,n] From pedronis at codespeak.net Wed Jun 15 02:21:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 02:21:28 +0200 (CEST) Subject: [pypy-svn] r13424 - pypy/dist/pypy/annotation Message-ID: <20050615002128.7EF1727BC2@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 02:21:27 2005 New Revision: 13424 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: oops 2 Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Wed Jun 15 02:21:27 2005 @@ -194,7 +194,7 @@ self.immutable_cache[id(x)] = result for ek, ev in x.iteritems(): result.dictdef.generalize_key(self.immutablevalue(ek)) - result.dictdef.generalize_key(self.immutablevalue(ek)) + result.dictdef.generalize_value(self.immutablevalue(ev)) elif ishashable(x) and x in BUILTIN_ANALYZERS: result = SomeBuiltin(BUILTIN_ANALYZERS[x]) elif isinstance(x, lltype._ptr): From arigo at codespeak.net Wed Jun 15 02:22:41 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 02:22:41 +0200 (CEST) Subject: [pypy-svn] r13425 - pypy/dist/pypy/translator/test Message-ID: <20050615002241.5EF9527BC2@code1.codespeak.net> Author: arigo Date: Wed Jun 15 02:22:39 2005 New Revision: 13425 Modified: pypy/dist/pypy/translator/test/test_annrpython.py Log: Testing immutable pre-built dictionaries. (or: another test for pedronis' other last check-in) Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jun 15 02:22:39 2005 @@ -1327,6 +1327,15 @@ s_item = s.listdef.listitem.s_value assert isinstance(s_item, annmodel.SomeInstance) + def test_immutable_dict(self): + d = {4: "hello", + 5: "world"} + def f(n): + return d[n] + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert isinstance(s, annmodel.SomeString) + def g(n): return [0,1,2,n] From arigo at codespeak.net Wed Jun 15 02:26:00 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 02:26:00 +0200 (CEST) Subject: [pypy-svn] r13426 - pypy/dist/pypy/translator/test Message-ID: <20050615002600.079AF27BC2@code1.codespeak.net> Author: arigo Date: Wed Jun 15 02:25:58 2005 New Revision: 13426 Modified: pypy/dist/pypy/translator/test/test_annrpython.py Log: A test for prebuilt lists that are self-recursive. Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jun 15 02:25:58 2005 @@ -1336,6 +1336,18 @@ s = a.build_types(f, [int]) assert isinstance(s, annmodel.SomeString) + def test_immutable_recursive_list(self): + l = [] + l.append(l) + def f(): + return l + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeList) + s_item = s.listdef.listitem.s_value + assert isinstance(s_item, annmodel.SomeList) + assert s_item.listdef.same_as(s.listdef) + def g(n): return [0,1,2,n] From pedronis at codespeak.net Wed Jun 15 03:04:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 03:04:54 +0200 (CEST) Subject: [pypy-svn] r13427 - pypy/dist/pypy/translator Message-ID: <20050615010454.0970627BB2@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 03:04:53 2005 New Revision: 13427 Modified: pypy/dist/pypy/translator/transform.py Log: passing around a dict block_subset. fixing quadratic behavior introduced by mistake for transfrom_dead_op_vars Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Wed Jun 15 03:04:53 2005 @@ -170,7 +170,11 @@ if ann.translator: ann.translator.checkgraphs() if block_subset is None: - block_subset = list(fully_annotated_blocks(ann)) + block_subset = fully_annotated_blocks(ann) + d = {} + for block in block_subset: + d[block] = True + block_subset = d transform_dead_code(ann, block_subset) for pass_ in extra_passes: pass_(ann, block_subset) From pedronis at codespeak.net Wed Jun 15 04:09:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 04:09:28 +0200 (CEST) Subject: [pypy-svn] r13428 - pypy/dist/pypy/translator/c Message-ID: <20050615020928.1792A27BA6@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 04:09:26 2005 New Revision: 13428 Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/g_exception.h Log: avoid leaking exc values when converting to CPython exceptions Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Wed Jun 15 04:09:26 2005 @@ -147,6 +147,13 @@ if node.globalcontainer: yield node + def get_lltype_of_exception_value(self): + if self.translator is not None and self.translator.rtyper is not None: + exceptiondata = self.translator.rtyper.getexceptiondata() + return exceptiondata.lltype_of_exception_value + else: + return Ptr(PyObject) + def pre_include_code_lines(self): # generate some #defines that go before the #include to control # what g_exception.h does Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Wed Jun 15 04:09:26 2005 @@ -91,12 +91,20 @@ raise TypeError, "expr(%r)" % (v,) def error_return_value(self): + returnlltype = self.lltypemap(self.graph.getreturnvar()) + return self.db.get(ErrorValue(returnlltype)) + + def return_with_error(self): if self.cpython_exc: + lltype_of_exception_value = self.db.get_lltype_of_exception_value(); + exc_value_typename = self.db.gettype(lltype_of_exception_value) assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr - return 'ConvertExceptionToCPython()' - else: - returnlltype = self.lltypemap(self.graph.getreturnvar()) - return self.db.get(ErrorValue(returnlltype)) + yield '{' + yield '\t%s;' % cdecl(exc_value_typename, 'vanishing_exc_value') + yield '\tConvertExceptionToCPython(vanishing_exc_value);' + yield '\t%s' % self.db.cdecrefstmt('vanishing_exc_value', lltype_of_exception_value) + yield '}' + yield 'return %s; ' % self.error_return_value() # ____________________________________________________________ @@ -191,7 +199,8 @@ exc_cls = self.expr(block.inputargs[0]) exc_value = self.expr(block.inputargs[1]) yield 'RaiseException(%s, %s);' % (exc_cls, exc_value) - yield 'return %s;' % self.error_return_value() + for line in self.return_with_error(): + yield line else: # regular return block retval = self.expr(block.inputargs[0]) @@ -287,7 +296,8 @@ yield 'err%d_%d:' % (blocknum[block], len(to_release)) err_reachable = True if err_reachable: - yield 'return %s;' % self.error_return_value() + for line in self.return_with_error(): + yield line # ____________________________________________________________ Modified: pypy/dist/pypy/translator/c/g_exception.h ============================================================================== --- pypy/dist/pypy/translator/c/g_exception.h (original) +++ pypy/dist/pypy/translator/c/g_exception.h Wed Jun 15 04:09:26 2005 @@ -40,7 +40,7 @@ rpython_exc_type = RPYTHON_TYPE_OF_EXC_INST(rpython_exc_value); } -static PyObject *ConvertExceptionToCPython(void) +static void _ConvertExceptionToCPython(void) { /* XXX 1. uses officially bad fishing */ /* XXX 2. looks for exception classes by name, fragile */ @@ -57,11 +57,15 @@ else { PyErr_SetString(RPythonError, clsname); } - rpython_exc_type = NULL; /* XXX leaks! */ - rpython_exc_value = NULL; - return NULL; } +#define ConvertExceptionToCPython(vanishing) \ + _ConvertExceptionToCPython(); \ + vanishing = rpython_exc_value; \ + rpython_exc_type = NULL; \ + rpython_exc_value = NULL; + + #define RaiseSimpleException(exc, msg) \ /* XXX 1. uses officially bad fishing */ \ /* XXX 2. msg is ignored */ \ @@ -86,7 +90,7 @@ } #define MatchException(etype) PyErr_ExceptionMatches(etype) #define ConvertExceptionFromCPython() /* nothing */ -#define ConvertExceptionToCPython() NULL +#define ConvertExceptionToCPython(vanishing) vanishing = NULL #define RaiseSimpleException(exc, msg) \ PyErr_SetString(Py##exc, msg) /* pun */ From arigo at codespeak.net Wed Jun 15 13:07:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 13:07:22 +0200 (CEST) Subject: [pypy-svn] r13433 - pypy/dist/pypy/translator/c Message-ID: <20050615110722.77FDD27B68@code1.codespeak.net> Author: arigo Date: Wed Jun 15 13:07:21 2005 New Revision: 13433 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: This is what you get for playing with C too much ;-) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Wed Jun 15 13:07:21 2005 @@ -96,7 +96,7 @@ def return_with_error(self): if self.cpython_exc: - lltype_of_exception_value = self.db.get_lltype_of_exception_value(); + lltype_of_exception_value = self.db.get_lltype_of_exception_value() exc_value_typename = self.db.gettype(lltype_of_exception_value) assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr yield '{' From arigo at codespeak.net Wed Jun 15 15:36:15 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 15:36:15 +0200 (CEST) Subject: [pypy-svn] r13438 - pypy/dist/pypy/translator/c Message-ID: <20050615133615.17C1327B71@code1.codespeak.net> Author: arigo Date: Wed Jun 15 15:36:13 2005 New Revision: 13438 Modified: pypy/dist/pypy/translator/c/node.py Log: Fix for some C compilers (VC++) pointed out by Ben Young. Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Wed Jun 15 15:36:13 2005 @@ -276,7 +276,7 @@ yield '{' if needs_refcount(self.T): yield '\t1,' - if self.T.OF == Void: + if self.T.OF == Void or len(self.obj.items) == 0: yield '\t%d' % len(self.obj.items) yield '}' else: From ale at codespeak.net Wed Jun 15 15:41:52 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 15 Jun 2005 15:41:52 +0200 (CEST) Subject: [pypy-svn] r13439 - in pypy/dist/pypy/rpython: . test Message-ID: <20050615134152.70AF927B70@code1.codespeak.net> Author: ale Date: Wed Jun 15 15:41:51 2005 New Revision: 13439 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: trying to understand the llinterpreter. Added a simpel test for list behaviour. Added op_malloc, op-getarraystruct, op_mallocvarsize, op_directcall Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Wed Jun 15 15:41:51 2005 @@ -4,7 +4,7 @@ class LLInterpreter(object): """ low level interpreter working with concrete values. """ - log = py.log.Producer('llinterp') +# log = py.log.Producer('llinterp') def __init__(self, flowgraphs): self.flowgraphs = flowgraphs @@ -67,7 +67,7 @@ # return block resultvar, = block.getvariables() result = self.getval(resultvar) - self.log.operation("returning", result) +# self.log.operation("returning", result) return None, result elif len(block.exits) == 1: index = 0 @@ -77,7 +77,7 @@ return link.target, [self.getval(x) for x in link.args] def eval_operation(self, operation): - self.log.operation("considering", operation) +# self.log.operation("considering", operation) ophandler = self.getoperationhandler(operation.opname) vals = [self.getval(x) for x in operation.args] retval = ophandler(*vals) @@ -92,8 +92,24 @@ def op_setfield(self, obj, fieldname, fieldvalue): # obj should be pointer setattr(obj, fieldname, fieldvalue) # is that right? + + def op_direct_call(self,f,*args): + res = self.eval_function(f._obj._callable,args) + return res + + def op_malloc(self,obj, n=None, immortal=False): + return malloc(obj,n,immortal) + + def op_getfield(self,obj,field): + return getattr(obj,field) + + def op_malloc_varsize(self,obj,size): + return self.op_malloc(obj,size) - + def op_getarraysubstruct(self,array,index): + #assert isinstance(array,_ptr) + return array[index] + # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Wed Jun 15 15:41:51 2005 @@ -55,7 +55,18 @@ return x[j] res = interpret(f, [10, 7]) assert res == 6 - + +# +#__________________________________________________________________ +# +# Test lists +def test_list_creation(): + def f(): + return [1,2,3] + res = interpret(f,[]) + assert len(res.items) == len([1,2,3]) + for i in range(3): + assert res.items[i]._getobj().item == i+1 #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() From rxe at codespeak.net Wed Jun 15 16:14:36 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Wed, 15 Jun 2005 16:14:36 +0200 (CEST) Subject: [pypy-svn] r13440 - pypy/dist/pypy/translator/tool Message-ID: <20050615141436.E1F8927B71@code1.codespeak.net> Author: rxe Date: Wed Jun 15 16:14:35 2005 New Revision: 13440 Removed: pypy/dist/pypy/translator/tool/flowtrace.py Log: This module is misleading and serves no purpose. Deleted: /pypy/dist/pypy/translator/tool/flowtrace.py ============================================================================== --- /pypy/dist/pypy/translator/tool/flowtrace.py Wed Jun 15 16:14:35 2005 +++ (empty file) @@ -1,394 +0,0 @@ -""" - -This is an experimental hack - use it at your peril! I (rxe) needed some sanity -check when (attempting) to write gencpp.py and this ended up being a useful -exercise. I doubt it much use to anyone else or the rest of the project, but it -might have some interesting possiblities later on once we have full translation. -:-) - -The idea is simple - take the basic blocks output via the flow object space and -evaluate them against the standard object space. It is effectively the same as -creating a C extension to the CPython interpreter to use the CPython API instead -of interpreting bytecodes - except in this case the we don't need to compile -anything and all space operations are emitted on the fly. One might call this a -flow interpreter - I wouldn't go that far! - -""" -import autopath -from pypy.objspace.flow import FlowObjSpace -from pypy.objspace.flow.model import traverse, Constant, Variable, Block, Link -from pypy.translator.simplify import simplify_graph -from pypy.interpreter.baseobjspace import OperationError -from pypy.interpreter.argument import Arguments - - -class FlowTracer(object): - - def __init__(self, flow_space, space, debug = False, trace = True): - self.space = space - self.flow_space = flow_space - self.trace = trace - self.debug = debug - - def pprint(self, v): - s = self.space.unwrap(self.space.repr(v.e_value)) - if len(s) > 30: - s = s[:27] + "..." - - if isinstance(v, Constant): - s = "Const(%s)" % s - - elif isinstance(v, Variable): - s = "%s(%s)" % (v, s) - - else: - assert False, "really?" - return s - - - def get_blocknames(self, graph): - blocknames = {} - def visit(n): - if isinstance(n, Block): - blocknames[n] = 'block%d' % len(blocknames) - - traverse(visit, graph) - return blocknames - - - def wrap_constants(self, graph): - all = [] - - def visit(n): - # Note - be careful with uniqueitems and constants, as there can - # multiple constant of the same value (XXX why?) - if isinstance(n, Block): - values = [] - values += n.inputargs - for op in n.operations: - values += op.args - - for ii in values: - all.append(ii) - - all.append(n.exitswitch) - - if isinstance(n, Link): - values = n.args - for ii in values: - all.append(ii) - - traverse(visit, graph) - for ii in all: - - if isinstance(ii, Constant) : - ii.e_value = self.space.wrap(ii.value) - - else: - assert (isinstance(ii, Variable) or ii is None) - - def wrap_linkexits(self, graph): - all = [] - - def visit(n): - if isinstance(n, Link): - all.append(n) - - traverse(visit, graph) - - for l in all: - l.exitcase = self.space.wrap(l.exitcase) - - - def execute_function(self, graph, *args_w): - - curblock = graph.startblock - assert len(curblock.inputargs) == len(args_w) - - # We add value as evaluated values during interpretation - # to variables, constants and exit switches. - # Variables are done on assignment (ie lazily) - for input, arg in zip(curblock.inputargs, args_w): - input.e_value = arg - - # Here we add value attribute with wrap - self.wrap_constants(graph) - self.wrap_linkexits(graph) - - blocknames = self.get_blocknames(graph) - last_exception = None - while True: - - if self.trace: - print 'Entering %s:' % blocknames[curblock] - print ' Input args :- %s' % (", ".join(map(self.pprint, curblock.inputargs))) - print ' Operations :-' - - for op in curblock.operations: - - # Why does op.args have a list in it? - opargs = [a.e_value for a in op.args] - if self.trace: - print ' %s = space.%s(%s)' % (op.result, - op.opname, - ", ".join(map(self.pprint, op.args))) - - if op.opname == "exception": - assert (len(opargs) == 1) - # XXX What we suppose to do with argument??? - if last_exception is not None: - res = last_exception - last_exception = None - else: - res = self.space.w_None - - elif op.opname == "call_args": - assert (len(opargs) >= 2) - shape = self.space.unwrap(opargs[1]) - args = Arguments.fromshape(shape, *opargs[2:]) - res = self.call_args(opargs[0], args) - - else: - # More special cases - spaceop = getattr(self.space, op.opname) - - if op.opname in ("newlist", "newdict", "newtuple"): - # These expect a list, not a *args - res = spaceop(opargs) - - else: - try: - res = spaceop(*opargs) - - # More special case - if op.opname == "is_true": - # Rewrap it! - res = self.space.wrap(res) - - except OperationError, exc: - last_exception = exc.w_type - res = self.space.w_None - - op.result.e_value = res - - if self.trace: - # Cases will likely not be a space object - if curblock.exits and curblock.exitswitch == op.result: - print ' %s := exit(%s)' % (op.result, op.result.e_value) - else: - print ' %s := %s' % (op.result, self.pprint(op.result)) - - # Switch to next block - if curblock.exits: - - # exits (safe code) - exit_link = None - if len(curblock.exits) == 1: - exit_link = curblock.exits[0] - - else: - exit_res = curblock.exitswitch.e_value - for link in curblock.exits: - if self.space.is_true(self.space.eq(exit_res, link.exitcase)): - exit_link = link - break - - assert exit_link is not None - - if self.trace: - print ' Exit to %s :- ' % blocknames[exit_link.target] - - sourceargs = exit_link.args - targetargs = exit_link.target.inputargs - assert len(sourceargs) == len(targetargs) - - for s, t in zip(sourceargs, targetargs): - if self.trace: - print " %s = %s" % (t, s) - - t.e_value = s.e_value - - curblock = exit_link.target - - if self.trace: - print - - elif len(curblock.inputargs) == 2: # exc_cls, exc_value - exc_cls, exc_value = curblock.inputargs - if self.trace: - print "Raising -", - print self.pprint(exc_cls), self.pprint(exc_value) - raise exc_cls.e_value, exc_value.e_value - - else: - result = curblock.inputargs[0] - if self.trace: - print "Returning -", self.pprint(result) - - return result.e_value - - - def call_args(self, w_func, args): - - func = self.space.unwrap(w_func) - if hasattr(func, "func_code"): - graph = self.flow_space.build_flow(func) - simplify_graph(graph) - if self.debug: - debug(func) - scope_w = args.parse(func.name, func.code.signature(), func.defs_w) - return self.execute_function(graph, *scope_w) - - else: - # XXX We could try creating the flow graph by runnning another - # flow objspace under self.space. Hmmm - if only I had - # bigger computer. - - # Instead we cheat (this is great fun when it is a fake type :-)) - if self.trace: - print "WOA! Cheating!", w_func - - return self.space.call_args(w_func, args) - - - def call(self, f, *args): - w = self.space.wrap - args_w = [w(ii) for ii in args] - w_func = w(f) - - res = self.call_args(w_func, Arguments(self.space, args_w)) - return self.space.unwrap(res) - - -def debug(func): - """Shows the control flow graph with annotations if computed. - Requires 'dot' and pygame.""" - from pypy.translator.tool.pygame.graphdisplay import GraphDisplay - from pypy.translator.tool.graphpage import FlowGraphPage - from pypy.translator.translator import Translator - t = Translator(func) - t.simplify() - #t.annotate([int]) - FlowGraphPage(t).display() - -def timeit(num, func, *args): - from time import time as now - start = now() - for i in xrange(num): - print func(*args) - return now() - start - -if __name__ == '__main__': - from pypy.objspace.std import Space - space = Space() - - def create_std_func(app_func): - - import new - from pypy.interpreter.gateway import app2interp - - # Horrible hack (ame needs to start with "app_") - app_func = new.function(app_func.func_code, - app_func.func_globals, - "app_" + app_func.__name__) - - # Create our function - func_gw = app2interp(app_func) - func = func_gw.get_function(space) - w_func = space.wrap(func) - - def f(*args): - args_w = [space.wrap(ii) for ii in args] - args_ = Arguments(space, args_w) - w_result = space.call_args(w_func, args_) - return space.unwrap(w_result) - return f - - def create_flow_func(f): - flow_space = FlowObjSpace() - interpreter = FlowTracer(flow_space, space) - def func(*args): - return interpreter.call(f, *args) - return func - - def do(f, *args): - print "doing %s(%s)" % (f.__name__, ", ".join(map(str, args))) - f_flow = create_flow_func(f) - res = f_flow(*args) - f_norm = create_std_func(f) - res_norm = f_norm(*args) - assert res == res_norm - return res - - def do_flow_only(f, *args): - print "doing %s(%s)" % (f.__name__, ", ".join(map(str, args))) - f_flow = create_flow_func(f) - res = f_flow(*args) - return res - - #///////////////////////////////////////////////////////////////////////////// - - def tests(): - from pypy.translator.test import snippet - - tests = [ - (snippet.if_then_else, 1, 2, 3), - (snippet.if_then_else, 0, 2, 3), - (snippet.my_gcd, 256, 192), - (snippet.is_perfect_number, 81), - (snippet.my_bool, 1), - (snippet.my_bool, 0), - (snippet.two_plus_two,), - #(snippet.sieve_of_eratosthenes,), - (snippet.simple_func, 10), - (snippet.nested_whiles, 1, 10), - (snippet.simple_func, 10), - (snippet.builtinusage,), - (snippet.poor_man_range, 10), - (snippet.poor_man_rev_range, 10), - (snippet.simple_id, 2) , - (snippet.branch_id, 1, "k", 1.0) , - (snippet.branch_id, False, "k", 1.0) , - (snippet.builtinusage,), - (snippet.yast, [1,2,3,4,5]), - (snippet.time_waster, 5), - (snippet.half_of_n, 20), - (snippet.int_id, 20), - (snippet.greet, "world"), - (snippet.choose_last,), - #(snippet.choose_last,), XXX Why does repeating this break? - (snippet.poly_branch, 1), - (snippet.s_and, 1, 1), - (snippet.s_and, 0, 1), - (snippet.s_and, 1, 0), - (snippet.s_and, 0, 0), - (snippet.break_continue, 15), - (snippet.reverse_3, ("k", 1, 1.0)), - (snippet.finallys, ("k", 1, 1.0)), - (snippet.finallys, ("k",)), - (snippet.finallys, []), - (snippet._append_five, []), - (snippet._append_five, [1,2,3]), - ] - for ii in tests: - print do(*ii) - - tests = [ - (snippet.factorial, 4), - (snippet.factorial2, 4), - (snippet.call_five,), - (snippet.build_instance,), - (snippet.set_attr,), - (snippet.merge_setattr, 0), - (snippet.merge_setattr, 1), - # XXX These don't work from test.snippet (haven't tried anymore) - #(snippet.inheritance1,), - #(snippet.inheritance2,), - - ] - - for ii in tests: - print do_flow_only(*ii) - - tests() - From arigo at codespeak.net Wed Jun 15 16:23:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 16:23:08 +0200 (CEST) Subject: [pypy-svn] r13441 - in pypy/dist/pypy/rpython: . test Message-ID: <20050615142308.2000527B71@code1.codespeak.net> Author: arigo Date: Wed Jun 15 16:23:06 2005 New Revision: 13441 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: * comments about the details of the low-level operations * assert(..., _ptr) looks indeed like the way to check for pointer-ness * _getobj() should not be called explicitely in the test (not needed here) Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Wed Jun 15 16:23:06 2005 @@ -1,4 +1,5 @@ from pypy.rpython.lltype import * +from pypy.rpython.lltype import _ptr import py @@ -91,24 +92,42 @@ def op_setfield(self, obj, fieldname, fieldvalue): # obj should be pointer - setattr(obj, fieldname, fieldvalue) # is that right? + setattr(obj, fieldname, fieldvalue) # is that right? -- yes def op_direct_call(self,f,*args): + # XXX the logic should be: + # if f._obj has a graph attribute, interpret + # that graph without looking at _callable res = self.eval_function(f._obj._callable,args) return res - def op_malloc(self,obj, n=None, immortal=False): - return malloc(obj,n,immortal) + def op_malloc(self,obj): + return malloc(obj) def op_getfield(self,obj,field): - return getattr(obj,field) - + # assert: obj should be pointer + result = getattr(obj,field) + # check the difference between op_getfield and op_getsubstruct: + # the former returns the real field, the latter a pointer to it + assert typeOf(result) == getattr(typeOf(obj).TO, field) + return result + + def op_getsubstruct(self,obj,field): + # assert: obj should be pointer + result = getattr(obj,field) + # check the difference between op_getfield and op_getsubstruct: + # the former returns the real field, the latter a pointer to it + assert typeOf(result) == Ptr(getattr(typeOf(obj).TO, field)) + return result + def op_malloc_varsize(self,obj,size): - return self.op_malloc(obj,size) + return malloc(obj,size) def op_getarraysubstruct(self,array,index): - #assert isinstance(array,_ptr) + assert isinstance(array,_ptr) return array[index] + # the diff between op_getarrayitem and op_getarraysubstruct + # is the same as between op_getfield and op_getsubstruct # __________________________________________________________ # primitive operations Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Wed Jun 15 16:23:06 2005 @@ -66,7 +66,7 @@ res = interpret(f,[]) assert len(res.items) == len([1,2,3]) for i in range(3): - assert res.items[i]._getobj().item == i+1 + assert res.items[i].item == i+1 #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() From adim at codespeak.net Wed Jun 15 16:24:42 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 15 Jun 2005 16:24:42 +0200 (CEST) Subject: [pypy-svn] r13442 - pypy/branch/pycompiler/module/recparser Message-ID: <20050615142442.8A9AF27B71@code1.codespeak.net> Author: adim Date: Wed Jun 15 16:24:39 2005 New Revision: 13442 Modified: pypy/branch/pycompiler/module/recparser/__init__.py pypy/branch/pycompiler/module/recparser/ebnfparse.py pypy/branch/pycompiler/module/recparser/tuplebuilder.py Log: misc tidy Modified: pypy/branch/pycompiler/module/recparser/__init__.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/__init__.py (original) +++ pypy/branch/pycompiler/module/recparser/__init__.py Wed Jun 15 16:24:39 2005 @@ -7,6 +7,11 @@ import pythonparse debug_print( "Loading grammar %s" % pythonparse.PYTHON_GRAMMAR ) +from pypy.interpreter.mixedmodule import MixedModule +class Module(MixedModule): + interpleveldefs = {} + appleveldefs = {} + ## from pypy.interpreter.mixedmodule import MixedModule ## class Module(MixedModule): ## """The builtin parser module. Modified: pypy/branch/pycompiler/module/recparser/ebnfparse.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/ebnfparse.py (original) +++ pypy/branch/pycompiler/module/recparser/ebnfparse.py Wed Jun 15 16:24:39 2005 @@ -75,6 +75,7 @@ class EBNFVisitor(object): + def __init__(self): self.rules = {} self.terminals = {} Modified: pypy/branch/pycompiler/module/recparser/tuplebuilder.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/tuplebuilder.py (original) +++ pypy/branch/pycompiler/module/recparser/tuplebuilder.py Wed Jun 15 16:24:39 2005 @@ -3,43 +3,43 @@ from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET -def _expand_nodes( nodes ): +def _expand_nodes(nodes): expanded = [] for n in nodes: - if n[0]==-2: - expanded.extend( expand_nodes(n[1:]) ) + if n[0] == -2: + expanded.extend(expand_nodes(n[1:])) else: expanded.append(n) return tuple(expanded) -def expand_nodes( nodes ): - r = _expand_nodes( nodes ) +def expand_nodes(nodes): + r = _expand_nodes(nodes) for n in nodes: - assert type(n[0])==int + assert type(n[0]) == int return r class TupleBuilder(BaseGrammarBuilder): """A builder that directly produce the AST""" - def __init__( self, rules=None, debug=0, lineno=True ): + def __init__(self, rules=None, debug=0, lineno=True): BaseGrammarBuilder.__init__(self, rules, debug ) self.lineno = lineno - def alternative( self, rule, source ): + def alternative(self, rule, source): # Do nothing, keep rule on top of the stack if rule.is_root(): node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] - node += expand_nodes( [self.stack[-1]] ) + node += expand_nodes( [self.stack[-1]] ) self.stack[-1] = tuple(node) return True def sequence(self, rule, source, elts_number): """ """ if rule.is_root(): - node = [ SYMBOLS.get( rule.name, (0,rule.name) ) ] + node = [SYMBOLS.get( rule.name, (0, rule.name) )] else: - node = [ -2 ] - if elts_number>0: + node = [-2] + if elts_number > 0: node += expand_nodes( self.stack[-elts_number:] ) self.stack[-elts_number:] = [tuple(node)] else: @@ -47,7 +47,7 @@ return True def token(self, name, value, source): - num = TOKEN_MAP.get( name, -1) + num = TOKEN_MAP.get(name, -1) lineno = source.current_line() if value is None: if name not in ("NEWLINE", "INDENT", "DEDENT", "ENDMARKER"): From adim at codespeak.net Wed Jun 15 16:27:27 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 15 Jun 2005 16:27:27 +0200 (CEST) Subject: [pypy-svn] r13443 - pypy/branch/pycompiler/module/recparser Message-ID: <20050615142727.C3E6527B71@code1.codespeak.net> Author: adim Date: Wed Jun 15 16:27:26 2005 New Revision: 13443 Added: pypy/branch/pycompiler/module/recparser/automata.py pypy/branch/pycompiler/module/recparser/pytokenize.py Log: added local modified versions of pypy.module.parser's used modules (Modifications done to make the annotator's life easier, but incompatible, as is, with the original pypy.module.parser's API) Added: pypy/branch/pycompiler/module/recparser/automata.py ============================================================================== --- (empty file) +++ pypy/branch/pycompiler/module/recparser/automata.py Wed Jun 15 16:27:26 2005 @@ -0,0 +1,98 @@ +#! /usr/bin/env python +# ______________________________________________________________________ +"""Module automata + +THIS FILE WAS COPIED FROM pypy/module/parser/pytokenize.py AND ADAPTED +TO BE ANNOTABLE (Mainly made the DFA's __init__ accept two lists +instead of a unique nested one) + +$Id: automata.py,v 1.2 2003/10/02 17:37:17 jriehl Exp $ +""" +# ______________________________________________________________________ +# Module level definitions + +# PYPY Modification: removed the EMPTY class as it's not needed here + + +# PYPY Modification: Make the DEFAULTClasse inherit from str +# to make the state dict homogeneous +class DEFAULTClass(str): + def __repr__ (self): + return 'automata.DEFAULT' + + def __eq__(self, other): + return False # Never equals other strings + + def __ne__(self, other): + return True # Always different from other strings + + +DEFAULT = DEFAULTClass() + +# PYPY Modification : removed all automata functions (any, maybe, +# newArcPair, etc.) + +class DFA: + # ____________________________________________________________ + def __init__(self, states, accepts, start = 0): + self.states = states + self.accepts = accepts + self.start = start + + # ____________________________________________________________ + def recognize (self, inVec, pos = 0, greedy = True): + crntState = self.start + i = pos + lastAccept = False + for item in inVec[pos:]: + # arcMap, accept = self.states[crntState] + arcMap = self.states[crntState] + accept = self.accepts[crntState] + if arcMap.has_key(item): + crntState = arcMap[item] + elif arcMap.has_key(DEFAULT): + crntState = arcMap[DEFAULT] + elif accept: + return i + elif lastAccept: + # This is now needed b/c of exception cases where there are + # transitions to dead states + return i - 1 + else: + return -1 + lastAccept = accept + i += 1 + # if self.states[crntState][1]: + if self.accepts[crntState]: + return i + elif lastAccept: + return i - 1 + else: + return -1 +# ______________________________________________________________________ + +class NonGreedyDFA (DFA): + def recognize (self, inVec, pos = 0): + crntState = self.start + i = pos + for item in inVec[pos:]: + # arcMap, accept = self.states[crntState] + arcMap = self.states[crntState] + accept = self.accepts[crntState] + if accept: + return i + elif arcMap.has_key(item): + crntState = arcMap[item] + elif arcMap.has_key(DEFAULT): + crntState = arcMap[DEFAULT] + else: + return -1 + i += 1 + # if self.states[crntState][1]: + if self.accepts[crntState]: + return i + else: + return -1 + +# ______________________________________________________________________ +# End of automata.py Added: pypy/branch/pycompiler/module/recparser/pytokenize.py ============================================================================== --- (empty file) +++ pypy/branch/pycompiler/module/recparser/pytokenize.py Wed Jun 15 16:27:26 2005 @@ -0,0 +1,334 @@ +#! /usr/bin/env python +# ______________________________________________________________________ +"""Module pytokenize + +THIS FILE WAS COPIED FROM pypy/module/parser/pytokenize.py AND ADAPTED +TO BE ANNOTABLE (Mainly made lists homogeneous) + +This is a modified version of Ka-Ping Yee's tokenize module found in the +Python standard library. + +The primary modification is the removal of the tokenizer's dependence on the +standard Python regular expression module, which is written in C. The regular +expressions have been replaced with hand built DFA's using the +basil.util.automata module. + +XXX This now assumes that the automata module is in the Python path. + +$Id: pytokenize.py,v 1.3 2003/10/03 16:31:53 jriehl Exp $ +""" +# ______________________________________________________________________ + +from __future__ import generators +import string +import automata + +# ______________________________________________________________________ +# COPIED: +from token import * + +import token +__all__ = [x for x in dir(token) if x[0] != '_'] + ["COMMENT", "tokenize", + "generate_tokens", "NL"] +del x +del token + +COMMENT = N_TOKENS +tok_name[COMMENT] = 'COMMENT' +NL = N_TOKENS + 1 +tok_name[NL] = 'NL' +N_TOKENS += 2 + +# ______________________________________________________________________ +# Automatically generated DFA's (with one or two hand tweeks): +pseudoStatesAccepts = [True, True, True, True, True, True, True, True, + True, True, False, True, True, True, False, False, + False, False, True, False, False, True, True, False, + True, False, True, False, True, False, True, False, + False, False, True, False, False, False, True] + +pseudoStates = [ + {'\t': 0, '\n': 13, '\x0c': 0, '\r': 14, ' ': 0, '!': 10, + '"': 16, '#': 18, '%': 12, '&': 12, + "'": 15, '(': 13, ')': 13, '*': 7, + '+': 12, ',': 13, '-': 12, '.': 6, + '/': 11, '0': 4, '1': 5, '2': 5, + '3': 5, '4': 5, '5': 5, '6': 5, + '7': 5, '8': 5, '9': 5, ':': 13, + ';': 13, '<': 9, '=': 12, '>': 8, 'A': 1, + 'B': 1, 'C': 1, 'D': 1, 'E': 1, + 'F': 1, 'G': 1, 'H': 1, 'I': 1, + 'J': 1, 'K': 1, 'L': 1, 'M': 1, + 'N': 1, 'O': 1, 'P': 1, 'Q': 1, + 'R': 2, 'S': 1, 'T': 1, 'U': 3, + 'V': 1, 'W': 1, 'X': 1, 'Y': 1, + 'Z': 1, '[': 13, '\\': 17, ']': 13, + '^': 12, '_': 1, '`': 13, 'a': 1, + 'b': 1, 'c': 1, 'd': 1, 'e': 1, + 'f': 1, 'g': 1, 'h': 1, 'i': 1, + 'j': 1, 'k': 1, 'l': 1, 'm': 1, + 'n': 1, 'o': 1, 'p': 1, 'q': 1, + 'r': 2, 's': 1, 't': 1, 'u': 3, + 'v': 1, 'w': 1, 'x': 1, 'y': 1, + 'z': 1, '{': 13, '|': 12, '}': 13, + '~': 13}, + + {'0': 1, '1': 1, '2': 1, '3': 1, + '4': 1, '5': 1, '6': 1, '7': 1, + '8': 1, '9': 1, 'A': 1, 'B': 1, + 'C': 1, 'D': 1, 'E': 1, 'F': 1, + 'G': 1, 'H': 1, 'I': 1, 'J': 1, + 'K': 1, 'L': 1, 'M': 1, 'N': 1, + 'O': 1, 'P': 1, 'Q': 1, 'R': 1, + 'S': 1, 'T': 1, 'U': 1, 'V': 1, + 'W': 1, 'X': 1, 'Y': 1, 'Z': 1, + '_': 1, 'a': 1, 'b': 1, 'c': 1, + 'd': 1, 'e': 1, 'f': 1, 'g': 1, + 'h': 1, 'i': 1, 'j': 1, 'k': 1, + 'l': 1, 'm': 1, 'n': 1, 'o': 1, + 'p': 1, 'q': 1, 'r': 1, 's': 1, + 't': 1, 'u': 1, 'v': 1, 'w': 1, + 'x': 1, 'y': 1, 'z': 1}, + + {'"': 20, "'": 19, '0': 1, '1': 1, + '2': 1, '3': 1, '4': 1, '5': 1, + '6': 1, '7': 1, '8': 1, '9': 1, + 'A': 1, 'B': 1, 'C': 1, 'D': 1, + 'E': 1, 'F': 1, 'G': 1, 'H': 1, + 'I': 1, 'J': 1, 'K': 1, 'L': 1, + 'M': 1, 'N': 1, 'O': 1, 'P': 1, + 'Q': 1, 'R': 1, 'S': 1, 'T': 1, + 'U': 1, 'V': 1, 'W': 1, 'X': 1, + 'Y': 1, 'Z': 1, '_': 1, 'a': 1, + 'b': 1, 'c': 1, 'd': 1, 'e': 1, + 'f': 1, 'g': 1, 'h': 1, 'i': 1, + 'j': 1, 'k': 1, 'l': 1, 'm': 1, + 'n': 1, 'o': 1, 'p': 1, 'q': 1, + 'r': 1, 's': 1, 't': 1, 'u': 1, + 'v': 1, 'w': 1, 'x': 1, 'y': 1, + 'z': 1}, + + {'"': 20, "'": 19, '0': 1, '1': 1, + '2': 1, '3': 1, '4': 1, '5': 1, + '6': 1, '7': 1, '8': 1, '9': 1, + 'A': 1, 'B': 1, 'C': 1, 'D': 1, + 'E': 1, 'F': 1, 'G': 1, 'H': 1, + 'I': 1, 'J': 1, 'K': 1, 'L': 1, + 'M': 1, 'N': 1, 'O': 1, 'P': 1, + 'Q': 1, 'R': 2, 'S': 1, 'T': 1, + 'U': 1, 'V': 1, 'W': 1, 'X': 1, + 'Y': 1, 'Z': 1, '_': 1, 'a': 1, + 'b': 1, 'c': 1, 'd': 1, 'e': 1, + 'f': 1, 'g': 1, 'h': 1, 'i': 1, + 'j': 1, 'k': 1, 'l': 1, 'm': 1, + 'n': 1, 'o': 1, 'p': 1, 'q': 1, + 'r': 2, 's': 1, 't': 1, 'u': 1, + 'v': 1, 'w': 1, 'x': 1, 'y': 1, + 'z': 1}, + + {'.': 24, '0': 22, '1': 22, '2': 22, + '3': 22, '4': 22, '5': 22, '6': 22, + '7': 22, '8': 23, '9': 23, 'E': 25, + 'J': 13, 'L': 13, 'X': 21, 'e': 25, + 'j': 13, 'l': 13, 'x': 21}, + + {'.': 24, '0': 5, '1': 5, '2': 5, + '3': 5, '4': 5, '5': 5, '6': 5, + '7': 5, '8': 5, '9': 5, 'E': 25, + 'J': 13, 'L': 13, 'e': 25, 'j': 13, + 'l': 13}, + + {'0': 26, '1': 26, '2': 26, '3': 26, + '4': 26, '5': 26, '6': 26, '7': 26, + '8': 26, '9': 26}, + + {'*': 12, '=': 13}, + + {'=': 13, '>': 12}, + + {'=': 13, '<': 12, '>': 13}, + + {'=': 13}, + + {'=': 13, '/': 12}, + + {'=': 13}, + + {}, + + {'\n': 13}, + + {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 28}, + + {automata.DEFAULT: 20, '"': 30, '\n': 27, '\\': 31}, + + {'\n': 13, '\r': 14}, + + {automata.DEFAULT: 18, '\n': 27, '\r': 27}, + + {automata.DEFAULT: 19, '\n': 27, '\\': 29, "'": 13}, + + {automata.DEFAULT: 20, '"': 13, '\n': 27, '\\': 31}, + + {'0': 21, '1': 21, '2': 21, '3': 21, + '4': 21, '5': 21, '6': 21, '7': 21, + '8': 21, '9': 21, 'A': 21, 'B': 21, + 'C': 21, 'D': 21, 'E': 21, 'F': 21, + 'L': 13, 'a': 21, 'b': 21, 'c': 21, + 'd': 21, 'e': 21, 'f': 21, 'l': 13}, + + {'.': 24, '0': 22, '1': 22, '2': 22, + '3': 22, '4': 22, '5': 22, '6': 22, + '7': 22, '8': 23, '9': 23, 'E': 25, + 'J': 13, 'L': 13, 'e': 25, 'j': 13, + 'l': 13}, + + {'.': 24, '0': 23, '1': 23, '2': 23, + '3': 23, '4': 23, '5': 23, '6': 23, + '7': 23, '8': 23, '9': 23, 'E': 25, + 'J': 13, 'e': 25, 'j': 13}, + + {'0': 24, '1': 24, '2': 24, '3': 24, + '4': 24, '5': 24, '6': 24, '7': 24, + '8': 24, '9': 24, 'E': 32, 'J': 13, + 'e': 32, 'j': 13}, + + {'+': 33, '-': 33, '0': 34, '1': 34, + '2': 34, '3': 34, '4': 34, '5': 34, + '6': 34, '7': 34, '8': 34, '9': 34}, + + {'0': 26, '1': 26, '2': 26, '3': 26, + '4': 26, '5': 26, '6': 26, '7': 26, + '8': 26, '9': 26, 'E': 32, 'J': 13, + 'e': 32, 'j': 13}, + + {}, + + {"'": 13}, + + {automata.DEFAULT: 35, '\n': 13, '\r': 14}, + + {'"': 13}, + + {automata.DEFAULT: 36, '\n': 13, '\r': 14}, + + {'+': 37, '-': 37, '0': 38, '1': 38, + '2': 38, '3': 38, '4': 38, '5': 38, + '6': 38, '7': 38, '8': 38, '9': 38}, + + + {'0': 34, '1': 34, '2': 34, '3': 34, + '4': 34, '5': 34, '6': 34, '7': 34, + '8': 34, '9': 34}, + + {'0': 34, '1': 34, '2': 34, '3': 34, + '4': 34, '5': 34, '6': 34, '7': 34, + '8': 34, '9': 34, 'J': 13, 'j': 13}, + + {automata.DEFAULT: 35, '\n': 27, '\\': 29, "'": 13}, + + {automata.DEFAULT: 36, '"': 13, '\n': 27, '\\': 31}, + + {'0': 38, '1': 38, '2': 38, '3': 38, + '4': 38, '5': 38, '6': 38, '7': 38, + '8': 38, '9': 38}, + + {'0': 38, '1': 38, '2': 38, '3': 38, + '4': 38, '5': 38, '6': 38, '7': 38, + '8': 38, '9': 38, 'J': 13, 'j': 13}, + ] + +pseudoDFA = automata.DFA(pseudoStates, pseudoStatesAccepts) + +double3StatesAccepts = [False, False, False, False, False, True] +double3States = [ + {automata.DEFAULT: 0, '"': 1, '\\': 2}, + {automata.DEFAULT: 4, '"': 3, '\\': 2}, + {automata.DEFAULT: 4}, + {automata.DEFAULT: 4, '"': 5, '\\': 2}, + {automata.DEFAULT: 4, '"': 1, '\\': 2}, + {automata.DEFAULT: 4, '"': 5, '\\': 2}, + ] +double3DFA = automata.NonGreedyDFA(double3States, double3StatesAccepts) + +single3StatesAccepts = [False, False, False, False, False, True] +single3States = [ + {automata.DEFAULT: 0, '\\': 2, "'": 1}, + {automata.DEFAULT: 4, '\\': 2, "'": 3}, + {automata.DEFAULT: 4}, + {automata.DEFAULT: 4, '\\': 2, "'": 5}, + {automata.DEFAULT: 4, '\\': 2, "'": 1}, + {automata.DEFAULT: 4, '\\': 2, "'": 5}, + ] +single3DFA = automata.NonGreedyDFA(single3States, single3StatesAccepts) + +singleStatesAccepts = [False, True, False] +singleStates = [ + {automata.DEFAULT: 0, '\\': 2, "'": 1}, + {}, + {automata.DEFAULT: 0}, + ] +singleDFA = automata.DFA(singleStates, singleStatesAccepts) + +doubleStatesAccepts = [False, True, False] +doubleStates = [ + {automata.DEFAULT: 0, '"': 1, '\\': 2}, + {}, + {automata.DEFAULT: 0}, + ] +doubleDFA = automata.DFA(doubleStates, doubleStatesAccepts) + +endDFAs = {"'" : singleDFA, + '"' : doubleDFA, + "r" : None, + "R" : None, + "u" : None, + "U" : None} + +for uniPrefix in ("", "u", "U"): + for rawPrefix in ("", "r", "R"): + prefix = uniPrefix + rawPrefix + endDFAs[prefix + "'''"] = single3DFA + endDFAs[prefix + '"""'] = double3DFA + +whiteSpaceStatesAccepts = [True] +whiteSpaceStates = [{'\t': 0, ' ': 0, '\x0c': 0}] +whiteSpaceDFA = automata.DFA(whiteSpaceStates, whiteSpaceStatesAccepts) + +# ______________________________________________________________________ +# COPIED: + +triple_quoted = {} +for t in ("'''", '"""', + "r'''", 'r"""', "R'''", 'R"""', + "u'''", 'u"""', "U'''", 'U"""', + "ur'''", 'ur"""', "Ur'''", 'Ur"""', + "uR'''", 'uR"""', "UR'''", 'UR"""'): + triple_quoted[t] = t +single_quoted = {} +for t in ("'", '"', + "r'", 'r"', "R'", 'R"', + "u'", 'u"', "U'", 'U"', + "ur'", 'ur"', "Ur'", 'Ur"', + "uR'", 'uR"', "UR'", 'UR"' ): + single_quoted[t] = t + +tabsize = 8 + +# PYPY MODIFICATION: removed TokenError class as it's not needed here + +# PYPY MODIFICATION: removed StopTokenizing class as it's not needed here + +# PYPY MODIFICATION: removed printtoken() as it's not needed here + +# PYPY MODIFICATION: removed tokenize() as it's not needed here + +# PYPY MODIFICATION: removed tokenize_loop() as it's not needed here + +# PYPY MODIFICATION: removed generate_tokens() as it was copied / modified +# in pythonlexer.py + +# PYPY MODIFICATION: removed main() as it's not needed here + +# ______________________________________________________________________ +# End of pytokenize.py From adim at codespeak.net Wed Jun 15 16:28:37 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Wed, 15 Jun 2005 16:28:37 +0200 (CEST) Subject: [pypy-svn] r13444 - pypy/branch/pycompiler/module/recparser Message-ID: <20050615142837.1AEC827B71@code1.codespeak.net> Author: adim Date: Wed Jun 15 16:28:35 2005 New Revision: 13444 Modified: pypy/branch/pycompiler/module/recparser/grammar.py pypy/branch/pycompiler/module/recparser/pythonlexer.py Log: - made the annotator's life easier - use the local version of automata.py / pytokenize.py in pythonlexer.py Modified: pypy/branch/pycompiler/module/recparser/grammar.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/grammar.py (original) +++ pypy/branch/pycompiler/module/recparser/grammar.py Wed Jun 15 16:28:35 2005 @@ -164,7 +164,8 @@ """ if not USE_LOOKAHEAD: return self._match(source, builder, level) - + pos1 = -1 # XXX make the annotator happy + pos2 = -1 # XXX make the annotator happy token = source.peek() if self._trace: pos1 = source.get_pos() Modified: pypy/branch/pycompiler/module/recparser/pythonlexer.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/pythonlexer.py (original) +++ pypy/branch/pycompiler/module/recparser/pythonlexer.py Wed Jun 15 16:28:35 2005 @@ -41,8 +41,7 @@ if encoding != '': return encoding return None - - + def _normalize_encoding(encoding): """returns normalized name for @@ -63,9 +62,9 @@ ################################################################################ import token as tokenmod -from pypy.module.parser.pytokenize import tabsize, \ - whiteSpaceDFA, triple_quoted, endDFAs, single_quoted, pseudoDFA -from pypy.module.parser import automata +from pytokenize import tabsize, whiteSpaceDFA, triple_quoted, endDFAs, \ + single_quoted, pseudoDFA +import automata # adopt pytokenize notations / values tokenmod.COMMENT = tokenmod.N_TOKENS @@ -112,7 +111,7 @@ strstart = (0, 0) lines.append('') # XXX HACK probably not needed - endDFA = automata.DFA([]) # XXX Make the translator happy + endDFA = automata.DFA([], []) # XXX Make the translator happy line = '' # XXX Make the translator happy for line in lines: lnum = lnum + 1 @@ -298,7 +297,7 @@ class PythonSource(TokenSource): """This source uses Jonathan's tokenizer""" def __init__(self, inpstring): - TokenSource.__init__(self) + # TokenSource.__init__(self) tokens, encoding = generate_tokens(inpstring.splitlines(True)) self.token_stack = tokens self.encoding = encoding From pedronis at codespeak.net Wed Jun 15 21:23:10 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 21:23:10 +0200 (CEST) Subject: [pypy-svn] r13449 - in pypy/dist/pypy/rpython: . test Message-ID: <20050615192310.E812F27B93@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 21:23:09 2005 New Revision: 13449 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py Log: support for runtime type info (as unique pointers to special opaque objects) for GcStructs, it is possible to attach a query function to GcStruct type that will be used to discover the runtime type info at runtime. attachRuntimeTypeInfo(GSTRUCT) activates the support for GCSTRUCT, optionally the function as functionptr with signature (Ptr(GCSTRUCT)) -> Ptr(RuntimeTypeInfo) can be passed. getRuntimeTypeInfo(GCSTRUCT) returns the statically associated runtime type info object of GCSTRUCT, runtime_type_info(p) is runtime invocable and returns the runtime type info for p, assuming p it's a pointer to a GcStruct. This support will be used to implement proper deallocation for pointers to inlined GcStructs. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Wed Jun 15 21:23:09 2005 @@ -151,7 +151,15 @@ return _struct(self, n) class GcStruct(Struct): - pass + _runtime_type_info = None + + def _attach_runtime_type_info_funcptr(self, funcptr): + if self._runtime_type_info is None: + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self) + if funcptr is not None: + if not typeOf(funcptr) == Ptr(FuncType([Ptr(self)], Ptr(RuntimeTypeInfo))): + raise TypeError, "expected a runtime type info function implementation, got: %s" % funcptr + self._runtime_type_info._obj.query_funcptr = funcptr class Array(ContainerType): __name__ = 'array' @@ -216,6 +224,17 @@ return self.RESULT._example() return _func(self, _callable=ex) +class OpaqueType(ContainerType): + + def __init__(self, tag): + self.tag = tag + self.__name__ = tag + + def __str__(self): + return "%s (opaque)" % self.tag + +RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo") + class PyObjectType(ContainerType): __name__ = 'PyObject' def __str__(self): @@ -652,6 +671,25 @@ def __str__(self): return "func %s" % self._name +class _opaque(object): + def __init__(self, TYPE, **attrs): + self._TYPE = TYPE + self._name = "?" + self.__dict__.update(attrs) + + def _parentstructure(self): + return None + + def _check(self): + pass + + def __repr__(self): + return '<%s>' % (self,) + + def __str__(self): + return "%s %s" % (self._TYPE.__name__, self._name) + + class _pyobject(Hashable): _TYPE = PyObject @@ -681,14 +719,54 @@ def functionptr(TYPE, name, **attrs): if not isinstance(TYPE, FuncType): - raise TypeError, "function() for FuncTypes only" + raise TypeError, "functionptr() for FuncTypes only" o = _func(TYPE, _name=name, **attrs) return _ptr(Ptr(TYPE), o) def nullptr(T): return Ptr(T)._defl() +def opaqueptr(TYPE, name, **attrs): + if not isinstance(TYPE, OpaqueType): + raise TypeError, "opaqueptr() for OpaqueTypes only" + o = _opaque(TYPE, _name=name, **attrs) + return _ptr(Ptr(TYPE), o, immortal=attrs.get('immortal', True)) + def pyobjectptr(obj): o = _pyobject(obj) return _ptr(Ptr(PyObject), o) +def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None): + if not isinstance(GCSTRUCT, GcStruct): + raise TypeError, "expected a GcStruct: %s" % GCSTRUCT + GCSTRUCT._attach_runtime_type_info_funcptr(funcptr) + return GCSTRUCT._runtime_type_info + +def getRuntimeTypeInfo(GCSTRUCT): + if not isinstance(GCSTRUCT, GcStruct): + raise TypeError, "expected a GcStruct: %s" % GCSTRUCT + if GCSTRUCT._runtime_type_info is None: + raise TypeError, "no attached runtime type info for %s" % GCSTRUCT + return GCSTRUCT._runtime_type_info + +def runtime_type_info(p): + T = typeOf(p) + if not isinstance(T, Ptr) or not isinstance(T.TO, GcStruct): + raise TypeError, "runtime_type_info on non-GcStruct pointer: %s" % p + top_parent = struct = p._obj + while True: + parent = top_parent._parentstructure() + if parent is None: + break + top_parent = parent + result = getRuntimeTypeInfo(top_parent._TYPE) + static_info = getRuntimeTypeInfo(T.TO) + query_funcptr = getattr(static_info._obj, 'query_funcptr', None) + if query_funcptr is not None: + result2 = query_funcptr(p) + if result != result2: + raise RuntimeError, ("runtime type-info function for %s:\n" + " returned: %s,\n" + "should have been: %s" % (p, result2, result)) + return result + Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Wed Jun 15 21:23:09 2005 @@ -338,3 +338,50 @@ del p p = cast_pointer(Ptr(S), p1) assert p.s1.x == 5 + +def test_getRuntimeTypeInfo(): + S = GcStruct('s', ('x', Signed)) + py.test.raises(TypeError, "getRuntimeTypeInfo(S)") + pinf0 = attachRuntimeTypeInfo(S) + assert pinf0._obj.about == S + pinf = getRuntimeTypeInfo(S) + assert pinf == pinf0 + pinf1 = getRuntimeTypeInfo(S) + assert pinf == pinf1 + Z = GcStruct('z', ('x', Unsigned)) + attachRuntimeTypeInfo(Z) + assert getRuntimeTypeInfo(Z) != pinf0 + Sbis = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(Sbis) + assert getRuntimeTypeInfo(Sbis) != pinf0 + assert Sbis != S # the attached runtime type info distinguishes them + +def test_runtime_type_info(): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + s = malloc(S) + assert runtime_type_info(s) == getRuntimeTypeInfo(S) + S1 = GcStruct('s1', ('sub', S), ('x', Signed)) + attachRuntimeTypeInfo(S1) + s1 = malloc(S1) + assert runtime_type_info(s1) == getRuntimeTypeInfo(S1) + assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) + assert runtime_type_info(cast_pointer(Ptr(S), s1)) == getRuntimeTypeInfo(S1) + def dynamic_type_info_S(p): + if p.x == 0: + return getRuntimeTypeInfo(S) + else: + return getRuntimeTypeInfo(S1) + fp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)), + "dynamic_type_info_S", + _callable=dynamic_type_info_S) + attachRuntimeTypeInfo(S, fp) + assert s.x == 0 + assert runtime_type_info(s) == getRuntimeTypeInfo(S) + s.x = 1 + py.test.raises(RuntimeError, "runtime_type_info(s)") + assert s1.sub.x == 0 + py.test.raises(RuntimeError, "runtime_type_info(s1.sub)") + s1.sub.x = 1 + assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1) + From arigo at codespeak.net Wed Jun 15 21:28:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 21:28:18 +0200 (CEST) Subject: [pypy-svn] r13450 - pypy/dist/pypy/rpython Message-ID: <20050615192818.8D5BF27B93@code1.codespeak.net> Author: arigo Date: Wed Jun 15 21:28:17 2005 New Revision: 13450 Modified: pypy/dist/pypy/rpython/rptr.py Log: Removed slightly fragile and unnecessary support for known-to-be-NULL pointers. Modified: pypy/dist/pypy/rpython/rptr.py ============================================================================== --- pypy/dist/pypy/rpython/rptr.py (original) +++ pypy/dist/pypy/rpython/rptr.py Wed Jun 15 21:28:17 2005 @@ -7,15 +7,15 @@ class __extend__(annmodel.SomePtr): def rtyper_makerepr(self, rtyper): - if self.is_constant() and not self.const: # constant NULL - return nullptr_repr - else: - return PtrRepr(self.ll_ptrtype) +## if self.is_constant() and not self.const: # constant NULL +## return nullptr_repr +## else: + return PtrRepr(self.ll_ptrtype) def rtyper_makekey(self): - if self.is_constant() and not self.const: - return None - else: - return self.ll_ptrtype +## if self.is_constant() and not self.const: +## return None +## else: + return self.ll_ptrtype class PtrRepr(Repr): @@ -83,18 +83,18 @@ # # Null Pointers -class NullPtrRepr(Repr): - lowleveltype = Void +##class NullPtrRepr(Repr): +## lowleveltype = Void - def rtype_is_true(self, hop): - return hop.inputconst(Bool, False) +## def rtype_is_true(self, hop): +## return hop.inputconst(Bool, False) -nullptr_repr = NullPtrRepr() +##nullptr_repr = NullPtrRepr() -class __extend__(pairtype(NullPtrRepr, PtrRepr)): - def convert_from_to((r_null, r_ptr), v, llops): - # nullptr to general pointer - return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) +##class __extend__(pairtype(NullPtrRepr, PtrRepr)): +## def convert_from_to((r_null, r_ptr), v, llops): +## # nullptr to general pointer +## return inputconst(r_ptr, _ptr(r_ptr.lowleveltype, None)) # ____________________________________________________________ # From pedronis at codespeak.net Wed Jun 15 21:37:47 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 21:37:47 +0200 (CEST) Subject: [pypy-svn] r13451 - in pypy/dist/pypy: annotation rpython/test Message-ID: <20050615193747.B01A327B95@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 21:37:46 2005 New Revision: 13451 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/test/test_llann.py Log: annotation support for getRuntimeTypeInfo and runtime_type_info with small tests Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Wed Jun 15 21:37:46 2005 @@ -316,9 +316,18 @@ cast_p = lltype.cast_pointer(PtrT.const, s_p.ll_ptrtype._defl()) return SomePtr(ll_ptrtype=lltype.typeOf(cast_p)) +def getRuntimeTypeInfo(T): + assert T.is_constant() + return immutablevalue(lltype.getRuntimeTypeInfo(T.const)) + +def runtime_type_info(s_p): + assert isinstance(s_p, SomePtr), "runtime_type_info of non-pointer: %r" % s_p + return SomePtr(lltype.typeOf(lltype.runtime_type_info(s_p.ll_ptrtype._example()))) BUILTIN_ANALYZERS[lltype.malloc] = malloc BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.nullptr] = nullptr BUILTIN_ANALYZERS[lltype.cast_pointer] = cast_pointer +BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo +BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info Modified: pypy/dist/pypy/rpython/test/test_llann.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llann.py (original) +++ pypy/dist/pypy/rpython/test/test_llann.py Wed Jun 15 21:37:46 2005 @@ -258,3 +258,25 @@ assert a.binding(vp).ll_ptrtype == T assert a.binding(rv) == annmodel.lltype_to_annotation(T.TO.OF) return a, vTs + + def test_getRuntimeTypeInfo(self): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + def llf(): + return getRuntimeTypeInfo(S) + a = self.RPythonAnnotator() + s, dontcare = annotate_lowlevel_helper(a, llf, []) + assert isinstance(s, annmodel.SomePtr) + assert s.ll_ptrtype == Ptr(RuntimeTypeInfo) + assert s.const == getRuntimeTypeInfo(S) + + def test_runtime_type_info(self): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + def llf(p): + return runtime_type_info(p) + a = self.RPythonAnnotator() + s, dontcare = annotate_lowlevel_helper(a, llf, [annmodel.SomePtr(Ptr(S))]) + assert isinstance(s, annmodel.SomePtr) + assert s.ll_ptrtype == Ptr(RuntimeTypeInfo) + From arigo at codespeak.net Wed Jun 15 22:04:34 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 22:04:34 +0200 (CEST) Subject: [pypy-svn] r13452 - pypy/dist/pypy/rpython Message-ID: <20050615200434.998A827B96@code1.codespeak.net> Author: arigo Date: Wed Jun 15 22:04:33 2005 New Revision: 13452 Modified: pypy/dist/pypy/rpython/rtyper.py Log: Better check the result of rtype_*() functions in the case where it is a Constant. This allows the corresponding code to be shared with the code for Variable results. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 15 22:04:33 2005 @@ -246,10 +246,18 @@ raise TyperError("the annotator doesn't agree that '%s' " "has no return value" % op.opname) op.result.concretetype = Void - elif isinstance(resultvar, Variable): + else: + assert isinstance(resultvar, (Variable, Constant)) # for simplicity of the translate_meth, resultvar is usually not # op.result here. We have to replace resultvar with op.result # in all generated operations. + if isinstance(resultvar, Constant): + if not hop.s_result.is_constant(): + raise TyperError("the annotator doesn't agree that '%s' " + "returns a constant" % op.opname) + if resultvar.value != hop.s_result.const: + raise TyperError("constant mismatch: %r vs %r" % ( + resultvar.value, hop.s_result.const)) resulttype = resultvar.concretetype op.result.concretetype = hop.r_result.lowleveltype if op.result.concretetype != resulttype: @@ -260,7 +268,8 @@ op.opname, hop.s_result, op.result.concretetype, resulttype)) # figure out if the resultvar is a completely fresh Variable or not - if (resultvar not in self.annotator.bindings and + if (isinstance(resultvar, Variable) and + resultvar not in self.annotator.bindings and resultvar not in varmapping): # fresh Variable: rename it to the previously existing op.result varmapping[resultvar] = op.result @@ -268,18 +277,6 @@ # renaming unsafe. Insert a 'same_as' operation... hop.llops.append(SpaceOperation('same_as', [resultvar], op.result)) - else: - # translate_meth() returned a Constant - assert isinstance(resultvar, Constant) - if not hop.s_result.is_constant(): - raise TyperError("the annotator doesn't agree that '%s' " - "returns a constant" % op.opname) - if resultvar.value != hop.s_result.const: - raise TyperError("constant mismatch: %r vs %r" % ( - resultvar.value, hop.s_result.const)) - op.result.concretetype = hop.r_result.lowleveltype - hop.llops.append(SpaceOperation('same_as', [resultvar], - op.result)) def gottypererror(self, e, block, position, llops): """Record a TyperError without crashing immediately. From arigo at codespeak.net Wed Jun 15 22:04:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 22:04:55 +0200 (CEST) Subject: [pypy-svn] r13453 - in pypy/dist/pypy/rpython: . test Message-ID: <20050615200455.1523827B96@code1.codespeak.net> Author: arigo Date: Wed Jun 15 22:04:53 2005 New Revision: 13453 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rptr.py Log: rtyping runtime_type_info() and getRuntimeTypeInfo(). Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Wed Jun 15 22:04:53 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.rpython import lltype from pypy.rpython import rarithmetic -from pypy.rpython.lltype import Void, Signed +from pypy.rpython.lltype import Void, Signed, Ptr, RuntimeTypeInfo from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range from pypy.rpython.rmodel import Repr, TyperError @@ -127,9 +127,20 @@ return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result resulttype = hop.r_result.lowleveltype) +def rtype_getRuntimeTypeInfo(hop): + return hop.inputconst(Ptr(RuntimeTypeInfo), hop.s_result.const) + +def rtype_runtime_type_info(hop): + assert isinstance(hop.args_r[0], rptr.PtrRepr) + vlist = hop.inputargs(hop.args_r[0]) + return hop.genop('runtime_type_info', vlist, + resulttype = rptr.PtrRepr(Ptr(RuntimeTypeInfo))) + BUILTIN_TYPER[lltype.malloc] = rtype_malloc BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result +BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_getRuntimeTypeInfo +BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask Modified: pypy/dist/pypy/rpython/test/test_rptr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rptr.py (original) +++ pypy/dist/pypy/rpython/test/test_rptr.py Wed Jun 15 22:04:53 2005 @@ -31,3 +31,15 @@ return cast_pointer(PS2, p) s, t = ll_rtype(llup, [annmodel.SomePtr(PS)]) assert s.ll_ptrtype == PS2 + +def test_runtime_type_info(): + S = GcStruct('s', ('x', Signed)) + attachRuntimeTypeInfo(S) + def ll_example(p): + return (runtime_type_info(p), + runtime_type_info(p) == getRuntimeTypeInfo(S)) + + assert ll_example(malloc(S)) == (getRuntimeTypeInfo(S), True) + s, t = ll_rtype(ll_example, [annmodel.SomePtr(Ptr(S))]) + assert s == annmodel.SomeTuple([annmodel.SomePtr(Ptr(RuntimeTypeInfo)), + annmodel.SomeBool()]) From arigo at codespeak.net Wed Jun 15 22:15:49 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 22:15:49 +0200 (CEST) Subject: [pypy-svn] r13454 - pypy/dist/pypy/rpython Message-ID: <20050615201549.0308727B95@code1.codespeak.net> Author: arigo Date: Wed Jun 15 22:15:47 2005 New Revision: 13454 Modified: pypy/dist/pypy/rpython/rbuiltin.py Log: Fix the rtyping of nullptr(). This gives a more general rtype_const_result() that can be reused for getRuntimeTypeInfo() too. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Wed Jun 15 22:15:47 2005 @@ -118,7 +118,7 @@ resulttype = hop.r_result.lowleveltype) def rtype_const_result(hop): - return hop.inputconst(Void, hop.s_result.const) + return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) def rtype_cast_pointer(hop): assert hop.args_s[0].is_constant() @@ -127,9 +127,6 @@ return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result resulttype = hop.r_result.lowleveltype) -def rtype_getRuntimeTypeInfo(hop): - return hop.inputconst(Ptr(RuntimeTypeInfo), hop.s_result.const) - def rtype_runtime_type_info(hop): assert isinstance(hop.args_r[0], rptr.PtrRepr) vlist = hop.inputargs(hop.args_r[0]) @@ -141,6 +138,6 @@ BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result -BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_getRuntimeTypeInfo +BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask From pedronis at codespeak.net Wed Jun 15 22:16:40 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 22:16:40 +0200 (CEST) Subject: [pypy-svn] r13455 - pypy/dist/pypy/annotation Message-ID: <20050615201640.ECB1027B95@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 22:16:40 2005 New Revision: 13455 Modified: pypy/dist/pypy/annotation/builtin.py Log: let nullptr annotation use immutable value too Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Wed Jun 15 22:16:40 2005 @@ -306,9 +306,7 @@ def nullptr(T): assert T.is_constant() p = lltype.nullptr(T.const) - r = SomePtr(lltype.typeOf(p)) - r.const = p - return r + return immutablevalue(p) def cast_pointer(PtrT, s_p): assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p From tismer at codespeak.net Wed Jun 15 22:52:00 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 15 Jun 2005 22:52:00 +0200 (CEST) Subject: [pypy-svn] r13457 - in pypy/dist/pypy/rpython: . test Message-ID: <20050615205200.3B9D627B8E@code1.codespeak.net> Author: tismer Date: Wed Jun 15 22:51:59 2005 New Revision: 13457 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_interp.py Log: started a bit with exceptions. stunned a bit how complicated exceptions look, in comparison to simple objects like number results? Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Wed Jun 15 22:51:59 2005 @@ -2,6 +2,8 @@ from pypy.rpython.lltype import _ptr import py +class RPythonError(Exception): + pass class LLInterpreter(object): """ low level interpreter working with concrete values. """ @@ -65,7 +67,15 @@ # determine nextblock and/or return value if len(block.exits) == 0: - # return block + # return block + if len(block.inputargs) == 2: + # exception + etypevar, evaluevar = block.getvariables() + etype = self.getval(etypevar) + #rint etype + evalue = self.getval(evaluevar) + # watch out, these are _ptr's + raise RPythonError(etype, evalue) resultvar, = block.getvariables() result = self.getval(resultvar) # self.log.operation("returning", result) @@ -80,7 +90,10 @@ def eval_operation(self, operation): # self.log.operation("considering", operation) ophandler = self.getoperationhandler(operation.opname) - vals = [self.getval(x) for x in operation.args] + vals = [self.getval(x) for x in operation.args] + # if these special cases pile up, do something better here + if operation.opname == 'cast_pointer': + vals.insert(0, operation.result.concretetype) retval = ophandler(*vals) self.setvar(operation.result, retval) @@ -127,8 +140,11 @@ assert isinstance(array,_ptr) return array[index] # the diff between op_getarrayitem and op_getarraysubstruct - # is the same as between op_getfield and op_getsubstruct - + # is the same as between op_getfield and op_getsubstruct + + def op_cast_pointer(self, tp, obj): + # well, actually this is what's now in the globals. + return cast_pointer(tp, obj) # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Wed Jun 15 22:51:59 2005 @@ -55,6 +55,14 @@ finally: TLS.nested_hash_level -= 1 + # due to this dynamic hash value, we must forbid + # pickling, until we have an algorithm for that + def __reduce_ex__(self, *args): + raise Exception('%s insts cannot be pickled, yet. __hash__ is not' + ' constant during reconstruction.' % + self.__class__.__name__) + __reduce__ = __reduce_ex__ + def __repr__(self): return '<%s>' % (self,) Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Wed Jun 15 22:51:59 2005 @@ -2,7 +2,7 @@ import py py.magic.autopath() from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.interp import LLInterpreter +from pypy.rpython.interp import LLInterpreter, RPythonError from pypy.translator.translator import Translator def gengraph(func, argtypes=[]): @@ -36,6 +36,15 @@ assert res == 43 res = interpret(simple_ifs, [1]) assert res == 42 + +def test_raise(): + res = interpret(raise_exception, [41]) + assert res == 41 + info = raises(RPythonError, interpret, raise_exception, [42]) + # XXX inspect which exception this was. + # rtyper.getexceptiondata().ll_exception_match() + # llexitcase not available here + # maybe I use pyexcclass2exc ??? def test_while_simple(): res = interpret(while_simple, [3]) @@ -99,7 +108,12 @@ while i > 0: sum += i i -= 1 - return sum + return sum + +def raise_exception(i): + if i == 42: + raise IndexError + return i #__________________________________________________________________ # interactive playing From arigo at codespeak.net Wed Jun 15 22:56:39 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 15 Jun 2005 22:56:39 +0200 (CEST) Subject: [pypy-svn] r13458 - pypy/dist/pypy/rpython/test Message-ID: <20050615205639.D2E8B27B8E@code1.codespeak.net> Author: arigo Date: Wed Jun 15 22:56:38 2005 New Revision: 13458 Modified: pypy/dist/pypy/rpython/test/test_interp.py Log: Actually, you don't need so many strange '._obj0' accesses to fish the information. All names starting with '_' are meant to be hidden and not used from outside. There are some exception that are ok to use in some specific cases. Note that at places like that we usually cannot remove the '_' because it might collide with an attribute or field name defined by the caller. Some guidelines of '_' attributes that are kind of ok to use: * '_obj' on a _ptr object *in special cases only*. Normally, the _struct and other classes are only an implementation detail; no instance of _struct should ever escape lltype. The _ptr provides an interface to all low-level operations on them. (Something missing now is an interface to access attributes of _func and _pyobject; right now there is no other way than via '_obj'.) * '_name', '_names', '_flds' on a Struct, to introspect its shape. Other attributes should have accessor functions, e.g. don't read '_TYPE' but call typeOf(), which works for primitive objects too. From the type, you can fish for most information: '.TO' to dereference a Ptr, '.OF' to get at the items of an Array, or '.fieldname' to get at the type of a field in a Struct. FuncTypes have an ARGS list and a RESULT. Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Wed Jun 15 22:56:38 2005 @@ -1,6 +1,7 @@ import py py.magic.autopath() +from pypy.rpython.lltype import typeOf from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.interp import LLInterpreter, RPythonError from pypy.translator.translator import Translator @@ -55,7 +56,7 @@ val1 = t(3) val2 = t(4) gcres = interpret(comparisons, [val1, val2]) - res = [getattr(gcres._obj0, x) for x in gcres._obj0._TYPE._names] + res = [getattr(gcres, x) for x in typeOf(gcres).TO._names] assert res == [True, True, False, True, False, False] def XXXtest_some_builtin(): From pedronis at codespeak.net Wed Jun 15 23:05:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 15 Jun 2005 23:05:53 +0200 (CEST) Subject: [pypy-svn] r13459 - pypy/dist/pypy/rpython Message-ID: <20050615210553.3D58527B93@code1.codespeak.net> Author: pedronis Date: Wed Jun 15 23:05:52 2005 New Revision: 13459 Modified: pypy/dist/pypy/rpython/lltype.py Log: added comment about the really internal detail nature of _ptr _setobj, _getobj and _obj0 vs. the _obj property Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Wed Jun 15 23:05:52 2005 @@ -456,6 +456,8 @@ def __nonzero__(self): return self._obj is not None + # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, + # use _obj if necessary instead ! def _setobj(self, pointing_to, immortal=False): if pointing_to is None: obj0 = None From hpk at codespeak.net Thu Jun 16 01:34:30 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 16 Jun 2005 01:34:30 +0200 (CEST) Subject: [pypy-svn] r13462 - in pypy/dist/pypy/rpython: . test Message-ID: <20050615233430.0359A27B95@code1.codespeak.net> Author: hpk Date: Thu Jun 16 01:34:27 2005 New Revision: 13462 Modified: pypy/dist/pypy/rpython/interp.py (contents, props changed) pypy/dist/pypy/rpython/rbool.py (props changed) pypy/dist/pypy/rpython/rfloat.py (props changed) pypy/dist/pypy/rpython/test/snippet.py (props changed) pypy/dist/pypy/rpython/test/test_interp.py (contents, props changed) pypy/dist/pypy/rpython/test/test_rbool.py (props changed) pypy/dist/pypy/rpython/test/test_rfloat.py (props changed) pypy/dist/pypy/rpython/test/test_rint.py (props changed) Log: puh, fixeol (also needed some manual tweaking because we had mixed line-styles and svn refuses to set line-styles then) Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 01:34:27 2005 @@ -2,8 +2,8 @@ from pypy.rpython.lltype import _ptr import py -class RPythonError(Exception): - pass +class RPythonError(Exception): + pass class LLInterpreter(object): """ low level interpreter working with concrete values. """ @@ -67,14 +67,14 @@ # determine nextblock and/or return value if len(block.exits) == 0: - # return block - if len(block.inputargs) == 2: - # exception - etypevar, evaluevar = block.getvariables() - etype = self.getval(etypevar) - #rint etype - evalue = self.getval(evaluevar) - # watch out, these are _ptr's + # return block + if len(block.inputargs) == 2: + # exception + etypevar, evaluevar = block.getvariables() + etype = self.getval(etypevar) + #rint etype + evalue = self.getval(evaluevar) + # watch out, these are _ptr's raise RPythonError(etype, evalue) resultvar, = block.getvariables() result = self.getval(resultvar) @@ -90,9 +90,9 @@ def eval_operation(self, operation): # self.log.operation("considering", operation) ophandler = self.getoperationhandler(operation.opname) - vals = [self.getval(x) for x in operation.args] - # if these special cases pile up, do something better here - if operation.opname == 'cast_pointer': + vals = [self.getval(x) for x in operation.args] + # if these special cases pile up, do something better here + if operation.opname == 'cast_pointer': vals.insert(0, operation.result.concretetype) retval = ophandler(*vals) self.setvar(operation.result, retval) @@ -140,10 +140,10 @@ assert isinstance(array,_ptr) return array[index] # the diff between op_getarrayitem and op_getarraysubstruct - # is the same as between op_getfield and op_getsubstruct + # is the same as between op_getfield and op_getsubstruct - def op_cast_pointer(self, tp, obj): - # well, actually this is what's now in the globals. + def op_cast_pointer(self, tp, obj): + # well, actually this is what's now in the globals. return cast_pointer(tp, obj) # __________________________________________________________ # primitive operations Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Thu Jun 16 01:34:27 2005 @@ -37,15 +37,15 @@ assert res == 43 res = interpret(simple_ifs, [1]) assert res == 42 - -def test_raise(): - res = interpret(raise_exception, [41]) - assert res == 41 - info = raises(RPythonError, interpret, raise_exception, [42]) - # XXX inspect which exception this was. - # rtyper.getexceptiondata().ll_exception_match() - # llexitcase not available here - # maybe I use pyexcclass2exc ??? + +def test_raise(): + res = interpret(raise_exception, [41]) + assert res == 41 + info = raises(RPythonError, interpret, raise_exception, [42]) + # XXX inspect which exception this was. + # rtyper.getexceptiondata().ll_exception_match() + # llexitcase not available here + # maybe I use pyexcclass2exc ??? def test_while_simple(): res = interpret(while_simple, [3]) @@ -109,11 +109,11 @@ while i > 0: sum += i i -= 1 - return sum - -def raise_exception(i): - if i == 42: - raise IndexError + return sum + +def raise_exception(i): + if i == 42: + raise IndexError return i #__________________________________________________________________ From arigo at codespeak.net Thu Jun 16 01:55:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 01:55:58 +0200 (CEST) Subject: [pypy-svn] r13463 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050615235558.D358B27B95@code1.codespeak.net> Author: arigo Date: Thu Jun 16 01:55:54 2005 New Revision: 13463 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_genc.py Log: - Enhanced the runtime type info query functions' allowed signature to allow structures and substructures to share the same function, which is usually what we need. - Sane comparison and hasing for _func. - An helper on the rtyper to produce these runtime type info query functions and attach them to the GcStructs. - Performance bug fix in annlowlevel.py. - Updated rclass.py to generate the appropriate runtime type info query functions, reading from an "rtti" field in the vtable. - Teached GenC about how to use these functions to perform the deallocations correctly. For now, this was probably the last big missing piece to make the GenC/lltype combination good enough. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Thu Jun 16 01:55:54 2005 @@ -56,7 +56,7 @@ (ll_function, args), key = decide_callable(annotator.bookkeeper, None, ll_function, args, mono=True, unpacked=True) args_s, kwds_s = args.unpack() assert not kwds_s - oldblocks = annotator.annotated.keys() + oldblocks = annotator.annotated.copy() s = annotator.build_types(ll_function, args_s) newblocks = [block for block in annotator.annotated.iterkeys() if block not in oldblocks] # invoke annotation simplifications for the new blocks Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Thu Jun 16 01:55:54 2005 @@ -165,8 +165,14 @@ if self._runtime_type_info is None: self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self) if funcptr is not None: - if not typeOf(funcptr) == Ptr(FuncType([Ptr(self)], Ptr(RuntimeTypeInfo))): - raise TypeError, "expected a runtime type info function implementation, got: %s" % funcptr + T = typeOf(funcptr) + if (not isinstance(T, Ptr) or + not isinstance(T.TO, FuncType) or + len(T.TO.ARGS) != 1 or + T.TO.RESULT != Ptr(RuntimeTypeInfo) or + castable(T.TO.ARGS[0], Ptr(self)) < 0): + raise TypeError("expected a runtime type info function " + "implementation, got: %s" % funcptr) self._runtime_type_info._obj.query_funcptr = funcptr class Array(ContainerType): @@ -681,6 +687,16 @@ def __str__(self): return "func %s" % self._name + def __eq__(self, other): + return (self.__class__ is other.__class__ and + self.__dict__ == other.__dict__) + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + return hash(frozendict(self.__dict__)) + class _opaque(object): def __init__(self, TYPE, **attrs): self._TYPE = TYPE @@ -773,7 +789,8 @@ static_info = getRuntimeTypeInfo(T.TO) query_funcptr = getattr(static_info._obj, 'query_funcptr', None) if query_funcptr is not None: - result2 = query_funcptr(p) + T = typeOf(query_funcptr).TO.ARGS[0] + result2 = query_funcptr(cast_pointer(T, p)) if result != result2: raise RuntimeError, ("runtime type-info function for %s:\n" " returned: %s,\n" Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 16 01:55:54 2005 @@ -11,6 +11,7 @@ # # struct object_vtable { # struct object_vtable* parenttypeptr; +# RuntimeTypeInfo * rtti; # array { char } * name; # } # @@ -37,6 +38,7 @@ TYPEPTR = Ptr(OBJECT_VTABLE) OBJECT_VTABLE.become(Struct('object_vtable', ('parenttypeptr', TYPEPTR), + ('rtti', Ptr(RuntimeTypeInfo)), ('name', Ptr(Array(Char))))) OBJECT = GcStruct('object', ('typeptr', TYPEPTR)) @@ -200,6 +202,9 @@ if self.classdef is None: # initialize the 'parenttypeptr' and 'name' fields vtable.parenttypeptr = rsubcls.rbase.getvtable() + rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) + rinstance.setup() + vtable.rtti = getRuntimeTypeInfo(rinstance.object_type) if rsubcls.classdef is None: name = 'object' else: @@ -338,6 +343,9 @@ allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields + self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, + ll_runtime_type_info, + OBJECT) self.initialized = True def convert_const(self, value, targetptr=None, vtable=None): @@ -506,3 +514,6 @@ return False subcls = subcls.parenttypeptr return True + +def ll_runtime_type_info(obj): + return obj.typeptr.rtti Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 16 01:55:54 2005 @@ -6,7 +6,8 @@ from pypy.objspace.flow.model import SpaceOperation, last_exception from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void from pypy.rpython.lltype import LowLevelType, Ptr, ContainerType -from pypy.rpython.lltype import FuncType, functionptr, typeOf +from pypy.rpython.lltype import FuncType, functionptr, typeOf, RuntimeTypeInfo +from pypy.rpython.lltype import attachRuntimeTypeInfo from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr @@ -336,6 +337,20 @@ return self.bindingrepr(v).lowleveltype return getfunctionptr(self.annotator.translator, func, getconcretetype) + def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): + self.call_all_setups() # compute ForwardReferences now + attachRuntimeTypeInfo(GCSTRUCT) + if ARG_GCSTRUCT is None: + ARG_GCSTRUCT = GCSTRUCT + args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))] + s, spec_function = annotate_lowlevel_helper(self.annotator, + func, args_s) + if (not isinstance(s, annmodel.SomePtr) or + s.ll_ptrtype != Ptr(RuntimeTypeInfo)): + raise TyperError("runtime type info function %r returns %r, " + "excepted Ptr(RuntimeTypeInfo)" % (func, s)) + funcptr = self.getfunctionptr(spec_function) + attachRuntimeTypeInfo(GCSTRUCT, funcptr) # ____________________________________________________________ Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Thu Jun 16 01:55:54 2005 @@ -1,6 +1,6 @@ from pypy.rpython.lltype import Primitive, Ptr, typeOf from pypy.rpython.lltype import Struct, Array, FuncType, PyObject, Void -from pypy.rpython.lltype import ContainerType, pyobjectptr +from pypy.rpython.lltype import ContainerType, pyobjectptr, OpaqueType, GcStruct from pypy.rpython.rmodel import getfunctionptr from pypy.objspace.flow.model import Constant from pypy.translator.c.primitive import PrimitiveName, PrimitiveType @@ -69,6 +69,11 @@ argtypes.append(cdecl(argtype, argname)) argtypes = ', '.join(argtypes) or 'void' return resulttype.replace('@', '(@)(%s)' % argtypes) + elif isinstance(T, OpaqueType): + if T.tag == 'RuntimeTypeInfo': + return 'void (@)(void *)' # void dealloc_xx(struct xx *) + else: + raise Exception("don't know about opaque type %r" % (T,)) else: raise Exception("don't know about type %r" % (T,)) Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Thu Jun 16 01:55:54 2005 @@ -1,7 +1,8 @@ from __future__ import generators from pypy.rpython.lltype import Struct, Array, FuncType, PyObjectType, typeOf from pypy.rpython.lltype import GcStruct, GcArray, GC_CONTAINER, ContainerType -from pypy.rpython.lltype import parentlink, Ptr, PyObject, Void +from pypy.rpython.lltype import parentlink, Ptr, PyObject, Void, OpaqueType +from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo from pypy.translator.c.funcgen import FunctionCodeGenerator from pypy.translator.c.external import CExternalFunctionCodeGenerator from pypy.translator.c.support import cdecl, somelettersfrom @@ -20,6 +21,7 @@ class StructDefNode: refcount = None deallocator = None + static_deallocator = None def __init__(self, db, STRUCT, varlength=1): self.db = db @@ -57,11 +59,35 @@ firstfieldname, firstfieldtype = self.fields[0] firstdefnode = db.gettypedefnode(T) self.refcount = '%s.%s' % (firstfieldname, firstdefnode.refcount) + # check here that there is enough run-time type information to + # handle this case + getRuntimeTypeInfo(STRUCT) + getRuntimeTypeInfo(T) - # is a specific deallocator needed? - if self.refcount and varlength == 1 and list(self.deallocator_lines('')): + # do we need deallocator(s)? + if self.refcount and varlength == 1: self.deallocator = db.namespace.uniquename('dealloc_'+self.name) + # are two deallocators needed (a dynamic one for DECREF, which checks + # the real type of the structure and calls the static deallocator) ? + if (isinstance(STRUCT, GcStruct) and + STRUCT._runtime_type_info is not None): + self.static_deallocator = db.namespace.uniquename( + 'staticdealloc_'+self.name) + fnptr = STRUCT._runtime_type_info._obj.query_funcptr + if fnptr is None: + raise NotImplementedError( + "attachRuntimeTypeInfo(): please provide a function") + self.rtti_query_funcptr = db.get(fnptr) + T = typeOf(fnptr).TO.ARGS[0] + self.rtti_query_funcptr_argtype = db.gettype(T) + else: + # is a deallocator really needed, or would it be empty? + if list(self.deallocator_lines('')): + self.static_deallocator = self.deallocator + else: + self.deallocator = None + def c_struct_field_name(self, name): return self.prefix + name @@ -83,12 +109,27 @@ line = '/* %s */' % line yield '\t' + line yield '};' - elif phase == 2 and self.deallocator: - yield 'void %s(struct %s *p) {' % (self.deallocator, self.name) - for line in self.deallocator_lines('p->'): - yield '\t' + line - yield '\tOP_FREE(p);' - yield '}' + + elif phase == 2: + if self.static_deallocator: + yield 'void %s(struct %s *p) {' % (self.static_deallocator, + self.name) + for line in self.deallocator_lines('p->'): + yield '\t' + line + yield '\tOP_FREE(p);' + yield '}' + if self.deallocator and self.deallocator != self.static_deallocator: + yield 'void %s(struct %s *p) {' % (self.deallocator, self.name) + yield '\tvoid (*staticdealloc) (void *);' + # the refcount should be 0; temporarily bump it to 1 + yield '\tp->%s = 1;' % (self.refcount,) + # cast 'p' to the type expected by the rtti_query function + yield '\tstaticdealloc = %s((%s) p);' % ( + self.rtti_query_funcptr, + cdecl(self.rtti_query_funcptr_argtype, '')) + yield '\tif (!--p->%s)' % (self.refcount,) + yield '\t\tstaticdealloc(p);' + yield '}' def deallocator_lines(self, prefix): STRUCT = self.STRUCT @@ -390,6 +431,28 @@ raise ValueError, "don't know how to generate code for %r" % (fnptr,) +class OpaqueNode(ContainerNode): + globalcontainer = True + typename = 'void (@)(void *)' + + def __init__(self, db, T, obj): + assert T == RuntimeTypeInfo + assert isinstance(obj.about, GcStruct) + self.db = db + self.obj = obj + defnode = db.gettypedefnode(obj.about) + self.implementationtypename = 'void (@)(struct %s *)' % ( + defnode.name,) + self.name = defnode.static_deallocator + self.ptrname = '((void (*)(void *)) %s)' % (self.name,) + + def enum_dependencies(self): + return [] + + def implementation(self): + return [] + + class PyObjectNode(ContainerNode): globalcontainer = True typename = 'PyObject @' @@ -422,5 +485,6 @@ Array: ArrayNode, GcArray: ArrayNode, FuncType: FuncNode, + OpaqueType: OpaqueNode, PyObjectType: PyObjectNode, } Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Thu Jun 16 01:55:54 2005 @@ -142,3 +142,43 @@ assert f1(12, "hello") == "hello" mallocs, frees = module.malloc_counters() assert mallocs == frees + + +def test_runtime_type_info(): + S = GcStruct('s', ('is_actually_s1', Bool)) + S1 = GcStruct('s1', ('sub', S)) + attachRuntimeTypeInfo(S) + attachRuntimeTypeInfo(S1) + def rtti_S(p): + if p.is_actually_s1: + return getRuntimeTypeInfo(S1) + else: + return getRuntimeTypeInfo(S) + def rtti_S1(p): + return getRuntimeTypeInfo(S1) + def does_stuff(): + p = malloc(S) + p.is_actually_s1 = False + p1 = malloc(S1) + p1.sub.is_actually_s1 = True + # and no crash when p and p1 are decref'ed + return sys + t = Translator(does_stuff) + t.annotate([]) + from pypy.rpython.rtyper import RPythonTyper + rtyper = RPythonTyper(t.annotator) + rtyper.attachRuntimeTypeInfoFunc(S, rtti_S) + rtyper.attachRuntimeTypeInfoFunc(S1, rtti_S1) + rtyper.specialize() + #t.view() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(does_stuff)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + f1() + mallocs, frees = module.malloc_counters() + assert mallocs == frees From arigo at codespeak.net Thu Jun 16 02:07:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 02:07:27 +0200 (CEST) Subject: [pypy-svn] r13464 - in pypy/dist/pypy: rpython translator/c/test Message-ID: <20050616000727.D0F0A27B95@code1.codespeak.net> Author: arigo Date: Thu Jun 16 02:07:25 2005 New Revision: 13464 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/translator/c/test/test_database.py Log: Bug fixes. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 16 02:07:25 2005 @@ -188,8 +188,7 @@ """Return a ptr to the vtable of this type.""" if self.vtable is None: self.vtable = malloc(self.vtable_type, immortal=True) - if self.classdef is not None: - self.setup_vtable(self.vtable, self) + self.setup_vtable(self.vtable, self) # vtable = self.vtable if cast_to_typeptr: @@ -201,7 +200,8 @@ given subclass.""" if self.classdef is None: # initialize the 'parenttypeptr' and 'name' fields - vtable.parenttypeptr = rsubcls.rbase.getvtable() + if rsubcls.classdef is not None: + vtable.parenttypeptr = rsubcls.rbase.getvtable() rinstance = getinstancerepr(self.rtyper, rsubcls.classdef) rinstance.setup() vtable.rtti = getRuntimeTypeInfo(rinstance.object_type) Modified: pypy/dist/pypy/translator/c/test/test_database.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_database.py (original) +++ pypy/dist/pypy/translator/c/test/test_database.py Thu Jun 16 02:07:25 2005 @@ -236,26 +236,26 @@ db.complete() dump_on_stdout(db) -def test_nested_gcstruct(): - S1 = GcStruct('inlined', ('x', Signed), ('y', Ptr(PyObject))) - S = GcStruct('testing', ('head', S1), - ('ptr2', Ptr(S1)), - ('z', Signed)) - def ll_f(x): - ptr2 = malloc(S1) - ptr2.x = x+1 - s = malloc(S) - s.head.x = x - s.ptr2 = ptr2 - return s.head.x * s.ptr2.x - t = Translator(ll_f) - t.annotate([int]) - t.specialize() +##def test_nested_gcstruct(): +## S1 = GcStruct('inlined', ('x', Signed), ('y', Ptr(PyObject))) +## S = GcStruct('testing', ('head', S1), +## ('ptr2', Ptr(S1)), +## ('z', Signed)) +## def ll_f(x): +## ptr2 = malloc(S1) +## ptr2.x = x+1 +## s = malloc(S) +## s.head.x = x +## s.ptr2 = ptr2 +## return s.head.x * s.ptr2.x +## t = Translator(ll_f) +## t.annotate([int]) +## t.specialize() - db = LowLevelDatabase(t) - db.get(getfunctionptr(t, ll_f)) - db.complete() - dump_on_stdout(db) +## db = LowLevelDatabase(t) +## db.get(getfunctionptr(t, ll_f)) +## db.complete() +## dump_on_stdout(db) def test_array(): A = GcArray(('obj', Ptr(PyObject))) From tismer at codespeak.net Thu Jun 16 02:49:36 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 16 Jun 2005 02:49:36 +0200 (CEST) Subject: [pypy-svn] r13465 - in pypy/dist/pypy/rpython: . test Message-ID: <20050616004936.0438427B95@code1.codespeak.net> Author: tismer Date: Thu Jun 16 02:49:35 2005 New Revision: 13465 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: exceptions work quite nicely, now. There is more work neededto handle functions that call functions that raise. Will get that ready in a few, hopefully. Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 02:49:35 2005 @@ -51,6 +51,9 @@ def eval_function(self, func, args=()): graph = self.flowgraphs[func] + return self.eval_graph(graph,args) + + def eval_graph(self, graph, args=()): nextblock = graph.startblock while 1: self.fillvars(nextblock, args) @@ -66,13 +69,12 @@ self.eval_operation(op) # determine nextblock and/or return value - if len(block.exits) == 0: + if len(block.exits) == 0: # return block if len(block.inputargs) == 2: # exception etypevar, evaluevar = block.getvariables() etype = self.getval(etypevar) - #rint etype evalue = self.getval(evaluevar) # watch out, these are _ptr's raise RPythonError(etype, evalue) @@ -107,37 +109,38 @@ # obj should be pointer setattr(obj, fieldname, fieldvalue) # is that right? -- yes - def op_direct_call(self,f,*args): + def op_direct_call(self, f, *args): # XXX the logic should be: # if f._obj has a graph attribute, interpret # that graph without looking at _callable - res = self.eval_function(f._obj._callable,args) - return res - - def op_malloc(self,obj): + if hasattr(f._obj, 'graph'): + return self.eval_graph(f._obj.graph, args) + return self.eval_function(f._obj._callable, args) + + def op_malloc(self, obj): return malloc(obj) - def op_getfield(self,obj,field): + def op_getfield(self, obj, field): # assert: obj should be pointer - result = getattr(obj,field) + result = getattr(obj, field) # check the difference between op_getfield and op_getsubstruct: # the former returns the real field, the latter a pointer to it assert typeOf(result) == getattr(typeOf(obj).TO, field) return result - def op_getsubstruct(self,obj,field): + def op_getsubstruct(self, obj, field): # assert: obj should be pointer - result = getattr(obj,field) + result = getattr(obj, field) # check the difference between op_getfield and op_getsubstruct: # the former returns the real field, the latter a pointer to it assert typeOf(result) == Ptr(getattr(typeOf(obj).TO, field)) return result - def op_malloc_varsize(self,obj,size): - return malloc(obj,size) + def op_malloc_varsize(self, obj, size): + return malloc(obj, size) - def op_getarraysubstruct(self,array,index): - assert isinstance(array,_ptr) + def op_getarraysubstruct(self, array, index): + assert isinstance(array, _ptr) return array[index] # the diff between op_getarrayitem and op_getarraysubstruct # is the same as between op_getfield and op_getsubstruct Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Thu Jun 16 02:49:35 2005 @@ -5,10 +5,22 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.interp import LLInterpreter, RPythonError from pypy.translator.translator import Translator +from pypy.rpython.lltype import pyobjectptr + +def find_exception(exc): + assert isinstance(exc, RPythonError) + import exceptions + klass, inst = exc.args + func = typer.getexceptiondata().ll_pyexcclass2exc + for cls in exceptions.__dict__.values(): + if type(cls) is type(Exception): + if func(pyobjectptr(cls)).typeptr == klass: + return cls def gengraph(func, argtypes=[]): t = Translator(func) t.annotate(argtypes) + global typer # we need it for find_exception typer = RPythonTyper(t.annotator) typer.specialize() #t.view() @@ -42,10 +54,17 @@ res = interpret(raise_exception, [41]) assert res == 41 info = raises(RPythonError, interpret, raise_exception, [42]) - # XXX inspect which exception this was. - # rtyper.getexceptiondata().ll_exception_match() - # llexitcase not available here - # maybe I use pyexcclass2exc ??? + assert find_exception(info.value) is IndexError + info = raises(RPythonError, interpret, raise_exception, [43]) + assert find_exception(info.value) is ValueError + +def XXXtest_call_raise(): + res = interpret(call_raise_intercept, [41]) + assert res == 41 + info = raises(RPythonError, interpret, call_raise_intercept, [42]) + assert find_exception(info.value) is IndexError + info = raises(RPythonError, interpret, call_raise_intercept, [43]) + assert find_exception(info.value) is TypeError def test_while_simple(): res = interpret(while_simple, [3]) @@ -114,8 +133,15 @@ def raise_exception(i): if i == 42: raise IndexError + elif i == 43: + raise ValueError return i +def call_raise_intercept(i): + try: + return raise_exception(i) + except ValueError: + raise TypeError #__________________________________________________________________ # interactive playing From tismer at codespeak.net Thu Jun 16 04:22:12 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 16 Jun 2005 04:22:12 +0200 (CEST) Subject: [pypy-svn] r13466 - in pypy/dist/pypy/rpython: . test Message-ID: <20050616022212.13FB127B95@code1.codespeak.net> Author: tismer Date: Thu Jun 16 04:22:11 2005 New Revision: 13466 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: waah!! got some serious thinking erroron exception handling. how do I pass exceptions, correctly? one test is failing for now. good nite Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 04:22:11 2005 @@ -1,5 +1,6 @@ from pypy.rpython.lltype import * from pypy.rpython.lltype import _ptr +from pypy.objspace.flow.model import Constant, last_exception import py class RPythonError(Exception): @@ -9,9 +10,10 @@ """ low level interpreter working with concrete values. """ # log = py.log.Producer('llinterp') - def __init__(self, flowgraphs): + def __init__(self, flowgraphs, typer): self.flowgraphs = flowgraphs self.bindings = {} + self.typer = typer # _______________________________________________________ # variable setters/getters helpers @@ -65,8 +67,14 @@ """ return (nextblock, values) tuple. If nextblock is None, values is the concrete return value. """ - for op in block.operations: - self.eval_operation(op) + catch_exception = block.exitswitch == Constant(last_exception) + e = None + + for op in block.operations: + try: + self.eval_operation(op) + except RPythonError, e: + assert catch_exception, 'exception received, but not expected' # determine nextblock and/or return value if len(block.exits) == 0: @@ -82,11 +90,26 @@ result = self.getval(resultvar) # self.log.operation("returning", result) return None, result - elif len(block.exits) == 1: - index = 0 + elif block.exitswitch is None: + # single-exit block + assert len(block.exits) == 1 + link = block.exits[0] + elif catch_exception: + link = block.exits[0] + if e: + exdata = self.typer.getexceptiondata() + cls, inst = e.args + for link in block.exits[1:]: + assert issubclass(link.exitcase, Exception) + if exdata.ll_exception_match(cls, link.llexitcase): + self.setvar(link.last_exception, cls) + self.setvar(link.last_exc_value, inst) + return link.target, [cls, inst] + else: + raise Exception, e # unhandled case, should not happen" else: - index = self.getval(block.exitswitch) - link = block.exits[index] + index = self.getval(block.exitswitch) + link = block.exits[index] return link.target, [self.getval(x) for x in link.args] def eval_operation(self, operation): Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Thu Jun 16 04:22:11 2005 @@ -25,11 +25,11 @@ typer.specialize() #t.view() t.checkgraphs() - return t + return t, typer def interpret(func, values): - t = gengraph(func, [type(x) for x in values]) - interp = LLInterpreter(t.flowgraphs) + t, typer = gengraph(func, [type(x) for x in values]) + interp = LLInterpreter(t.flowgraphs, typer) res = interp.eval_function(func, values) return res @@ -58,7 +58,7 @@ info = raises(RPythonError, interpret, raise_exception, [43]) assert find_exception(info.value) is ValueError -def XXXtest_call_raise(): +def test_call_raise(): res = interpret(call_raise_intercept, [41]) assert res == 41 info = raises(RPythonError, interpret, call_raise_intercept, [42]) From pedronis at codespeak.net Thu Jun 16 05:26:57 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Jun 2005 05:26:57 +0200 (CEST) Subject: [pypy-svn] r13467 - in pypy/dist/pypy: annotation translator translator/goal Message-ID: <20050616032657.B2AB527B95@code1.codespeak.net> Author: pedronis Date: Thu Jun 16 05:26:56 2005 New Revision: 13467 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/goal/query.py Log: start of simple support for keeping statics and infos while annotating of for example violations to additional constraints imposed by rtyper, for example for newslice and the rules (slightly different form what rtyper right now supports): if ((s_start.is_constant() or (isinstance(s_start, SomeInteger) and s_start.nonneg)) and (s_stop.is_constant() or (isinstance(s_stop, SomeInteger) and s_stop.nonneg)) and (s_step.is_constant() and (s_step.const == 1 or s_step.const == None))): return 'proper' return 'inproper' we get after translate_pypy annotation: (Pdb) query.statsfor(t, 'newslice') newslice total = 39 proper | 30 improper | 9 Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 16 05:26:56 2005 @@ -39,6 +39,26 @@ self.objects.update(other.objects) self.patterns.update(other.patterns) +class Stats: + + def __init__(self, bookkeeper): + self.bookkeeper = bookkeeper + self.classify = {} + + def count(self, category, *args): + for_category = self.classify.setdefault(category, {}) + classifier = getattr(self, 'consider_%s' % category) + outcome = classifier(*args) + for_category[self.bookkeeper.position_key] = outcome + + def consider_newslice(self, s_start, s_stop, s_step): + if ((s_start.is_constant() or (isinstance(s_start, SomeInteger) and s_start.nonneg)) and + (s_stop.is_constant() or (isinstance(s_stop, SomeInteger) and s_stop.nonneg)) and + (s_step.is_constant() and (s_step.const == 1 or s_step.const == None))): + return 'proper' + return 'improper' + + class Bookkeeper: """The log of choices that have been made while analysing the operations. It ensures that the same 'choice objects' will be returned if we ask @@ -69,11 +89,15 @@ self.pbc_call_sites = {} - + self.stats = Stats(self) + # import ordering hack global BUILTIN_ANALYZERS from pypy.annotation.builtin import BUILTIN_ANALYZERS + def count(self, category, *args): + self.stats.count(category, *args) + def enter(self, position_key): """Start of an operation. The operation is uniquely identified by the given key.""" Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Thu Jun 16 05:26:56 2005 @@ -611,6 +611,7 @@ return self.bookkeeper.newdict(*items_s) def consider_op_newslice(self, start, stop, step): + self.bookkeeper.count('newslice', start, stop, step) return annmodel.SomeSlice(start, stop, step) Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 16 05:26:56 2005 @@ -311,6 +311,17 @@ print " - many callables, many patterns -" print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) +def statsfor(t, category): + stats = t.annotator.bookkeeper.stats + for_category = stats.classify[category] + print "%s total = %d" % (category, len(for_category)) + counters = {} + for pos, outcome in for_category.iteritems(): + counters[outcome] = counters.get(outcome, 0) + 1 + w = max([len(o) for o in counters.keys()])+1 + for outcome, n in counters.iteritems(): + print "%*s | %d" % (w, outcome, n) + # debug helper def tryout(f, *args): try: From cfbolz at codespeak.net Thu Jun 16 13:20:50 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 16 Jun 2005 13:20:50 +0200 (CEST) Subject: [pypy-svn] r13470 - pypy/dist/pypy/rpython/test Message-ID: <20050616112050.23D0B27B97@code1.codespeak.net> Author: cfbolz Date: Thu Jun 16 13:20:49 2005 New Revision: 13470 Modified: pypy/dist/pypy/rpython/test/test_interp.py Log: Fix interactive use of test_interp. Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Thu Jun 16 13:20:49 2005 @@ -152,10 +152,10 @@ except ImportError: pass - t = gengraph(number_ops, [int]) - interp = LLInterpreter(t.flowgraphs) + t, typer = gengraph(number_ops, [int]) + interp = LLInterpreter(t.flowgraphs, typer) res = interp.eval_function(number_ops, [3]) - assert res == 6 + assert res == number_ops(3) for name, value in globals().items(): if name not in _snap and name[0] != '_': print "%20s: %s" %(name, value) From ale at codespeak.net Thu Jun 16 13:22:22 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 16 Jun 2005 13:22:22 +0200 (CEST) Subject: [pypy-svn] r13471 - pypy/dist/pypy/rpython Message-ID: <20050616112222.AA7AF27B9E@code1.codespeak.net> Author: ale Date: Thu Jun 16 13:22:21 2005 New Revision: 13471 Modified: pypy/dist/pypy/rpython/interp.py Log: added getarraysize Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 13:22:21 2005 @@ -164,10 +164,15 @@ def op_getarraysubstruct(self, array, index): assert isinstance(array, _ptr) + return array[index] # the diff between op_getarrayitem and op_getarraysubstruct # is the same as between op_getfield and op_getsubstruct + def op_getarraysize(self,array): + #print array,type(array),dir(array) + return len(array) + def op_cast_pointer(self, tp, obj): # well, actually this is what's now in the globals. return cast_pointer(tp, obj) From arigo at codespeak.net Thu Jun 16 14:02:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 14:02:20 +0200 (CEST) Subject: [pypy-svn] r13472 - pypy/dist/pypy/rpython Message-ID: <20050616120220.C563127B93@code1.codespeak.net> Author: arigo Date: Thu Jun 16 14:02:19 2005 New Revision: 13472 Modified: pypy/dist/pypy/rpython/rstr.py Log: rstr.py uses Array(Char) instead of Array(('ch', Char)) now. Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 16 14:02:19 2005 @@ -13,13 +13,11 @@ # # struct str { # hash: Signed -# chars: array { -# Char ch -# } +# chars: array of Char # } STR = GcStruct('str', ('hash', Signed), - ('chars', Array(('ch', Char)))) + ('chars', Array(Char))) class __extend__(annmodel.SomeString): @@ -50,7 +48,7 @@ except KeyError: p = malloc(STR, len(value)) for i in range(len(value)): - p.chars[i].ch = value[i] + p.chars[i] = value[i] ll_strhash(p) # precompute the hash CONST_STR_CACHE[value] = p return p @@ -141,11 +139,8 @@ resulttype=Ptr(STR.chars)) v_size = llops.genop('getarraysize', [v_chars], resulttype=Signed) - czero = inputconst(Signed, 0) - v_char0ptr = llops.genop('getarraysubstruct', [v_chars, czero], - resulttype=Ptr(STR.chars.OF)) - return llops.gencapicall('PyString_FromStringAndSize_Hack', - [v_char0ptr, v_size], + return llops.gencapicall('PyString_FromRPythonCharArrayAndSize', + [v_chars, v_size], resulttype=pyobj_repr) # ____________________________________________________________ @@ -158,12 +153,12 @@ return len(s.chars) def ll_stritem_nonneg(s, i): - return s.chars[i].ch + return s.chars[i] def ll_stritem(s, i): if i<0: i += len(s.chars) - return s.chars[i].ch + return s.chars[i] def ll_str_is_true(s): # check if a string is True, allowing for None @@ -171,7 +166,7 @@ def ll_chr2str(ch): s = malloc(STR, 1) - s.chars[0].ch = ch + s.chars[0] = ch return s def ll_strhash(s): @@ -184,10 +179,10 @@ if length == 0: x = -1 else: - x = ord(s.chars[0].ch) << 7 + x = ord(s.chars[0]) << 7 i = 1 while i < length: - x = (1000003*x) ^ ord(s.chars[i].ch) + x = (1000003*x) ^ ord(s.chars[i]) i += 1 x ^= length if x == 0: @@ -201,11 +196,11 @@ newstr = malloc(STR, len1 + len2) j = 0 while j < len1: - newstr.chars[j].ch = s1.chars[j].ch + newstr.chars[j] = s1.chars[j] j += 1 i = 0 while i < len2: - newstr.chars[j].ch = s2.chars[i].ch + newstr.chars[j] = s2.chars[i] i += 1 j += 1 return newstr From adim at codespeak.net Thu Jun 16 14:09:26 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 16 Jun 2005 14:09:26 +0200 (CEST) Subject: [pypy-svn] r13473 - pypy/branch/pycompiler/module/recparser Message-ID: <20050616120926.8796327B93@code1.codespeak.net> Author: adim Date: Thu Jun 16 14:09:24 2005 New Revision: 13473 Modified: pypy/branch/pycompiler/module/recparser/syntaxtree.py pypy/branch/pycompiler/module/recparser/tuplebuilder.py Log: small cleanups in SYMBOL's management Modified: pypy/branch/pycompiler/module/recparser/syntaxtree.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/syntaxtree.py (original) +++ pypy/branch/pycompiler/module/recparser/syntaxtree.py Thu Jun 16 14:09:24 2005 @@ -61,12 +61,13 @@ "|=" : token.VBAREQUAL, } NT_OFFSET = token.NT_OFFSET + SYMBOLS = {} # copies the numerical mapping between symbol name and symbol value # into SYMBOLS -for k,v in symbol.__dict__.items(): - if type(v)==int: - SYMBOLS[k] = v +for k,v in symbol.sym_name.items(): + SYMBOLS[v] = k +SYMBOLS['UNKNOWN'] = -1 class SyntaxNode(object): Modified: pypy/branch/pycompiler/module/recparser/tuplebuilder.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/tuplebuilder.py (original) +++ pypy/branch/pycompiler/module/recparser/tuplebuilder.py Thu Jun 16 14:09:24 2005 @@ -3,11 +3,13 @@ from syntaxtree import TOKEN_MAP, SYMBOLS # , NT_OFFSET +class def _expand_nodes(nodes): expanded = [] for n in nodes: if n[0] == -2: - expanded.extend(expand_nodes(n[1:])) + # expanded.extend(expand_nodes(n[1:])) + expanded.extend(n[1:]) else: expanded.append(n) return tuple(expanded) @@ -24,6 +26,7 @@ def __init__(self, rules=None, debug=0, lineno=True): BaseGrammarBuilder.__init__(self, rules, debug ) self.lineno = lineno + self._unknown = -10 def alternative(self, rule, source): # Do nothing, keep rule on top of the stack @@ -36,7 +39,12 @@ def sequence(self, rule, source, elts_number): """ """ if rule.is_root(): - node = [SYMBOLS.get( rule.name, (0, rule.name) )] + if SYMBOLS.has_key(rule.name): + node = [SYMBOLS[rule.name]] + else: + node = [self._unknown] + SYMBOLS[rule.name] = self._unknown + self._unknown -= 1 else: node = [-2] if elts_number > 0: From arigo at codespeak.net Thu Jun 16 14:10:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 14:10:14 +0200 (CEST) Subject: [pypy-svn] r13474 - pypy/dist/pypy/rpython Message-ID: <20050616121014.1983127B93@code1.codespeak.net> Author: arigo Date: Thu Jun 16 14:10:12 2005 New Revision: 13474 Modified: pypy/dist/pypy/rpython/rlist.py Log: rlist.py now uses GcArray(ITEM) directly instead of GcArray(('item, ITEM)). (This breaks a test in test_interp, because it introduces uses of the new operations 'getarrayitem' and 'setarrayitem'...) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 16 14:10:12 2005 @@ -51,7 +51,7 @@ self.item_repr = self._item_repr_computer() if isinstance(self.LIST, GcForwardReference): ITEM = self.item_repr.lowleveltype - ITEMARRAY = GcArray(("item", ITEM)) + ITEMARRAY = GcArray(ITEM) self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY)))) def rtype_len(self, hop): @@ -149,26 +149,26 @@ newitems = malloc(typeOf(l).TO.items.TO, length+1) i = 0 while i= len(l.items): raise StopIteration iter.index = index + 1 - return l.items[index].item + return l.items[index] From adim at codespeak.net Thu Jun 16 14:10:50 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Thu, 16 Jun 2005 14:10:50 +0200 (CEST) Subject: [pypy-svn] r13476 - pypy/branch/pycompiler/module/recparser Message-ID: <20050616121050.0266627B93@code1.codespeak.net> Author: adim Date: Thu Jun 16 14:10:49 2005 New Revision: 13476 Modified: pypy/branch/pycompiler/module/recparser/automata.py Log: We don't need DEFAULTClass. Using None for DEFAULT is sufficient, and simplifies the annotator work. Modified: pypy/branch/pycompiler/module/recparser/automata.py ============================================================================== --- pypy/branch/pycompiler/module/recparser/automata.py (original) +++ pypy/branch/pycompiler/module/recparser/automata.py Thu Jun 16 14:10:49 2005 @@ -14,21 +14,11 @@ # PYPY Modification: removed the EMPTY class as it's not needed here -# PYPY Modification: Make the DEFAULTClasse inherit from str -# to make the state dict homogeneous -class DEFAULTClass(str): - def __repr__ (self): - return 'automata.DEFAULT' - - def __eq__(self, other): - return False # Never equals other strings - - def __ne__(self, other): - return True # Always different from other strings - - -DEFAULT = DEFAULTClass() - +# PYPY Modification: we don't need a particuliar DEFAULT class here +# a simple None works fine. +# (Having a DefaultClass inheriting from str makes +# the annotator crash) +DEFAULT = None # PYPY Modification : removed all automata functions (any, maybe, # newArcPair, etc.) @@ -69,6 +59,7 @@ return i - 1 else: return -1 + # ______________________________________________________________________ class NonGreedyDFA (DFA): From pedronis at codespeak.net Thu Jun 16 16:07:48 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Jun 2005 16:07:48 +0200 (CEST) Subject: [pypy-svn] r13477 - in pypy/dist/pypy: annotation translator/goal Message-ID: <20050616140748.AAF1927B9E@code1.codespeak.net> Author: pedronis Date: Thu Jun 16 16:07:47 2005 New Revision: 13477 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/translator/goal/query.py Log: some other statics about border-case RPython usages. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 16 16:07:47 2005 @@ -95,42 +95,49 @@ if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const < obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def le((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const <= obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def eq((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const == obj2.const) else: + getbookkeeper().count("non_int_eq", obj1, obj2) return SomeBool() def ne((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const != obj2.const) else: + getbookkeeper().count("non_int_eq", obj1, obj2) return SomeBool() def gt((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const > obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def ge((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(obj1.const >= obj2.const) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeBool() def cmp((obj1, obj2)): if obj1.is_constant() and obj2.is_constant(): return immutablevalue(cmp(obj1.const, obj2.const)) else: + getbookkeeper().count("non_int_comp", obj1, obj2) return SomeInteger() def is_((obj1, obj2)): @@ -388,6 +395,7 @@ except IndexError: return SomeImpossibleValue() else: + getbookkeeper().count("tuple_random_getitem", tup1) return unionof(*tup1.items) Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 16 16:07:47 2005 @@ -58,6 +58,35 @@ return 'proper' return 'improper' + def consider_non_int_eq(self, obj1, obj2): + return obj1.knowntype.__name__, obj2.knowntype.__name__ + + def consider_non_int_comp(self, obj1, obj2): + return obj1.knowntype.__name__, obj2.knowntype.__name__ + + def short(self, obj): + if isinstance(obj, SomeInstance): + return obj.classdef.cls.__name__ + else: + return obj.knowntype.__name__ + + def consider_tuple_iter(self, tup): + if tup.is_constant(): + return 'constant tuple' + else: + return tuple([self.short(x) for x in tup.items]) + + def consider_tuple_random_getitem(self, tup): + return tuple([self.short(x) for x in tup.items]) + + def consider_list_index(self): + return '!' + + def consider_str_join(self, s): + if s.is_constant(): + return repr(s.const) + else: + return "NON-CONSTANT" class Bookkeeper: """The log of choices that have been made while analysing the operations. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Thu Jun 16 16:07:47 2005 @@ -197,6 +197,7 @@ return immutablevalue(len(tup.items)) def iter(tup): + getbookkeeper().count("tuple_iter", tup) return SomeIterator(tup) def getanyitem(tup): @@ -226,6 +227,7 @@ return lst.listdef.read_item() def method_index(lst, el): + getbookkeeper().count("list_index") return SomeInteger(nonneg=True) def len(lst): @@ -289,6 +291,7 @@ return SomeBool() def method_join(str, s_list): + getbookkeeper().count("str_join", str) return SomeString() def iter(str): Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 16 16:07:47 2005 @@ -318,7 +318,7 @@ counters = {} for pos, outcome in for_category.iteritems(): counters[outcome] = counters.get(outcome, 0) + 1 - w = max([len(o) for o in counters.keys()])+1 + w = max([len(str(o)) for o in counters.keys()])+1 for outcome, n in counters.iteritems(): print "%*s | %d" % (w, outcome, n) From arigo at codespeak.net Thu Jun 16 16:37:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 16:37:27 +0200 (CEST) Subject: [pypy-svn] r13478 - pypy/dist/pypy/translator/c Message-ID: <20050616143727.DEEE527B99@code1.codespeak.net> Author: arigo Date: Thu Jun 16 16:37:26 2005 New Revision: 13478 Modified: pypy/dist/pypy/translator/c/g_support.h Log: Oups, forgot to check this in. Modified: pypy/dist/pypy/translator/c/g_support.h ============================================================================== --- pypy/dist/pypy/translator/c/g_support.h (original) +++ pypy/dist/pypy/translator/c/g_support.h Thu Jun 16 16:37:26 2005 @@ -369,5 +369,5 @@ return PyTuple_SetItem(tuple, index, o); } -#define PyString_FromStringAndSize_Hack(s, size) \ - PyString_FromStringAndSize((char*)(s), size) +#define PyString_FromRPythonCharArrayAndSize(itemsarray, size) \ + PyString_FromStringAndSize(itemsarray->items, size) From arigo at codespeak.net Thu Jun 16 17:17:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 17:17:09 +0200 (CEST) Subject: [pypy-svn] r13479 - pypy/dist/pypy/translator Message-ID: <20050616151709.0C87527B99@code1.codespeak.net> Author: arigo Date: Thu Jun 16 17:17:08 2005 New Revision: 13479 Removed: pypy/dist/pypy/translator/typer.py Log: Removed the old typer. Most of the logic was copied into the rtyper. Deleted: /pypy/dist/pypy/translator/typer.py ============================================================================== --- /pypy/dist/pypy/translator/typer.py Thu Jun 16 17:17:08 2005 +++ (empty file) @@ -1,209 +0,0 @@ -from __future__ import generators -import autopath -from pypy.objspace.flow.model import SpaceOperation, Variable, Constant -from pypy.objspace.flow.model import Block, Link, uniqueitems -from pypy.translator.unsimplify import insert_empty_block - - -class TyperError(Exception): - def __str__(self): - result = Exception.__str__(self) - if hasattr(self, 'where'): - result += '\n.. %r\n.. %r' % self.where - return result - - -class Specializer: - - def __init__(self, annotator, defaultconcretetype, typematches, - specializationtable): - self.annotator = annotator - self.defaultconcretetype = defaultconcretetype - self.typematches = typematches - # turn the table into a dict for faster look-ups - d = {} - for e in specializationtable: - opname1 = e[0] - opname2 = e[1] - spectypes = e[2:-1] - restype = e[-1] - info = opname2, spectypes, restype - d.setdefault(opname1, []).append(info) - d.setdefault(opname2, []).append(info) - self.specializationdict = d - - def specialize(self): - """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.""" - assert isinstance(a, Variable) - if hasattr(a, 'concretetype') and a.concretetype != concretetype: - raise TyperError, "inconsitent type for %r: %r != %r" % ( - a, a.concretetype, concretetype) - a.concretetype = concretetype - - def setbesttype(self, a): - """Set the best concretetype for a Variable according to - the annotations.""" - try: - return a.concretetype - except AttributeError: - s_value = self.annotator.binding(a, True) - if s_value is not None: - besttype = self.annotation2concretetype(s_value) - else: - besttype = self.defaultconcretetype - self.settype(a, besttype) - return besttype - - def annotation2concretetype(self, s_value): - for concretetype in self.typematches: - if concretetype.s_annotation.contains(s_value): - return concretetype - return self.defaultconcretetype - - def convertvar(self, v, concretetype): - """Get the operation(s) needed to convert 'v' to the given type.""" - ops = [] - if isinstance(v, Constant): - # we should never modify a Constant in-place - v = Constant(v.value) - v.concretetype = concretetype - - elif hasattr(v, 'concretetype') and v.concretetype != concretetype: - # XXX do we need better conversion paths? - - # 1) convert to the generic type - if v.concretetype != self.defaultconcretetype: - v2 = Variable() - v2.concretetype = self.defaultconcretetype - newops = list(v.concretetype.convert_to_obj(self, v, v2)) - v = v2 - ops += newops - - # 2) convert back from the generic type - if concretetype != self.defaultconcretetype: - v2 = Variable() - v2.concretetype = concretetype - newops = list(concretetype.convert_from_obj(self, v, v2)) - v = v2 - ops += newops - - return v, ops - - def specialize_block(self, block): - # give the best possible types to the input args - for a in block.inputargs: - self.setbesttype(a) - - # specialize all the operations, as far as possible - newops = [] - for op in block.operations: - - args = list(op.args) - bindings = [self.annotator.binding(a, True) for a in args] - - # replace constant annotations with real Constants - for i in range(len(op.args)): - if isinstance(args[i], Variable) and bindings[i] is not None: - if bindings[i].is_constant(): - args[i] = Constant(bindings[i].const) - op = SpaceOperation(op.opname, args, op.result) - - # make a specialized version of the current operation - # (which may become several operations) - try: - flatten_ops(self.specialized_op(op, bindings), newops) - except TyperError, e: - e.where = (block, op) - raise - - block.operations[:] = newops - self.insert_link_conversions(block) - - - def typed_op(self, op, argtypes, restype, newopname=None): - """Make a typed copy of the given SpaceOperation.""" - result = [] - args = list(op.args) - assert len(argtypes) == len(args) - - # type-convert the input arguments - for i in range(len(args)): - args[i], convops = self.convertvar(args[i], argtypes[i]) - result += convops - - # store the result variable's type - self.settype(op.result, restype) - - # store the possibly modified SpaceOperation - op = SpaceOperation(newopname or op.opname, args, op.result) - result.append(op) - return result - - - def insert_link_conversions(self, block): - # insert the needed conversions on the links - can_insert_here = block.exitswitch is None and len(block.exits) == 1 - for link in block.exits: - try: - for i in range(len(link.args)): - a1 = link.args[i] - if a1 in (link.last_exception, link.last_exc_value):# treated specially in gen_link - continue - a2 = link.target.inputargs[i] - a2type = self.setbesttype(a2) - a1, convops = self.convertvar(a1, a2type) - if convops and not can_insert_here: - # cannot insert conversion operations around a single - # link, unless it is the only exit of this block. - # create a new block along the link... - newblock = insert_empty_block(self.annotator.translator, - link) - # ...and do the conversions there. - self.insert_link_conversions(newblock) - break # done with this link - flatten_ops(convops, block.operations) - link.args[i] = a1 - except TyperError, e: - e.where = (block, link) - raise - - - def specialized_op(self, op, bindings): - specializations = self.specializationdict.get(op.opname, ()) - for opname2, spectypes, restype in specializations: - assert len(spectypes) == len(op.args) == len(bindings) - for i in range(len(spectypes)): - if bindings[i] is None: - break - if not spectypes[i].s_annotation.contains(bindings[i]): - break - else: - # specialization found - yield self.typed_op(op, spectypes, restype, newopname=opname2) - return - # specialization not found - argtypes = [self.defaultconcretetype] * len(op.args) - yield self.typed_op(op, argtypes, self.defaultconcretetype) - - -def flatten_ops(op, newops): - # Flatten lists and generators and record all SpaceOperations found - if isinstance(op, SpaceOperation): - newops.append(op) - else: - for op1 in op: - flatten_ops(op1, newops) From arigo at codespeak.net Thu Jun 16 17:32:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 17:32:22 +0200 (CEST) Subject: [pypy-svn] r13480 - in pypy/dist/pypy/rpython: . test Message-ID: <20050616153222.2219B27B80@code1.codespeak.net> Author: arigo Date: Thu Jun 16 17:32:19 2005 New Revision: 13480 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rclass.py Log: - Use cast_pointer more explicitely in rclass.py. Required for prebuilt instances to work -- but there was no test for them. - Docstring of rtyper module. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 16 17:32:19 2005 @@ -391,33 +391,31 @@ raise MissingRTypeAttribute(attr) return self.rbase.getfieldrepr(attr) - def getfield(self, vinst, attr, llops, start_repr=None): + def getfield(self, vinst, attr, llops, force_cast=False): """Read the given attribute (or __class__ for the type) of 'vinst'.""" - if start_repr is None: - start_repr = self if attr in self.fields: mangled_name, r = self.fields[attr] cname = inputconst(Void, mangled_name) - vinst = llops.convertvar(vinst, start_repr, self) + if force_cast: + vinst = llops.genop('cast_pointer', [vinst], resulttype=self) return llops.genop('getfield', [vinst, cname], resulttype=r) else: if self.classdef is None: raise MissingRTypeAttribute(attr) - return self.rbase.getfield(vinst, attr, llops, start_repr=start_repr) + return self.rbase.getfield(vinst, attr, llops, force_cast=True) - def setfield(self, vinst, attr, vvalue, llops, start_repr=None): + def setfield(self, vinst, attr, vvalue, llops, force_cast=False): """Write the given attribute (or __class__ for the type) of 'vinst'.""" - if start_repr is None: - start_repr = self if attr in self.fields: mangled_name, r = self.fields[attr] cname = inputconst(Void, mangled_name) - vinst = llops.convertvar(vinst, start_repr, self) + if force_cast: + vinst = llops.genop('cast_pointer', [vinst], resulttype=self) llops.genop('setfield', [vinst, cname, vvalue]) else: if self.classdef is None: raise MissingRTypeAttribute(attr) - self.rbase.setfield(vinst, attr, vvalue, llops, start_repr=start_repr) + self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True) def new_instance(self, llops): """Build a new instance, without calling __init__.""" Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 16 17:32:19 2005 @@ -1,3 +1,16 @@ +""" +RTyper: converts high-level operations into low-level operations in flow graphs. + +The main class, with code to walk blocks and dispatch individual operations +to the care of the rtype_*() methods implemented in the other r* modules. +For each high-level operation 'hop', the rtype_*() methods produce low-level +operations that are collected in the 'llops' list defined here. When necessary, +convertions are inserted. + +This logic borrows a bit from pypy.translator.annrpython, without the fixpoint +computation part. +""" + from __future__ import generators import sys from pypy.annotation.pairtype import pair @@ -19,9 +32,6 @@ debug = False crash_on_first_typeerror = True -# XXX copied from pypy.translator.typer and modified. -# We'll remove pypy.translator.typer at some point. -# It also borrows a bit from pypy.translator.annrpython. class RPythonTyper: Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Thu Jun 16 17:32:19 2005 @@ -48,3 +48,22 @@ x.xyzzy += 1 return x.xyzzy rtype(dummyfn) + +def test_prebuilt_instance(): + a = EmptyBase() + a.x = 5 + def dummyfn(): + a.x += 1 + return a.x + rtype(dummyfn) + +def WORKING_ON_test_recursive_prebuilt_instance(): + a = EmptyBase() + b = EmptyBase() + a.x = 5 + b.x = 6 + a.peer = b + b.peer = a + def dummyfn(): + return a.peer.x + rtype(dummyfn) From arigo at codespeak.net Thu Jun 16 18:05:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 18:05:16 +0200 (CEST) Subject: [pypy-svn] r13481 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050616160516.D77DF27B85@code1.codespeak.net> Author: arigo Date: Thu Jun 16 18:05:13 2005 New Revision: 13481 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/rpython/exceptiondata.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: Recursive prebuilt instances in the rtyper. Commented out a debugging print statement. The annotator now says 'readonly=False' for attributes that exist on prebuilt instances, which allows 'readonly' to be used as a flag to know if the attribute must be attached to the instance or to the class. Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Thu Jun 16 18:05:13 2005 @@ -16,6 +16,9 @@ # immutablevalue() wouldn't be happy with them # * there is an infinite recursion between immutablevalue() and # add_source_for_attribute() for cyclic constant structures. + # NB2. an attribute is readonly if it is a constant class attribute. + # Both writing to the instance attribute and discovering prebuilt + # instances that have the attribute set will turn off readonly-ness. def __init__(self, name, bookkeeper): self.name = name @@ -120,6 +123,8 @@ homedef = self.locate_attribute(attr) attrdef = homedef.attrs[attr] attrdef.sources[source] = clsdef + if clsdef is None: + attrdef.readonly = False # see note about 'readonly' in ClassDef if attrdef.read_locations: # we should reflow from all the reader's position, # but as an optimization we try to see if the attribute Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Thu Jun 16 18:05:13 2005 @@ -88,7 +88,7 @@ for cls in table.keys(): add_class(cls) assert table == {} - print sortedtable + #print sortedtable A = Array(('pycls', Ptr(PyObject)), ('excinst', self.lltype_of_exception_value)) Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 16 18:05:13 2005 @@ -298,6 +298,7 @@ self.object_type = OBJECT else: self.object_type = GcForwardReference() + self.prebuiltinstances = {} # { id(x): (x, _ptr) } self.lowleveltype = Ptr(self.object_type) def __repr__(self): @@ -348,32 +349,46 @@ OBJECT) self.initialized = True - def convert_const(self, value, targetptr=None, vtable=None): + def convert_const(self, value): if value is None: return nullptr(self.object_type) - # we will need the vtable pointer, so ask it first, to let - # ClassRepr.convert_const() perform all the necessary checks on 'value' - if vtable is None: - vtable = self.rclass.convert_const(value.__class__) - if targetptr is None: - targetptr = malloc(self.object_type) - # - if self.classdef is None: - # instantiate 'object': should be disallowed, but it's convenient - # to write convert_const() this way and use itself recursively - targetptr.typeptr = cast_vtable_to_typeptr(vtable) - else: - # build the parent part of the instance - self.rbase.convert_const(value, - targetptr = targetptr.super, - vtable = vtable) - # add instance attributes from this level + try: + classdef = self.rtyper.annotator.getuserclasses()[value.__class__] + except KeyError: + raise TyperError("no classdef: %r" % (value.__class__,)) + if classdef != self.classdef: + # if the class does not match exactly, check that 'value' is an + # instance of a subclass and delegate to that InstanceRepr + if classdef is None: + raise TyperError("not implemented: object() instance") + if classdef.commonbase(self.classdef) != self.classdef: + raise TyperError("not an instance of %r: %r" % ( + self.classdef.cls, value)) + rinstance = getinstancerepr(self.rtyper, classdef) + return rinstance.convert_const(value) + # common case + try: + return self.prebuiltinstances[id(value)][1] + except KeyError: + result = malloc(self.object_type) + self.prebuiltinstances[id(value)] = value, result + self.initialize_prebuilt_instance(value, classdef, result) + return result + + def initialize_prebuilt_instance(self, value, classdef, result): + if self.classdef is not None: + # recursively build the parent part of the instance + self.rbase.initialize_prebuilt_instance(value, classdef, + result.super) + # then add instance attributes from this level for name, (mangled_name, r) in self.fields.items(): attrvalue = getattr(value, name) - # XXX RECURSIVE PREBUILT DATA STRUCTURES XXX llattrvalue = r.convert_const(attrvalue) - setattr(targetptr, mangled_name, llattrvalue) - return targetptr + setattr(result, mangled_name, llattrvalue) + else: + # OBJECT part + rclass = getclassrepr(self.rtyper, classdef) + result.typeptr = rclass.getvtable() #def parentpart(self, vinst, llops): # """Return the pointer 'vinst' cast to the parent type.""" Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Thu Jun 16 18:05:13 2005 @@ -57,7 +57,7 @@ return a.x rtype(dummyfn) -def WORKING_ON_test_recursive_prebuilt_instance(): +def test_recursive_prebuilt_instance(): a = EmptyBase() b = EmptyBase() a.x = 5 From pedronis at codespeak.net Thu Jun 16 18:08:21 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Jun 2005 18:08:21 +0200 (CEST) Subject: [pypy-svn] r13482 - in pypy/dist/pypy: annotation translator/goal Message-ID: <20050616160821.B554227B85@code1.codespeak.net> Author: pedronis Date: Thu Jun 16 18:08:17 2005 New Revision: 13482 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/goal/query.py Log: some more statics and tweaks, tuple_iter tries to capture the context in which iter annotation has been used, Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 16 18:08:17 2005 @@ -405,13 +405,16 @@ return getbookkeeper().newlist(lst1.listdef.read_item()) def getitem((lst1, int2)): + getbookkeeper().count("list_getitem", int2) return lst1.listdef.read_item() def setitem((lst1, int2), s_value): + getbookkeeper().count("list_setitem", int2) lst1.listdef.mutate() lst1.listdef.generalize(s_value) def delitem((lst1, int2)): + getbookkeeper().count("list_delitem", int2) lst1.listdef.resize() class __extend__(pairtype(SomeList, SomeSlice)): @@ -435,6 +438,7 @@ class __extend__(pairtype(SomeString, SomeInteger)): def getitem((str1, int2)): + getbookkeeper().count("str_getitem", int2) return SomeChar() def mul((str1, int2)): # xxx do we want to support this Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 16 18:08:17 2005 @@ -51,43 +51,80 @@ outcome = classifier(*args) for_category[self.bookkeeper.position_key] = outcome - def consider_newslice(self, s_start, s_stop, s_step): - if ((s_start.is_constant() or (isinstance(s_start, SomeInteger) and s_start.nonneg)) and - (s_stop.is_constant() or (isinstance(s_stop, SomeInteger) and s_stop.nonneg)) and - (s_step.is_constant() and (s_step.const == 1 or s_step.const == None))): - return 'proper' - return 'improper' + def indexrepr(self, idx): + if idx.is_constant(): + if idx.const is None: + return '' + if isinstance(idx, SomeInteger): + if idx.const >=0: + return 'pos-constant' + else: + return 'Neg-constant' + return idx.const + else: + if isinstance(idx, SomeInteger): + if idx.nonneg: + return "non-neg" + else: + return "MAYBE-NEG" + else: + return self.typerepr(idx) + + def steprepr(self, stp): + if stp.is_constant(): + if stp.const in (1, None): + return 'step=1' + else: + return 'step=%s?' % stp.const + else: + return 'non-const-step %s' % self.typerepr(stp) + + def consider_newslice(self, s_start, s_stop, s_step): + return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)]) def consider_non_int_eq(self, obj1, obj2): return obj1.knowntype.__name__, obj2.knowntype.__name__ def consider_non_int_comp(self, obj1, obj2): return obj1.knowntype.__name__, obj2.knowntype.__name__ - def short(self, obj): + def typerepr(self, obj): if isinstance(obj, SomeInstance): return obj.classdef.cls.__name__ else: return obj.knowntype.__name__ def consider_tuple_iter(self, tup): + ctxt = "[%s]" % sys._getframe(4).f_code.co_name if tup.is_constant(): - return 'constant tuple' + return ctxt, tup.const else: - return tuple([self.short(x) for x in tup.items]) + return ctxt, tuple([self.typerepr(x) for x in tup.items]) def consider_tuple_random_getitem(self, tup): - return tuple([self.short(x) for x in tup.items]) + return tuple([self.typerepr(x) for x in tup.items]) def consider_list_index(self): return '!' + def consider_list_getitem(self, idx): + return self.indexrepr(idx) + + def consider_list_setitem(self, idx): + return self.indexrepr(idx) + + def consider_list_delitem(self, idx): + return self.indexrepr(idx) + def consider_str_join(self, s): if s.is_constant(): return repr(s.const) else: return "NON-CONSTANT" + def consider_str_getitem(self, idx): + return self.indexrepr(idx) + class Bookkeeper: """The log of choices that have been made while analysing the operations. It ensures that the same 'choice objects' will be returned if we ask Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 16 18:08:17 2005 @@ -318,9 +318,15 @@ counters = {} for pos, outcome in for_category.iteritems(): counters[outcome] = counters.get(outcome, 0) + 1 - w = max([len(str(o)) for o in counters.keys()])+1 + def keyrepr(k): + if isinstance(k, tuple): + return "(%s)" % ', '.join([keyrepr(x) for x in k]) + else: + return str(k) + + w = max([len(keyrepr(o)) for o in counters.keys()])+1 for outcome, n in counters.iteritems(): - print "%*s | %d" % (w, outcome, n) + print "%*s | %d" % (w, keyrepr(outcome), n) # debug helper def tryout(f, *args): From arigo at codespeak.net Thu Jun 16 18:18:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 18:18:13 +0200 (CEST) Subject: [pypy-svn] r13483 - in pypy/dist/pypy: annotation rpython Message-ID: <20050616161813.1F43E27B85@code1.codespeak.net> Author: arigo Date: Thu Jun 16 18:18:10 2005 New Revision: 13483 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rmodel.py Log: Pointer typing bug fix. Fixed a possible crash of classdef.commonbase(None). Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Thu Jun 16 18:18:10 2005 @@ -154,7 +154,7 @@ while other is not None and not issubclass(self.cls, other.cls): other = other.basedef # special case for MI with Exception - if not other: + if other is None and other1 is not None: if issubclass(self.cls, Exception) and issubclass(other1.cls, Exception): return self.bookkeeper.getclassdef(Exception) return other Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Thu Jun 16 18:18:10 2005 @@ -365,7 +365,8 @@ raise TyperError("not an instance of %r: %r" % ( self.classdef.cls, value)) rinstance = getinstancerepr(self.rtyper, classdef) - return rinstance.convert_const(value) + result = rinstance.convert_const(value) + return cast_pointer(self.lowleveltype, result) # common case try: return self.prebuiltinstances[id(value)][1] Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Thu Jun 16 18:18:10 2005 @@ -168,8 +168,10 @@ except (AssertionError, AttributeError): realtype = '???' if realtype != lltype: - raise TyperError("inputconst(reqtype = %s, value = %s)" % ( - reqtype, value)) + raise TyperError("inputconst(reqtype = %s, value = %s):\n" + "expected a %r,\n" + " got a %r" % (reqtype, value, + lltype, realtype)) c = Constant(value) c.concretetype = lltype return c From ale at codespeak.net Thu Jun 16 18:18:27 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 16 Jun 2005 18:18:27 +0200 (CEST) Subject: [pypy-svn] r13484 - pypy/dist/pypy/rpython Message-ID: <20050616161827.1F11D27B8C@code1.codespeak.net> Author: ale Date: Thu Jun 16 18:18:25 2005 New Revision: 13484 Modified: pypy/dist/pypy/rpython/interp.py Log: added setarrayitem and getarrayitem started to make setval work for lists, i am not sure if this is he right way to do it Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 18:18:25 2005 @@ -1,5 +1,7 @@ from pypy.rpython.lltype import * from pypy.rpython.lltype import _ptr +from pypy.translator.translator import Translator +from pypy.tool.sourcetools import compile2 from pypy.objspace.flow.model import Constant, last_exception import py @@ -28,6 +30,20 @@ def setvar(self, var, val): # XXX assert that val "matches" lowlevel type + if isinstance(val,list): + fun = compile2(""" + def f(): + r = %s + return r"""%repr(val)) + exec fun + t=Translator(f) + t.annotate([]) + t.specialize() + t.view() + + val = self.eval_graph(t.getflowgraph()) + print val + self.bindings[var] = val def getval(self, varorconst): @@ -129,9 +145,20 @@ return x def op_setfield(self, obj, fieldname, fieldvalue): - # obj should be pointer - setattr(obj, fieldname, fieldvalue) # is that right? -- yes + # obj should be pointer + try: + setattr(obj, fieldname, fieldvalue) # is that right? -- yes + except TypeError: + print fieldname,fieldvalue + raise + + def op_getarrayitem(self,array,index): + return array[index] + def op_setarrayitem(self,array,index,item): + array[index] = item + return array + def op_direct_call(self, f, *args): # XXX the logic should be: # if f._obj has a graph attribute, interpret From ale at codespeak.net Thu Jun 16 18:21:16 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 16 Jun 2005 18:21:16 +0200 (CEST) Subject: [pypy-svn] r13485 - pypy/dist/pypy/rpython Message-ID: <20050616162116.63B1A27B93@code1.codespeak.net> Author: ale Date: Thu Jun 16 18:21:15 2005 New Revision: 13485 Modified: pypy/dist/pypy/rpython/interp.py Log: removed print statement and pygame invokation,oups Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 18:21:15 2005 @@ -39,7 +39,7 @@ t=Translator(f) t.annotate([]) t.specialize() - t.view() + #t.view() val = self.eval_graph(t.getflowgraph()) print val @@ -146,11 +146,7 @@ def op_setfield(self, obj, fieldname, fieldvalue): # obj should be pointer - try: - setattr(obj, fieldname, fieldvalue) # is that right? -- yes - except TypeError: - print fieldname,fieldvalue - raise + setattr(obj, fieldname, fieldvalue) # is that right? -- yes def op_getarrayitem(self,array,index): return array[index] From arigo at codespeak.net Thu Jun 16 19:33:17 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 19:33:17 +0200 (CEST) Subject: [pypy-svn] r13486 - pypy/dist/pypy/annotation Message-ID: <20050616173317.836EC27B8C@code1.codespeak.net> Author: arigo Date: Thu Jun 16 19:33:16 2005 New Revision: 13486 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: Looks like a bug. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 16 19:33:16 2005 @@ -390,7 +390,7 @@ break if first is not None: - change, rep, access = access_sets.find(objects[0]) + change, rep, access = access_sets.find(first) for obj in objects: if obj is not None: change1, rep, access = access_sets.union(rep, obj) From arigo at codespeak.net Thu Jun 16 19:53:01 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 19:53:01 +0200 (CEST) Subject: [pypy-svn] r13487 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050616175301.408DD27B8C@code1.codespeak.net> Author: arigo Date: Thu Jun 16 19:52:59 2005 New Revision: 13487 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/test/test_annrpython.py Log: It seems useful for the rtyper to ask the bookkeeper to record the annotation given to a attribute read from a set of PBCs. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 16 19:52:59 2005 @@ -380,38 +380,36 @@ access_sets = self.pbc_maximal_access_sets objects = pbc.prebuiltinstances.keys() - access = None - first = None - change = False - + for obj in objects: if obj is not None: first = obj break + else: + return SomeImpossibleValue() + + change, rep, access = access_sets.find(first) + for obj in objects: + if obj is not None: + change1, rep, access = access_sets.union(rep, obj) + change = change or change1 - if first is not None: - change, rep, access = access_sets.find(first) - for obj in objects: - if obj is not None: - change1, rep, access = access_sets.union(rep, obj) - change = change or change1 - - access.attrs[attr] = True - position = self.position_key - access.read_locations[position] = True + position = self.position_key + access.read_locations[position] = True actuals = [] + for c in access.objects: + if hasattr(c, attr): + actuals.append(self.immutablevalue(getattr(c, attr))) + s_result = unionof(*actuals) - if access: - for c in access.objects: - if hasattr(c, attr): - actuals.append(self.immutablevalue(getattr(c, attr))) + access.attrs[attr] = s_result if change: for position in access.read_locations: self.annotator.reflowfromposition(position) - return unionof(*actuals) + return s_result def consider_pbc_call(self, pbc, shape, spaceop=None, implicit_init=None): # computation done at fix-point if not isinstance(pbc, SomePBC): Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Thu Jun 16 19:52:59 2005 @@ -810,7 +810,7 @@ assert acc1 is acc2 is acc3 assert len(acc1.objects) == 3 - assert acc1.attrs == {'v1': True, 'v2': True} + assert dict.fromkeys(acc1.attrs) == {'v1': None, 'v2': None} assert access_sets[c1] is acc1 py.test.raises(KeyError, "access_sets[object()]") From arigo at codespeak.net Thu Jun 16 20:28:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 20:28:53 +0200 (CEST) Subject: [pypy-svn] r13488 - in pypy/dist/pypy/rpython: . test Message-ID: <20050616182853.3AE3B27B7D@code1.codespeak.net> Author: arigo Date: Thu Jun 16 20:28:50 2005 New Revision: 13488 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: rtyper support for PBC structures, implemented as a pointer to one of a set of prebuilt Structs. The shape of the Struct is deduced from annotator-supplied usage patterns. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Jun 16 20:28:50 2005 @@ -2,7 +2,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef -from pypy.rpython.lltype import typeOf, Void +from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct +from pypy.rpython.lltype import Ptr, malloc, nullptr from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass @@ -38,7 +39,7 @@ raise TyperError("don't know about callable %r" % (x,)) else: # frozen object - choice = FrozenPBCRepr + choice = getFrozenPBCRepr if cdefflag: raise TyperError("unexpected classdef in PBC set %r" % ( @@ -60,18 +61,92 @@ # ____________________________________________________________ -class FrozenPBCRepr(Repr): +def getFrozenPBCRepr(rtyper, s_pbc): + if len(s_pbc.prebuiltinstances) <= 1: + return single_frozen_pbc_repr + else: + pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys() + if pbc is not None] + access_sets = rtyper.annotator.getpbcaccesssets() + _, _, access = access_sets.find(pbcs[0]) + for obj in pbcs[1:]: + _, _, access1 = access_sets.find(obj) + assert access1 is access # XXX not implemented + try: + return rtyper.pbc_reprs[access] + except KeyError: + result = MultipleFrozenPBCRepr(rtyper, access) + rtyper.pbc_reprs[access] = result + return result + + +class SingleFrozenPBCRepr(Repr): """Representation selected for a single non-callable pre-built constant.""" lowleveltype = Void - def __init__(self, rtyper, s_pbc): - assert len(s_pbc.prebuiltinstances) == 1 # XXX not implemented - def rtype_getattr(_, hop): if not hop.s_result.is_constant(): raise TyperError("getattr on a constant PBC returns a non-constant") return hop.inputconst(hop.r_result, hop.s_result.const) +single_frozen_pbc_repr = SingleFrozenPBCRepr() + + +class MultipleFrozenPBCRepr(Repr): + """Representation selected for multiple non-callable pre-built constants.""" + initialized = False + + def __init__(self, rtyper, access_set): + self.rtyper = rtyper + self.access_set = access_set + self.pbc_type = ForwardReference() + self.lowleveltype = Ptr(self.pbc_type) + self.pbc_cache = {} + + def setup(self): + if self.initialized: + assert self.initialized == True + return + self.initialized = "in progress" + llfields = [] + llfieldmap = {} + attrlist = self.access_set.attrs.keys() + attrlist.sort() + for attr in attrlist: + s_value = self.access_set.attrs[attr] + r_value = self.rtyper.getrepr(s_value) + mangled_name = 'pbc_' + attr + llfields.append((mangled_name, r_value.lowleveltype)) + llfieldmap[attr] = mangled_name, r_value + self.pbc_type.become(Struct('pbc', *llfields)) + self.llfieldmap = llfieldmap + self.initialized = True + + def convert_const(self, pbc): + if pbc is None: + return nullptr(self.pbc_type) + if pbc not in self.access_set.objects: + raise TyperError("not found in PBC set: %r" % (pbc,)) + try: + return self.pbc_cache[pbc] + except KeyError: + self.setup() + result = malloc(self.pbc_type, immortal=True) + self.pbc_cache[pbc] = result + for attr, (mangled_name, r_value) in self.llfieldmap.items(): + thisattrvalue = getattr(pbc, attr) + llvalue = r_value.convert_const(thisattrvalue) + setattr(result, mangled_name, llvalue) + return result + + def rtype_getattr(self, hop): + attr = hop.args_s[1].const + vpbc, vattr = hop.inputargs(self, Void) + mangled_name, r_value = self.llfieldmap[attr] + cmangledname = hop.inputconst(Void, mangled_name) + return hop.genop('getfield', [vpbc, cmangledname], + resulttype = r_value) + # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 16 20:28:50 2005 @@ -42,6 +42,7 @@ self.specialized_ll_functions = {} self.class_reprs = {} self.instance_reprs = {} + self.pbc_reprs = {} self.typererror = None # make the primitive_to_repr constant mapping self.primitive_to_repr = {} Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Thu Jun 16 20:28:50 2005 @@ -57,3 +57,25 @@ obj.z = a return obj.m(b) rtype(f, [int, int]) + + +class Freezing: + def _freeze_(self): + return True + +def test_freezing(): + fr1 = Freezing() + fr2 = Freezing() + fr1.x = 5 + fr2.x = 6 + def g(fr): + return fr.x + def f(n): + if n > 0: + fr = fr1 + elif n < 0: + fr = fr2 + else: + fr = None + return g(fr) + rtype(f, [int]) From pedronis at codespeak.net Thu Jun 16 22:25:31 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Jun 2005 22:25:31 +0200 (CEST) Subject: [pypy-svn] r13489 - pypy/dist/pypy/annotation Message-ID: <20050616202531.3DDDA27B96@code1.codespeak.net> Author: pedronis Date: Thu Jun 16 22:25:29 2005 New Revision: 13489 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: missing blank line Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 16 22:25:29 2005 @@ -82,6 +82,7 @@ def consider_newslice(self, s_start, s_stop, s_step): return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)]) + def consider_non_int_eq(self, obj1, obj2): return obj1.knowntype.__name__, obj2.knowntype.__name__ From pedronis at codespeak.net Thu Jun 16 22:26:00 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Jun 2005 22:26:00 +0200 (CEST) Subject: [pypy-svn] r13490 - pypy/dist/pypy/translator/goal Message-ID: <20050616202600.56EE027B96@code1.codespeak.net> Author: pedronis Date: Thu Jun 16 22:25:59 2005 New Revision: 13490 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: specialize now is called trough the translator Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Thu Jun 16 22:25:59 2005 @@ -91,7 +91,7 @@ if not options['-no-s']: a.simplify() if not options['-no-t']: - a.specialize() + t.specialize() t.frozen = True # cannot freeze if we don't have annotations if not options['-no-mark-some-objects']: options['-no-mark-some-objects'] = True # Do not do this again From arigo at codespeak.net Thu Jun 16 23:07:00 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 23:07:00 +0200 (CEST) Subject: [pypy-svn] r13491 - pypy/dist/pypy/rpython Message-ID: <20050616210700.C802227B85@code1.codespeak.net> Author: arigo Date: Thu Jun 16 23:06:59 2005 New Revision: 13491 Modified: pypy/dist/pypy/rpython/interp.py Log: Updated XXX comments. Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Thu Jun 16 23:06:59 2005 @@ -90,6 +90,8 @@ try: self.eval_operation(op) except RPythonError, e: + # XXX should only catch exceptions from the last operation + # XXX non-caught exceptions should just be allowed to propagate assert catch_exception, 'exception received, but not expected' # determine nextblock and/or return value @@ -146,19 +148,15 @@ def op_setfield(self, obj, fieldname, fieldvalue): # obj should be pointer - setattr(obj, fieldname, fieldvalue) # is that right? -- yes + setattr(obj, fieldname, fieldvalue) def op_getarrayitem(self,array,index): return array[index] def op_setarrayitem(self,array,index,item): array[index] = item - return array def op_direct_call(self, f, *args): - # XXX the logic should be: - # if f._obj has a graph attribute, interpret - # that graph without looking at _callable if hasattr(f._obj, 'graph'): return self.eval_graph(f._obj.graph, args) return self.eval_function(f._obj._callable, args) From arigo at codespeak.net Thu Jun 16 23:33:12 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 16 Jun 2005 23:33:12 +0200 (CEST) Subject: [pypy-svn] r13492 - pypy/dist/pypy/interpreter Message-ID: <20050616213312.DEEFC27B85@code1.codespeak.net> Author: arigo Date: Thu Jun 16 23:33:11 2005 New Revision: 13492 Modified: pypy/dist/pypy/interpreter/eval.py pypy/dist/pypy/interpreter/pyopcode.py Log: A couple of changes to make the rtyper happy with function calls. The rule is: if a call point can invoke several different functions, then these functions should always be called using the same "call shape" (i.e. # of args provided, */** arguments). It's fine to use various call shapes to call a single function explicitely, though; this rule is only about calls via a "function pointer" or an overridden method. These two changes were all that is needed in the whole of PyPy. Modified: pypy/dist/pypy/interpreter/eval.py ============================================================================== --- pypy/dist/pypy/interpreter/eval.py (original) +++ pypy/dist/pypy/interpreter/eval.py Thu Jun 16 23:33:11 2005 @@ -19,7 +19,7 @@ def exec_code(self, space, w_globals, w_locals): "Implements the 'exec' statement." - frame = self.create_frame(space, w_globals) + frame = self.create_frame(space, w_globals, None) frame.setdictscope(w_locals) return frame.run() Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Thu Jun 16 23:33:11 2005 @@ -626,7 +626,7 @@ block = pyframe.FinallyBlock(f, f.next_instr + offsettoend) f.blockstack.push(block) - def CALL_FUNCTION(f, oparg, w_star=None, w_starstar=None): + def call_function(f, oparg, w_star=None, w_starstar=None): n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = {} @@ -642,18 +642,21 @@ w_result = f.space.call_args(w_function, args) f.valuestack.push(w_result) + def CALL_FUNCTION(f, oparg): + f.call_function(oparg) + def CALL_FUNCTION_VAR(f, oparg): w_varargs = f.valuestack.pop() - f.CALL_FUNCTION(oparg, w_varargs) + f.call_function(oparg, w_varargs) def CALL_FUNCTION_KW(f, oparg): w_varkw = f.valuestack.pop() - f.CALL_FUNCTION(oparg, None, w_varkw) + f.call_function(oparg, None, w_varkw) def CALL_FUNCTION_VAR_KW(f, oparg): w_varkw = f.valuestack.pop() w_varargs = f.valuestack.pop() - f.CALL_FUNCTION(oparg, w_varargs, w_varkw) + f.call_function(oparg, w_varargs, w_varkw) def MAKE_FUNCTION(f, numdefaults): w_codeobj = f.valuestack.pop() From pedronis at codespeak.net Thu Jun 16 23:36:44 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 16 Jun 2005 23:36:44 +0200 (CEST) Subject: [pypy-svn] r13493 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050616213644.BD7AC27B85@code1.codespeak.net> Author: pedronis Date: Thu Jun 16 23:36:43 2005 New Revision: 13493 Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py Log: merge tweaks to make the rtyper happy Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/eval.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/eval.py Thu Jun 16 23:36:43 2005 @@ -19,7 +19,7 @@ def exec_code(self, space, w_globals, w_locals): "Implements the 'exec' statement." - frame = self.create_frame(space, w_globals) + frame = self.create_frame(space, w_globals, None) frame.setdictscope(w_locals) return frame.run() Modified: pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pyopcode.py Thu Jun 16 23:36:43 2005 @@ -626,7 +626,7 @@ block = pyframe.FinallyBlock(f, f.next_instr + offsettoend) f.blockstack.push(block) - def CALL_FUNCTION(f, oparg, w_star=None, w_starstar=None): + def call_function(f, oparg, w_star=None, w_starstar=None): n_arguments = oparg & 0xff n_keywords = (oparg>>8) & 0xff keywords = {} @@ -642,18 +642,21 @@ w_result = f.space.call_args(w_function, args) f.valuestack.push(w_result) + def CALL_FUNCTION(f, oparg): + f.call_function(oparg) + def CALL_FUNCTION_VAR(f, oparg): w_varargs = f.valuestack.pop() - f.CALL_FUNCTION(oparg, w_varargs) + f.call_function(oparg, w_varargs) def CALL_FUNCTION_KW(f, oparg): w_varkw = f.valuestack.pop() - f.CALL_FUNCTION(oparg, None, w_varkw) + f.call_function(oparg, None, w_varkw) def CALL_FUNCTION_VAR_KW(f, oparg): w_varkw = f.valuestack.pop() w_varargs = f.valuestack.pop() - f.CALL_FUNCTION(oparg, w_varargs, w_varkw) + f.call_function(oparg, w_varargs, w_varkw) def MAKE_FUNCTION(f, numdefaults): w_codeobj = f.valuestack.pop() From ale at codespeak.net Fri Jun 17 00:20:50 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 17 Jun 2005 00:20:50 +0200 (CEST) Subject: [pypy-svn] r13494 - pypy/dist/pypy/rpython Message-ID: <20050616222050.1EEB027B62@code1.codespeak.net> Author: ale Date: Fri Jun 17 00:20:49 2005 New Revision: 13494 Modified: pypy/dist/pypy/rpython/interp.py Log: reverting changes to setvar Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Fri Jun 17 00:20:49 2005 @@ -30,19 +30,6 @@ def setvar(self, var, val): # XXX assert that val "matches" lowlevel type - if isinstance(val,list): - fun = compile2(""" - def f(): - r = %s - return r"""%repr(val)) - exec fun - t=Translator(f) - t.annotate([]) - t.specialize() - #t.view() - - val = self.eval_graph(t.getflowgraph()) - print val self.bindings[var] = val From arigo at codespeak.net Fri Jun 17 00:38:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 00:38:43 +0200 (CEST) Subject: [pypy-svn] r13495 - pypy/dist/pypy/rpython Message-ID: <20050616223843.E34E327B72@code1.codespeak.net> Author: arigo Date: Fri Jun 17 00:38:42 2005 New Revision: 13495 Modified: pypy/dist/pypy/rpython/rclass.py Log: Ordering issue. Cannot call attachRuntimeTypeInfo() before setup() says it is ready because the former cna call the latter again. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 17 00:38:42 2005 @@ -344,10 +344,10 @@ allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields + self.initialized = True self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT) - self.initialized = True def convert_const(self, value): if value is None: From arigo at codespeak.net Fri Jun 17 00:43:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 00:43:27 +0200 (CEST) Subject: [pypy-svn] r13496 - in pypy/dist/pypy: objspace/flow rpython rpython/test Message-ID: <20050616224327.25A2427B72@code1.codespeak.net> Author: arigo Date: Fri Jun 17 00:43:24 2005 New Revision: 13496 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_normalizecalls.py Log: Normalizing calls to multiple functions with keywords. Done by matching the (single) call shape to each function in turn, and fixing the function's graph to insert default arguments if necessary when not provided by keywords, and reorder arguments so that they appear in the same order as the keywords in the call_args. Oups, just found a bug. Will check in a test and a fix in the next commit... Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Fri Jun 17 00:43:24 2005 @@ -31,7 +31,6 @@ __metaclass__ = type class FunctionGraph(object): - __slots__ = """func source name startblock returnblock exceptblock""".split() def __init__(self, name, startblock, return_var=None): self.name = name # function name (possibly mangled already) Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 00:43:24 2005 @@ -40,55 +40,76 @@ functions)) pattern, = family.patterns shape_cnt, shape_keys, shape_star, shape_stst = pattern - assert not shape_keys, "XXX not implemented" assert not shape_star, "XXX not implemented" assert not shape_stst, "XXX not implemented" # for the first 'shape_cnt' arguments we need to generalize to # a common type - generalizedargs = [] graph_bindings = {} - default_values = {} + graph_argorders = {} for func in functions: assert not has_varargs(func), "XXX not implemented" graph = annotator.translator.getflowgraph(func) graph_bindings[graph] = [annotator.binding(v) for v in graph.getargs()] - for i in range(shape_cnt): + argorder = range(shape_cnt) + for key in shape_keys: + i = list(func.func_code.co_varnames).index(key) + assert i not in argorder + argorder.append(i) + graph_argorders[graph] = argorder + + call_nbargs = shape_cnt + len(shape_keys) + generalizedargs = [] + for i in range(call_nbargs): args_s = [] - for bindings in graph_bindings.values(): - args_s.append(bindings[i]) + for graph, bindings in graph_bindings.items(): + j = graph_argorders[graph][i] + args_s.append(bindings[j]) s_value = unionof(*args_s) generalizedargs.append(s_value) + for func in functions: graph = annotator.translator.getflowgraph(func) bindings = graph_bindings[graph] - if generalizedargs != bindings: #NB. bindings can also be longer + argorder = graph_argorders[graph] + need_reordering = (argorder != range(call_nbargs)) + need_conversion = (generalizedargs != bindings) + if need_reordering or need_conversion: oldblock = graph.startblock - vlist = [] - for i in range(len(generalizedargs)): - v = Variable(graph.getargs()[i]) - annotator.setbinding(v, generalizedargs[i]) - vlist.append(v) - newblock = Block(vlist) - # add the defaults as constants + inlist = [] + for s_value, j in zip(generalizedargs, argorder): + v = Variable(graph.getargs()[j]) + annotator.setbinding(v, s_value) + inlist.append(v) + newblock = Block(inlist) + # prepare the output args of newblock: + # 1. collect the positional arguments + outlist = inlist[:shape_cnt] + # 2. add defaults and keywords defaults = func.func_defaults or () - for i in range(len(generalizedargs), len(bindings)): + for j in range(shape_cnt, len(bindings)): try: - default = defaults[i-len(bindings)] - except IndexError: - raise TyperError("call pattern has %d arguments, " - "but %r takes at least %d " - "arguments" % ( - len(generalizedargs), func, - len(bindings) - len(defaults))) - vlist.append(Constant(default)) - newblock.closeblock(Link(vlist, oldblock)) + i = argorder.index(j) + v = inlist[i] + except ValueError: + try: + default = defaults[j-len(bindings)] + except IndexError: + raise TyperError( + "call pattern has %d positional arguments, " + "but %r takes at least %d arguments" % ( + shape_cnt, func, + len(bindings) - len(defaults))) + v = Constant(default) + outlist.append(v) + newblock.closeblock(Link(outlist, oldblock)) oldblock.isstartblock = False newblock.isstartblock = True graph.startblock = newblock # finished checkgraph(graph) annotator.annotated[newblock] = annotator.annotated[oldblock] + graph.normalized_for_calls = True # XXX convert the return value too Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jun 17 00:43:24 2005 @@ -213,6 +213,15 @@ vlist[0] = hop.inputconst(typeOf(f), f) return hop.genop('direct_call', vlist, resulttype = rresult) + def rtype_call_args(self, hop): + f, rinputs, rresult = self.function_signatures.itervalues().next() + # the function arguments may have been normalized by normalizecalls() + # already + if not f._obj.graph.normalized_for_calls: + assert False, "XXX do stuff here" + vlist = hop.inputargs(self, Void, *rinputs) + return hop.genop('direct_call', vlist[:1] + vlist[2:], + resulttype = rresult) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/test/test_normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_normalizecalls.py (original) +++ pypy/dist/pypy/rpython/test/test_normalizecalls.py Fri Jun 17 00:43:24 2005 @@ -36,3 +36,22 @@ assert s_l1.__class__ == annmodel.SomeString # and not SomeChar assert s_l2.__class__ == annmodel.SomeString # and not SomeChar #translator.view() + +def test_normalize_keyword_call(): + def f1(a, b): + return (a, b, 0, 0) + def f2(b, c=123, a=456, d=789): + return (a, b, c, d) + def g(n): + if n > 0: + f = f1 + else: + f = f2 + f(a=5, b=6) + + translator = rtype(g, [int]) + f1graph = translator.getflowgraph(f1) + f2graph = translator.getflowgraph(f2) + assert len(f1graph.getargs()) == 2 + assert len(f2graph.getargs()) == 2 # normalized to the common call pattern + #translator.view() From arigo at codespeak.net Fri Jun 17 01:00:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 01:00:36 +0200 (CEST) Subject: [pypy-svn] r13497 - pypy/dist/pypy/rpython Message-ID: <20050616230036.7E82527B7D@code1.codespeak.net> Author: arigo Date: Fri Jun 17 01:00:34 2005 New Revision: 13497 Modified: pypy/dist/pypy/rpython/normalizecalls.py Log: Ignore calls to classes for the purpose of call normalization. The __init__ methods (in unbound version) are also in the call families computed by the annotator. Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 01:00:34 2005 @@ -1,3 +1,4 @@ +import types from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, checkgraph from pypy.annotation.model import * @@ -31,8 +32,12 @@ func_family.patterns[pattern] = True # find the most general signature of each family for family in call_families.infos(): + # collect functions in this family, ignoring: + # - methods: taken care of above + # - classes: their __init__ unbound methods are also families functions = [func for classdef, func in family.objects - if classdef is None] # ignore methods now + if classdef is None and + not isinstance(func, (type, types.ClassType))] if len(functions) > 1: # otherwise, nothing to do if len(family.patterns) > 1: raise TyperError("don't support multiple call patterns " From tismer at codespeak.net Fri Jun 17 01:39:36 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:39:36 +0200 (CEST) Subject: [pypy-svn] r13498 - pypy/dist/pypy/annotation Message-ID: <20050616233936.983B527B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:39:35 2005 New Revision: 13498 Modified: pypy/dist/pypy/annotation/model.py Log: typo Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Fri Jun 17 01:39:35 2005 @@ -50,7 +50,7 @@ So I trashed 8 hours of work, without a check-in. (Just writing this here to leave *some* trace of work). -Then I tried to make allinstances unique and wrote a lot +Then I tried to make all instances unique and wrote a lot of attribute tracking code here, locked write access outside of __init__, and patched many modules and several hundred lines of code. From tismer at codespeak.net Fri Jun 17 01:40:51 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:40:51 +0200 (CEST) Subject: [pypy-svn] r13499 - pypy/dist/pypy/annotation Message-ID: <20050616234051.7C04027B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:40:50 2005 New Revision: 13499 Modified: pypy/dist/pypy/annotation/pairtype.py Log: avoid override of the __module__ attribute. XXX it is not yet clear to me if we need to do something else, to enable pickling Modified: pypy/dist/pypy/annotation/pairtype.py ============================================================================== --- pypy/dist/pypy/annotation/pairtype.py (original) +++ pypy/dist/pypy/annotation/pairtype.py Fri Jun 17 01:40:50 2005 @@ -9,6 +9,9 @@ if name == '__extend__': cls = bases[0] # override data into the existing base for key, value in dict.items(): + if key == '__module__': + continue + # XXX do we need to provide something more for pickling? setattr(cls, key, value) return None else: From tismer at codespeak.net Fri Jun 17 01:42:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:42:16 +0200 (CEST) Subject: [pypy-svn] r13500 - in pypy/dist/pypy/rpython: . test Message-ID: <20050616234216.0298227B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:42:14 2005 New Revision: 13500 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: interp is now working nicely with exceptions. After all, it was easy. Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Fri Jun 17 01:42:14 2005 @@ -60,26 +60,32 @@ def eval_graph(self, graph, args=()): nextblock = graph.startblock + excblock = graph.exceptblock while 1: self.fillvars(nextblock, args) - nextblock, args = self.eval_block(nextblock) + nextblock, args = self.eval_block(nextblock, excblock) if nextblock is None: return args - def eval_block(self, block): + def eval_block(self, block, excblock): """ return (nextblock, values) tuple. If nextblock is None, values is the concrete return value. """ catch_exception = block.exitswitch == Constant(last_exception) e = None - for op in block.operations: - try: + try: + for op in block.operations: self.eval_operation(op) - except RPythonError, e: - # XXX should only catch exceptions from the last operation - # XXX non-caught exceptions should just be allowed to propagate - assert catch_exception, 'exception received, but not expected' + except RPythonError, e: + if not catch_exception: + # there is no explicit handler. + # we could simply re-raise here, but it is cleaner + # to redirect to the provided default exception block + block = excblock + cls, inst = e.args + self.setvar(block.inputargs[0], cls) + self.setvar(block.inputargs[1], inst) # determine nextblock and/or return value if len(block.exits) == 0: @@ -109,9 +115,9 @@ if exdata.ll_exception_match(cls, link.llexitcase): self.setvar(link.last_exception, cls) self.setvar(link.last_exc_value, inst) - return link.target, [cls, inst] + break else: - raise Exception, e # unhandled case, should not happen" + raise Exception, e # unhandled case, should not happen else: index = self.getval(block.exitswitch) link = block.exits[index] Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Fri Jun 17 01:42:14 2005 @@ -59,10 +59,18 @@ assert find_exception(info.value) is ValueError def test_call_raise(): - res = interpret(call_raise_intercept, [41]) + res = interpret(call_raise, [41]) assert res == 41 - info = raises(RPythonError, interpret, call_raise_intercept, [42]) + info = raises(RPythonError, interpret, call_raise, [42]) assert find_exception(info.value) is IndexError + info = raises(RPythonError, interpret, call_raise, [43]) + assert find_exception(info.value) is ValueError + +def test_call_raise_intercept(): + res = interpret(call_raise_intercept, [41]) + assert res == 41 + res = interpret(call_raise_intercept, [42]) + assert res == 42 info = raises(RPythonError, interpret, call_raise_intercept, [43]) assert find_exception(info.value) is TypeError @@ -137,9 +145,14 @@ raise ValueError return i +def call_raise(i): + return raise_exception(i) + def call_raise_intercept(i): try: return raise_exception(i) + except IndexError: + return i except ValueError: raise TypeError #__________________________________________________________________ From tismer at codespeak.net Fri Jun 17 01:44:40 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:44:40 +0200 (CEST) Subject: [pypy-svn] r13501 - pypy/dist/pypy/translator Message-ID: <20050616234440.9D49827B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:44:39 2005 New Revision: 13501 Modified: pypy/dist/pypy/translator/translator.py Log: aspecial __setstate__ to get things slightly more ordered. Actually it didn't have a real effect. But one really big effect was that it told me how genpickle really should work! See next check-in Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Fri Jun 17 01:44:39 2005 @@ -39,6 +39,15 @@ if self.entrypoint: self.getflowgraph() + def __getstate__(self): + # try to produce things a bit more ordered + return self.entrypoint, self.functions, self.__dict__ + + def __setstate__(self, args): + assert len(args) == 3 + self.__dict__.update(args[2]) + assert args[0] is self.entrypoint and args[1] is self.functions + def getflowgraph(self, func=None, called_by=None, call_tag=None): """Get the flow graph for a function (default: the entry point).""" func = func or self.entrypoint @@ -139,7 +148,7 @@ def source(self, func=None): """Returns original Python source. - Returns for functions written while the + Returns for functions written during the interactive session. """ func = func or self.entrypoint From tismer at codespeak.net Fri Jun 17 01:47:37 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:47:37 +0200 (CEST) Subject: [pypy-svn] r13502 - pypy/dist/pypy/translator/pickle Message-ID: <20050616234737.0068227B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:47:36 2005 New Revision: 13502 Modified: pypy/dist/pypy/translator/pickle/genpickle.py pypy/dist/pypy/translator/pickle/loader.py pypy/dist/pypy/translator/pickle/main.py pypy/dist/pypy/translator/pickle/writer.py Log: quite a rewrite of genpickle. This version does not have any latercode, anymore. There is a need to increase the recursionlimit, but only marginal. The key point is to register objects as soon as possible. This check-in was overdue, the interp thing got into the way. Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Fri Jun 17 01:47:36 2005 @@ -33,6 +33,8 @@ from types import * import types +class AlreadyCreated(Exception): pass + # ____________________________________________________________ @@ -40,188 +42,246 @@ def __init__(self, translator, writer = None): self.translator = translator - self.initcode = [ + self.writer = writer + self.initcode = [] + self.produce = self._produce() + self.produce( 'from __future__ import %s\n' % ', '.join(all_feature_names) + 'import new, types, sys', - ] - - self.latercode = [] # list of generators generating extra lines - self.debugstack = () # linked list of nested nameof() - - self.picklenames = {Constant(None): 'None', - Constant(False): 'False', - Constant(True): 'True', - # hack: overflowed float - Constant(float("1e10000000000000000000000000000000")): - 'float("1e10000000000000000000000000000000")', - } + ) + self.picklenames = {} # memoize objects + self.memoize(float("1e10000000000000000000000000000000"), + 'float("1e10000000000000000000000000000000")') for name in all_feature_names + "new types sys".split(): - self.picklenames[Constant(globals()[name])] = name + self.memoize(globals()[name], name) self.namespace = NameManager() + self.uniquename = self.namespace.uniquename self.namespace.make_reserved_names('None False True') self.namespace.make_reserved_names('new types sys') self.namespace.make_reserved_names(' '.join(all_feature_names)) + self.namespace.make_reserved_names('result') # result dict + self.result = {} + self.simple_const_types = { + int: repr, + long: repr, + float: repr, + str: repr, + unicode: repr, + type(None): repr, + bool: repr, + } + self.typecache = {} # hold types vs. nameof methods # we distinguish between the "user program" and other stuff. # "user program" will never use save_global. self.domains = ( 'pypy.objspace.std.', + 'pypy.objspace.descroperation', 'pypy._cache.', 'pypy.interpreter.', 'pypy.module.', '__main__', ) self.shortnames = { - SpaceOperation: 'SOP', Variable: 'V', Constant: 'C', Block: 'B', SpamBlock: 'SB', EggBlock: 'EB', Link: 'L', - FunctionGraph: 'F', - SomeInteger: 'SI', - SomeObject: 'SO', - SomeChar: 'SC', - SomeBool: 'SB', - SomeList: 'SL', - SomeString: 'SS', - SomeTuple: 'ST', - SomeInstance: 'SIN', + FunctionGraph: 'FG', + SomeInteger: 'sI', + SomeObject: 'sO', + SomeChar: 'sC', + SomeBool: 'sB', + SomeList: 'sL', + SomeString: 'sS', + SomeTuple: 'sT', + SomeInstance: 'sIn', } - self.writer = writer + self.inline_instances = { + SpaceOperation: True, + } + + def pickle(self, **kwds): + for obj in kwds.values(): + self.nameof(obj) + self.result.update(kwds) + + def finish(self): + self.nameof(self.result) + self.pickle() + self.produce('result = %s' % self.nameof(self.result)) + if self.writer: + self.writer.close() + + def memoize(self, obj, name): + self.picklenames[id(obj)] = name + return name + + def memoize_unique(self, obj, basename): + if id(obj) in self.picklenames: + raise AlreadyCreated + return self.memoize(obj, self.uniquename(basename)) - def nameof(self, obj, debug=None, namehint=None): - key = Constant(obj) + def _produce(self): + writer = self.writer + down = 1234 + cnt = [0, 0] # text, calls + self.last_progress = '' + if writer: + write = writer.write + else: + write = self.initcode.append + def produce(text): + write(text+'\n') + cnt[0] += len(text) + 1 + cnt[1] += 1 + if cnt[1] == down: + cnt[1] = 0 + self.progress("%d" % cnt[0]) + return produce + + def progress(self, txt): + back = '\x08' * len(self.last_progress) + self.last_progress = txt+' ' # soft space + print back+txt, + + def spill(self): + self.progress_count += len(self.initcode) + writer = self.writer + if writer: + for line in self.initcode: + writer.write(line+'\n') + del self.initcode[:] + if self.progress_count - self.progress_last >= 1234: + print '%s%d' % (20*'\x08', self.progress_count), + self.progress_last = self.progress_count + + def nameof(self, obj): try: - return self.picklenames[key] + try: + return self.picklenames[id(obj)] + except KeyError: + typ = type(obj) + return self.simple_const_types[typ](obj) except KeyError: - if debug: - stackentry = debug, obj - else: - stackentry = obj - self.debugstack = (self.debugstack, stackentry) - obj_builtin_base = builtin_base(obj) - if obj_builtin_base in (object, int, long) and type(obj) is not obj_builtin_base: - # assume it's a user defined thingy - name = self.nameof_instance(obj) - else: - for cls in type(obj).__mro__: - meth = getattr(self, - 'nameof_' + ''.join( [ - c for c in cls.__name__ - if c.isalpha() or c == '_'] ), - None) - if meth: - break - else: - raise Exception, "nameof(%r)" % (obj,) - - code = meth.im_func.func_code - if namehint and 'namehint' in code.co_varnames[:code.co_argcount]: - name = meth(obj, namehint=namehint) - else: - name = meth(obj) - self.debugstack, x = self.debugstack - assert x is stackentry - if name[0].isalpha(): - # avoid to store things which are used just once - self.picklenames[key] = name + try: + try: + meth = self.typecache[typ] + except KeyError: + obj_builtin_base = builtin_base(obj) + if (obj_builtin_base in (object,) + tuple( + self.simple_const_types.keys()) and + typ is not obj_builtin_base): + # assume it's a user defined thingy + meth = self.nameof_instance + else: + for cls in typ.__mro__: + meth = getattr(self, 'nameof_' + ''.join( + [ c for c in cls.__name__ + if c.isalpha() or c == '_'] ), None) + if meth: + break + else: + raise Exception, "nameof(%r)" % (obj,) + self.typecache[typ] = meth + name = meth(obj) + except AlreadyCreated: + name = self.picklenames[id(obj)] return name def nameofargs(self, tup, plain_tuple = False): """ a string with the nameofs, concatenated """ # see if we can build a compact representation - for each in tup: - if type(each) is tuple and len(each) > 2: - break - else: - ret = ', '.join([self.nameof(arg) for arg in tup]) - if plain_tuple and len(tup) == 1: - ret += ',' - if len(ret) <= 90: - return ret - ret = '\n ' + (',\n ').join( + ret = ', '.join([self.nameof(arg) for arg in tup]) + if plain_tuple and len(tup) == 1: + ret += ',' + if len(ret) <= 90: + return ret + ret = '\n ' + ',\n '.join( [self.nameof(arg) for arg in tup]) + ',\n ' return ret - def uniquename(self, basename): - return self.namespace.uniquename(basename) - - def initcode_python(self, name, pyexpr): - # generate init code that will evaluate the given Python expression - #self.initcode.append("print 'setting up', %r" % name) - self.initcode.append("%s = %s" % (name, pyexpr)) - def nameof_object(self, value): if type(value) is not object: - raise Exception, "nameof(%r)" % (value,) - name = self.uniquename('g_object') - self.initcode_python(name, "object()") + raise Exception, "nameof(%r): type %s not object" % ( + value, type(value).__name__) + name = self.memoize_unique(value, 'g_object') + self.produce('%s = object()' % name) return name def nameof_module(self, value): # all allowed here, we reproduce ourselves if self.is_app_domain(value.__name__): - name = self.uniquename('gmod_%s' % value.__name__) - self.initcode.append('%s = new.module(%r)\n' - 'sys.modules[%r] = %s'% ( + name = self.memoize_unique(value, 'gmod_%s' % value.__name__) + self.produce('%s = new.module(%r)\n' + 'sys.modules[%r] = %s'% ( name, value.__name__, value.__name__, name) ) def initmodule(): - for k, v in value.__dict__.items(): + names = value.__dict__.keys() + names.sort() + for k in names: try: + v = value.__dict__[k] nv = self.nameof(v) yield '%s.%s = %s' % (name, k, nv) except PicklingError: pass - self.later(initmodule()) + for line in initmodule(): + self.produce(line) else: - name = self.uniquename(value.__name__) - self.initcode_python(name, "__import__(%r)" % (value.__name__,)) + name = self.memoize_unique(value, value.__name__) + self.produce('%s = __import__(%r)' % (name, value.__name__,)) return name - def nameof_int(self, value): - return repr(value) - - # we don't need to name the following const types. - # the compiler folds the consts the same way as we do. - # note that true pickling is more exact, here. - nameof_long = nameof_float = nameof_bool = nameof_NoneType = nameof_int - nameof_str = nameof_unicode = nameof_int - - def skipped_function(self, func): + def skipped_function(self, func, reason=None, _dummydict={}): # Generates a placeholder for missing functions # that raises an exception when called. # The original code object is retained in an # attribute '_skipped_code' - name = self.uniquename('gskippedfunc_' + func.__name__) - codename = self.nameof(func.func_code) - self.initcode.append('def %s(*a,**k):\n' - ' raise NotImplementedError' % name) - self.initcode.append('%s._skipped_code = %s' % (name, codename) ) - return name + skipname = 'gskippedfunc_' + func.__name__ + funcname = func.__name__ + # need to handle this specially + if id(func) in self.picklenames: + raise AlreadyCreated + # generate code object before the skipped func (reads better) + func_code = getattr(func, 'func_code', None) # maybe builtin + self.nameof(func_code) + if reason: + text = 'skipped: %r, see _skipped_code attr: %s' % ( + reason, funcname) + else: + text = 'skipped, see _skipped_code attr: %s' % funcname + def dummy(*args, **kwds): + raise NotImplementedError, text + skippedfunc = new.function(dummy.func_code, _dummydict, skipname, (), + dummy.func_closure) + skippedfunc._skipped_code = func_code + name = self.nameof(skippedfunc) + return self.memoize(func, name) def nameof_staticmethod(self, sm): # XXX XXX XXXX func = sm.__get__(42.5) - name = self.uniquename('gsm_' + func.__name__) functionname = self.nameof(func) - self.initcode_python(name, 'staticmethod(%s)' % functionname) + name = self.memoize_unique(sm, 'gsm_' + func.__name__) + self.produce('%s = staticmethod(%s)' % (name, functionname)) return name def nameof_instancemethod(self, meth): + func = self.nameof(meth.im_func) + typ = self.nameof(meth.im_class) if meth.im_self is None: # no error checking here - return self.nameof(meth.im_func) + name = self.memoize_unique(meth, 'gmeth_' + func) + self.produce('%s = %s.%s' % (name, typ, meth.__name__)) else: ob = self.nameof(meth.im_self) - func = self.nameof(meth.im_func) - typ = self.nameof(meth.im_class) - name = self.uniquename('gmeth_'+meth.im_func.__name__) - self.initcode_python(name, 'new.instancemethod(%s, %s, %s)' % ( - func, ob, typ)) - return name + name = self.memoize_unique(meth, 'gumeth_'+ func) + self.produce('%s = new.instancemethod(%s, %s, %s)' % ( + name, func, ob, typ)) + return name - # new version: save if we don't know def should_translate_attr(self, pbc, attr): ann = self.translator.annotator if ann: @@ -241,22 +301,31 @@ # builtin function # where does it come from? Python2.2 doesn't have func.__module__ for modname, module in sys.modules.items(): - # here we don't ignore extension modules + # here we don't ignore extension modules, but it must be + # a builtin module + if not module: continue + if hasattr(module, '__file__'): + fname = module.__file__.lower() + pyendings = '.py', '.pyc', '.pyo' + if [fname.endswith(ending) for ending in pyendings]: + continue if func is getattr(module, func.__name__, None): break else: - raise Exception, '%r not found in any built-in module' % (func,) - name = self.uniquename('gbltin_' + func.__name__) + #raise Exception, '%r not found in any built-in module' % (func,) + return self.skipped_function( + func, 'not found in any built-in module') + name = self.memoize_unique(func, 'gbltin_' + func.__name__) if modname == '__builtin__': - self.initcode_python(name, func.__name__) + self.produce('%s = %s' % (name, func.__name__)) else: modname = self.nameof(module) - self.initcode_python(name, '%s.%s' % (modname, func.__name__)) + self.produce('%s = %s.%s' % (name, modname, func.__name__)) else: # builtin (bound) method - name = self.uniquename('gbltinmethod_' + func.__name__) selfname = self.nameof(func.__self__) - self.initcode_python(name, '%s.%s' % (selfname, func.__name__)) + name = self.memoize_unique(func, 'gbltinmethod_' + func.__name__) + self.produce('%s = %s.%s' % (name, selfname, func.__name__)) return name def nameof_classobj(self, cls): @@ -265,27 +334,21 @@ try: return self.save_global(cls) - except PicklingError: + except PicklingError, e: pass metaclass = "type" if issubclass(cls, Exception): # if cls.__module__ == 'exceptions': # don't rely on this, py.magic redefines AssertionError - if getattr(__builtin__,cls.__name__,None) is cls: - name = self.uniquename('gexc_' + cls.__name__) - self.initcode_python(name, cls.__name__) + if getattr(__builtin__, cls.__name__, None) is cls: + name = self.memoize_unique(cls, 'gexc_' + cls.__name__) + self.produce('%s = %s' % (name, cls.__name__)) return name - #else: - # # exceptions must be old-style classes (grr!) - # metaclass = "&PyClass_Type" - # For the moment, use old-style classes exactly when the - # pypy source uses old-style classes, to avoid strange problems. if not isinstance(cls, type): assert type(cls) is ClassType metaclass = "types.ClassType" - name = self.uniquename('gcls_' + cls.__name__) basenames = [self.nameof(base) for base in cls.__bases__] def initclassobj(): content = cls.__dict__.items() @@ -302,7 +365,6 @@ if isapp: if (isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen): - print value continue if isinstance(value, classmethod): doc = value.__get__(cls).__doc__ @@ -310,7 +372,6 @@ continue if (isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen): - print value continue if key in ignore: continue @@ -322,15 +383,16 @@ baseargs = ", ".join(basenames) if baseargs: baseargs = '(%s)' % baseargs + name = self.memoize_unique(cls, 'gcls_' + cls.__name__) ini = 'class %s%s:\n __metaclass__ = %s' % (name, baseargs, metaclass) if '__slots__' in cls.__dict__: ini += '\n __slots__ = %r' % cls.__slots__ - self.initcode.append(ini) - self.initcode.append('%s.name = %r' % (name, cls.__name__)) - # squeeze it out, now# self.later(initclassobj()) - self.picklenames[Constant(cls)] = name + self.produce(ini) + self.produce('%s.__name__ = %r' % (name, cls.__name__)) + self.produce('%s.__module__ = %r' % (name, cls.__module__)) + # squeeze it out, early # self.later(initclassobj()) for line in initclassobj(): - self.initcode.append(line) + self.produce(line) return name nameof_class = nameof_classobj # for Python 2.2 @@ -357,6 +419,8 @@ type(type.__dict__['__basicsize__']): "type(type.__dict__['__basicsize__'])", # type 'instancemethod': type(Exception().__init__): 'type(Exception().__init__)', + # type 'listiterator': + type(iter([])): 'type(iter([]))', } descriptor_filter = {} for _key in typename_mapping.keys(): @@ -367,46 +431,54 @@ def nameof_type(self, cls): if cls.__module__ != '__builtin__': return self.nameof_classobj(cls) # user-defined type - name = self.uniquename('gtype_%s' % cls.__name__) + name = self.memoize_unique(cls, 'gtype_%s' % cls.__name__) if getattr(__builtin__, cls.__name__, None) is cls: expr = cls.__name__ # type available from __builtin__ elif cls in types.__dict__.values(): for key, value in types.__dict__.items(): if value is cls: break - self.initcode.append('from types import %s as %s' % ( + self.produce('from types import %s as %s' % ( key, name)) return name else: expr = self.typename_mapping[cls] - self.initcode_python(name, expr) + self.produce('%s = %s' % (name, expr)) return name def nameof_tuple(self, tup): chunk = 20 - name = self.uniquename('T%d' % len(tup)) + # first create all arguments + for i in range(0, len(tup), chunk): + self.nameofargs(tup[i:i+chunk], True) + # see if someone else created us meanwhile + name = self.memoize_unique(tup, 'T%d' % len(tup)) argstr = self.nameofargs(tup[:chunk], True) - self.initcode_python(name, '(%s)' % argstr) + self.produce('%s = (%s)' % (name, argstr)) for i in range(chunk, len(tup), chunk): argstr = self.nameofargs(tup[i:i+chunk], True) - self.initcode.append('%s += (%s)' % (name, argstr) ) + self.produce('%s += (%s)' % (name, argstr) ) return name def nameof_list(self, lis): chunk = 20 - name = self.uniquename('L%d' % len(lis)) def initlist(): - chunk = 20 for i in range(0, len(lis), chunk): argstr = self.nameofargs(lis[i:i+chunk]) yield '%s += [%s]' % (name, argstr) - self.initcode_python(name, '[]') - self.later(initlist()) + name = self.memoize_unique(lis, 'L%d' % len(lis)) + self.produce('%s = []' % name) + for line in initlist(): + self.produce(line) return name def is_app_domain(self, modname): for domain in self.domains: - if modname.startswith(domain): + if domain.endswith('.') and modname.startswith(domain): + # handle subpaths + return True + if modname == domain: + # handle exact module names return True return False @@ -414,6 +486,8 @@ if '__name__' in dic: module = dic['__name__'] try: + if type(module) is str and self.is_app_domain(module): + raise ImportError __import__(module) mod = sys.modules[module] except (ImportError, KeyError, TypeError): @@ -421,51 +495,38 @@ else: if dic is mod.__dict__ and not self.is_app_domain(module): dictname = module.split('.')[-1] + '__dict__' - dictname = self.uniquename(dictname) - self.initcode.append('from %s import __dict__ as %s' % ( - module, dictname) ) - self.picklenames[Constant(dic)] = dictname + dictname = self.memoize_unique(dic, dictname) + self.produce('from %s import __dict__ as %s' % ( + module, dictname) ) return dictname - name = self.uniquename('D%d' % len(dic)) def initdict(): - for k in dic: + keys = dic.keys() + keys.sort() + for k in keys: try: - if type(k) is str: - yield '%s[%r] = %s' % (name, k, self.nameof(dic[k])) - else: - yield '%s[%s] = %s' % (name, self.nameof(k), - self.nameof(dic[k])) + nk, nv = self.nameof(k), self.nameof(dic[k]) + yield '%s[%s] = %s' % (name, nk, nv) except PicklingError: pass - self.initcode_python(name, '{}') - self.later(initdict()) + name = self.memoize_unique(dic, 'D%d' % len(dic)) + self.produce('%s = {}' % name) + for line in initdict(): + self.produce(line) return name # strange prebuilt instances below, don't look too closely # XXX oh well. def nameof_member_descriptor(self, md): - name = self.uniquename('gdescriptor_%s_%s' % ( - md.__objclass__.__name__, md.__name__)) cls = self.nameof(md.__objclass__) - self.initcode_python(name, '%s.__dict__[%r]' % (cls, md.__name__)) + name = self.memoize_unique(md, 'gdescriptor_%s_%s' % ( + md.__objclass__.__name__, md.__name__)) + self.produce('%s = %s.__dict__[%r]' % (name, cls, md.__name__)) return name nameof_getset_descriptor = nameof_member_descriptor nameof_method_descriptor = nameof_member_descriptor nameof_wrapper_descriptor = nameof_member_descriptor def nameof_instance(self, instance): - klass = instance.__class__ - if klass in self.shortnames: - name = self.uniquename(self.shortnames[klass]) - else: - name = self.uniquename('ginst_' + klass.__name__) - cls = self.nameof(klass) - if hasattr(klass, '__base__'): - base_class = builtin_base(instance) - base = self.nameof(base_class) - else: - base_class = None - base = cls def initinstance(): if hasattr(instance, '__setstate__'): # the instance knows what to do @@ -481,14 +542,33 @@ "%s has no dict and no __setstate__" % name) content = restorestate.items() content.sort() + attrs = [] for key, value in content: if self.should_translate_attr(instance, key): if hasattr(value, '__doc__'): doc = value.__doc__ if type(doc) is str and doc.lstrip().startswith('NOT_RPYTHON'): continue - line = '%s.%s = %s' % (name, key, self.nameof(value)) - yield line + attrs.append( (key, self.nameof(value)) ) + for k, v in attrs: + yield '%s.%s = %s' % (name, k, v) + + klass = instance.__class__ + cls = self.nameof(klass) + if hasattr(klass, '__base__'): + base_class = builtin_base(instance) + base = self.nameof(base_class) + else: + base_class = None + base = cls + if klass in self.inline_instances: + immediate = True + else: + if klass in self.shortnames: + name = self.memoize_unique(instance, self.shortnames[klass]) + else: + name = self.memoize_unique(instance, 'ginst_' + klass.__name__) + immediate = False if hasattr(instance, '__reduce_ex__'): try: reduced = instance.__reduce_ex__() @@ -501,7 +581,7 @@ assert not hasattr(instance, '__dict__'), ('wrong assumptions' ' about __slots__ in %s instance without __setstate__,' ' please update %s' % (cls.__name__, __name__) ) - restorestate = slotted.__getstate__(instance) + restorestate = _get(instance) restorer = _rec restoreargs = klass, else: @@ -526,50 +606,50 @@ else: restorestate = instance.__dict__ restoreargstr = self.nameofargs(restoreargs) + if immediate: + assert restorestate is None + return '%s(%s)' % (restorename, restoreargstr) if isinstance(klass, type): - self.initcode.append('%s = %s(%s)' % (name, restorename, - restoreargstr)) + self.produce('%s = %s(%s)' % (name, restorename, restoreargstr)) else: - self.initcode.append('%s = new.instance(%s)' % (name, cls)) + self.produce('%s = new.instance(%s)' % (name, cls)) if restorestate is not None: - self.later(initinstance()) + for line in initinstance(): + self.produce(line) return name def save_global(self, obj): # this is almost similar to pickle.py name = obj.__name__ - key = Constant(obj) - if key not in self.picklenames: - module = getattr(obj, "__module__", None) - if module is None: - module = whichmodule(obj, name) - if self.is_app_domain(module): - # not allowed to import this - raise PicklingError('%s belongs to the user program' % - name) - try: - __import__(module) - mod = sys.modules[module] - klass = getattr(mod, name) - except (ImportError, KeyError, AttributeError): + module = getattr(obj, "__module__", None) + if module is None: + module = whichmodule(obj, name) + if self.is_app_domain(module): + # not allowed to import this + raise PicklingError('%s belongs to the user program' % + name) + try: + __import__(module) + mod = sys.modules[module] + klass = getattr(mod, name) + except (ImportError, KeyError, AttributeError): + raise PicklingError( + "Can't pickle %r: it's not found as %s.%s" % + (obj, module, name)) + else: + if klass is not obj: raise PicklingError( - "Can't pickle %r: it's not found as %s.%s" % + "Can't pickle %r: it's not the same object as %s.%s" % (obj, module, name)) - else: - if klass is not obj: - raise PicklingError( - "Can't pickle %r: it's not the same object as %s.%s" % - (obj, module, name)) - # from here we do our own stuff - restorename = self.uniquename(obj.__name__) - if restorename != obj.__name__: - self.initcode.append('from %s import %s as %s' % ( - module, obj.__name__, restorename) ) - else: - self.initcode.append('from %s import %s' % ( - module, obj.__name__) ) - self.picklenames[key] = restorename - return self.picklenames[key] + # from here we do our own stuff + restorename = self.memoize_unique(obj, obj.__name__) + if restorename != obj.__name__: + self.produce('from %s import %s as %s' % ( + module, obj.__name__, restorename) ) + else: + self.produce('from %s import %s' % ( + module, obj.__name__) ) + return restorename def nameof_function(self, func): # look for skipped functions @@ -578,41 +658,50 @@ # see if this is in translator's domain module = whichmodule(func, func.__name__) if self.is_app_domain(module): - return self.skipped_function(func) + # see if this buddy has been skipped in another save, before + if not hasattr(func, '_skipped_code'): + return self.skipped_function(func, + 'not found in translator\'s flowgraphs') else: if (func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON')): - return self.skipped_function(func) + return self.skipped_function(func, 'tagged as NOT_RPYTHON') try: return self.save_global(func) except PicklingError: pass args = (func.func_code, func.func_globals, func.func_name, func.func_defaults, func.func_closure) - pyfuncobj = self.uniquename('gfunc_' + func.__name__) - self.initcode.append('%s = new.function(%s)' % (pyfuncobj, - self.nameofargs(args)) ) + argstr = self.nameofargs(args) + if hasattr(func, '_skipped_code'): + name = self.memoize_unique(func, func.__name__) + else: + name = self.memoize_unique(func, 'gfunc_' + func.__name__) + self.produce('%s = new.function(%s)' % (name, argstr) ) if func.__dict__: - for k, v in func.__dict__.items(): - try: - self.initcode.append('%s.%s = %s' % ( - pyfuncobj, k, self.nameof(v)) ) - except PicklingError: - pass - return pyfuncobj + def initfunction(): + items = func.__dict__.items() + items.sort() + for k, v in items: + try: + yield '%s.%s = %s' % (name, k, self.nameof(v)) + except PicklingError: + pass + for line in initfunction(): + self.produce(line) + return name def nameof_cell(self, cel): + # no need to name cells. Their contents is what is shared. obj = break_cell(cel) - pycell = self.uniquename('gcell_' + self.nameof(obj)) - self.initcode.append('%s = %s(%s)' % (pycell, self.nameof(make_cell), - self.nameof(obj)) ) - return pycell + return '%s(%s)' % (self.nameof(make_cell), self.nameof(obj)) def nameof_property(self, prop): - pyprop = self.uniquename('gprop_') - self.initcode.append('%s = property(%s)' % (pyprop, self.nameofargs( - (prop.fget, prop.fset, prop.fdel, prop.__doc__))) ) - return pyprop + argstr = self.nameofargs((prop.fget, prop.fset, prop.fdel, + prop.__doc__)) + name = self.memoize_unique(prop, 'gprop_') + self.produce('%s = property(%s)' % (name, argstr) ) + return name def nameof_code(self, code): args = (code.co_argcount, code.co_nlocals, code.co_stacksize, @@ -621,9 +710,9 @@ code.co_firstlineno, code.co_lnotab, code.co_freevars, code.co_cellvars) argstr = self.nameofargs(args) - codeobj = self.uniquename('gcode_' + code.co_name) - self.initcode.append('%s = new.code(%s)' % (codeobj, argstr)) - return codeobj + name = self.memoize_unique(code, 'gcode_' + code.co_name) + self.produce('%s = new.code(%s)' % (name, argstr)) + return name def nameof_file(self, fil): if fil is sys.stdin: return "sys.stdin" @@ -633,46 +722,10 @@ def nameof_methodwrapper(self, wp): # this object should be enhanced in CPython! - reprwp = repr(wp) - name = wp.__name__ - def dummy_methodwrapper(): - return reprwp + (': method %s of unknown object ' - 'cannot be reconstructed, sorry!' % name ) - return self.nameof(dummy_methodwrapper) - - def later(self, gen): - self.latercode.append((gen, self.debugstack)) + msg = '%r: method %s of unknown object cannot be reconstructed' % ( + wp, wp.__name__) + return self.skipped_function(wp, msg) - def collect_initcode(self): - writer = self.writer - while self.latercode: - gen, self.debugstack = self.latercode.pop() - #self.initcode.extend(gen) -- eats TypeError! bad CPython! - for line in gen: - self.initcode.append(line) - self.debugstack = () - if writer: - for line in self.initcode: - writer.write(line) - del self.initcode[:] - if writer: - writer.close() - - def getfrozenbytecode(self): - self.initcode.append('') - source = '\n'.join(self.initcode) - del self.initcode[:] - co = compile(source, '', 'exec') - originalsource = source - small = zlib.compress(marshal.dumps(co)) - source = """if 1: - import zlib, marshal - exec marshal.loads(zlib.decompress(%r))""" % small - # Python 2.2 SyntaxError without newline: Bug #501622 - source += '\n' - co = compile(source, '', 'exec') - del source - return marshal.dumps(co), originalsource def make_cell(obj): def func(): @@ -693,5 +746,10 @@ def _rec(klass, base=object, state=None): return _reconstructor(klass, base, state) +def _get(obj): + return slotted.__getstate__(obj) + def _set(obj, *args): slotted.__setstate__(obj, args) + +__all__ = ['GenPickle'] Modified: pypy/dist/pypy/translator/pickle/loader.py ============================================================================== --- pypy/dist/pypy/translator/pickle/loader.py (original) +++ pypy/dist/pypy/translator/pickle/loader.py Fri Jun 17 01:47:36 2005 @@ -2,6 +2,7 @@ class Loader: def __init__(self, fname): + self.opened = False self.f = self.open_file(fname) def open_file(self, fname): @@ -15,18 +16,22 @@ for blk in self.next_block(): exec blk in dic try: - return dic['ginst_Translator'] + return dic['result'] finally: self.close() def close(self): - self.f.close() + if self.opened: + self.f.close() class TextLoader(Loader): def open_file(self, fname): - return file(fname) + if type(fname) is str: + self.opened = True + return file(fname) + return fname # should be a file-like object def next_block(self): data = self.f.read().split('## SECTION ##\n') @@ -37,7 +42,10 @@ """ load compiled code from a ZIP file """ def open_file(self, fname): - return zipfile.ZipFile(fname, "r") + if type(fname) is str: + self.opened = True + return zipfile.ZipFile(fname, "r") + return fname def next_block(self): root = self.f.read('root') @@ -48,3 +56,5 @@ dump = self.f.read(name) assert md5.new(dump).hexdigest() == name, "broken checksum" yield marshal.loads(dump) + +__all__ = ['Loader', 'TextLoader', 'ZipLoader'] Modified: pypy/dist/pypy/translator/pickle/main.py ============================================================================== --- pypy/dist/pypy/translator/pickle/main.py (original) +++ pypy/dist/pypy/translator/pickle/main.py Fri Jun 17 01:47:36 2005 @@ -1,5 +1,37 @@ +import sys +from pypy.translator.pickle.genpickle import GenPickle +from pypy.translator.pickle.writer import Writer, TextWriter, ZipWriter +from pypy.translator.pickle.loader import Loader, TextLoader, ZipLoader + def load(fname): - pass + loader = _select(fname)[0] + assert loader, 'only .py and .zip files supported' + return loader(fname).load() + +def save(translator, fname, **objects): + writer = _select(fname)[1] + assert writer, 'only .py and .zip files supported' + assert objects, 'please provide objects to be saved as keywords' + pickler = GenPickle(translator, writer(fname)) + hold = sys.getrecursionlimit() + if hold < 5000: + sys.setrecursionlimit(5000) + try: + pickler.pickle(**objects) + finally: + sys.setrecursionlimit(hold) + pickler.finish() + return pickler # for debugging purposes + +# and that's all, folks! +# _________________________________________________________________ + +def _select(fname): + name = fname.lower() + if name.endswith('.py'): + return TextLoader, TextWriter + elif name.endswith('.zip'): + return ZipLoader, ZipWriter + else: + return None, None -def save(translator, fname): - pass Modified: pypy/dist/pypy/translator/pickle/writer.py ============================================================================== --- pypy/dist/pypy/translator/pickle/writer.py (original) +++ pypy/dist/pypy/translator/pickle/writer.py Fri Jun 17 01:47:36 2005 @@ -6,6 +6,7 @@ self.chunksize = 100000 self.count = 0 self.blocknum = 0 + self.opened = False self.f = self.open_file(fname) def open_file(self, fname): @@ -15,17 +16,18 @@ self.pieces.append(text) self.count += len(text) + 1 if self.count >= self.chunksize: - src = '\n'.join(self.pieces) + src = ''.join(self.pieces) del self.pieces[:] self.count -= self.chunksize self.putblock(src) self.blocknum += 1 def close(self): - src = '\n'.join(self.pieces) + src = ''.join(self.pieces) self.putblock(src) self.finalize() - self.f.close() + if self.opened: + self.f.close() def finalize(self): pass @@ -34,10 +36,13 @@ class TextWriter(Writer): def open_file(self, fname): - return file(fname, 'w') + if type(fname) is str: + self.opened = True + return file(fname, 'w') + return fname # should be a file-like object def putblock(self, src): - print >> self.f, src + self.f.write(src) print >> self.f, '## SECTION ##' class ZipWriter(Writer): @@ -48,7 +53,10 @@ self.blocknames = [] def open_file(self, fname): - return zipfile.ZipFile(fname, "w", zipfile.ZIP_DEFLATED) + if type(fname) is str: + self.opened = True + return zipfile.ZipFile(fname, "w", zipfile.ZIP_DEFLATED) + return fname def putblock(self, src): cod = compile(src, 'block_%d' % self.blocknum, 'exec') @@ -62,3 +70,5 @@ digest = md5.new(dump).hexdigest() self.f.writestr(digest, dump) self.f.writestr('root', digest) + +__all__ = ['Writer', 'TextWriter', 'ZipWriter'] From tismer at codespeak.net Fri Jun 17 01:48:30 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:48:30 +0200 (CEST) Subject: [pypy-svn] r13503 - pypy/dist/pypy/translator/goal Message-ID: <20050616234830.38D2827B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:48:29 2005 New Revision: 13503 Modified: pypy/dist/pypy/translator/goal/targetrpystone.py Log: removed obsolete import Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Fri Jun 17 01:48:29 2005 @@ -1,4 +1,3 @@ -import buildcache2 from pypy.objspace.std.objspace import StdObjSpace from pypy.translator.test import rpystone From tismer at codespeak.net Fri Jun 17 01:50:00 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:50:00 +0200 (CEST) Subject: [pypy-svn] r13504 - pypy/dist/pypy/translator/goal Message-ID: <20050616235000.D0EF827B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:50:00 2005 New Revision: 13504 Modified: pypy/dist/pypy/translator/goal/targetpypymain.py Log: removeda bad "import *" which caused some weird objects to be pulledinto __main__. And since I haveto pickle __main__ anyway, this is no good. Modified: pypy/dist/pypy/translator/goal/targetpypymain.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypymain.py (original) +++ pypy/dist/pypy/translator/goal/targetpypymain.py Fri Jun 17 01:50:00 2005 @@ -1,6 +1,9 @@ import os, sys from pypy.objspace.std.objspace import StdObjSpace -from pypy.annotation.model import * +# XXX from pypy.annotation.model import * +# since we are execfile()'ed this would pull some +# weird objects into the globals, which we would try to pickle. +from pypy.annotation.model import SomeList, SomeString from pypy.annotation.listdef import ListDef from pypy.interpreter import gateway From tismer at codespeak.net Fri Jun 17 01:51:02 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:51:02 +0200 (CEST) Subject: [pypy-svn] r13505 - pypy/dist/pypy/translator/goal Message-ID: <20050616235102.5825A27B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:51:01 2005 New Revision: 13505 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: enabled loading and saving of pickled translators. Something is still wrong here -- I seem to pickle some things by ID, which cannot be restored. Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Fri Jun 17 01:51:01 2005 @@ -65,7 +65,8 @@ from pypy.annotation.model import SomeObject from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_print - +from pypy.rpython.rtyper import RPythonTyper +from pypy.translator.pickle.main import load, save # XXX this tries to make compiling faster from pypy.translator.tool import buildpyxmodule @@ -77,11 +78,12 @@ # __________ Main __________ def analyse(target): - global t, entry_point - - entry_point, inputtypes = target() + global t, entry_point, inputtypes - t = Translator(entry_point, verbose=True, simplifying=True) + if target: + entry_point, inputtypes = target() + t = Translator(entry_point, verbose=True, simplifying=True) + # otherwise we have been loaded if listen_port: run_async_server() if not options['-no-a']: @@ -91,7 +93,8 @@ if not options['-no-s']: a.simplify() if not options['-no-t']: - t.specialize() + typer = RPythonTyper(a) + typer.specialize() t.frozen = True # cannot freeze if we don't have annotations if not options['-no-mark-some-objects']: options['-no-mark-some-objects'] = True # Do not do this again @@ -225,6 +228,8 @@ targetspec = 'targetpypymain' huge = 100 + load_file = None + save_file =None options = {'-text': False, '-no-c': False, @@ -236,9 +241,12 @@ '-no-t': False, '-tcc': False, '-no-d': False, + '-load': False, + '-save': False, } listen_port = None - for arg in sys.argv[1:]: + argiter = iter(sys.argv[1:]) + for arg in argiter: if arg in ('-h', '--help'): print __doc__.strip() sys.exit() @@ -256,6 +264,11 @@ else: assert arg in options, "unknown option %r" % (arg,) options[arg] = True + if arg == '-load': + load_file = argiter.next() + loaded_dic = load(load_file) + if arg == '-save': + save_file = argiter.next() if options['-tcc']: os.environ['PYPY_CC'] = 'tcc -shared -o "%s.so" "%s.c"' if options['-no-d']: @@ -455,12 +468,39 @@ cleanup() try: - targetspec_dic = {} - sys.path.insert(0, os.path.dirname(targetspec)) - execfile(targetspec+'.py',targetspec_dic) - print "Analysing target as defined by %s" % targetspec - analyse(targetspec_dic['target']) + if load_file: + t = loaded_dic['trans'] + entry_point = t.entrypoint + inputtypes = loaded_dic['inputtypes'] + targetspec_dic = loaded_dic['targetspec_dic'] + targetspec = loaded_dic['targetspec'] + old_options = loaded_dic['options'] + for name in '-no-a -no-s -no-t'.split(): + # if one of these options has not been set, before, + # then the action has been done and must be prevented, now. + if not old_options[name]: + if options[name]: + print 'option %s is implied by the load' % name + options[name] = True + print "continuing Analysis as defined by %s, loaded from %s" %( + targetspec, load_file) + analyse(None) + else: + targetspec_dic = {} + sys.path.insert(0, os.path.dirname(targetspec)) + execfile(targetspec+'.py', targetspec_dic) + print "Analysing target as defined by %s" % targetspec + analyse(targetspec_dic['target']) print '-'*60 + if save_file: + print 'saving state to %s' % save_file + save(t, save_file, + trans=t, + inputtypes=inputtypes, + targetspec=targetspec, + targetspec_dic=targetspec_dic, + options=options, + ) if options['-no-c']: print 'Not generating C code.' elif options['-c']: From tismer at codespeak.net Fri Jun 17 01:54:46 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 01:54:46 +0200 (CEST) Subject: [pypy-svn] r13506 - pypy/dist/pypy/rpython/test Message-ID: <20050616235446.1CAF827B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 01:54:45 2005 New Revision: 13506 Modified: pypy/dist/pypy/rpython/test/test_interp.py Log: hum. somebody checked in an untested test. funny... Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Fri Jun 17 01:54:45 2005 @@ -103,7 +103,7 @@ res = interpret(f,[]) assert len(res.items) == len([1,2,3]) for i in range(3): - assert res.items[i].item == i+1 + assert res.items[i] == i+1 #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() From tismer at codespeak.net Fri Jun 17 02:01:07 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 02:01:07 +0200 (CEST) Subject: [pypy-svn] r13507 - pypy/dist/pypy/translator/goal Message-ID: <20050617000107.6A3A527B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 02:01:06 2005 New Revision: 13507 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: added help text about load/save Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Fri Jun 17 02:01:06 2005 @@ -25,6 +25,10 @@ -no-d Disable recording of debugging information -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed + -save filename saves the translator to a file. The file type can either + be .py or .zip (recommended). + -load filename restores the translator from a file. The file type must + be either .py or.zip . """ import autopath, sys, os From arigo at codespeak.net Fri Jun 17 02:19:04 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 02:19:04 +0200 (CEST) Subject: [pypy-svn] r13508 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617001904.DEF7127B7D@code1.codespeak.net> Author: arigo Date: Fri Jun 17 02:19:02 2005 New Revision: 13508 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Fixed normalizecalls to know about classes. Call the __init__ of classes when building instances. Our first test that uses the LLInterpreter :-) Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 02:19:02 2005 @@ -30,6 +30,19 @@ argcount = pattern[0] pattern = (argcount+1,) + pattern[1:] func_family.patterns[pattern] = True + # for classes that appear in families, unify their __init__ as well + for family in call_families.infos(): + prevkey = None + for _, klass in family.objects: + if isinstance(klass, (type, types.ClassType)): + try: + initfunc = klass.__init__.im_func + except AttributeError: + continue + if prevkey is None: + prevkey = (None, initfunc) + else: + call_families.union((None, initfunc), prevkey) # find the most general signature of each family for family in call_families.infos(): # collect functions in this family, ignoring: Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 17 02:19:02 2005 @@ -512,6 +512,13 @@ rinstance = getinstancerepr(hop.rtyper, classdef) return rinstance.new_instance(hop.llops) +def instance_annotation_for_cls(rtyper, cls): + try: + classdef = rtyper.annotator.getuserclasses()[cls] + except KeyError: + raise TyperError("no classdef: %r" % (cls,)) + return annmodel.SomeInstance(classdef) + # ____________________________________________________________ # # Low-level implementation of operations on classes and instances Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jun 17 02:19:02 2005 @@ -2,10 +2,12 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef +from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct from pypy.rpython.lltype import Ptr, malloc, nullptr from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass +from pypy.rpython.rtyper import HighLevelOp class __extend__(annmodel.SomePBC): @@ -316,5 +318,25 @@ ## s_pbc.prebuiltinstances,)) def rtype_simple_call(self, hop): - return rclass.rtype_new_instance(self.s_pbc.const, hop) - # XXX call __init__ somewhere + klass = self.s_pbc.const + v_instance = rclass.rtype_new_instance(klass, hop) + try: + initfunc = klass.__init__.im_func + except AttributeError: + assert hop.nb_args == 1, ("arguments passed to __init__, " + "but no __init__!") + else: + if initfunc == Exception.__init__.im_func: + return v_instance # ignore __init__ and arguments completely + s_instance = rclass.instance_annotation_for_cls(self.rtyper, klass) + s_init = annmodel.SomePBC({initfunc: True}) + hop2 = hop.copy() + hop2.r_s_popfirstarg() # discard the class pointer argument + hop2.v_s_insertfirstarg(v_instance, s_instance) # (instance, *args) + c = Constant(initfunc) + hop2.v_s_insertfirstarg(c, s_init) # (initfunc, instance, *args) + hop2.s_result = annmodel.SomePBC({None: True}) + hop2.r_result = self.rtyper.getrepr(hop2.s_result) + r_init = self.rtyper.getrepr(s_init) + r_init.rtype_simple_call(hop2) + return v_instance Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Fri Jun 17 02:19:02 2005 @@ -366,14 +366,14 @@ # ____________________________________________________________ -class HighLevelOp: - nb_popped = 0 +class HighLevelOp(object): def __init__(self, rtyper, spaceop, exceptionlinks, llops): self.rtyper = rtyper self.spaceop = spaceop self.nb_args = len(spaceop.args) self.llops = llops + self.args_v = list(spaceop.args) self.args_s = [rtyper.binding(a) for a in spaceop.args] self.s_result = rtyper.binding(spaceop.result) self.args_r = [rtyper.getrepr(s_a) for s_a in self.args_s] @@ -381,6 +381,14 @@ rtyper.call_all_setups() # compute ForwardReferences now self.exceptionlinks = exceptionlinks + def copy(self): + result = HighLevelOp.__new__(HighLevelOp) + for key, value in self.__dict__.items(): + if type(value) is list: # grunt + value = value[:] + setattr(result, key, value) + return result + def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, as a Variable or Constant converted to the requested type. @@ -389,7 +397,7 @@ """ if not isinstance(converted_to, Repr): converted_to = self.rtyper.primitive_to_repr[converted_to] - v = self.spaceop.args[self.nb_popped + arg] + v = self.args_v[arg] if isinstance(v, Constant): return inputconst(converted_to, v.value) assert hasattr(v, 'concretetype') @@ -405,8 +413,8 @@ def inputargs(self, *converted_to): assert len(converted_to) == self.nb_args, ( - "operation argument count mismatch: '%s' has %d+%d arguments" % ( - self.spaceop.opname, self.nb_popped, self.nb_args)) + "operation argument count mismatch: '%s' has %d arguments" % ( + self.spaceop.opname, self.nb_args)) vars = [] for i in range(len(converted_to)): vars.append(self.inputarg(converted_to[i], i)) @@ -420,10 +428,17 @@ def r_s_popfirstarg(self): "Return and discard the first argument." - self.nb_popped += 1 self.nb_args -= 1 + self.args_v.pop(0) return self.args_r.pop(0), self.args_s.pop(0) + def v_s_insertfirstarg(self, v_newfirstarg, s_newfirstarg): + r_newfirstarg = self.rtyper.getrepr(s_newfirstarg) + self.args_v.insert(0, v_newfirstarg) + self.args_r.insert(0, r_newfirstarg) + self.args_s.insert(0, s_newfirstarg) + self.nb_args += 1 + def has_implicit_exception(self, exc_cls): for link in self.exceptionlinks: if issubclass(exc_cls, link.exitcase): Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Jun 17 02:19:02 2005 @@ -1,6 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.test.test_interp import interpret def rtype(fn, argtypes=[]): @@ -59,6 +60,17 @@ rtype(f, [int, int]) +class MyBaseWithInit: + def __init__(self, a): + self.a1 = a + +def test_class_init(): + def f(a): + instance = MyBaseWithInit(a) + return instance.a1 + assert interpret(f, [5]) == 5 + + class Freezing: def _freeze_(self): return True From arigo at codespeak.net Fri Jun 17 02:29:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 02:29:21 +0200 (CEST) Subject: [pypy-svn] r13509 - pypy/dist/pypy/rpython Message-ID: <20050617002921.92EFB27B7D@code1.codespeak.net> Author: arigo Date: Fri Jun 17 02:29:20 2005 New Revision: 13509 Modified: pypy/dist/pypy/rpython/normalizecalls.py Log: Check for and complain if there are skipped functions in call families. Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 02:29:20 2005 @@ -66,7 +66,11 @@ graph_argorders = {} for func in functions: assert not has_varargs(func), "XXX not implemented" - graph = annotator.translator.getflowgraph(func) + try: + graph = annotator.translator.flowgraphs[func] + except KeyError: + raise TyperError("the skipped %r must not show up in a " + "call family" % (func,)) graph_bindings[graph] = [annotator.binding(v) for v in graph.getargs()] argorder = range(shape_cnt) From pedronis at codespeak.net Fri Jun 17 02:33:22 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 02:33:22 +0200 (CEST) Subject: [pypy-svn] r13510 - pypy/dist/pypy/module/sys Message-ID: <20050617003322.95B2627B7D@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 02:33:21 2005 New Revision: 13510 Modified: pypy/dist/pypy/module/sys/state.py Log: don't let the ignored pypy_getudir function share call family with others Modified: pypy/dist/pypy/module/sys/state.py ============================================================================== --- pypy/dist/pypy/module/sys/state.py (original) +++ pypy/dist/pypy/module/sys/state.py Fri Jun 17 02:33:21 2005 @@ -76,11 +76,17 @@ def get(space): return space.fromcache(State) -def pypy_getudir(space): +def _pypy_getudir(space): """NOT_RPYTHON""" from pypy.tool.udir import udir return space.wrap(str(udir)) -pypy_getudir._annspecialcase_ = "override:ignore" +_pypy_getudir._annspecialcase_ = "override:ignore" + +# we need the inderaction because this function will live in a dictionary with other +# RPYTHON functions and share call sites with them. Better it not be a special-case +# directly. +def pypy_getudir(space): + return _pypy_getudir(space) def getdefaultencoding(space): return space.wrap(sys.getdefaultencoding()) From pedronis at codespeak.net Fri Jun 17 02:34:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 02:34:28 +0200 (CEST) Subject: [pypy-svn] r13511 - pypy/branch/pypy-translation-snapshot/module/sys Message-ID: <20050617003428.AA30A27B7D@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 02:34:27 2005 New Revision: 13511 Modified: pypy/branch/pypy-translation-snapshot/module/sys/state.py Log: merge pypy_getudir additional indirection Modified: pypy/branch/pypy-translation-snapshot/module/sys/state.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/module/sys/state.py (original) +++ pypy/branch/pypy-translation-snapshot/module/sys/state.py Fri Jun 17 02:34:27 2005 @@ -76,11 +76,17 @@ def get(space): return space.fromcache(State) -def pypy_getudir(space): +def _pypy_getudir(space): """NOT_RPYTHON""" from pypy.tool.udir import udir return space.wrap(str(udir)) -pypy_getudir._annspecialcase_ = "override:ignore" +_pypy_getudir._annspecialcase_ = "override:ignore" + +# we need the inderaction because this function will live in a dictionary with other +# RPYTHON functions and share call sites with them. Better it not be a special-case +# directly. +def pypy_getudir(space): + return _pypy_getudir(space) def getdefaultencoding(space): return space.wrap(sys.getdefaultencoding()) From pedronis at codespeak.net Fri Jun 17 03:29:15 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 03:29:15 +0200 (CEST) Subject: [pypy-svn] r13512 - pypy/dist/pypy/translator Message-ID: <20050617012915.D29DC27B8C@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 03:29:14 2005 New Revision: 13512 Modified: pypy/dist/pypy/translator/translator.py Log: disallow getflowgraph on everything but functions Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Fri Jun 17 03:29:14 2005 @@ -4,7 +4,7 @@ translation-related code. It can be used for interactive testing of the translator; see pypy/bin/translator.py. """ -import autopath, os, sys +import autopath, os, sys, types from pypy.objspace.flow.model import * from pypy.translator.simplify import simplify_graph @@ -51,6 +51,8 @@ def getflowgraph(self, func=None, called_by=None, call_tag=None): """Get the flow graph for a function (default: the entry point).""" func = func or self.entrypoint + if not isinstance(func, types.FunctionType): + raise Exception, "getflowgraph() expects a function, got %s" % func try: graph = self.flowgraphs[func] except KeyError: From pedronis at codespeak.net Fri Jun 17 04:01:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 04:01:54 +0200 (CEST) Subject: [pypy-svn] r13513 - pypy/dist/pypy/translator/goal Message-ID: <20050617020154.41F6E27B8C@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 04:01:52 2005 New Revision: 13513 Modified: pypy/dist/pypy/translator/goal/query.py Log: query specific about bound methods Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Fri Jun 17 04:01:52 2005 @@ -251,6 +251,16 @@ if len(callb[x]) >= 2 and x not in b_nb: print ' '.join([prettycallable((classdef and classdef.cls, func)) for (classdef,func) in callb[x].keys()]) +def pretty_els(objs): + accum = [] + for classdef, obj in objs: + cls = classdef and classdef.cls + accum.append(prettycallable((cls, obj))) + els = ' '.join(accum) + if len(accum) == 1: + return els + else: + return "{%s}" % els def pbccall(translator): fams = translator.annotator.getpbccallfamilies().root_info.itervalues() @@ -282,17 +292,6 @@ else: return "in total %d %s" % (nels, prettycallable(kinds)) - def pretty_els(objs): - accum = [] - for classdef, obj in objs: - cls = classdef and classdef.cls - accum.append(prettycallable((cls, obj))) - els = ' '.join(accum) - if len(accum) == 1: - return els - else: - return "{%s}" % els - items = one_pattern_fams.items() items.sort(lambda a,b: cmp((a[0][1],a[1][1]), (b[0][1],b[1][1]))) # sort by pattern and then by els @@ -311,6 +310,34 @@ print " - many callables, many patterns -" print "family of", pretty_els(objs), "with call-patterns:", prettypatt(patts) +def pbcbmsanity(translator): + callb = translator.annotator.getpbccallables() + bk = translator.annotator.bookkeeper + bmeths = [x for x in callb if isinstance(x, types.MethodType) and x.im_self is not None] + print "%d bound-methods" % len(bmeths) + fams = translator.annotator.getpbccallfamilies() + plural_bm_families = {} + one_el = 0 + for bm in bmeths: + notpbc = bm.im_self not in bk.pbccache + freestanding = bm.im_func in callb + if notpbc or freestanding: + print "! %s," % bm, + if notpbc: + print "of non-PBC %s,", + if freestanding: + print "found freestanding too" + bm_fam = fams[(None, bm)] + if len(bm_fam.objects) == 1: + one_el += 1 + else: + plural_bm_families[bm_fam] = True + print "%d families of one bound-method" % one_el + print "%d families with more than just one bound-method" % len(plural_bm_families) + for bm_fam in plural_bm_families: + print pretty_els(bm_fam.objects) + return plural_bm_families + def statsfor(t, category): stats = t.annotator.bookkeeper.stats for_category = stats.classify[category] From pedronis at codespeak.net Fri Jun 17 04:45:04 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 04:45:04 +0200 (CEST) Subject: [pypy-svn] r13514 - pypy/dist/pypy/rpython Message-ID: <20050617024504.2F6A627B8C@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 04:45:03 2005 New Revision: 13514 Modified: pypy/dist/pypy/rpython/normalizecalls.py Log: for now accept family of bound methods referring to the same function, code like this regarding methods on pbcs involves them: def m1(pbc,...): ... def m2(pbc, ...): pbc.m1(...) pbc.m1 call site is annotated with such a family Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 04:45:03 2005 @@ -60,6 +60,17 @@ shape_cnt, shape_keys, shape_star, shape_stst = pattern assert not shape_star, "XXX not implemented" assert not shape_stst, "XXX not implemented" + # for bound methods families for now just accept and check that + # they all refer to the same function + if isinstance(functions[0], types.MethodType): + methfunc = functions[0].im_func + assert functions[0].im_self is not None + for func in functions: + if getattr(func, 'im_func', None) is not methfunc: + raise TypeError("invalid familily of bound methods: %r" % + functions) + continue + # for the first 'shape_cnt' arguments we need to generalize to # a common type graph_bindings = {} From hpk at codespeak.net Fri Jun 17 07:46:50 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 07:46:50 +0200 (CEST) Subject: [pypy-svn] r13516 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617054650.79A5027B80@code1.codespeak.net> Author: hpk Date: Fri Jun 17 07:46:49 2005 New Revision: 13516 Modified: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Log: - use new logging API, re-enable logging API from tests Modified: pypy/dist/pypy/rpython/interp.py ============================================================================== --- pypy/dist/pypy/rpython/interp.py (original) +++ pypy/dist/pypy/rpython/interp.py Fri Jun 17 07:46:49 2005 @@ -5,12 +5,13 @@ from pypy.objspace.flow.model import Constant, last_exception import py +log = py.log.Producer('llinterp') + class RPythonError(Exception): pass class LLInterpreter(object): """ low level interpreter working with concrete values. """ -# log = py.log.Producer('llinterp') def __init__(self, flowgraphs, typer): self.flowgraphs = flowgraphs @@ -30,7 +31,6 @@ def setvar(self, var, val): # XXX assert that val "matches" lowlevel type - self.bindings[var] = val def getval(self, varorconst): @@ -59,6 +59,7 @@ return self.eval_graph(graph,args) def eval_graph(self, graph, args=()): + log.graph("evaluating", graph.name) nextblock = graph.startblock excblock = graph.exceptblock while 1: @@ -99,7 +100,7 @@ raise RPythonError(etype, evalue) resultvar, = block.getvariables() result = self.getval(resultvar) -# self.log.operation("returning", result) + log.operation("returning", result) return None, result elif block.exitswitch is None: # single-exit block @@ -124,7 +125,7 @@ return link.target, [self.getval(x) for x in link.args] def eval_operation(self, operation): -# self.log.operation("considering", operation) + log.operation("considering", operation) ophandler = self.getoperationhandler(operation.opname) vals = [self.getval(x) for x in operation.args] # if these special cases pile up, do something better here @@ -178,7 +179,6 @@ def op_getarraysubstruct(self, array, index): assert isinstance(array, _ptr) - return array[index] # the diff between op_getarrayitem and op_getarraysubstruct # is the same as between op_getfield and op_getsubstruct @@ -217,3 +217,7 @@ return func(x) """ % locals()).compile() +# by default we route all logging messages to nothingness +# e.g. tests can then switch on logging to get more help +# for failing tests +py.log.setconsumer('llinterp', None) Modified: pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_interp.py Fri Jun 17 07:46:49 2005 @@ -1,12 +1,20 @@ import py -py.magic.autopath() from pypy.rpython.lltype import typeOf from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.interp import LLInterpreter, RPythonError from pypy.translator.translator import Translator from pypy.rpython.lltype import pyobjectptr +# switch on logging of interp to show more info on failing tests + +def setup_module(mod): + mod.logstate = py.log._getstate() + py.log.setconsumer("llinterp", py.log.STDOUT) + +def teardown_module(mod): + py.log._setstate(mod.logstate) + def find_exception(exc): assert isinstance(exc, RPythonError) import exceptions From hpk at codespeak.net Fri Jun 17 07:51:46 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 07:51:46 +0200 (CEST) Subject: [pypy-svn] r13517 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617055146.81B4427B80@code1.codespeak.net> Author: hpk Date: Fri Jun 17 07:51:44 2005 New Revision: 13517 Added: pypy/dist/pypy/rpython/llinterp.py - copied unchanged from r13516, pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_llinterp.py - copied, changed from r13516, pypy/dist/pypy/rpython/test/test_interp.py Removed: pypy/dist/pypy/rpython/interp.py pypy/dist/pypy/rpython/test/test_interp.py Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: rename interp.py to llinterp.py and test_interp.py to test_llinterp.py Deleted: /pypy/dist/pypy/rpython/interp.py ============================================================================== --- /pypy/dist/pypy/rpython/interp.py Fri Jun 17 07:51:44 2005 +++ (empty file) @@ -1,223 +0,0 @@ -from pypy.rpython.lltype import * -from pypy.rpython.lltype import _ptr -from pypy.translator.translator import Translator -from pypy.tool.sourcetools import compile2 -from pypy.objspace.flow.model import Constant, last_exception -import py - -log = py.log.Producer('llinterp') - -class RPythonError(Exception): - pass - -class LLInterpreter(object): - """ low level interpreter working with concrete values. """ - - def __init__(self, flowgraphs, typer): - self.flowgraphs = flowgraphs - self.bindings = {} - self.typer = typer - - # _______________________________________________________ - # variable setters/getters helpers - - def fillvars(self, block, values): - vars = block.inputargs - assert len(vars) == len(values), ( - "block %s received %d args, expected %d" % ( - block, len(values), len(vars))) - for var, val in zip(vars, values): - self.setvar(var, val) - - def setvar(self, var, val): - # XXX assert that val "matches" lowlevel type - self.bindings[var] = val - - def getval(self, varorconst): - try: - return varorconst.value - except AttributeError: - return self.bindings[varorconst] - - # _______________________________________________________ - # other helpers - def getoperationhandler(self, opname): - try: - return getattr(self, 'op_' + opname) - except AttributeError: - g = globals() - assert opname in g, ( - "cannot handle operation %r yet" %(opname,)) - ophandler = g[opname] - return ophandler - - # _______________________________________________________ - # evaling functions - - def eval_function(self, func, args=()): - graph = self.flowgraphs[func] - return self.eval_graph(graph,args) - - def eval_graph(self, graph, args=()): - log.graph("evaluating", graph.name) - nextblock = graph.startblock - excblock = graph.exceptblock - while 1: - self.fillvars(nextblock, args) - nextblock, args = self.eval_block(nextblock, excblock) - if nextblock is None: - return args - - def eval_block(self, block, excblock): - """ return (nextblock, values) tuple. If nextblock - is None, values is the concrete return value. - """ - catch_exception = block.exitswitch == Constant(last_exception) - e = None - - try: - for op in block.operations: - self.eval_operation(op) - except RPythonError, e: - if not catch_exception: - # there is no explicit handler. - # we could simply re-raise here, but it is cleaner - # to redirect to the provided default exception block - block = excblock - cls, inst = e.args - self.setvar(block.inputargs[0], cls) - self.setvar(block.inputargs[1], inst) - - # determine nextblock and/or return value - if len(block.exits) == 0: - # return block - if len(block.inputargs) == 2: - # exception - etypevar, evaluevar = block.getvariables() - etype = self.getval(etypevar) - evalue = self.getval(evaluevar) - # watch out, these are _ptr's - raise RPythonError(etype, evalue) - resultvar, = block.getvariables() - result = self.getval(resultvar) - log.operation("returning", result) - return None, result - elif block.exitswitch is None: - # single-exit block - assert len(block.exits) == 1 - link = block.exits[0] - elif catch_exception: - link = block.exits[0] - if e: - exdata = self.typer.getexceptiondata() - cls, inst = e.args - for link in block.exits[1:]: - assert issubclass(link.exitcase, Exception) - if exdata.ll_exception_match(cls, link.llexitcase): - self.setvar(link.last_exception, cls) - self.setvar(link.last_exc_value, inst) - break - else: - raise Exception, e # unhandled case, should not happen - else: - index = self.getval(block.exitswitch) - link = block.exits[index] - return link.target, [self.getval(x) for x in link.args] - - def eval_operation(self, operation): - log.operation("considering", operation) - ophandler = self.getoperationhandler(operation.opname) - vals = [self.getval(x) for x in operation.args] - # if these special cases pile up, do something better here - if operation.opname == 'cast_pointer': - vals.insert(0, operation.result.concretetype) - retval = ophandler(*vals) - self.setvar(operation.result, retval) - - # __________________________________________________________ - # misc LL operation implementations - - def op_same_as(self, x): - return x - - def op_setfield(self, obj, fieldname, fieldvalue): - # obj should be pointer - setattr(obj, fieldname, fieldvalue) - - def op_getarrayitem(self,array,index): - return array[index] - - def op_setarrayitem(self,array,index,item): - array[index] = item - - def op_direct_call(self, f, *args): - if hasattr(f._obj, 'graph'): - return self.eval_graph(f._obj.graph, args) - return self.eval_function(f._obj._callable, args) - - def op_malloc(self, obj): - return malloc(obj) - - def op_getfield(self, obj, field): - # assert: obj should be pointer - result = getattr(obj, field) - # check the difference between op_getfield and op_getsubstruct: - # the former returns the real field, the latter a pointer to it - assert typeOf(result) == getattr(typeOf(obj).TO, field) - return result - - def op_getsubstruct(self, obj, field): - # assert: obj should be pointer - result = getattr(obj, field) - # check the difference between op_getfield and op_getsubstruct: - # the former returns the real field, the latter a pointer to it - assert typeOf(result) == Ptr(getattr(typeOf(obj).TO, field)) - return result - - def op_malloc_varsize(self, obj, size): - return malloc(obj, size) - - def op_getarraysubstruct(self, array, index): - assert isinstance(array, _ptr) - return array[index] - # the diff between op_getarrayitem and op_getarraysubstruct - # is the same as between op_getfield and op_getsubstruct - - def op_getarraysize(self,array): - #print array,type(array),dir(array) - return len(array) - - def op_cast_pointer(self, tp, obj): - # well, actually this is what's now in the globals. - return cast_pointer(tp, obj) -# __________________________________________________________ -# primitive operations -from pypy.objspace.flow.operation import FunctionByName -opimpls = FunctionByName.copy() -opimpls['is_true'] = bool - -for typ in (float, int): - typname = typ.__name__ - for opname in ('add', 'sub', 'mul', 'div', 'gt', 'lt', - 'ge', 'ne', 'le', 'eq'): - assert opname in opimpls - exec py.code.Source(""" - def %(typname)s_%(opname)s(x, y): - assert isinstance(x, %(typname)s) - assert isinstance(y, %(typname)s) - func = opimpls[%(opname)r] - return func(x, y) - """ % locals()).compile() - for opname in 'is_true',: - assert opname in opimpls - exec py.code.Source(""" - def %(typname)s_%(opname)s(x): - assert isinstance(x, %(typname)s) - func = opimpls[%(opname)r] - return func(x) - """ % locals()).compile() - -# by default we route all logging messages to nothingness -# e.g. tests can then switch on logging to get more help -# for failing tests -py.log.setconsumer('llinterp', None) Deleted: /pypy/dist/pypy/rpython/test/test_interp.py ============================================================================== --- /pypy/dist/pypy/rpython/test/test_interp.py Fri Jun 17 07:51:44 2005 +++ (empty file) @@ -1,184 +0,0 @@ - -import py -from pypy.rpython.lltype import typeOf -from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.interp import LLInterpreter, RPythonError -from pypy.translator.translator import Translator -from pypy.rpython.lltype import pyobjectptr - -# switch on logging of interp to show more info on failing tests - -def setup_module(mod): - mod.logstate = py.log._getstate() - py.log.setconsumer("llinterp", py.log.STDOUT) - -def teardown_module(mod): - py.log._setstate(mod.logstate) - -def find_exception(exc): - assert isinstance(exc, RPythonError) - import exceptions - klass, inst = exc.args - func = typer.getexceptiondata().ll_pyexcclass2exc - for cls in exceptions.__dict__.values(): - if type(cls) is type(Exception): - if func(pyobjectptr(cls)).typeptr == klass: - return cls - -def gengraph(func, argtypes=[]): - t = Translator(func) - t.annotate(argtypes) - global typer # we need it for find_exception - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - return t, typer - -def interpret(func, values): - t, typer = gengraph(func, [type(x) for x in values]) - interp = LLInterpreter(t.flowgraphs, typer) - res = interp.eval_function(func, values) - return res - -#__________________________________________________________________ -# tests - -def test_int_ops(): - res = interpret(number_ops, [3]) - assert res == 4 - -def test_float_ops(): - res = interpret(number_ops, [3.5]) - assert res == 4.5 - -def test_ifs(): - res = interpret(simple_ifs, [0]) - assert res == 43 - res = interpret(simple_ifs, [1]) - assert res == 42 - -def test_raise(): - res = interpret(raise_exception, [41]) - assert res == 41 - info = raises(RPythonError, interpret, raise_exception, [42]) - assert find_exception(info.value) is IndexError - info = raises(RPythonError, interpret, raise_exception, [43]) - assert find_exception(info.value) is ValueError - -def test_call_raise(): - res = interpret(call_raise, [41]) - assert res == 41 - info = raises(RPythonError, interpret, call_raise, [42]) - assert find_exception(info.value) is IndexError - info = raises(RPythonError, interpret, call_raise, [43]) - assert find_exception(info.value) is ValueError - -def test_call_raise_intercept(): - res = interpret(call_raise_intercept, [41]) - assert res == 41 - res = interpret(call_raise_intercept, [42]) - assert res == 42 - info = raises(RPythonError, interpret, call_raise_intercept, [43]) - assert find_exception(info.value) is TypeError - -def test_while_simple(): - res = interpret(while_simple, [3]) - assert res == 6 - -def test_number_comparisons(): - for t in float, int: - val1 = t(3) - val2 = t(4) - gcres = interpret(comparisons, [val1, val2]) - res = [getattr(gcres, x) for x in typeOf(gcres).TO._names] - assert res == [True, True, False, True, False, False] - -def XXXtest_some_builtin(): - def f(i, j): - x = range(i) - return x[j] - res = interpret(f, [10, 7]) - assert res == 6 - -# -#__________________________________________________________________ -# -# Test lists -def test_list_creation(): - def f(): - return [1,2,3] - res = interpret(f,[]) - assert len(res.items) == len([1,2,3]) - for i in range(3): - assert res.items[i] == i+1 -#__________________________________________________________________ -# example functions for testing the LLInterpreter -_snap = globals().copy() - -def number_ops(i): - j = i + 2 - k = j * 2 - m = k / 2 - return m - 1 - -def comparisons(x, y): - return (x < y, - x <= y, - x == y, - x != y, - #x is None, - #x is not None, - x >= y, - x > y, - ) - -def simple_ifs(i): - if i: - return 42 - else: - return 43 - -def while_simple(i): - sum = 0 - while i > 0: - sum += i - i -= 1 - return sum - -def raise_exception(i): - if i == 42: - raise IndexError - elif i == 43: - raise ValueError - return i - -def call_raise(i): - return raise_exception(i) - -def call_raise_intercept(i): - try: - return raise_exception(i) - except IndexError: - return i - except ValueError: - raise TypeError -#__________________________________________________________________ -# interactive playing - -if __name__ == '__main__': - try: - import rlcompleter2 as _rl2 - _rl2.setup() - except ImportError: - pass - - t, typer = gengraph(number_ops, [int]) - interp = LLInterpreter(t.flowgraphs, typer) - res = interp.eval_function(number_ops, [3]) - assert res == number_ops(3) - for name, value in globals().items(): - if name not in _snap and name[0] != '_': - print "%20s: %s" %(name, value) - - Copied: pypy/dist/pypy/rpython/test/test_llinterp.py (from r13516, pypy/dist/pypy/rpython/test/test_interp.py) ============================================================================== --- pypy/dist/pypy/rpython/test/test_interp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 07:51:44 2005 @@ -2,7 +2,7 @@ import py from pypy.rpython.lltype import typeOf from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.interp import LLInterpreter, RPythonError +from pypy.rpython.llinterp import LLInterpreter, RPythonError from pypy.translator.translator import Translator from pypy.rpython.lltype import pyobjectptr Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Jun 17 07:51:44 2005 @@ -1,7 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.test.test_interp import interpret +from pypy.rpython.test.test_llinterp import interpret def rtype(fn, argtypes=[]): From hpk at codespeak.net Fri Jun 17 07:56:59 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 07:56:59 +0200 (CEST) Subject: [pypy-svn] r13518 - pypy/dist/pypy/rpython/test Message-ID: <20050617055659.CAD8027B80@code1.codespeak.net> Author: hpk Date: Fri Jun 17 07:56:58 2005 New Revision: 13518 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py Log: reenable test with calling range Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 07:56:58 2005 @@ -94,10 +94,10 @@ res = [getattr(gcres, x) for x in typeOf(gcres).TO._names] assert res == [True, True, False, True, False, False] -def XXXtest_some_builtin(): +def test_some_builtin(): def f(i, j): x = range(i) - return x[j] + return x[j-1] res = interpret(f, [10, 7]) assert res == 6 From hpk at codespeak.net Fri Jun 17 08:01:37 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 08:01:37 +0200 (CEST) Subject: [pypy-svn] r13519 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617060137.65AF027B95@code1.codespeak.net> Author: hpk Date: Fri Jun 17 08:01:36 2005 New Revision: 13519 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: rename RPythonError to LLException. (think it makes sense, doesn't it? ... i'd like to try to distinguish LL from RPython) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 08:01:36 2005 @@ -7,7 +7,7 @@ log = py.log.Producer('llinterp') -class RPythonError(Exception): +class LLException(Exception): pass class LLInterpreter(object): @@ -78,7 +78,7 @@ try: for op in block.operations: self.eval_operation(op) - except RPythonError, e: + except LLException, e: if not catch_exception: # there is no explicit handler. # we could simply re-raise here, but it is cleaner @@ -97,7 +97,7 @@ etype = self.getval(etypevar) evalue = self.getval(evaluevar) # watch out, these are _ptr's - raise RPythonError(etype, evalue) + raise LLException(etype, evalue) resultvar, = block.getvariables() result = self.getval(resultvar) log.operation("returning", result) Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 08:01:36 2005 @@ -2,7 +2,7 @@ import py from pypy.rpython.lltype import typeOf from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.llinterp import LLInterpreter, RPythonError +from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.translator.translator import Translator from pypy.rpython.lltype import pyobjectptr @@ -16,7 +16,7 @@ py.log._setstate(mod.logstate) def find_exception(exc): - assert isinstance(exc, RPythonError) + assert isinstance(exc, LLException) import exceptions klass, inst = exc.args func = typer.getexceptiondata().ll_pyexcclass2exc @@ -61,17 +61,17 @@ def test_raise(): res = interpret(raise_exception, [41]) assert res == 41 - info = raises(RPythonError, interpret, raise_exception, [42]) + info = raises(LLException, interpret, raise_exception, [42]) assert find_exception(info.value) is IndexError - info = raises(RPythonError, interpret, raise_exception, [43]) + info = raises(LLException, interpret, raise_exception, [43]) assert find_exception(info.value) is ValueError def test_call_raise(): res = interpret(call_raise, [41]) assert res == 41 - info = raises(RPythonError, interpret, call_raise, [42]) + info = raises(LLException, interpret, call_raise, [42]) assert find_exception(info.value) is IndexError - info = raises(RPythonError, interpret, call_raise, [43]) + info = raises(LLException, interpret, call_raise, [43]) assert find_exception(info.value) is ValueError def test_call_raise_intercept(): @@ -79,7 +79,7 @@ assert res == 41 res = interpret(call_raise_intercept, [42]) assert res == 42 - info = raises(RPythonError, interpret, call_raise_intercept, [43]) + info = raises(LLException, interpret, call_raise_intercept, [43]) assert find_exception(info.value) is TypeError def test_while_simple(): From hpk at codespeak.net Fri Jun 17 08:38:55 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 08:38:55 +0200 (CEST) Subject: [pypy-svn] r13522 - pypy/extradoc/sprintinfo Message-ID: <20050617063855.9000B27B93@code1.codespeak.net> Author: hpk Date: Fri Jun 17 08:38:54 2005 New Revision: 13522 Added: pypy/extradoc/sprintinfo/EP2005-people.txt Log: I think we need to get a better picture of who is coming when to the sprints and PyPy events around EuroPython Added: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 08:38:54 2005 @@ -0,0 +1,52 @@ + +People coming to PyPy EuroPython Sprints/Events +================================================== + +List Of Attendants for pre-EP sprint (23rd-26th) +------------------------------------------------- + +=================== ============== ===================== + Name Time Accomodation +=================== ============== ===================== +Armin Rigo 23rd-26th June private +Samuele Pedroni 23rd-26th June private +Holger Krekel 23rd-26th June ? +=================== ============== ===================== + + +List Of Attendants for POST-EP sprint (1st-7th) +------------------------------------------------- + +=================== ============== ===================== + Name Time Accomodation +=================== ============== ===================== +Armin Rigo 1st-7th July private +Samuele Pedroni 1st-7th July private +Carl Friedrich Bolz 1st-7th July ? +Eric van Riet Paap 1st-7th July ? +Holger Krekel 1st-7th July ? +Richard Emslie 1st-7th July ? +Jacob Hallen ? ? +Laura Creighton ? ? +Christian Tismer ? ? +Adrien Di Mascio ? ? +Ludovic Aubry ? ? +Anders Lehmann ? ? +=================== ============== ===================== + + +List Of Attendants for EU workshop July 8th +------------------------------------------------- + +=================== ============== ===================== + Name Time Accomodation +=================== ============== ===================== +Armin Rigo 8th July private +Samuele Pedroni 8th July private +Holger Krekel 8th July ? +Bea During 8th July private +Jacob Hallen 8th July ? +Laura Creighton 8th July ? +Christian Tismer 8th July ? +Stephan Busemann 8th July ? +=================== ============== ===================== From hpk at codespeak.net Fri Jun 17 08:45:59 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 08:45:59 +0200 (CEST) Subject: [pypy-svn] r13523 - pypy/extradoc/sprintinfo Message-ID: <20050617064559.232C627B93@code1.codespeak.net> Author: hpk Date: Fri Jun 17 08:45:58 2005 New Revision: 13523 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: hinted at 'private' accomodation for laura+jacob Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 08:45:58 2005 @@ -26,8 +26,8 @@ Eric van Riet Paap 1st-7th July ? Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? -Jacob Hallen ? ? -Laura Creighton ? ? +Jacob Hallen ? private +Laura Creighton ? private Christian Tismer ? ? Adrien Di Mascio ? ? Ludovic Aubry ? ? @@ -45,8 +45,8 @@ Samuele Pedroni 8th July private Holger Krekel 8th July ? Bea During 8th July private -Jacob Hallen 8th July ? -Laura Creighton 8th July ? +Jacob Hallen 8th July private +Laura Creighton 8th July private Christian Tismer 8th July ? Stephan Busemann 8th July ? =================== ============== ===================== From hpk at codespeak.net Fri Jun 17 09:00:53 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 09:00:53 +0200 (CEST) Subject: [pypy-svn] r13524 - pypy/extradoc/sprintinfo Message-ID: <20050617070053.130FB27B7D@code1.codespeak.net> Author: hpk Date: Fri Jun 17 09:00:52 2005 New Revision: 13524 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: some clarifications Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 09:00:52 2005 @@ -2,20 +2,20 @@ People coming to PyPy EuroPython Sprints/Events ================================================== -List Of Attendants for pre-EP sprint (23rd-26th) -------------------------------------------------- +List Of Attendants for pre-EP sprint (4 full days 23rd-26th) +--------------------------------------------------------------- =================== ============== ===================== - Name Time Accomodation + Name Arrive/Depart Accomodation =================== ============== ===================== -Armin Rigo 23rd-26th June private -Samuele Pedroni 23rd-26th June private -Holger Krekel 23rd-26th June ? +Armin Rigo 23rd- private +Samuele Pedroni 23rd- private +Holger Krekel 23rd- ? =================== ============== ===================== -List Of Attendants for POST-EP sprint (1st-7th) -------------------------------------------------- +List Of Attendants for POST-EP sprint (7 full days 1st-7th) +------------------------------------------------------------ =================== ============== ===================== Name Time Accomodation @@ -35,11 +35,11 @@ =================== ============== ===================== -List Of Attendants for EU workshop July 8th -------------------------------------------------- +List Of Attendants for EU workshop July 8th (whole day) +---------------------------------------------------------- =================== ============== ===================== - Name Time Accomodation + Name Time Accomodation =================== ============== ===================== Armin Rigo 8th July private Samuele Pedroni 8th July private From hpk at codespeak.net Fri Jun 17 09:11:15 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 09:11:15 +0200 (CEST) Subject: [pypy-svn] r13525 - pypy/extradoc/sprintinfo Message-ID: <20050617071115.44BFB27B80@code1.codespeak.net> Author: hpk Date: Fri Jun 17 09:11:14 2005 New Revision: 13525 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: actually Bert Freudenberg from Impara told me he'll come! Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 09:11:14 2005 @@ -26,6 +26,7 @@ Eric van Riet Paap 1st-7th July ? Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? +Bert Freudenberg 1st-7th July ? Jacob Hallen ? private Laura Creighton ? private Christian Tismer ? ? From hpk at codespeak.net Fri Jun 17 09:45:28 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 09:45:28 +0200 (CEST) Subject: [pypy-svn] r13526 - pypy/extradoc/sprintinfo Message-ID: <20050617074528.BC11B27B95@code1.codespeak.net> Author: hpk Date: Fri Jun 17 09:45:27 2005 New Revision: 13526 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: Lene is bound to come to the EU workshop as well Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 09:45:27 2005 @@ -48,6 +48,7 @@ Bea During 8th July private Jacob Hallen 8th July private Laura Creighton 8th July private +Lene Wagner 8th July ? Christian Tismer 8th July ? Stephan Busemann 8th July ? =================== ============== ===================== From ale at codespeak.net Fri Jun 17 10:32:31 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 17 Jun 2005 10:32:31 +0200 (CEST) Subject: [pypy-svn] r13528 - pypy/extradoc/sprintinfo Message-ID: <20050617083231.697F827B93@code1.codespeak.net> Author: ale Date: Fri Jun 17 10:32:27 2005 New Revision: 13528 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: Added my sprint attendance info Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 10:32:27 2005 @@ -11,6 +11,7 @@ Armin Rigo 23rd- private Samuele Pedroni 23rd- private Holger Krekel 23rd- ? +Anders Lehmann 22nd-26th SGS =================== ============== ===================== @@ -32,7 +33,6 @@ Christian Tismer ? ? Adrien Di Mascio ? ? Ludovic Aubry ? ? -Anders Lehmann ? ? =================== ============== ===================== From mwh at codespeak.net Fri Jun 17 11:26:27 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 17 Jun 2005 11:26:27 +0200 (CEST) Subject: [pypy-svn] r13529 - pypy/extradoc/sprintinfo Message-ID: <20050617092627.A3C1827B93@code1.codespeak.net> Author: mwh Date: Fri Jun 17 11:26:27 2005 New Revision: 13529 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: my details Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 11:26:27 2005 @@ -12,6 +12,7 @@ Samuele Pedroni 23rd- private Holger Krekel 23rd- ? Anders Lehmann 22nd-26th SGS +Michael Hudson 23rd- private =================== ============== ===================== From adim at codespeak.net Fri Jun 17 11:57:04 2005 From: adim at codespeak.net (adim at codespeak.net) Date: Fri, 17 Jun 2005 11:57:04 +0200 (CEST) Subject: [pypy-svn] r13530 - pypy/extradoc/sprintinfo Message-ID: <20050617095704.7D03B27B8E@code1.codespeak.net> Author: adim Date: Fri Jun 17 11:57:03 2005 New Revision: 13530 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: registered to the Post-EP sprint Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 11:57:03 2005 @@ -32,8 +32,8 @@ Jacob Hallen ? private Laura Creighton ? private Christian Tismer ? ? -Adrien Di Mascio ? ? -Ludovic Aubry ? ? +Adrien Di Mascio 1st-5th July Nice Hotel +Ludovic Aubry 1st-5th July Nice Hotel =================== ============== ===================== From bea at codespeak.net Fri Jun 17 13:24:04 2005 From: bea at codespeak.net (bea at codespeak.net) Date: Fri, 17 Jun 2005 13:24:04 +0200 (CEST) Subject: [pypy-svn] r13532 - pypy/extradoc/sprintinfo Message-ID: <20050617112404.C8D7A27B62@code1.codespeak.net> Author: bea Date: Fri Jun 17 13:24:03 2005 New Revision: 13532 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: updated with my participation Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 13:24:03 2005 @@ -11,6 +11,7 @@ Armin Rigo 23rd- private Samuele Pedroni 23rd- private Holger Krekel 23rd- ? +Beatrice D?ring visiting private Anders Lehmann 22nd-26th SGS Michael Hudson 23rd- private =================== ============== ===================== @@ -28,7 +29,8 @@ Eric van Riet Paap 1st-7th July ? Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? -Bert Freudenberg 1st-7th July ? +Richard Emslie 1st-7th July ? +Beatrice D?ring visiting private Jacob Hallen ? private Laura Creighton ? private Christian Tismer ? ? From hpk at codespeak.net Fri Jun 17 13:56:52 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 13:56:52 +0200 (CEST) Subject: [pypy-svn] r13533 - pypy/extradoc/sprintinfo Message-ID: <20050617115652.9F62227B7A@code1.codespeak.net> Author: hpk Date: Fri Jun 17 13:56:51 2005 New Revision: 13533 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: fix ReST Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 13:56:51 2005 @@ -11,7 +11,7 @@ Armin Rigo 23rd- private Samuele Pedroni 23rd- private Holger Krekel 23rd- ? -Beatrice D?ring visiting private +Beatrice D?ring visiting private Anders Lehmann 22nd-26th SGS Michael Hudson 23rd- private =================== ============== ===================== @@ -30,7 +30,7 @@ Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? Richard Emslie 1st-7th July ? -Beatrice D?ring visiting private +Beatrice D?ring visiting private Jacob Hallen ? private Laura Creighton ? private Christian Tismer ? ? From arigo at codespeak.net Fri Jun 17 14:18:19 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 14:18:19 +0200 (CEST) Subject: [pypy-svn] r13534 - pypy/dist/pypy/rpython/test Message-ID: <20050617121819.D306027B72@code1.codespeak.net> Author: arigo Date: Fri Jun 17 14:18:18 2005 New Revision: 13534 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py Log: Exceptions are quite difficult to get right, because they are full of implicitness. I suggest re-reading the corresponding documentation http://codespeak.net/pypy/index.cgi?doc/objspace.html#the-flow-model and then trying to pass this test I check in :-) Also note that it's quite possible that exceptions are not handled by a handler, and should simply be re-raised. Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 14:18:18 2005 @@ -74,6 +74,19 @@ info = raises(LLException, interpret, call_raise, [43]) assert find_exception(info.value) is ValueError +def test_call_raise_twice(): + py.test.skip("exceptions in progress") + res = interpret(call_raise_twice, [6, 7]) + assert res == 13 + info = raises(LLException, interpret, call_raise_twice, [6, 42]) + assert find_exception(info.value) is IndexError + res = interpret(call_raise_twice, [6, 43]) + assert res == 1006 + info = raises(LLException, interpret, call_raise_twice, [42, 7]) + assert find_exception(info.value) is IndexError + info = raises(LLException, interpret, call_raise_twice, [43, 7]) + assert find_exception(info.value) is ValueError + def test_call_raise_intercept(): res = interpret(call_raise_intercept, [41]) assert res == 41 @@ -156,6 +169,14 @@ def call_raise(i): return raise_exception(i) +def call_raise_twice(i, j): + x = raise_exception(i) + try: + y = raise_exception(j) + except ValueError: + y = 1000 + return x + y + def call_raise_intercept(i): try: return raise_exception(i) From arigo at codespeak.net Fri Jun 17 14:31:44 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 14:31:44 +0200 (CEST) Subject: [pypy-svn] r13535 - pypy/extradoc/sprintinfo Message-ID: <20050617123144.77D1427B80@code1.codespeak.net> Author: arigo Date: Fri Jun 17 14:31:44 2005 New Revision: 13535 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: Oups! Bert disappeared and was replaced by a clone of Richard in Bea's checkin. Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 14:31:44 2005 @@ -29,7 +29,7 @@ Eric van Riet Paap 1st-7th July ? Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? -Richard Emslie 1st-7th July ? +Bert Freudenberg 1st-7th July ? Beatrice D?ring visiting private Jacob Hallen ? private Laura Creighton ? private From ericvrp at codespeak.net Fri Jun 17 15:40:16 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Fri, 17 Jun 2005 15:40:16 +0200 (CEST) Subject: [pypy-svn] r13536 - pypy/extradoc/sprintinfo Message-ID: <20050617134016.77FED27B80@code1.codespeak.net> Author: ericvrp Date: Fri Jun 17 15:40:15 2005 New Revision: 13536 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: my details Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 15:40:15 2005 @@ -26,7 +26,7 @@ Armin Rigo 1st-7th July private Samuele Pedroni 1st-7th July private Carl Friedrich Bolz 1st-7th July ? -Eric van Riet Paap 1st-7th July ? +Eric van Riet Paap 1st-7th July SGS Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? Bert Freudenberg 1st-7th July ? From tismer at codespeak.net Fri Jun 17 15:40:29 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 15:40:29 +0200 (CEST) Subject: [pypy-svn] r13537 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617134029.9DDF827B72@code1.codespeak.net> Author: tismer Date: Fri Jun 17 15:40:29 2005 New Revision: 13537 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: passing the arigo test. Yes, the exception handler is only for the last operation. In any other case, we need to use the default exception handler. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 15:40:29 2005 @@ -79,7 +79,7 @@ for op in block.operations: self.eval_operation(op) except LLException, e: - if not catch_exception: + if not (catch_exception and op is block.operations[-1]): # there is no explicit handler. # we could simply re-raise here, but it is cleaner # to redirect to the provided default exception block Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 15:40:29 2005 @@ -75,7 +75,7 @@ assert find_exception(info.value) is ValueError def test_call_raise_twice(): - py.test.skip("exceptions in progress") + #py.test.skip("exceptions in progress") res = interpret(call_raise_twice, [6, 7]) assert res == 13 info = raises(LLException, interpret, call_raise_twice, [6, 42]) From tismer at codespeak.net Fri Jun 17 15:41:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 15:41:11 +0200 (CEST) Subject: [pypy-svn] r13538 - pypy/dist/pypy/rpython/test Message-ID: <20050617134111.28DE527B80@code1.codespeak.net> Author: tismer Date: Fri Jun 17 15:41:10 2005 New Revision: 13538 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py Log: dropped in-progress comment Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 15:41:10 2005 @@ -75,7 +75,6 @@ assert find_exception(info.value) is ValueError def test_call_raise_twice(): - #py.test.skip("exceptions in progress") res = interpret(call_raise_twice, [6, 7]) assert res == 13 info = raises(LLException, interpret, call_raise_twice, [6, 42]) From pedronis at codespeak.net Fri Jun 17 16:06:07 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 16:06:07 +0200 (CEST) Subject: [pypy-svn] r13539 - pypy/dist/pypy/rpython Message-ID: <20050617140607.3E6FD27B97@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 16:06:06 2005 New Revision: 13539 Modified: pypy/dist/pypy/rpython/normalizecalls.py Log: check that callables in bound methods are not present in freestanding form Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 16:06:06 2005 @@ -65,6 +65,9 @@ if isinstance(functions[0], types.MethodType): methfunc = functions[0].im_func assert functions[0].im_self is not None + if (None, methfunc) in call_families: + raise TypeError("function appears both in bound method and" + "freestanding: %r" % methfunc) for func in functions: if getattr(func, 'im_func', None) is not methfunc: raise TypeError("invalid familily of bound methods: %r" % From tismer at codespeak.net Fri Jun 17 16:13:56 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 16:13:56 +0200 (CEST) Subject: [pypy-svn] r13540 - pypy/dist/pypy/rpython Message-ID: <20050617141356.5C3F027B97@code1.codespeak.net> Author: tismer Date: Fri Jun 17 16:13:55 2005 New Revision: 13540 Modified: pypy/dist/pypy/rpython/llinterp.py Log: final refinemets, no XXX left so far Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 16:13:55 2005 @@ -2,7 +2,7 @@ from pypy.rpython.lltype import _ptr from pypy.translator.translator import Translator from pypy.tool.sourcetools import compile2 -from pypy.objspace.flow.model import Constant, last_exception +from pypy.objspace.flow.model import Constant, Variable, last_exception import py log = py.log.Producer('llinterp') @@ -29,9 +29,15 @@ for var, val in zip(vars, values): self.setvar(var, val) - def setvar(self, var, val): - # XXX assert that val "matches" lowlevel type - self.bindings[var] = val + def setvar(self, var, val): + if var.concretetype != Void: + assert var.concretetype == typeOf(val) + assert isinstance(var, Variable) + self.bindings[var] = val + + def setifvar(self, var, val): + if isinstance(var, Variable): + self.setvar(var, val) def getval(self, varorconst): try: @@ -52,23 +58,22 @@ return ophandler # _______________________________________________________ - # evaling functions + # evaling functions - def eval_function(self, func, args=()): + def eval_function(self, func, args=()): graph = self.flowgraphs[func] return self.eval_graph(graph,args) def eval_graph(self, graph, args=()): - log.graph("evaluating", graph.name) + log.graph("evaluating", graph.name) nextblock = graph.startblock - excblock = graph.exceptblock while 1: self.fillvars(nextblock, args) - nextblock, args = self.eval_block(nextblock, excblock) - if nextblock is None: - return args + nextblock, args = self.eval_block(nextblock) + if nextblock is None: + return args - def eval_block(self, block, excblock): + def eval_block(self, block): """ return (nextblock, values) tuple. If nextblock is None, values is the concrete return value. """ @@ -80,13 +85,7 @@ self.eval_operation(op) except LLException, e: if not (catch_exception and op is block.operations[-1]): - # there is no explicit handler. - # we could simply re-raise here, but it is cleaner - # to redirect to the provided default exception block - block = excblock - cls, inst = e.args - self.setvar(block.inputargs[0], cls) - self.setvar(block.inputargs[1], inst) + raise # determine nextblock and/or return value if len(block.exits) == 0: @@ -114,11 +113,12 @@ for link in block.exits[1:]: assert issubclass(link.exitcase, Exception) if exdata.ll_exception_match(cls, link.llexitcase): - self.setvar(link.last_exception, cls) - self.setvar(link.last_exc_value, inst) + self.setifvar(link.last_exception, cls) + self.setifvar(link.last_exc_value, inst) break else: - raise Exception, e # unhandled case, should not happen + # no handler found, pass on + raise e else: index = self.getval(block.exitswitch) link = block.exits[index] From tismer at codespeak.net Fri Jun 17 16:28:22 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 16:28:22 +0200 (CEST) Subject: [pypy-svn] r13541 - pypy/dist/pypy/rpython Message-ID: <20050617142822.7C07727B96@code1.codespeak.net> Author: tismer Date: Fri Jun 17 16:28:21 2005 New Revision: 13541 Modified: pypy/dist/pypy/rpython/llinterp.py Log: removed trailing spaces. It would be nice if everybody would check editor settings if possible? Space lines between python functions are quite usual, but there we many single spaces at line ends all over the place. ??? Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 16:28:21 2005 @@ -1,34 +1,34 @@ -from pypy.rpython.lltype import * +from pypy.rpython.lltype import * from pypy.rpython.lltype import _ptr from pypy.translator.translator import Translator from pypy.tool.sourcetools import compile2 from pypy.objspace.flow.model import Constant, Variable, last_exception import py -log = py.log.Producer('llinterp') +log = py.log.Producer('llinterp') class LLException(Exception): pass -class LLInterpreter(object): - """ low level interpreter working with concrete values. """ +class LLInterpreter(object): + """ low level interpreter working with concrete values. """ - def __init__(self, flowgraphs, typer): - self.flowgraphs = flowgraphs + def __init__(self, flowgraphs, typer): + self.flowgraphs = flowgraphs self.bindings = {} self.typer = typer # _______________________________________________________ - # variable setters/getters helpers - - def fillvars(self, block, values): - vars = block.inputargs + # variable setters/getters helpers + + def fillvars(self, block, values): + vars = block.inputargs assert len(vars) == len(values), ( "block %s received %d args, expected %d" % ( block, len(values), len(vars))) - for var, val in zip(vars, values): - self.setvar(var, val) - + for var, val in zip(vars, values): + self.setvar(var, val) + def setvar(self, var, val): if var.concretetype != Void: assert var.concretetype == typeOf(val) @@ -39,18 +39,18 @@ if isinstance(var, Variable): self.setvar(var, val) - def getval(self, varorconst): - try: + def getval(self, varorconst): + try: return varorconst.value - except AttributeError: + except AttributeError: return self.bindings[varorconst] # _______________________________________________________ - # other helpers - def getoperationhandler(self, opname): - try: - return getattr(self, 'op_' + opname) - except AttributeError: + # other helpers + def getoperationhandler(self, opname): + try: + return getattr(self, 'op_' + opname) + except AttributeError: g = globals() assert opname in g, ( "cannot handle operation %r yet" %(opname,)) @@ -64,18 +64,18 @@ graph = self.flowgraphs[func] return self.eval_graph(graph,args) - def eval_graph(self, graph, args=()): + def eval_graph(self, graph, args=()): log.graph("evaluating", graph.name) nextblock = graph.startblock - while 1: - self.fillvars(nextblock, args) + while 1: + self.fillvars(nextblock, args) nextblock, args = self.eval_block(nextblock) if nextblock is None: return args - def eval_block(self, block): - """ return (nextblock, values) tuple. If nextblock - is None, values is the concrete return value. + def eval_block(self, block): + """ return (nextblock, values) tuple. If nextblock + is None, values is the concrete return value. """ catch_exception = block.exitswitch == Constant(last_exception) e = None @@ -87,7 +87,7 @@ if not (catch_exception and op is block.operations[-1]): raise - # determine nextblock and/or return value + # determine nextblock and/or return value if len(block.exits) == 0: # return block if len(block.inputargs) == 2: @@ -98,9 +98,9 @@ # watch out, these are _ptr's raise LLException(etype, evalue) resultvar, = block.getvariables() - result = self.getval(resultvar) - log.operation("returning", result) - return None, result + result = self.getval(resultvar) + log.operation("returning", result) + return None, result elif block.exitswitch is None: # single-exit block assert len(block.exits) == 1 @@ -119,37 +119,37 @@ else: # no handler found, pass on raise e - else: + else: index = self.getval(block.exitswitch) link = block.exits[index] return link.target, [self.getval(x) for x in link.args] - - def eval_operation(self, operation): - log.operation("considering", operation) - ophandler = self.getoperationhandler(operation.opname) + + def eval_operation(self, operation): + log.operation("considering", operation) + ophandler = self.getoperationhandler(operation.opname) vals = [self.getval(x) for x in operation.args] # if these special cases pile up, do something better here if operation.opname == 'cast_pointer': vals.insert(0, operation.result.concretetype) - retval = ophandler(*vals) + retval = ophandler(*vals) self.setvar(operation.result, retval) # __________________________________________________________ - # misc LL operation implementations + # misc LL operation implementations - def op_same_as(self, x): + def op_same_as(self, x): return x - def op_setfield(self, obj, fieldname, fieldvalue): + def op_setfield(self, obj, fieldname, fieldvalue): # obj should be pointer setattr(obj, fieldname, fieldvalue) - + def op_getarrayitem(self,array,index): return array[index] - + def op_setarrayitem(self,array,index,item): array[index] = item - + def op_direct_call(self, f, *args): if hasattr(f._obj, 'graph'): return self.eval_graph(f._obj.graph, args) @@ -157,7 +157,7 @@ def op_malloc(self, obj): return malloc(obj) - + def op_getfield(self, obj, field): # assert: obj should be pointer result = getattr(obj, field) @@ -186,38 +186,38 @@ def op_getarraysize(self,array): #print array,type(array),dir(array) return len(array) - + def op_cast_pointer(self, tp, obj): # well, actually this is what's now in the globals. return cast_pointer(tp, obj) # __________________________________________________________ -# primitive operations -from pypy.objspace.flow.operation import FunctionByName +# primitive operations +from pypy.objspace.flow.operation import FunctionByName opimpls = FunctionByName.copy() -opimpls['is_true'] = bool +opimpls['is_true'] = bool -for typ in (float, int): +for typ in (float, int): typname = typ.__name__ - for opname in ('add', 'sub', 'mul', 'div', 'gt', 'lt', - 'ge', 'ne', 'le', 'eq'): - assert opname in opimpls + for opname in ('add', 'sub', 'mul', 'div', 'gt', 'lt', + 'ge', 'ne', 'le', 'eq'): + assert opname in opimpls exec py.code.Source(""" - def %(typname)s_%(opname)s(x, y): + def %(typname)s_%(opname)s(x, y): assert isinstance(x, %(typname)s) assert isinstance(y, %(typname)s) func = opimpls[%(opname)r] - return func(x, y) + return func(x, y) """ % locals()).compile() - for opname in 'is_true',: - assert opname in opimpls + for opname in 'is_true',: + assert opname in opimpls exec py.code.Source(""" - def %(typname)s_%(opname)s(x): + def %(typname)s_%(opname)s(x): assert isinstance(x, %(typname)s) func = opimpls[%(opname)r] - return func(x) + return func(x) """ % locals()).compile() # by default we route all logging messages to nothingness -# e.g. tests can then switch on logging to get more help -# for failing tests -py.log.setconsumer('llinterp', None) +# e.g. tests can then switch on logging to get more help +# for failing tests +py.log.setconsumer('llinterp', None) From hpk at codespeak.net Fri Jun 17 17:10:00 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 17:10:00 +0200 (CEST) Subject: [pypy-svn] r13542 - pypy/extradoc/sprintinfo Message-ID: <20050617151000.0755B27B97@code1.codespeak.net> Author: hpk Date: Fri Jun 17 17:09:59 2005 New Revision: 13542 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: Carl's real dates Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 17 17:09:59 2005 @@ -25,7 +25,7 @@ =================== ============== ===================== Armin Rigo 1st-7th July private Samuele Pedroni 1st-7th July private -Carl Friedrich Bolz 1st-7th July ? +Carl Friedrich Bolz 1st-6th July private Eric van Riet Paap 1st-7th July SGS Holger Krekel 1st-7th July ? Richard Emslie 1st-7th July ? From pedronis at codespeak.net Fri Jun 17 17:51:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 17 Jun 2005 17:51:28 +0200 (CEST) Subject: [pypy-svn] r13543 - pypy/dist/pypy/translator/pickle Message-ID: <20050617155128.3B26327B72@code1.codespeak.net> Author: pedronis Date: Fri Jun 17 17:51:27 2005 New Revision: 13543 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: fixing pickling of OVERFLOwDED_FLOAT Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Fri Jun 17 17:51:27 2005 @@ -38,6 +38,9 @@ # ____________________________________________________________ +#XXX Hack: This float is supposed to overflow to inf +OVERFLOWED_FLOAT = float("1e10000000000000000000000000000000") + class GenPickle: def __init__(self, translator, writer = None): @@ -50,8 +53,6 @@ 'import new, types, sys', ) self.picklenames = {} # memoize objects - self.memoize(float("1e10000000000000000000000000000000"), - 'float("1e10000000000000000000000000000000")') for name in all_feature_names + "new types sys".split(): self.memoize(globals()[name], name) self.namespace = NameManager() @@ -64,7 +65,7 @@ self.simple_const_types = { int: repr, long: repr, - float: repr, + float: self.save_float, str: repr, unicode: repr, type(None): repr, @@ -102,6 +103,11 @@ SpaceOperation: True, } + def save_float(self, fl): + if fl == OVERFLOWED_FLOAT: + return 'float("1e10000000000000000000000000000000")' + return repr(fl) + def pickle(self, **kwds): for obj in kwds.values(): self.nameof(obj) From tismer at codespeak.net Fri Jun 17 17:57:00 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 17:57:00 +0200 (CEST) Subject: [pypy-svn] r13544 - in pypy/dist/pypy: objspace/flow translator/goal translator/pickle Message-ID: <20050617155700.5BD5627B96@code1.codespeak.net> Author: tismer Date: Fri Jun 17 17:56:58 2005 New Revision: 13544 Modified: pypy/dist/pypy/objspace/flow/flowcontext.py pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/pickle/genpickle.py Log: made slots optional for debugging purposes. modified analyse to be restartable. Now we still have some problem with checkgraph() Modified: pypy/dist/pypy/objspace/flow/flowcontext.py ============================================================================== --- pypy/dist/pypy/objspace/flow/flowcontext.py (original) +++ pypy/dist/pypy/objspace/flow/flowcontext.py Fri Jun 17 17:56:58 2005 @@ -20,8 +20,9 @@ class SpamBlock(Block): - - __slots__ = "dead framestate fillcolor".split() + # make slots optional, for debugging + if hasattr(Block, '__slots__'): + __slots__ = "dead framestate fillcolor".split() def __init__(self, framestate): Block.__init__(self, framestate.getvariables()) @@ -36,8 +37,9 @@ class EggBlock(Block): - - __slots__ = "prevblock booloutcome last_exception fillcolor".split() + # make slots optional, for debugging + if hasattr(Block, '__slots__'): + __slots__ = "prevblock booloutcome last_exception fillcolor".split() def __init__(self, inputargs, prevblock, booloutcome): Block.__init__(self, inputargs) Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Fri Jun 17 17:56:58 2005 @@ -448,7 +448,11 @@ assert issubclass(link.exitcase, Exception) exc_links[link] = True else: - assert isinstance(block.exitswitch, Variable) + try: + assert isinstance(block.exitswitch, Variable) + except AssertionError: + print type(block.exitswitch), block.exitswitch + raise assert block.exitswitch in vars for link in block.exits: Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Fri Jun 17 17:56:58 2005 @@ -25,10 +25,12 @@ -no-d Disable recording of debugging information -huge=% Threshold in the number of functions after which only a local call graph and not a full one is displayed - -save filename saves the translator to a file. The file type can either + -save filename + saves the translator to a file. The file type can either be .py or .zip (recommended). - -load filename restores the translator from a file. The file type must - be either .py or.zip . + -load filename + restores the translator from a file. The file type must + be either .py or .zip . """ import autopath, sys, os @@ -87,22 +89,29 @@ if target: entry_point, inputtypes = target() t = Translator(entry_point, verbose=True, simplifying=True) - # otherwise we have been loaded + a = None + else: + # otherwise we have been loaded + a = t.annotator + t.frozen = False if listen_port: run_async_server() if not options['-no-a']: + print 'Annotating...' a = t.annotate(inputtypes, policy=PyPyAnnotatorPolicy()) sanity_check_exceptblocks(t) worstblocks_topten(a) - if not options['-no-s']: - a.simplify() - if not options['-no-t']: - typer = RPythonTyper(a) - typer.specialize() - t.frozen = True # cannot freeze if we don't have annotations - if not options['-no-mark-some-objects']: - options['-no-mark-some-objects'] = True # Do not do this again - find_someobjects(t) + if a and not options['-no-s']: + print 'Simplifying...' + a.simplify() + if a and not options['-no-t']: + print 'Specializing...' + typer = RPythonTyper(a) + typer.specialize() + t.frozen = True # cannot freeze if we don't have annotations + if not options['-no-mark-some-objects']: + options['-no-mark-some-objects'] = True # Do not do this again + find_someobjects(t) def sanity_check_exceptblocks(translator): annotator = translator.annotator @@ -488,12 +497,14 @@ options[name] = True print "continuing Analysis as defined by %s, loaded from %s" %( targetspec, load_file) + print 'options in effect:', options analyse(None) else: targetspec_dic = {} sys.path.insert(0, os.path.dirname(targetspec)) execfile(targetspec+'.py', targetspec_dic) print "Analysing target as defined by %s" % targetspec + print 'options in effect:', options analyse(targetspec_dic['target']) print '-'*60 if save_file: Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Fri Jun 17 17:56:58 2005 @@ -508,12 +508,26 @@ def initdict(): keys = dic.keys() keys.sort() + told = False for k in keys: try: nk, nv = self.nameof(k), self.nameof(dic[k]) yield '%s[%s] = %s' % (name, nk, nv) except PicklingError: pass + else: + # some sanity check + if type(k) is int: + if k in self.picklenames: + print ('WARNING: this dict most likely contains ' + 'the id of some object!!') + print 'name of object: %s' % self.picklenames[k] + elif k == id(dic[k]): + print ('WARNING: this dict most likely contains ' + 'the id of one of it\'s objects!!') + if not told: + print dic + told = True name = self.memoize_unique(dic, 'D%d' % len(dic)) self.produce('%s = {}' % name) for line in initdict(): From hpk at codespeak.net Fri Jun 17 18:19:55 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 18:19:55 +0200 (CEST) Subject: [pypy-svn] r13545 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617161955.E61FC27B9C@code1.codespeak.net> Author: hpk Date: Fri Jun 17 18:19:55 2005 New Revision: 13545 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: (cfbolz,hpk) - introduced LLFrame class to allow recursive calls (and handle local variable bindings more effectively as a side effect) - i am using stricter vim-settings which will probably generate large diffs in the future Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 18:19:55 2005 @@ -18,6 +18,21 @@ self.bindings = {} self.typer = typer + def getgraph(self, func): + return self.flowgraphs[func] + + def eval_function(self, func, args=()): + graph = self.getgraph(func) + llframe = LLFrame(graph, args, self) + return llframe.eval() + +class LLFrame(object): + def __init__(self, graph, args, llinterpreter): + self.graph = graph + self.args = args + self.llinterpreter = llinterpreter + self.bindings = {} + # _______________________________________________________ # variable setters/getters helpers @@ -60,13 +75,11 @@ # _______________________________________________________ # evaling functions - def eval_function(self, func, args=()): - graph = self.flowgraphs[func] - return self.eval_graph(graph,args) - - def eval_graph(self, graph, args=()): - log.graph("evaluating", graph.name) + def eval(self): + graph = self.graph + log.frame("evaluating", graph.name) nextblock = graph.startblock + args = self.args while 1: self.fillvars(nextblock, args) nextblock, args = self.eval_block(nextblock) @@ -108,7 +121,7 @@ elif catch_exception: link = block.exits[0] if e: - exdata = self.typer.getexceptiondata() + exdata = self.llinterpreter.typer.getexceptiondata() cls, inst = e.args for link in block.exits[1:]: assert issubclass(link.exitcase, Exception) @@ -152,8 +165,11 @@ def op_direct_call(self, f, *args): if hasattr(f._obj, 'graph'): - return self.eval_graph(f._obj.graph, args) - return self.eval_function(f._obj._callable, args) + graph = f._obj.graph + else: + graph = self.llinterpreter.getgraph(f._obj._callable) + frame = self.__class__(graph, args, self.llinterpreter) + return frame.eval() def op_malloc(self, obj): return malloc(obj) Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 18:19:55 2005 @@ -1,19 +1,19 @@ import py from pypy.rpython.lltype import typeOf -from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.llinterp import LLInterpreter, LLException -from pypy.translator.translator import Translator +from pypy.translator.translator import Translator from pypy.rpython.lltype import pyobjectptr # switch on logging of interp to show more info on failing tests -def setup_module(mod): +def setup_module(mod): mod.logstate = py.log._getstate() - py.log.setconsumer("llinterp", py.log.STDOUT) + py.log.setconsumer("llinterp", py.log.STDOUT) -def teardown_module(mod): - py.log._setstate(mod.logstate) +def teardown_module(mod): + py.log._setstate(mod.logstate) def find_exception(exc): assert isinstance(exc, LLException) @@ -25,7 +25,7 @@ if func(pyobjectptr(cls)).typeptr == klass: return cls -def gengraph(func, argtypes=[]): +def gengraph(func, argtypes=[]): t = Translator(func) t.annotate(argtypes) global typer # we need it for find_exception @@ -35,28 +35,30 @@ t.checkgraphs() return t, typer -def interpret(func, values): +def interpret(func, values, view=False): t, typer = gengraph(func, [type(x) for x in values]) + if view: + t.view() interp = LLInterpreter(t.flowgraphs, typer) - res = interp.eval_function(func, values) - return res + res = interp.eval_function(func, values) + return res #__________________________________________________________________ -# tests - -def test_int_ops(): +# tests + +def test_int_ops(): res = interpret(number_ops, [3]) - assert res == 4 + assert res == 4 -def test_float_ops(): +def test_float_ops(): res = interpret(number_ops, [3.5]) - assert res == 4.5 + assert res == 4.5 -def test_ifs(): +def test_ifs(): res = interpret(simple_ifs, [0]) - assert res == 43 + assert res == 43 res = interpret(simple_ifs, [1]) - assert res == 42 + assert res == 42 def test_raise(): res = interpret(raise_exception, [41]) @@ -87,32 +89,42 @@ assert find_exception(info.value) is ValueError def test_call_raise_intercept(): - res = interpret(call_raise_intercept, [41]) + res = interpret(call_raise_intercept, [41], view=False) assert res == 41 res = interpret(call_raise_intercept, [42]) assert res == 42 info = raises(LLException, interpret, call_raise_intercept, [43]) assert find_exception(info.value) is TypeError -def test_while_simple(): +def test_while_simple(): res = interpret(while_simple, [3]) assert res == 6 -def test_number_comparisons(): - for t in float, int: +def test_number_comparisons(): + for t in float, int: val1 = t(3) val2 = t(4) gcres = interpret(comparisons, [val1, val2]) res = [getattr(gcres, x) for x in typeOf(gcres).TO._names] assert res == [True, True, False, True, False, False] -def test_some_builtin(): - def f(i, j): - x = range(i) +def test_some_builtin(): + def f(i, j): + x = range(i) return x[j-1] res = interpret(f, [10, 7]) assert res == 6 +def test_recursion_does_not_overwrite_my_variables(): + def f(i): + j = i + 1 + if i > 0: + f(i-1) + return j + + res = interpret(f, [4]) + assert res == 5 + # #__________________________________________________________________ # @@ -125,35 +137,35 @@ for i in range(3): assert res.items[i] == i+1 #__________________________________________________________________ -# example functions for testing the LLInterpreter +# example functions for testing the LLInterpreter _snap = globals().copy() -def number_ops(i): +def number_ops(i): j = i + 2 - k = j * 2 + k = j * 2 m = k / 2 return m - 1 -def comparisons(x, y): - return (x < y, - x <= y, - x == y, - x != y, - #x is None, - #x is not None, - x >= y, - x > y, +def comparisons(x, y): + return (x < y, + x <= y, + x == y, + x != y, + #x is None, + #x is not None, + x >= y, + x > y, ) -def simple_ifs(i): - if i: - return 42 - else: - return 43 +def simple_ifs(i): + if i: + return 42 + else: + return 43 -def while_simple(i): +def while_simple(i): sum = 0 - while i > 0: + while i > 0: sum += i i -= 1 return sum @@ -184,21 +196,21 @@ except ValueError: raise TypeError #__________________________________________________________________ -# interactive playing +# interactive playing -if __name__ == '__main__': +if __name__ == '__main__': try: import rlcompleter2 as _rl2 - _rl2.setup() - except ImportError: + _rl2.setup() + except ImportError: pass t, typer = gengraph(number_ops, [int]) interp = LLInterpreter(t.flowgraphs, typer) res = interp.eval_function(number_ops, [3]) assert res == number_ops(3) - for name, value in globals().items(): - if name not in _snap and name[0] != '_': + for name, value in globals().items(): + if name not in _snap and name[0] != '_': print "%20s: %s" %(name, value) From tismer at codespeak.net Fri Jun 17 18:34:44 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 18:34:44 +0200 (CEST) Subject: [pypy-svn] r13546 - in pypy/dist/pypy: objspace/flow translator/pickle Message-ID: <20050617163444.3EE5A27B98@code1.codespeak.net> Author: tismer Date: Fri Jun 17 18:34:43 2005 New Revision: 13546 Modified: pypy/dist/pypy/objspace/flow/model.py pypy/dist/pypy/translator/pickle/genpickle.py Log: removed debuggind code. changed Atom a bit to allow it to pickle instances by save_global special-cased Atom in genpickle. now this works.Remaining problem is intialization of the bookkeeper. Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Fri Jun 17 18:34:43 2005 @@ -303,9 +303,9 @@ class Atom: def __init__(self, name): - self.name = name + self.__name__ = name # make save_global happy def __repr__(self): - return self.name + return self.__name__ last_exception = Atom('last_exception') # if Block().exitswitch == Constant(last_exception), it means that we are @@ -448,11 +448,7 @@ assert issubclass(link.exitcase, Exception) exc_links[link] = True else: - try: - assert isinstance(block.exitswitch, Variable) - except AssertionError: - print type(block.exitswitch), block.exitswitch - raise + assert isinstance(block.exitswitch, Variable) assert block.exitswitch in vars for link in block.exits: Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Fri Jun 17 18:34:43 2005 @@ -17,7 +17,7 @@ from pypy.translator.gensupp import builtin_base from pypy.rpython.rarithmetic import r_int, r_uint from pypy.objspace.flow.model import Variable, Constant, SpaceOperation -from pypy.objspace.flow.model import FunctionGraph, Block, Link +from pypy.objspace.flow.model import FunctionGraph, Block, Link, Atom from pypy.objspace.flow.flowcontext import SpamBlock, EggBlock from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool from pypy.annotation.model import SomeList, SomeString, SomeTuple @@ -547,6 +547,10 @@ nameof_wrapper_descriptor = nameof_member_descriptor def nameof_instance(self, instance): + if isinstance(instance, Atom): + # cannot reconstruct this, it *must* be + # the one from model + return self.save_global(instance) def initinstance(): if hasattr(instance, '__setstate__'): # the instance knows what to do From arigo at codespeak.net Fri Jun 17 19:15:44 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 19:15:44 +0200 (CEST) Subject: [pypy-svn] r13547 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617171544.BFACB27B98@code1.codespeak.net> Author: arigo Date: Fri Jun 17 19:15:41 2005 New Revision: 13547 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Calls to methods of frozen PBCs. Tried to make hacking the HighLevelOp instances easier, via improvements on the interface. Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 17 19:15:41 2005 @@ -7,10 +7,11 @@ def normalize_function_signatures(annotator): - # make sure that all functions called in a group have exactly - # the same signature, by hacking their flow graphs if needed - callables = annotator.getpbccallables() + """Make sure that all functions called in a group have exactly + the same signature, by hacking their flow graphs if needed. + """ call_families = annotator.getpbccallfamilies() + # for methods, we create or complete a corresponding function-only # family with call patterns that have the extra 'self' argument for family in call_families.infos(): @@ -30,7 +31,8 @@ argcount = pattern[0] pattern = (argcount+1,) + pattern[1:] func_family.patterns[pattern] = True - # for classes that appear in families, unify their __init__ as well + + # for classes that appear in families, unify their __init__ as well. for family in call_families.infos(): prevkey = None for _, klass in family.objects: @@ -43,14 +45,37 @@ prevkey = (None, initfunc) else: call_families.union((None, initfunc), prevkey) + + # for bound method objects, make sure the im_func shows up too. + for family in call_families.infos(): + first = family.objects.keys()[0][1] + for _, callable in family.objects: + if isinstance(callable, types.MethodType): + # for bound methods families for now just accept and check that + # they all refer to the same function + if not isinstance(first, types.MethodType): + raise TyperError("call family with both bound methods and " + "%r" % (first,)) + if first.im_func is not callable.im_func: + raise TyperError("call family of bound methods: should all " + "refer to the same function") + # create a family for the common im_func + if isinstance(first, types.MethodType): + _, _, func_family = call_families.find((None, first.im_func)) + for pattern in family.patterns: + argcount = pattern[0] + pattern = (argcount+1,) + pattern[1:] + func_family.patterns[pattern] = True + # find the most general signature of each family for family in call_families.infos(): # collect functions in this family, ignoring: # - methods: taken care of above + # - bound methods: their im_func will also show up # - classes: their __init__ unbound methods are also families functions = [func for classdef, func in family.objects if classdef is None and - not isinstance(func, (type, types.ClassType))] + not isinstance(func, (type, types.ClassType, types.MethodType))] if len(functions) > 1: # otherwise, nothing to do if len(family.patterns) > 1: raise TyperError("don't support multiple call patterns " @@ -60,19 +85,6 @@ shape_cnt, shape_keys, shape_star, shape_stst = pattern assert not shape_star, "XXX not implemented" assert not shape_stst, "XXX not implemented" - # for bound methods families for now just accept and check that - # they all refer to the same function - if isinstance(functions[0], types.MethodType): - methfunc = functions[0].im_func - assert functions[0].im_self is not None - if (None, methfunc) in call_families: - raise TypeError("function appears both in bound method and" - "freestanding: %r" % methfunc) - for func in functions: - if getattr(func, 'im_func', None) is not methfunc: - raise TypeError("invalid familily of bound methods: %r" % - functions) - continue # for the first 'shape_cnt' arguments we need to generalize to # a common type Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Fri Jun 17 19:15:41 2005 @@ -40,8 +40,9 @@ except KeyError: raise TyperError("don't know about built-in function %r" % ( self.builtinfunc,)) - hop.r_s_popfirstarg() - return bltintyper(hop) + hop2 = hop.copy() + hop2.r_s_popfirstarg() + return bltintyper(hop2) class BuiltinMethodRepr(Repr): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jun 17 19:15:41 2005 @@ -15,17 +15,19 @@ # for now, we require that the PBC fits neatly into one of the Repr # categories below, and doesn't for example mix functions, classes # and methods. - callb = rtyper.annotator.getpbccallables() + call_families = rtyper.annotator.getpbccallfamilies() choices = {} for x, classdef in self.prebuiltinstances.items(): cdefflag = isclassdef(classdef) + if not cdefflag: + classdef = None # consider unbound methods as plain functions if isinstance(x, types.MethodType) and x.im_self is None: x = x.im_func # callable or frozen object? - if x in callb: + if (classdef, x) in call_families: # what type of callable? if isinstance(x, types.FunctionType): if cdefflag: @@ -35,8 +37,8 @@ choice = FunctionsPBCRepr elif isinstance(x, (type, types.ClassType)): choice = ClassesPBCRepr - #elif isinstance(x, types.MethodType): - # choice = ConstMethodsPBCRepr + elif isinstance(x, types.MethodType): + choice = MethodOfFrozenPBCRepr else: raise TyperError("don't know about callable %r" % (x,)) else: @@ -153,6 +155,43 @@ # ____________________________________________________________ +class MethodOfFrozenPBCRepr(Repr): + """Representation selected for a PBC of method object(s) of frozen PBCs. + It assumes that all methods are the same function bound to different PBCs. + The low-level representation can then be a pointer to that PBC.""" + + def __init__(self, rtyper, s_pbc): + self.rtyper = rtyper + self.function = s_pbc.prebuiltinstances.keys()[0].im_func + im_selves = {} + for pbc, not_a_classdef in s_pbc.prebuiltinstances.items(): + assert pbc.im_func is self.function + assert not isclassdef(not_a_classdef) + im_selves[pbc.im_self] = True + self.s_im_self = annmodel.SomePBC(im_selves) + self.r_im_self = rtyper.getrepr(self.s_im_self) + self.lowleveltype = self.r_im_self.lowleveltype + + def convert_const(self, method): + if getattr(method, 'im_func', None) is not self.function: + raise TyperError("not a method bound on %r: %r" % (self.function, + method)) + return self.r_im_self.convert_const(method.im_self) + + def rtype_simple_call(self, hop): + s_function = annmodel.SomePBC({self.function: True}) + hop2 = hop.copy() + hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' + hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') + c = Constant(self.function) + hop2.v_s_insertfirstarg(c, s_function) # insert 'function' + # now hop2 looks like simple_call(function, self, args...) + return hop2.dispatch() + + +# ____________________________________________________________ + + def getsignature(rtyper, func): f = rtyper.getfunctionptr(func) graph = f._obj.graph @@ -332,11 +371,11 @@ s_init = annmodel.SomePBC({initfunc: True}) hop2 = hop.copy() hop2.r_s_popfirstarg() # discard the class pointer argument - hop2.v_s_insertfirstarg(v_instance, s_instance) # (instance, *args) + hop2.v_s_insertfirstarg(v_instance, s_instance) # add 'instance' c = Constant(initfunc) - hop2.v_s_insertfirstarg(c, s_init) # (initfunc, instance, *args) + hop2.v_s_insertfirstarg(c, s_init) # add 'initfunc' hop2.s_result = annmodel.SomePBC({None: True}) hop2.r_result = self.rtyper.getrepr(hop2.s_result) - r_init = self.rtyper.getrepr(s_init) - r_init.rtype_simple_call(hop2) + # now hop2 looks like simple_call(initfunc, instance, args...) + hop2.dispatch() return v_instance Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Fri Jun 17 19:15:41 2005 @@ -248,10 +248,8 @@ def translate_hl_to_ll(self, hop, varmapping): if debug: print hop.spaceop.opname, hop.args_s + resultvar = hop.dispatch() op = hop.spaceop - translate_meth = getattr(self, 'translate_op_'+op.opname, - self.missing_operation) - resultvar = translate_meth(hop) if resultvar is None: # no return value if hop.s_result != annmodel.SomeImpossibleValue(): @@ -389,6 +387,13 @@ setattr(result, key, value) return result + def dispatch(self): + op = self.spaceop + rtyper = self.rtyper + translate_meth = getattr(rtyper, 'translate_op_'+op.opname, + rtyper.missing_operation) + return translate_meth(self) + def inputarg(self, converted_to, arg): """Returns the arg'th input argument of the current operation, as a Variable or Constant converted to the requested type. Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Jun 17 19:15:41 2005 @@ -74,6 +74,8 @@ class Freezing: def _freeze_(self): return True + def mymethod(self, y): + return self.x + y def test_freezing(): fr1 = Freezing() @@ -91,3 +93,23 @@ fr = None return g(fr) rtype(f, [int]) + +def test_call_frozen_pbc_simple(): + fr1 = Freezing() + fr1.x = 5 + def f(n): + return fr1.mymethod(n) + rtype(f, [int]) + +def test_call_frozen_pbc_multiple(): + fr1 = Freezing() + fr2 = Freezing() + fr1.x = 5 + fr2.x = 6 + def f(n): + if n > 0: + fr = fr1 + else: + fr = fr2 + return fr.mymethod(n) + rtype(f, [int]) From tismer at codespeak.net Fri Jun 17 19:17:59 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 19:17:59 +0200 (CEST) Subject: [pypy-svn] r13548 - pypy/dist/pypy/annotation Message-ID: <20050617171759.15C1227B98@code1.codespeak.net> Author: tismer Date: Fri Jun 17 19:17:58 2005 New Revision: 13548 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: added __setstate__ that does the needed import. The stuff might work now! I'm not sure, because translation of targetrpystone does not work with rtyper now, at all. But I get the same error message after loading a saved session. Maybe it is fine, now. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Jun 17 19:17:58 2005 @@ -134,6 +134,12 @@ Currently used for factories and user-defined classes.""" + def __setstate__(self, dic): + self.__dict__.update(dic) # normal action + # import ordering hack + global BUILTIN_ANALYZERS + from pypy.annotation.builtin import BUILTIN_ANALYZERS + def __init__(self, annotator): self.annotator = annotator self.userclasses = {} # map classes to ClassDefs From cfbolz at codespeak.net Fri Jun 17 19:46:42 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 17 Jun 2005 19:46:42 +0200 (CEST) Subject: [pypy-svn] r13549 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617174642.32BA927B7D@code1.codespeak.net> Author: cfbolz Date: Fri Jun 17 19:46:41 2005 New Revision: 13549 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: (cf + hpk) added tests for list operations added some assertions Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 19:46:41 2005 @@ -175,7 +175,7 @@ return malloc(obj) def op_getfield(self, obj, field): - # assert: obj should be pointer + assert isinstance(obj, _ptr) result = getattr(obj, field) # check the difference between op_getfield and op_getsubstruct: # the former returns the real field, the latter a pointer to it @@ -183,7 +183,7 @@ return result def op_getsubstruct(self, obj, field): - # assert: obj should be pointer + assert isinstance(obj, _ptr) result = getattr(obj, field) # check the difference between op_getfield and op_getsubstruct: # the former returns the real field, the latter a pointer to it @@ -195,12 +195,14 @@ def op_getarraysubstruct(self, array, index): assert isinstance(array, _ptr) - return array[index] + result = array[index] + return result # the diff between op_getarrayitem and op_getarraysubstruct # is the same as between op_getfield and op_getsubstruct - def op_getarraysize(self,array): + def op_getarraysize(self, array): #print array,type(array),dir(array) + assert isinstance(typeOf(array).TO, Array) return len(array) def op_cast_pointer(self, tp, obj): Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 19:46:41 2005 @@ -136,6 +136,16 @@ assert len(res.items) == len([1,2,3]) for i in range(3): assert res.items[i] == i+1 + +def test_list_operations(): + def f(i): + l = [1, i] + l[0] = len(l) + l += [i + 1, 9] +# l *= 2 + return l[0] + l[1] + l[2]# + len(l) + res = interpret(f, [3]) + assert res == 2 + 3 + 4# + 8 #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() From tismer at codespeak.net Fri Jun 17 19:48:45 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 19:48:45 +0200 (CEST) Subject: [pypy-svn] r13550 - pypy/dist/pypy/translator/pickle Message-ID: <20050617174845.86C1F27B7D@code1.codespeak.net> Author: tismer Date: Fri Jun 17 19:48:44 2005 New Revision: 13550 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: loading and saving now works with targetrpystone. The reloaded graph compiles and runs! Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Fri Jun 17 19:48:44 2005 @@ -80,6 +80,7 @@ 'pypy._cache.', 'pypy.interpreter.', 'pypy.module.', + 'pypy.translator.test.', '__main__', ) self.shortnames = { @@ -260,6 +261,7 @@ text = 'skipped, see _skipped_code attr: %s' % funcname def dummy(*args, **kwds): raise NotImplementedError, text + _dummydict['__builtins__'] = __builtins__ skippedfunc = new.function(dummy.func_code, _dummydict, skipname, (), dummy.func_closure) skippedfunc._skipped_code = func_code @@ -478,12 +480,12 @@ self.produce(line) return name - def is_app_domain(self, modname): + def is_app_domain(self, modname, exclude=()): for domain in self.domains: if domain.endswith('.') and modname.startswith(domain): # handle subpaths return True - if modname == domain: + if modname == domain and modname not in exclude: # handle exact module names return True return False @@ -681,7 +683,7 @@ if func not in self.translator.flowgraphs: # see if this is in translator's domain module = whichmodule(func, func.__name__) - if self.is_app_domain(module): + if self.is_app_domain(module, exclude=['__main__']): # see if this buddy has been skipped in another save, before if not hasattr(func, '_skipped_code'): return self.skipped_function(func, From tismer at codespeak.net Fri Jun 17 20:17:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 17 Jun 2005 20:17:11 +0200 (CEST) Subject: [pypy-svn] r13551 - pypy/dist/pypy/translator/pickle Message-ID: <20050617181711.BB7C527B96@code1.codespeak.net> Author: tismer Date: Fri Jun 17 20:17:11 2005 New Revision: 13551 Modified: pypy/dist/pypy/translator/pickle/loader.py pypy/dist/pypy/translator/pickle/main.py Log: added a bit of screen play for the loading phase. loading targetpypymain takes 7 seconds on my machine. The created zip file is 9.2 MB still no idea what kind of test this should use, help :-) Modified: pypy/dist/pypy/translator/pickle/loader.py ============================================================================== --- pypy/dist/pypy/translator/pickle/loader.py (original) +++ pypy/dist/pypy/translator/pickle/loader.py Fri Jun 17 20:17:11 2005 @@ -11,10 +11,12 @@ def next_block(self): raise SyntaxError, "implement next_block" - def load(self): + def load(self, progress=None): dic = {} for blk in self.next_block(): exec blk in dic + if progress: + progress() try: return dic['result'] finally: Modified: pypy/dist/pypy/translator/pickle/main.py ============================================================================== --- pypy/dist/pypy/translator/pickle/main.py (original) +++ pypy/dist/pypy/translator/pickle/main.py Fri Jun 17 20:17:11 2005 @@ -6,7 +6,12 @@ def load(fname): loader = _select(fname)[0] assert loader, 'only .py and .zip files supported' - return loader(fname).load() + print "Loading:", + def progress(): + sys.stdout.write('.') + ret = loader(fname).load(progress) + print + return ret def save(translator, fname, **objects): writer = _select(fname)[1] From arigo at codespeak.net Fri Jun 17 20:21:11 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 20:21:11 +0200 (CEST) Subject: [pypy-svn] r13552 - pypy/dist/pypy/objspace/std Message-ID: <20050617182111.B0B1F27B96@code1.codespeak.net> Author: arigo Date: Fri Jun 17 20:21:10 2005 New Revision: 13552 Modified: pypy/dist/pypy/objspace/std/unicodetype.py Log: Using the now-standard way of calling the __init__ constructor as an unbound method. Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Fri Jun 17 20:21:10 2005 @@ -105,7 +105,7 @@ # help the annotator! also the ._value depends on W_UnicodeObject layout assert isinstance(w_value, W_UnicodeObject) w_newobj = space.allocate_instance(W_UnicodeObject, w_unicodetype) - w_newobj.__init__(space, w_value._value) + W_UnicodeObject.__init__(w_newobj, space, w_value._value) return w_newobj # ____________________________________________________________ From hpk at codespeak.net Fri Jun 17 20:40:28 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 17 Jun 2005 20:40:28 +0200 (CEST) Subject: [pypy-svn] r13553 - in pypy/dist/pypy: annotation rpython/test Message-ID: <20050617184028.4993A27B96@code1.codespeak.net> Author: hpk Date: Fri Jun 17 20:40:26 2005 New Revision: 13553 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: (cf+hpk+arigo) - added some list tests - list.extend now unifies the two listdefs Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Fri Jun 17 20:40:26 2005 @@ -212,8 +212,11 @@ def method_extend(lst, s_iterable): lst.listdef.resize() - s_iter = s_iterable.iter() - pair(lst, SomeInteger()).setitem(s_iter.next()) + if isinstance(s_iterable, SomeList): # unify the two lists + lst.listdef.union(s_iterable.listdef) + else: + s_iter = s_iterable.iter() + pair(lst, SomeInteger()).setitem(s_iter.next()) def method_reverse(lst): lst.listdef.mutate() @@ -221,7 +224,7 @@ def method_insert(lst, s_index, s_value): lst.listdef.resize() pair(lst, SomeInteger()).setitem(s_value) - + def method_pop(lst, s_index=None): lst.listdef.resize() return lst.listdef.read_item() @@ -254,7 +257,7 @@ r.const = 0 return r return SomeObject.len(dct) - + def iter(dct): return SomeIterator(dct) @@ -280,7 +283,7 @@ def method_items(dct): return getbookkeeper().newlist(SomeTuple((dct.dictdef.read_key(), dct.dictdef.read_value()))) - + class __extend__(SomeString): @@ -375,14 +378,14 @@ return bltn.analyser(bltn.s_self, *args) else: return bltn.analyser(*args) - + class __extend__(SomePBC): def getattr(pbc, s_attr): bookkeeper = getbookkeeper() return bookkeeper.pbc_getattr(pbc, s_attr) - + def setattr(pbc, s_attr, s_value): getbookkeeper().warning("setattr not wanted on %r" % (pbc,)) @@ -393,21 +396,21 @@ #bookkeeper = getbookkeeper() #results = [] #for func, classdef in pbc.prebuiltinstances.items(): - # if isclassdef(classdef): + # if isclassdef(classdef): # s_self = SomeInstance(classdef) # args1 = args.prepend(s_self) # else: # args1 = args # results.append(bookkeeper.pycall(func, args1)) - #return unionof(*results) + #return unionof(*results) - def bindcallables(pbc, classdef): - """ turn the callables in the given SomeCallable 'cal' + def bindcallables(pbc, classdef): + """ turn the callables in the given SomeCallable 'cal' into bound versions. """ d = {} for func, value in pbc.prebuiltinstances.items(): - if isinstance(func, FunctionType): + if isinstance(func, FunctionType): if isclassdef(value): getbookkeeper().warning("rebinding an already bound " "method %r with %r" % (func, value)) @@ -415,7 +418,7 @@ elif isinstance(func, staticmethod): d[func.__get__(43)] = value else: - d[func] = value + d[func] = value return SomePBC(d) def is_true(pbc): @@ -427,8 +430,8 @@ if outcome != bool(c): return SomeBool() return immutablevalue(outcome) - - + + # annotation of low-level types from pypy.annotation.model import SomePtr, ll_to_annotation, annotation_to_lltype class __extend__(SomePtr): Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 20:40:26 2005 @@ -28,6 +28,7 @@ def gengraph(func, argtypes=[]): t = Translator(func) t.annotate(argtypes) + #t.view() global typer # we need it for find_exception typer = RPythonTyper(t.annotator) typer.specialize() @@ -137,15 +138,39 @@ for i in range(3): assert res.items[i] == i+1 -def test_list_operations(): +def test_list_itemops(): def f(i): l = [1, i] - l[0] = len(l) - l += [i + 1, 9] -# l *= 2 - return l[0] + l[1] + l[2]# + len(l) + l[0] = 0 + del l[1] + return l[-1] + res = interpret(f, [3]) + assert res == 0 + +def test_list_append(): + def f(i): + l = [1] + l.append(i) + return l[0] + l[1] res = interpret(f, [3]) - assert res == 2 + 3 + 4# + 8 + assert res == 4 + +def test_list_extend(): + def f(i): + l = [1] + l.extend([i]) + return l[0] + l[1] + res = interpret(f, [3]) + assert res == 4 + +def test_list_multiply(): + def f(i): + l = [i] + l = l * i # uses alloc_and_set for len(l) == 1 + return len(l) + res = interpret(f, [3]) + assert res == 3 + #__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() From cfbolz at codespeak.net Fri Jun 17 21:17:09 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 17 Jun 2005 21:17:09 +0200 (CEST) Subject: [pypy-svn] r13554 - pypy/dist/pypy/rpython/test Message-ID: <20050617191709.15A9D27B96@code1.codespeak.net> Author: cfbolz Date: Fri Jun 17 21:17:08 2005 New Revision: 13554 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rclass.py Log: (hpk, cfbolz) changed test_rclass to use the llinterpreter. unfortunately it all seems to work Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 21:17:08 2005 @@ -172,6 +172,21 @@ assert res == 3 #__________________________________________________________________ +# +# Test objects and instances + +class ExampleClass: + def __init__(self, x): + self.x = x + 1 + +def test_basic_instantiation(): + def f(x): + return ExampleClass(x).x + res = interpret(f, [4], view=True) + assert res == 5 + + +#__________________________________________________________________ # example functions for testing the LLInterpreter _snap = globals().copy() Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Fri Jun 17 21:17:08 2005 @@ -1,16 +1,6 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * -from pypy.rpython.rtyper import RPythonTyper - - -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - return t +from pypy.rpython.test.test_llinterp import interpret class EmptyBase(object): @@ -21,7 +11,9 @@ def dummyfn(): x = EmptyBase() return x - rtype(dummyfn) + res = interpret(dummyfn, []) + T = typeOf(res) + assert isinstance(T, Ptr) and isinstance(T.TO, GcStruct) def test_instanceattr(): def dummyfn(): @@ -29,8 +21,8 @@ x.a = 5 x.a += 1 return x.a - rtype(dummyfn) - + res = interpret(dummyfn, []) + assert res == 6 class Random: xyzzy = 12 @@ -40,14 +32,16 @@ def dummyfn(): x = Random() return x.xyzzy - rtype(dummyfn) + res = interpret(dummyfn, []) + assert res == 12 def test_classattr_as_defaults(): def dummyfn(): x = Random() x.xyzzy += 1 return x.xyzzy - rtype(dummyfn) + res = interpret(dummyfn, []) + assert res == 13 def test_prebuilt_instance(): a = EmptyBase() @@ -55,7 +49,7 @@ def dummyfn(): a.x += 1 return a.x - rtype(dummyfn) + interpret(dummyfn, []) def test_recursive_prebuilt_instance(): a = EmptyBase() @@ -65,5 +59,30 @@ a.peer = b b.peer = a def dummyfn(): - return a.peer.x - rtype(dummyfn) + return a.peer.peer.peer.x + res = interpret(dummyfn, []) + assert res == 6 + +# method calls +class A: + def f(self): + return self.g() + + def g(self): + return 42 + +class B(A): + def g(self): + return 1 + +def test_simple_method_call(): + def f(i): + if i: + a = A() + else: + a = B() + return a.f() + res = interpret(f, [True]) + assert res == 42 + res = interpret(f, [False]) + assert res == 1 From cfbolz at codespeak.net Fri Jun 17 21:44:27 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 17 Jun 2005 21:44:27 +0200 (CEST) Subject: [pypy-svn] r13555 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617194427.13F0F27B96@code1.codespeak.net> Author: cfbolz Date: Fri Jun 17 21:44:26 2005 New Revision: 13555 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: (hpk, cfbolz) converted some more tests to use interpret added cast_int_to_float Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 21:44:26 2005 @@ -208,6 +208,10 @@ def op_cast_pointer(self, tp, obj): # well, actually this is what's now in the globals. return cast_pointer(tp, obj) + + def op_cast_int_to_float(self, i): + assert isinstance(i, int) + return float(i) # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Jun 17 21:44:26 2005 @@ -4,21 +4,13 @@ from pypy.rpython.test.test_llinterp import interpret -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - typer = RPythonTyper(t.annotator) - typer.specialize() - t.checkgraphs() - return t - - def test_easy_call(): def f(x): return x+1 def g(y): return f(y+2) - rtype(g, [int]) + res = interpret(g, [5]) + assert res == 8 def test_multiple_call(): def f1(x): @@ -31,7 +23,10 @@ else: f = f2 return f(y+3) - rtype(g, [int]) + res = interpret(g, [-1]) + assert res == 3 + res = interpret(g, [1]) + assert res == 6 class MyBase: @@ -47,7 +42,8 @@ obj = MyBase() obj.z = a return obj.m(b) - rtype(f, [int, int]) + res = interpret(f, [4, 5]) + assert res == 9 def test_virtual_method_call(): def f(a, b): @@ -57,7 +53,10 @@ obj = MySubclass() obj.z = a return obj.m(b) - rtype(f, [int, int]) + res = interpret(f, [1, 2.3]) + assert res == 3.3 + res = interpret(f, [-1, 2.3]) + assert res == -3.3 class MyBaseWithInit: @@ -92,14 +91,18 @@ else: fr = None return g(fr) - rtype(f, [int]) + res = interpret(f, [1]) + assert res == 5 + res = interpret(f, [-1]) + assert res == 6 def test_call_frozen_pbc_simple(): fr1 = Freezing() fr1.x = 5 def f(n): return fr1.mymethod(n) - rtype(f, [int]) + res = interpret(f, [6]) + assert res == 11 def test_call_frozen_pbc_multiple(): fr1 = Freezing() @@ -112,4 +115,7 @@ else: fr = fr2 return fr.mymethod(n) - rtype(f, [int]) + res = interpret(f, [1]) + assert res == 6 + res = interpret(f, [-1]) + assert res == 5 From arigo at codespeak.net Fri Jun 17 22:33:40 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 22:33:40 +0200 (CEST) Subject: [pypy-svn] r13556 - in pypy/dist/pypy: annotation translator/test Message-ID: <20050617203340.CAB1527B96@code1.codespeak.net> Author: arigo Date: Fri Jun 17 22:33:38 2005 New Revision: 13556 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/translator/test/test_annrpython.py Log: Refactored the Attribute model of classdef.py to allow for more precise annotations, after we discovered a corner case in which too much generalization occurred. This is also an important santitization, I guess. We can now write a nice explanation blurb with invariants that are preserved. (This text should go into documentation/ too.) Fixed tests accordingly. Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Fri Jun 17 22:33:38 2005 @@ -7,48 +7,94 @@ from pypy.annotation.model import SomeImpossibleValue, SomePBC, tracking_unionof +# The main purpose of a ClassDef is to collect information about class/instance +# attributes as they are really used. An Attribute object is stored in the +# most general ClassDef where an attribute of that name is read/written: +# classdef.attrs = {'attrname': Attribute()} +# +# The following invariants hold: +# +# (A) if an attribute is read/written on an instance of class A, then the +# classdef of A or a parent class of A has an Attribute object corresponding +# to that name. +# +# (I) if B is a subclass of A, then they don't have both an Attribute for the +# same name. (All information from B's Attribute must be merged into A's.) +# +# Additionally, each ClassDef records an 'attr_sources': it maps attribute +# names to a set of objects that want to provide a constant value for this +# attribute at the level of this class. The attrsources provide information +# higher in the class hierarchy than concrete Attribute()s. It is for the case +# where (so far or definitely) the user program only reads/writes the attribute +# at the level of a subclass, but a value for this attribute could possibly +# exist in the parent class or in an instance of a parent class. +# +# The point of not automatically forcing the Attribute instance up to the +# parent class which has a class attribute of the same name is apparent with +# multiple subclasses: +# +# A +# attr=s1 +# / \ +# / \ +# B C +# attr=s2 attr=s3 +# +# In this case, as long as 'attr' is only read/written from B or C, the +# Attribute on B says that it can be 's1 or s2', and the Attribute on C says +# it can be 's1 or s3'. Merging them into a single Attribute on A would give +# the more imprecise 's1 or s2 or s3'. +# +# The following invariant holds: +# +# (II) if a class A has an Attribute, the 'attrsources' for the same name is +# empty. It is also empty on all subclasses of A. (The information goes +# into the Attribute directly in this case.) +# +# The attrsources have the format {object: classdef}. For class attributes, +# 'object' is the class in question and 'classdef' its corresponding classdef, +# used for binding methods. For attribute sources that are prebuilt instances, +# 'classdef' is None. +# +# The following invariant holds: +# +# (III) for a class A, each attrsource that comes from the class (as opposed to +# from a prebuilt instance) must be merged into all Attributes of the +# same name in all subclasses of A, if any. (Parent class attributes can +# be visible in reads from instances of subclasses.) + + class Attribute: # readonly-ness # SomeThing-ness - # more potential sources (pbcs or classes) of information - # NB. the laziness of 'sources' was required for two reasons: - # * some strange attributes exist on classes but are never touched, - # immutablevalue() wouldn't be happy with them - # * there is an infinite recursion between immutablevalue() and - # add_source_for_attribute() for cyclic constant structures. - # NB2. an attribute is readonly if it is a constant class attribute. + # NB. an attribute is readonly if it is a constant class attribute. # Both writing to the instance attribute and discovering prebuilt # instances that have the attribute set will turn off readonly-ness. def __init__(self, name, bookkeeper): self.name = name self.bookkeeper = bookkeeper - self.sources = {} # source -> None or ClassDef # XXX a SomeImpossibleValue() constant? later!! self.s_value = SomeImpossibleValue() self.readonly = True self.read_locations = {} + def add_constant_source(self, source, classdef): + s_value = self.bookkeeper.immutablevalue( + source.__dict__[self.name]) + if classdef: + s_value = s_value.bindcallables(classdef) + else: + # a prebuilt instance source forces readonly=False, see above + self.readonly = False + self.s_value = tracking_unionof(self, self.s_value, s_value) + def getvalue(self): - while self.sources: - source, classdef = self.sources.iteritems().next() - s_value = self.bookkeeper.immutablevalue( - source.__dict__[self.name]) - # warning: 'source' should not be removed from the dict before - # immutablevalue() finished, because the latter can move attrdefs - # around and this would gets this source lost - try: - del self.sources[source] - except KeyError: - pass - if classdef: - s_value = s_value.bindcallables(classdef) - self.s_value = tracking_unionof(self, self.s_value, s_value) + # Same as 'self.s_value' for historical reasons. return self.s_value def merge(self, other): assert self.name == other.name - self.sources.update(other.sources) self.s_value = tracking_unionof(self, self.s_value, other.s_value) self.readonly = self.readonly and other.readonly self.read_locations.update(other.read_locations) @@ -63,6 +109,7 @@ #self.instantiation_locations = {} self.cls = cls self.subdefs = {} + self.attr_sources = {} # {name: {constant_object: classdef_or_None}} base = object mixeddict = {} sources = {} @@ -120,19 +167,35 @@ self.bookkeeper.annotator.reflowfromposition(position) def add_source_for_attribute(self, attr, source, clsdef=None): - homedef = self.locate_attribute(attr) - attrdef = homedef.attrs[attr] - attrdef.sources[source] = clsdef - if clsdef is None: - attrdef.readonly = False # see note about 'readonly' in ClassDef - if attrdef.read_locations: - # we should reflow from all the reader's position, - # but as an optimization we try to see if the attribute - # has really been generalized - s_prev_value = attrdef.s_value - s_next_value = attrdef.getvalue() - if s_prev_value != s_next_value: - self.attr_mutated(homedef, attrdef) + """Adds information about a constant source for an attribute. + """ + for cdef in self.getmro(): + if attr in cdef.attrs: + # the Attribute() exists already for this class (or a parent) + attrdef = cdef.attrs[attr] + s_prev_value = attrdef.s_value + attrdef.add_constant_source(source, clsdef) + # we should reflow from all the reader's position, + # but as an optimization we try to see if the attribute + # has really been generalized + if attrdef.s_value != s_prev_value: + for position in attrdef.read_locations: + self.bookkeeper.annotator.reflowfromposition(position) + return + else: + # remember the source in self.attr_sources + sources = self.attr_sources.setdefault(attr, {}) + sources[source] = clsdef + # register the source in any Attribute found in subclasses, + # to restore invariant (III) + # NB. add_constant_source() may discover new subdefs but the + # right thing will happen to them because self.attr_sources + # was already updated + if clsdef is not None: + for subdef in self.getallsubdefs(): + if attr in subdef.attrs: + attrdef = subdef.attrs[attr] + attrdef.add_constant_source(source, clsdef) def locate_attribute(self, attr): while True: @@ -183,34 +246,53 @@ pending.append(sub) seen[sub] = True -## def getallinstantiations(self): -## locations = {} -## for clsdef in self.getallsubdefs(): -## locations.update(clsdef.instantiation_locations) -## return locations - def _generalize_attr(self, attr, s_value): # first remove the attribute from subclasses -- including us! + # invariant (I) subclass_attrs = [] + constant_sources = {} for subdef in self.getallsubdefs(): if attr in subdef.attrs: subclass_attrs.append(subdef.attrs[attr]) del subdef.attrs[attr] + if attr in subdef.attr_sources: + # accumulate attr_sources for this attribute from all subclasses + d = subdef.attr_sources[attr] + constant_sources.update(d) + d.clear() # invariant (II) + + # accumulate attr_sources for this attribute from all parents, too + # invariant (III) + for superdef in self.getmro(): + if attr in superdef.attr_sources: + for source, classdef in superdef.attr_sources[attr].items(): + if classdef is not None: + constant_sources[source] = classdef - # do the generalization + # create the Attribute and do the generalization asked for newattr = Attribute(attr, self.bookkeeper) if s_value: newattr.s_value = s_value - + + # keep all subattributes' values for subattr in subclass_attrs: newattr.merge(subattr) + + # store this new Attribute, generalizing the previous ones from + # subclasses -- invariant (A) self.attrs[attr] = newattr + # add the values of the pending constant attributes + # completes invariants (II) and (III) + for source, classdef in constant_sources.items(): + newattr.add_constant_source(source, classdef) + # reflow from all read positions self.attr_mutated(self, newattr) def generalize_attr(self, attr, s_value=None): - # if the attribute exists in a superclass, generalize there. + # if the attribute exists in a superclass, generalize there, + # as imposed by invariant (I) for clsdef in self.getmro(): if attr in clsdef.attrs: clsdef._generalize_attr(attr, s_value) Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Fri Jun 17 22:33:38 2005 @@ -1276,26 +1276,20 @@ a = self.RPythonAnnotator() s = a.build_types(f, []) assert isinstance(s, annmodel.SomeInstance) - assert s.can_be_None + assert not s.can_be_None assert s.classdef.cls is A - def test_attr_moving_from_subclass_to_class_to_parent(self): - class A: pass - class B(A): pass - class C(B): pass - a1 = A() - a1.stuff = None - c1 = C() - c1.stuff = a1 + def test_class_attribute(self): + class A: + stuff = 42 + class B(A): + pass def f(): b = B() - b.consider_me = c1 return b.stuff a = self.RPythonAnnotator() s = a.build_types(f, []) - assert isinstance(s, annmodel.SomeInstance) - assert s.can_be_None - assert s.classdef.cls is A + assert s == a.bookkeeper.immutablevalue(42) def test_attr_recursive_getvalue(self): class A: pass From arigo at codespeak.net Fri Jun 17 22:38:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 22:38:43 +0200 (CEST) Subject: [pypy-svn] r13557 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617203843.54E9327B96@code1.codespeak.net> Author: arigo Date: Fri Jun 17 22:38:41 2005 New Revision: 13557 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Replace unbound methods (as they can appear as Constants in flow graphs) with bare functions, like the annotator generally does. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jun 17 22:38:41 2005 @@ -240,6 +240,8 @@ ## assert not shape_stst, "XXX not implemented" def convert_const(self, value): + if isinstance(value, types.MethodType) and value.im_self is None: + value = value.im_func # unbound method -> bare function if value not in self.function_signatures: raise TyperError("%r not in %r" % (value, self.s_pbc.prebuiltinstances)) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Jun 17 22:38:41 2005 @@ -119,3 +119,11 @@ assert res == 6 res = interpret(f, [-1]) assert res == 5 + +def test_unbound_method(): + def f(): + inst = MySubclass() + inst.z = 40 + return MyBase.m(inst, 2) + res = interpret(f, []) + assert res == 42 From arigo at codespeak.net Fri Jun 17 23:01:59 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 23:01:59 +0200 (CEST) Subject: [pypy-svn] r13558 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617210159.6F45527B96@code1.codespeak.net> Author: arigo Date: Fri Jun 17 23:01:57 2005 New Revision: 13558 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/test/test_rbool.py Log: Boolean conversions from/to PyObjects. LLInterp support and tests for cast_bool_to_int. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 17 23:01:57 2005 @@ -210,8 +210,16 @@ return cast_pointer(tp, obj) def op_cast_int_to_float(self, i): - assert isinstance(i, int) + assert type(i) is int return float(i) + + def op_cast_bool_to_int(self, b): + assert type(b) is bool + return int(b) + + def op_cast_bool_to_float(self, b): + assert type(b) is bool + return float(b) # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Fri Jun 17 23:01:57 2005 @@ -1,7 +1,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, pyobjectptr from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, BoolRepr +from pypy.rpython.robject import PyObjRepr debug = False @@ -46,3 +47,32 @@ if debug: print 'explicit cast_bool_to_int' return llops.genop('cast_bool_to_int', [v], resulttype=Signed) return NotImplemented + +pyobj_true = pyobjectptr(True) +pyobj_false = pyobjectptr(False) + +def ll_pyobj2bool(pyobjptr): + if pyobjptr == pyobj_true: + return True + elif pyobjptr == pyobj_false: + return False + else: + raise TypeError + +def ll_bool2pyobj(boolval): + if boolval: + return pyobj_true + else: + return pyobj_false + +class __extend__(pairtype(PyObjRepr, BoolRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_to.lowleveltype == Bool: + return llops.gendirectcall(ll_pyobj2bool, v) + return NotImplemented + +class __extend__(pairtype(BoolRepr, PyObjRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Bool: + return llops.gendirectcall(ll_bool2pyobj, v) + return NotImplemented Modified: pypy/dist/pypy/rpython/test/test_rbool.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rbool.py (original) +++ pypy/dist/pypy/rpython/test/test_rbool.py Fri Jun 17 23:01:57 2005 @@ -1,7 +1,9 @@ from pypy.translator.translator import Translator +from pypy.rpython.lltype import pyobjectptr from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet +from pypy.rpython.test.test_llinterp import interpret class TestSnippet(object): @@ -36,3 +38,13 @@ # XXX TODO test if all binary operations are implemented for opname in annmodel.BINARY_OPERATIONS: print 'BINARY_OPERATIONS:', opname + + def test_bool2int(self): + def f(n): + if n: + n = 2 + return n + res = interpret(f, [False]) + assert res == 0 and res is not False # forced to int by static typing + res = interpret(f, [True]) + assert res == 2 From arigo at codespeak.net Fri Jun 17 23:18:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 23:18:24 +0200 (CEST) Subject: [pypy-svn] r13559 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617211824.3D3FC27B99@code1.codespeak.net> Author: arigo Date: Fri Jun 17 23:18:22 2005 New Revision: 13559 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rstr.py Log: - Constant characters, with test - Removed a view=True in a test - More subtle interpret() to cope with arg values that are characters Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Fri Jun 17 23:18:22 2005 @@ -95,6 +95,11 @@ class __extend__(CharRepr): + def convert_const(self, value): + if not isinstance(value, str) or len(value) != 1: + raise TyperError("not a character: %r" % (value,)) + return value + def rtype_len(_, hop): return hop.inputconst(Signed, 1) Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 17 23:18:22 2005 @@ -5,6 +5,7 @@ from pypy.rpython.llinterp import LLInterpreter, LLException from pypy.translator.translator import Translator from pypy.rpython.lltype import pyobjectptr +from pypy.annotation.model import lltype_to_annotation # switch on logging of interp to show more info on failing tests @@ -37,7 +38,7 @@ return t, typer def interpret(func, values, view=False): - t, typer = gengraph(func, [type(x) for x in values]) + t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) for x in values]) if view: t.view() interp = LLInterpreter(t.flowgraphs, typer) @@ -182,7 +183,7 @@ def test_basic_instantiation(): def f(x): return ExampleClass(x).x - res = interpret(f, [4], view=True) + res = interpret(f, [4]) assert res == 5 Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Fri Jun 17 23:18:22 2005 @@ -1,6 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.test.test_llinterp import interpret def test_simple(): @@ -53,3 +54,11 @@ typer.specialize() #t.view() t.checkgraphs() + +def test_char_constant(): + def dummyfn(s): + return s + '.' + res = interpret(dummyfn, ['x']) + assert len(res.chars) == 2 + assert res.chars[0] == 'x' + assert res.chars[1] == '.' From arigo at codespeak.net Fri Jun 17 23:26:34 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 23:26:34 +0200 (CEST) Subject: [pypy-svn] r13560 - pypy/dist/pypy/annotation Message-ID: <20050617212634.5871827B9C@code1.codespeak.net> Author: arigo Date: Fri Jun 17 23:26:32 2005 New Revision: 13560 Modified: pypy/dist/pypy/annotation/unaryop.py Log: Details. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Fri Jun 17 23:26:32 2005 @@ -236,9 +236,7 @@ def len(lst): s_item = lst.listdef.read_item() if isinstance(s_item, SomeImpossibleValue): - r = SomeInteger(nonneg=True) - r.const = 0 - return r + return immutablevalue(0) return SomeObject.len(lst) def iter(lst): @@ -252,10 +250,8 @@ def len(dct): s_key = dct.dictdef.read_key() s_value = dct.dictdef.read_value() - if isinstance(s_key, SomeImpossibleValue) and isinstance(s_value, SomeImpossibleValue): - r = SomeInteger(nonneg=True) - r.const = 0 - return r + if isinstance(s_key, SomeImpossibleValue) or isinstance(s_value, SomeImpossibleValue): + return immutablevalue(0) return SomeObject.len(dct) def iter(dct): @@ -442,7 +438,8 @@ return ll_to_annotation(v) def len(p): - return ll_to_annotation(len(p.ll_ptrtype._example())) + len(p.ll_ptrtype._example()) # just doing checking + return SomeObject.len(p) def setattr(p, s_attr, s_value): # just doing checking assert s_attr.is_constant(), "getattr on ptr %r with non-constant field-name" % p.ll_ptrtype From cfbolz at codespeak.net Fri Jun 17 23:30:57 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 17 Jun 2005 23:30:57 +0200 (CEST) Subject: [pypy-svn] r13561 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050617213057.1E5F427BA1@code1.codespeak.net> Author: cfbolz Date: Fri Jun 17 23:30:56 2005 New Revision: 13561 Added: pypy/dist/pypy/translator/llvm2/ - copied from r13558, pypy/dist/pypy/translator/llvm/ Log: (cfbolz, hpk) experimental rewrite of genllvm From cfbolz at codespeak.net Fri Jun 17 23:47:43 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 17 Jun 2005 23:47:43 +0200 (CEST) Subject: [pypy-svn] r13562 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050617214743.8734F27BA8@code1.codespeak.net> Author: cfbolz Date: Fri Jun 17 23:47:43 2005 New Revision: 13562 Removed: pypy/dist/pypy/translator/llvm2/ Log: starting anew From arigo at codespeak.net Fri Jun 17 23:56:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 23:56:43 +0200 (CEST) Subject: [pypy-svn] r13563 - pypy/dist/pypy/annotation Message-ID: <20050617215643.EDDAC27BAC@code1.codespeak.net> Author: arigo Date: Fri Jun 17 23:56:42 2005 New Revision: 13563 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: A global cache! then we get ListDefs attached to an old bookkeeper in this global cache! makes new Translators veeery confused... Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Jun 17 23:56:42 2005 @@ -150,7 +150,8 @@ self.seen_mutable = {} self.listdefs = {} # map position_keys to ListDefs self.dictdefs = {} # map position_keys to DictDefs - + self.immutable_cache = {} + # mapping position -> key, prev_result for specializations self.spec_callsite_keys_results = {} @@ -244,8 +245,6 @@ dictdef.generalize_value(s_value) return SomeDict(dictdef) - immutable_cache = {} - def immutablevalue(self, x): """The most precise SomeValue instance that contains the immutable value x.""" From arigo at codespeak.net Fri Jun 17 23:58:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 17 Jun 2005 23:58:18 +0200 (CEST) Subject: [pypy-svn] r13564 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617215818.B0A3D27BB4@code1.codespeak.net> Author: arigo Date: Fri Jun 17 23:58:16 2005 New Revision: 13564 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: Prebuilt lists. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Fri Jun 17 23:58:16 2005 @@ -44,6 +44,7 @@ else: self.item_repr = item_repr self.listitem = listitem + self.list_cache = {} # setup() needs to be called to finish this initialization def setup(self): @@ -54,6 +55,22 @@ ITEMARRAY = GcArray(ITEM) self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY)))) + def convert_const(self, listobj): + if not isinstance(listobj, list): + raise TyperError("expected a list: %r" % (listobj,)) + try: + return self.list_cache[id(listobj)][1] + except KeyError: + self.setup() + result = malloc(self.LIST, immortal=True) + self.list_cache[id(listobj)] = listobj, result + result.items = malloc(self.LIST.items.TO, len(listobj)) + r_item = self.item_repr + for i in range(len(listobj)): + x = listobj[i] + result.items[i] = r_item.convert_const(x) + return result + def rtype_len(self, hop): v_lst, = hop.inputargs(self) return hop.gendirectcall(ll_len, v_lst) Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Fri Jun 17 23:58:16 2005 @@ -4,6 +4,7 @@ from pypy.rpython.rlist import * from pypy.rpython.rslice import ll_newslice from pypy.rpython.rint import signed_repr +from pypy.rpython.test.test_llinterp import interpret def sample_list(): @@ -151,3 +152,14 @@ del l[-1] del l[:] rtype(dummyfn) + +def test_prebuilt_list(): + klist = ['a', 'd', 'z', 'k'] + def dummyfn(n): + return klist[n] + res = interpret(dummyfn, [0]) + assert res == 'a' + res = interpret(dummyfn, [3]) + assert res == 'k' + res = interpret(dummyfn, [-2]) + assert res == 'z' From pedronis at codespeak.net Sat Jun 18 00:01:21 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 00:01:21 +0200 (CEST) Subject: [pypy-svn] r13565 - pypy/dist/pypy/annotation Message-ID: <20050617220121.C29B627BB5@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 00:01:21 2005 New Revision: 13565 Modified: pypy/dist/pypy/annotation/classdef.py Log: when a attrdef gets generalized reflow (and check possibly for method demotion) Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Sat Jun 18 00:01:21 2005 @@ -99,6 +99,23 @@ self.readonly = self.readonly and other.readonly self.read_locations.update(other.read_locations) + def mutated(self, homedef): # reflow from attr read positions + s_newvalue = self.getvalue() + # check for method demotion + if isinstance(s_newvalue, SomePBC): + attr = self.name + meth = False + for func, classdef in s_newvalue.prebuiltinstances.items(): + if isclassdef(classdef): + meth = True + break + if meth and getattr(homedef.cls, attr, None) is None: + self.bookkeeper.warning("demoting method %s to base class %s" % (self.name, homedef)) + + for position in self.read_locations: + self.bookkeeper.annotator.reflowfromposition(position) + + class ClassDef: "Wraps a user class." @@ -150,22 +167,6 @@ value.class_ = cls # remember that this is really a method self.add_source_for_attribute(name, sources.get(name, cls), self) - def attr_mutated(self, homedef, attrdef): # reflow from attr read positions - s_newvalue = attrdef.getvalue() - # check for method demotion - if isinstance(s_newvalue, SomePBC): - attr = attrdef.name - meth = False - for func, classdef in s_newvalue.prebuiltinstances.items(): - if isclassdef(classdef): - meth = True - break - if meth and getattr(homedef.cls, attr, None) is None: - self.bookkeeper.warning("demoting method %s to base class %s" % (attrdef.name, homedef)) - - for position in attrdef.read_locations: - self.bookkeeper.annotator.reflowfromposition(position) - def add_source_for_attribute(self, attr, source, clsdef=None): """Adds information about a constant source for an attribute. """ @@ -179,8 +180,7 @@ # but as an optimization we try to see if the attribute # has really been generalized if attrdef.s_value != s_prev_value: - for position in attrdef.read_locations: - self.bookkeeper.annotator.reflowfromposition(position) + attrdef.mutated(cdef) # reflow from all read positions return else: # remember the source in self.attr_sources @@ -195,7 +195,10 @@ for subdef in self.getallsubdefs(): if attr in subdef.attrs: attrdef = subdef.attrs[attr] + s_prev_value = attrdef.s_value attrdef.add_constant_source(source, clsdef) + if attrdef.s_value != s_prev_value: + attrdef.mutated(subdef) # reflow from all read positions def locate_attribute(self, attr): while True: @@ -288,7 +291,7 @@ newattr.add_constant_source(source, classdef) # reflow from all read positions - self.attr_mutated(self, newattr) + newattr.mutated(self) def generalize_attr(self, attr, s_value=None): # if the attribute exists in a superclass, generalize there, From arigo at codespeak.net Sat Jun 18 00:10:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 00:10:31 +0200 (CEST) Subject: [pypy-svn] r13566 - in pypy/dist/pypy/rpython: . test Message-ID: <20050617221031.3769327B52@code1.codespeak.net> Author: arigo Date: Sat Jun 18 00:10:27 2005 New Revision: 13566 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: Character comparisons. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat Jun 18 00:10:27 2005 @@ -247,6 +247,17 @@ return func(x) """ % locals()).compile() +for opname in ('gt', 'lt', 'ge', 'ne', 'le', 'eq'): + assert opname in opimpls + exec py.code.Source(""" + def char_%(opname)s(x, y): + assert isinstance(x, str) and len(x) == 1 + assert isinstance(y, str) and len(y) == 1 + func = opimpls[%(opname)r] + return func(x, y) + """ % locals()).compile() + + # by default we route all logging messages to nothingness # e.g. tests can then switch on logging to get more help # for failing tests Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jun 18 00:10:27 2005 @@ -34,6 +34,9 @@ CONST_STR_CACHE = WeakValueDictionary() +string_repr = StringRepr() +char_repr = CharRepr() + class __extend__(StringRepr): lowleveltype = Ptr(STR) @@ -112,6 +115,23 @@ return hop.genop('cast_char_to_int', vlist, resulttype=Signed) +class __extend__(pairtype(CharRepr, CharRepr)): + def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq') + def rtype_ne(_, hop): return _rtype_compare_template(hop, 'ne') + def rtype_lt(_, hop): return _rtype_compare_template(hop, 'lt') + def rtype_le(_, hop): return _rtype_compare_template(hop, 'le') + def rtype_gt(_, hop): return _rtype_compare_template(hop, 'gt') + def rtype_ge(_, hop): return _rtype_compare_template(hop, 'ge') + +#Helper functions for comparisons + +def _rtype_compare_template(hop, func): + vlist = hop.inputargs(char_repr, char_repr) + return hop.genop('char_'+func, vlist, resulttype=Bool) + +# +# _________________________ Conversions _________________________ + class __extend__(pairtype(CharRepr, StringRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from == char_repr and r_to == string_repr: @@ -125,13 +145,6 @@ return llops.gendirectcall(ll_stritem_nonneg, v, c_zero) return NotImplemented - -string_repr = StringRepr() -char_repr = CharRepr() - -# -# _________________________ Conversions _________________________ - ##class __extend__(pairtype(PyObjRepr, StringRepr)): ## def convert_from_to((r_from, r_to), v, llops): ## XXX Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sat Jun 18 00:10:27 2005 @@ -62,3 +62,11 @@ assert len(res.chars) == 2 assert res.chars[0] == 'x' assert res.chars[1] == '.' + +def test_char_compare(): + res = interpret(lambda c1, c2: c1 == c2, ['a', 'b']) + assert res is False + res = interpret(lambda c1, c2: c1 == c2, ['a', 'a']) + assert res is True + res = interpret(lambda c1, c2: c1 <= c2, ['z', 'a']) + assert res is False From tismer at codespeak.net Sat Jun 18 00:25:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 18 Jun 2005 00:25:26 +0200 (CEST) Subject: [pypy-svn] r13567 - pypy/dist/pypy/translator/pickle Message-ID: <20050617222526.1396627B49@code1.codespeak.net> Author: tismer Date: Sat Jun 18 00:25:24 2005 New Revision: 13567 Modified: pypy/dist/pypy/translator/pickle/genpickle.py Log: a few refinements and clean-up of dead code. also found that I'm saving some dicts which contain id()s! need to find which objects these are and change their way of pickling. Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Sat Jun 18 00:25:24 2005 @@ -55,6 +55,7 @@ self.picklenames = {} # memoize objects for name in all_feature_names + "new types sys".split(): self.memoize(globals()[name], name) + self.memoize((), '()') self.namespace = NameManager() self.uniquename = self.namespace.uniquename self.namespace.make_reserved_names('None False True') @@ -109,14 +110,15 @@ return 'float("1e10000000000000000000000000000000")' return repr(fl) - def pickle(self, **kwds): + def pickle(self, *args, **kwds): + for obj in args: + self.nameof(obj) for obj in kwds.values(): self.nameof(obj) self.result.update(kwds) def finish(self): - self.nameof(self.result) - self.pickle() + self.pickle(self.result) self.produce('result = %s' % self.nameof(self.result)) if self.writer: self.writer.close() @@ -153,17 +155,6 @@ self.last_progress = txt+' ' # soft space print back+txt, - def spill(self): - self.progress_count += len(self.initcode) - writer = self.writer - if writer: - for line in self.initcode: - writer.write(line+'\n') - del self.initcode[:] - if self.progress_count - self.progress_last >= 1234: - print '%s%d' % (20*'\x08', self.progress_count), - self.progress_last = self.progress_count - def nameof(self, obj): try: try: @@ -398,7 +389,6 @@ self.produce(ini) self.produce('%s.__name__ = %r' % (name, cls.__name__)) self.produce('%s.__module__ = %r' % (name, cls.__module__)) - # squeeze it out, early # self.later(initclassobj()) for line in initclassobj(): self.produce(line) return name From tismer at codespeak.net Sat Jun 18 00:41:49 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 18 Jun 2005 00:41:49 +0200 (CEST) Subject: [pypy-svn] r13568 - pypy/dist/pypy/annotation Message-ID: <20050617224149.6E69D27B62@code1.codespeak.net> Author: tismer Date: Sat Jun 18 00:41:48 2005 New Revision: 13568 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: changed immutable_cache to use Constant() insteadof id(). This supports pickling. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sat Jun 18 00:41:48 2005 @@ -274,20 +274,22 @@ result = SomeFloat() elif tp is list: try: - return self.immutable_cache[id(x)] + key = Constant(x) + return self.immutable_cache[key] except KeyError: result = SomeList(ListDef(self, SomeImpossibleValue())) - self.immutable_cache[id(x)] = result + self.immutable_cache[key] = result for e in x: result.listdef.generalize(self.immutablevalue(e)) elif tp is dict: # exactly a dict try: - return self.immutable_cache[id(x)] + key = Constant(x) + return self.immutable_cache[key] except KeyError: result = SomeDict(DictDef(self, SomeImpossibleValue(), SomeImpossibleValue())) - self.immutable_cache[id(x)] = result + self.immutable_cache[key] = result for ek, ev in x.iteritems(): result.dictdef.generalize_key(self.immutablevalue(ek)) result.dictdef.generalize_value(self.immutablevalue(ev)) From pedronis at codespeak.net Sat Jun 18 01:13:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 01:13:55 +0200 (CEST) Subject: [pypy-svn] r13569 - pypy/dist/pypy/annotation Message-ID: <20050617231355.17A4227B97@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 01:13:54 2005 New Revision: 13569 Modified: pypy/dist/pypy/annotation/model.py Log: oops, equality of SomeLists and SomeDicts was ignoring .const etc, this meant contains succeeding when they should have not and missed reflowing Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sat Jun 18 01:13:54 2005 @@ -204,8 +204,15 @@ def __init__(self, listdef): self.listdef = listdef def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.listdef.same_as(other.listdef)) + if self.__class__ is not other.__class__: + return False + if not self.listdef.same_as(other.listdef): + return False + selfdic = self.__dict__.copy() + otherdic = self.__dict__.copy() + del selfdic['listdef'] + del otherdic['listdef'] + return selfdic == otherdic def can_be_none(self): return True @@ -240,8 +247,15 @@ def __init__(self, dictdef): self.dictdef = dictdef def __eq__(self, other): - return (self.__class__ is other.__class__ and - self.dictdef.same_as(other.dictdef)) + if self.__class__ is not other.__class__: + return False + if not self.dictdef.same_as(other.dictdef): + return False + selfdic = self.__dict__.copy() + otherdic = self.__dict__.copy() + del selfdic['dictdef'] + del otherdic['dictdef'] + return selfdic == otherdic def can_be_none(self): return False From tismer at codespeak.net Sat Jun 18 01:15:36 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 18 Jun 2005 01:15:36 +0200 (CEST) Subject: [pypy-svn] r13570 - pypy/dist/pypy/rpython Message-ID: <20050617231536.11D9927B97@code1.codespeak.net> Author: tismer Date: Sat Jun 18 01:15:34 2005 New Revision: 13570 Modified: pypy/dist/pypy/rpython/rlist.py Log: changed list_cache to use Constant, just in case we want to pickle such things. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Jun 18 01:15:34 2005 @@ -59,11 +59,12 @@ if not isinstance(listobj, list): raise TyperError("expected a list: %r" % (listobj,)) try: - return self.list_cache[id(listobj)][1] + key = Constant(listobj) + return self.list_cache[key][1] except KeyError: self.setup() result = malloc(self.LIST, immortal=True) - self.list_cache[id(listobj)] = listobj, result + self.list_cache[key] = listobj, result result.items = malloc(self.LIST.items.TO, len(listobj)) r_item = self.item_repr for i in range(len(listobj)): From pedronis at codespeak.net Sat Jun 18 01:18:28 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 01:18:28 +0200 (CEST) Subject: [pypy-svn] r13571 - pypy/dist/pypy/annotation Message-ID: <20050617231828.1EF9127B97@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 01:18:27 2005 New Revision: 13571 Modified: pypy/dist/pypy/annotation/model.py Log: oops Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sat Jun 18 01:18:27 2005 @@ -209,7 +209,7 @@ if not self.listdef.same_as(other.listdef): return False selfdic = self.__dict__.copy() - otherdic = self.__dict__.copy() + otherdic = other.__dict__.copy() del selfdic['listdef'] del otherdic['listdef'] return selfdic == otherdic @@ -252,7 +252,7 @@ if not self.dictdef.same_as(other.dictdef): return False selfdic = self.__dict__.copy() - otherdic = self.__dict__.copy() + otherdic = other.__dict__.copy() del selfdic['dictdef'] del otherdic['dictdef'] return selfdic == otherdic From arigo at codespeak.net Sat Jun 18 01:21:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 01:21:43 +0200 (CEST) Subject: [pypy-svn] r13572 - pypy/dist/pypy/translator/test Message-ID: <20050617232143.E661B27B97@code1.codespeak.net> Author: arigo Date: Sat Jun 18 01:21:42 2005 New Revision: 13572 Modified: pypy/dist/pypy/translator/test/test_annrpython.py Log: Test for last fix by Samuele. Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Sat Jun 18 01:21:42 2005 @@ -1342,6 +1342,25 @@ assert isinstance(s_item, annmodel.SomeList) assert s_item.listdef.same_as(s.listdef) + def test_defaults_with_list_or_dict(self): + def fn1(a=[]): + return a + def fn2(a={}): + return a + def f(): + fn1() + fn2() + return fn1([6, 7]), fn2({2: 3, 4: 5}) + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s, annmodel.SomeTuple) + s1, s2 = s.items + assert not s1.is_constant() + assert not s2.is_constant() + assert isinstance(s1.listdef.listitem. s_value, annmodel.SomeInteger) + assert isinstance(s2.dictdef.dictkey. s_value, annmodel.SomeInteger) + assert isinstance(s2.dictdef.dictvalue.s_value, annmodel.SomeInteger) + def g(n): return [0,1,2,n] From pedronis at codespeak.net Sat Jun 18 01:50:40 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 01:50:40 +0200 (CEST) Subject: [pypy-svn] r13573 - pypy/dist/pypy/annotation Message-ID: <20050617235040.CEBBB27B97@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 01:50:40 2005 New Revision: 13573 Modified: pypy/dist/pypy/annotation/binaryop.py Log: union of SomeBuiltin should consider the methodname too Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sat Jun 18 01:50:40 2005 @@ -473,11 +473,11 @@ class __extend__(pairtype(SomeBuiltin, SomeBuiltin)): def union((bltn1, bltn2)): - if bltn1.analyser != bltn2.analyser: + if bltn1.analyser != bltn2.analyser or bltn1.methodname != bltn2.methodname: raise UnionError("merging incompatible builtins == BAD!") else: s_self = unionof(bltn1.s_self, bltn2.s_self) - return SomeBuiltin(bltn1.analyser, s_self) + return SomeBuiltin(bltn1.analyser, s_self, methodname=bltn1.methodname) class __extend__(pairtype(SomePBC, SomePBC)): def union((pbc1, pbc2)): From cfbolz at codespeak.net Sat Jun 18 02:15:26 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 18 Jun 2005 02:15:26 +0200 (CEST) Subject: [pypy-svn] r13574 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050618001526.2B7A527B97@code1.codespeak.net> Author: cfbolz Date: Sat Jun 18 02:15:25 2005 New Revision: 13574 Added: pypy/dist/pypy/translator/llvm2/ (props changed) pypy/dist/pypy/translator/llvm2/__init__.py - copied unchanged from r13561, pypy/dist/pypy/translator/__init__.py pypy/dist/pypy/translator/llvm2/build_llvm_module.py - copied, changed from r13561, pypy/dist/pypy/translator/llvm/build_llvm_module.py pypy/dist/pypy/translator/llvm2/funcgen.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/llvmbc.py - copied, changed from r13561, pypy/dist/pypy/translator/llvm/llvmbc.py pypy/dist/pypy/translator/llvm2/test/ (props changed) pypy/dist/pypy/translator/llvm2/test/__init__.py - copied unchanged from r13561, pypy/dist/pypy/translator/llvm/__init__.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py - copied, changed from r13561, pypy/dist/pypy/translator/llvm/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) a first two-hour hack to produce a cleaner llvm generator the emphasis right now is on hack. Copied: pypy/dist/pypy/translator/llvm2/build_llvm_module.py (from r13561, pypy/dist/pypy/translator/llvm/build_llvm_module.py) ============================================================================== --- pypy/dist/pypy/translator/llvm/build_llvm_module.py (original) +++ pypy/dist/pypy/translator/llvm2/build_llvm_module.py Sat Jun 18 02:15:25 2005 @@ -2,12 +2,11 @@ Build a Python module out of llvmfile and a Pyrex wrapper file. """ -import autopath - import os, sys, inspect, re, exceptions from py.process import cmdexec from py import path +import py from pypy.tool.udir import udir from pypy.translator.pyrex.genpyrex import GenPyrex @@ -22,7 +21,7 @@ OPTIMIZATION_SWITCHES = "-simplifycfg -mem2reg -instcombine -dce -inline" def make_module_from_llvm(llvmfile, pyxfile, optimize=False): - include_dir = autopath.this_dir + include_dir = py.magic.autopath().dirpath() dirpath = llvmfile.dirpath() lastdir = path.local() os.chdir(str(dirpath)) Added: pypy/dist/pypy/translator/llvm2/funcgen.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/funcgen.py Sat Jun 18 02:15:25 2005 @@ -0,0 +1,77 @@ +import py +from pypy.translator.llvm2 import llvmbc +from pypy.rpython import lltype +from pypy.objspace.flow.model import Block, Constant, Variable, flatten, mkentrymap + + +PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} + +log = py.log.Producer('genllvm') + +class FunctionCodeGenerator(object): + def __init__(self, graph, func): + self.graph = graph + self.func = func + + def declaration(self): + returntype = self.getllvmname(self.graph.returnblock.inputargs[0]) + argtypes = self.getllvmtypes(self.graph.startblock.inputargs) + funcname = "%" + self.func.func_name + # XXX varnames + result = "%s %s(%s)" % (returntype, funcname, + ", ".join(argtypes)) + return result + + def implementation(self): + graph = self.graph + log.gen("starting", graph.name) + nextblock = graph.startblock + args = graph.startblock.inputargs + l = [x for x in flatten(graph) if isinstance(x, Block)] + self.block_to_name = {} + for i, block in enumerate(l): + self.block_to_name[block] = "block%s" % i + for block in l: + for line in self.gen_block(block): + yield line + + def gen_block(self, block): + inputargs = self.getllvmnames(block.inputargs) + inputargtypes = self.getllvmtypes(block.inputargs) + yield self.block_to_name[block] + ":" + entrylinks = mkentrymap(self.graph)[block] + for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)): + line = [arg, " = phi ", type_] + for link in entrylinks: + line.append(" [%s, %%%s]" % (self.getllvmname(link.args[i]), + self.block_to_name[link.prevblock])) + yield "".join(line) + if block is self.graph.returnblock: + assert len(inputargs) == 1 + yield "ret %s %s" % (inputargtypes[0], inputargs[0]) + else: + #operations + #branches + assert len(block.exits) == 1 + yield "br label %%%s" % self.block_to_name[block.exits[0].target] + + def getllvmname(self, arg): + if isinstance(arg, Constant): + return str(arg.value).lower() #False --> false + elif isinstance(arg, Variable): + return "%" + str(arg) + else: + raise TypeError, arg + + def getllvmtype(self, arg): + log.type(arg) + return PRIMITIVES_TO_LLVM[arg.concretetype] + + def getllvmnames(self, args): + return [self.getllvmname(arg) for arg in args] + + def getllvmtypes(self, args): + return [self.getllvmtype(arg) for arg in args] + +py.log.setconsumer('genllvm', None) + Added: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jun 18 02:15:25 2005 @@ -0,0 +1,25 @@ +from pypy.translator.llvm2 import build_llvm_module +from pypy.translator.llvm2.funcgen import FunctionCodeGenerator +from pypy.tool.udir import udir +import py + +def genllvm(translator): + func = translator.entrypoint + graph = translator.getflowgraph(func) + targetdir = udir + funcgen = FunctionCodeGenerator(graph, func) + llvmfile = targetdir.join("f.ll") + pyxfile = targetdir.join("f.pyx") + f = llvmfile.open("w") + print >> f, funcgen.declaration() + print >> f, "{" + for line in funcgen.implementation(): + print >> f, line + print >> f, "}" + f.close() + f = pyxfile.open("w") + py.test.skip("no pyrex wrapping support, check back tomorrow") + for line in funcgen.pyrex_wrapper(): + print >> f, line + f.close() + return build_llvm_module.make_module_from_llvm(llvmfile, pyxfile) Copied: pypy/dist/pypy/translator/llvm2/llvmbc.py (from r13561, pypy/dist/pypy/translator/llvm/llvmbc.py) ============================================================================== --- pypy/dist/pypy/translator/llvm/llvmbc.py (original) +++ pypy/dist/pypy/translator/llvm2/llvmbc.py Sat Jun 18 02:15:25 2005 @@ -3,8 +3,6 @@ subclases of LLVMRepr as arguments. """ -import autopath - import exceptions from pypy.objspace.flow.model import Variable, Constant, SpaceOperation Copied: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (from r13561, pypy/dist/pypy/translator/llvm/test/llvmsnippet.py) ============================================================================== --- pypy/dist/pypy/translator/llvm/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jun 18 02:15:25 2005 @@ -1,4 +1,3 @@ -import autopath #function snippets def simple1(): Added: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jun 18 02:15:25 2005 @@ -0,0 +1,28 @@ +from __future__ import division + +import sys +import py + +from pypy.translator.translator import Translator +from pypy.translator.llvm2.genllvm import genllvm +from pypy.translator.llvm2.test import llvmsnippet +from pypy.objspace.flow.model import Constant, Variable + +from pypy.rpython.rtyper import RPythonTyper + +py.log.setconsumer("genllvm", py.log.STDOUT) + +## def setup_module(mod): +## mod.llvm_found = is_on_path("llvm-as") + +def compile_function(function, annotate): + t = Translator(function) + a = t.annotate(annotate) + rt = RPythonTyper(a) + rt.specialize() + a.simplify() + return genllvm(t) + +def test_genllvm(): + f = compile_function(llvmsnippet.simple1, []) + assert f() == 1 From pedronis at codespeak.net Sat Jun 18 02:34:53 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 02:34:53 +0200 (CEST) Subject: [pypy-svn] r13575 - pypy/dist/pypy/translator/test Message-ID: <20050618003453.EC30C27B98@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 02:34:53 2005 New Revision: 13575 Modified: pypy/dist/pypy/translator/test/rpystone.py Log: avoid spurious SomeObject Modified: pypy/dist/pypy/translator/test/rpystone.py ============================================================================== --- pypy/dist/pypy/translator/test/rpystone.py (original) +++ pypy/dist/pypy/translator/test/rpystone.py Sat Jun 18 02:34:53 2005 @@ -65,7 +65,7 @@ class Record: def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0, - IntComp = 0, StringComp = 0): + IntComp = 0, StringComp = ""): self.PtrComp = PtrComp self.Discr = Discr self.EnumComp = EnumComp From pedronis at codespeak.net Sat Jun 18 03:19:27 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 03:19:27 +0200 (CEST) Subject: [pypy-svn] r13576 - pypy/dist/pypy/translator/goal Message-ID: <20050618011927.C210027B98@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 03:19:24 2005 New Revision: 13576 Modified: pypy/dist/pypy/translator/goal/targetrpystone.py pypy/dist/pypy/translator/goal/targetrpystone2.py Log: slightly rerworked rpystone targets to make them more directly approachable for rtyper (avoiding extra string methods and string formatting code for now in rpystone entrypoint&main) Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Sat Jun 18 03:19:24 2005 @@ -8,28 +8,30 @@ # rpystone.setslow(False) def entry_point(): - rpystone.entrypoint(LOOPS) + return rpystone.pystones(LOOPS) # _____ Define and setup target _____ def target(): - global space, mmentrypoints - space = StdObjSpace() - - # ------------------------------------------------------------ - return entry_point, [] # _____ Run translated _____ def run(c_entry_point): - res_w = c_entry_point() - print res_w + res = c_entry_point() + benchtime, stones = res + print "translated rpystone.pystones time for %d passes = %g" % \ + (LOOPS, benchtime) + print "This machine benchmarks at %g translated rpystone pystones/second" % stones print "CPython:" - rpystone.entrypoint(50000) + benchtime, stones = rpystone.pystones(50000) + print "rpystone.pystones time for %d passes = %g" % \ + (50000, benchtime) + print "This machine benchmarks at %g rpystone pystones/second" % stones -if __name__ == "__main__": - # just run it without translation - LOOPS = 50000 - target() - run(entry_point) - \ No newline at end of file + +#if __name__ == "__main__": +# # just run it without translation +# LOOPS = 50000 +# target() +# run(entry_point) + Modified: pypy/dist/pypy/translator/goal/targetrpystone2.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone2.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone2.py Sat Jun 18 03:19:24 2005 @@ -9,28 +9,30 @@ rpystone.setslow(False) def entry_point(): - rpystone.entrypoint(LOOPS) + return rpystone.pystones(LOOPS) # _____ Define and setup target _____ def target(): - global space, mmentrypoints - space = StdObjSpace() - - # ------------------------------------------------------------ - return entry_point, [] # _____ Run translated _____ def run(c_entry_point): - res_w = c_entry_point() - print res_w + res = c_entry_point() + benchtime, stones = res + print "translated rpystone.pystones/fast time for %d passes = %g" % \ + (LOOPS, benchtime) + print "This machine benchmarks at %g translated rpystone/fast pystones/second" % stones print "CPython:" - rpystone.entrypoint(50000) + benchtime, stones = rpystone.pystones(50000) + print "rpystone.pystones/fast time for %d passes = %g" % \ + (50000, benchtime) + print "This machine benchmarks at %g rpystone/fast pystones/second" % stones -if __name__ == "__main__": - # just run it without translation - LOOPS = 50000 - target() - run(entry_point) - \ No newline at end of file + +#if __name__ == "__main__": +# # just run it without translation +# LOOPS = 50000 +# target() +# run(entry_point) + From pedronis at codespeak.net Sat Jun 18 03:58:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sat, 18 Jun 2005 03:58:54 +0200 (CEST) Subject: [pypy-svn] r13577 - in pypy/dist/pypy: rpython translator/c/test Message-ID: <20050618015854.AB12527B97@code1.codespeak.net> Author: pedronis Date: Sat Jun 18 03:58:51 2005 New Revision: 13577 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/translator/c/test/test_genc.py Log: time.clock support in rtyper, by now piggy-backing on CPython one Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 18 03:58:51 2005 @@ -7,6 +7,8 @@ from pypy.rpython.rrange import rtype_builtin_range from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rptr +from pypy.rpython.robject import pyobj_repr +from pypy.rpython.rfloat import float_repr class __extend__(annmodel.SomeBuiltin): @@ -142,3 +144,15 @@ BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask + +import time + +def rtype_time_clock(hop): + c = hop.inputconst(pyobj_repr, time.clock) + v = hop.genop('simple_call', [c], resulttype = pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, float_repr) + +BUILTIN_TYPER[time.clock] = rtype_time_clock + + + Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Sat Jun 18 03:58:51 2005 @@ -182,3 +182,27 @@ f1() mallocs, frees = module.malloc_counters() assert mallocs == frees + +def test_time_clock(): + import time + def does_stuff(): + return time.clock() + t = Translator(does_stuff) + t.annotate([]) + t.specialize() + #t.view() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(does_stuff)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + t0 = time.clock() + t1 = f1() + assert type(t1) is float + t2 = time.clock() + assert t0 <= t1 <= t2 + mallocs, frees = module.malloc_counters() + assert mallocs == frees From cfbolz at codespeak.net Sat Jun 18 12:06:14 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 18 Jun 2005 12:06:14 +0200 (CEST) Subject: [pypy-svn] r13579 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050618100614.B10AB27B72@code1.codespeak.net> Author: cfbolz Date: Sat Jun 18 12:06:14 2005 New Revision: 13579 Modified: pypy/dist/pypy/translator/llvm2/funcgen.py pypy/dist/pypy/translator/llvm2/genllvm.py Log: new llvm passes first trivial test: generation of Pyrex wrapper works Modified: pypy/dist/pypy/translator/llvm2/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcgen.py (original) +++ pypy/dist/pypy/translator/llvm2/funcgen.py Sat Jun 18 12:06:14 2005 @@ -5,6 +5,7 @@ PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} +PRIMITIVES_TO_C = {lltype.Signed: "int"} log = py.log.Producer('genllvm') @@ -12,16 +13,34 @@ def __init__(self, graph, func): self.graph = graph self.func = func + self.funcname = self.func.func_name def declaration(self): - returntype = self.getllvmname(self.graph.returnblock.inputargs[0]) - argtypes = self.getllvmtypes(self.graph.startblock.inputargs) - funcname = "%" + self.func.func_name - # XXX varnames - result = "%s %s(%s)" % (returntype, funcname, - ", ".join(argtypes)) + startblock = self.graph.startblock + returnblock = self.graph.returnblock + inputargs = self.getllvmnames(startblock.inputargs) + inputargtypes = self.getllvmtypes(startblock.inputargs) + returntype = self.getllvmtype(self.graph.returnblock.inputargs[0]) + result = "%s %%%s" % (returntype, self.funcname) + args = ["%s %s" % item for item in zip(inputargs, inputargtypes)] + result += "(%s)" % ", ".join(args) return result + def c_declaration(self): + returntype = PRIMITIVES_TO_C[ + self.graph.returnblock.inputargs[0].concretetype] + inputargtypes = [PRIMITIVES_TO_C[arg.concretetype] + for arg in self.graph.startblock.inputargs] + result = "%s %s(%s)" % (returntype, self.funcname, + ", ".join(inputargtypes)) + return result + + def pyrex_wrapper(self): + inputargs = self.getllvmnames(self.graph.startblock.inputargs) + yield "cdef extern " + self.c_declaration() + yield "def %s_wrapper(%s):" % (self.funcname, ", ".join(inputargs)) + yield " return %s(%s)" % (self.funcname, ", ".join(inputargs)) + def implementation(self): graph = self.graph log.gen("starting", graph.name) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jun 18 12:06:14 2005 @@ -8,18 +8,18 @@ graph = translator.getflowgraph(func) targetdir = udir funcgen = FunctionCodeGenerator(graph, func) - llvmfile = targetdir.join("f.ll") - pyxfile = targetdir.join("f.pyx") - f = llvmfile.open("w") + llvmsource = targetdir.join(func.func_name).new(ext='.ll') + pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+'.pyx') + f = llvmsource.open("w") print >> f, funcgen.declaration() print >> f, "{" for line in funcgen.implementation(): print >> f, line print >> f, "}" f.close() - f = pyxfile.open("w") - py.test.skip("no pyrex wrapping support, check back tomorrow") + f = pyxsource.open("w") for line in funcgen.pyrex_wrapper(): print >> f, line f.close() - return build_llvm_module.make_module_from_llvm(llvmfile, pyxfile) + mod = build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) + return getattr(mod, func.func_name + "_wrapper") From hpk at codespeak.net Sat Jun 18 14:30:42 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 18 Jun 2005 14:30:42 +0200 (CEST) Subject: [pypy-svn] r13580 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050618123042.AC00227B62@code1.codespeak.net> Author: hpk Date: Sat Jun 18 14:30:42 2005 New Revision: 13580 Added: pypy/dist/pypy/translator/llvm2/codewriter.py (contents, props changed) pypy/dist/pypy/translator/llvm2/database.py (contents, props changed) pypy/dist/pypy/translator/llvm2/funcnode.py (contents, props changed) - copied, changed from r13579, pypy/dist/pypy/translator/llvm2/funcgen.py pypy/dist/pypy/translator/llvm2/log.py (contents, props changed) pypy/dist/pypy/translator/llvm2/pyxwrapper.py (contents, props changed) Removed: pypy/dist/pypy/translator/llvm2/funcgen.py pypy/dist/pypy/translator/llvm2/llvmbc.py Modified: pypy/dist/pypy/translator/llvm2/genllvm.py (contents, props changed) pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (props changed) Log: (cfbolz, hpk) refactoring inspired by the new genc but not using 'yield' Added: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jun 18 14:30:42 2005 @@ -0,0 +1,43 @@ +import py +from pypy.translator.llvm2.log import log + +log = log.codewriter + +class CodeWriter(object): + def __init__(self): + self._lines = [] + + def append(self, line): + self._lines.append(line) + log(line) + + def indent(self, line): + self.append(" " + line) + + def label(self, name): + self.append("%s:" % name) + + def declare(self, decl): + self.append("declare %s" %(decl,)) + + def br_uncond(self, blockname): + self.indent("br label %%%s" %(blockname,)) + + def openfunc(self, decl): + self.append("%s {" % (decl,)) + + def closefunc(self): + self.append("}") + + def ret(self, type_, ref): + self.indent("ret %s %s" % (type_, ref)) + + def phi(self, targetvar, type_, refs, blocknames): + assert targetvar.startswith('%') + mergelist = ", ".join( + ["[%s, %%%s]" % item + for item in zip(refs, blocknames)]) + self.indent("%s = phi %s %s" %(targetvar, type_, mergelist)) + + def __str__(self): + return "\n".join(self._lines) Added: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jun 18 14:30:42 2005 @@ -0,0 +1,34 @@ +from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.funcnode import FuncNode + +log = log.database + +class Database(object): + def __init__(self, translator): + self._translator = translator + self.obj2node = {} + self._pendingsetup = [] + + def getgraph(self, func): + return self._translator.flowgraphs[func] + + def getnode(self, obj): + assert hasattr(obj, 'func_code') + try: + return self.obj2node[obj] + except KeyError: + node = FuncNode(self, obj) + self.obj2node[obj] = node + log("add pending setup", node.ref) + self._pendingsetup.append(node) + return node + + def process(self): + if self._pendingsetup: + self._pendingsetup.pop().setup() + return bool(self._pendingsetup) + + def getobjects(self): + return self.obj2node.values() + + Deleted: /pypy/dist/pypy/translator/llvm2/funcgen.py ============================================================================== --- /pypy/dist/pypy/translator/llvm2/funcgen.py Sat Jun 18 14:30:42 2005 +++ (empty file) @@ -1,96 +0,0 @@ -import py -from pypy.translator.llvm2 import llvmbc -from pypy.rpython import lltype -from pypy.objspace.flow.model import Block, Constant, Variable, flatten, mkentrymap - - -PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} -PRIMITIVES_TO_C = {lltype.Signed: "int"} - -log = py.log.Producer('genllvm') - -class FunctionCodeGenerator(object): - def __init__(self, graph, func): - self.graph = graph - self.func = func - self.funcname = self.func.func_name - - def declaration(self): - startblock = self.graph.startblock - returnblock = self.graph.returnblock - inputargs = self.getllvmnames(startblock.inputargs) - inputargtypes = self.getllvmtypes(startblock.inputargs) - returntype = self.getllvmtype(self.graph.returnblock.inputargs[0]) - result = "%s %%%s" % (returntype, self.funcname) - args = ["%s %s" % item for item in zip(inputargs, inputargtypes)] - result += "(%s)" % ", ".join(args) - return result - - def c_declaration(self): - returntype = PRIMITIVES_TO_C[ - self.graph.returnblock.inputargs[0].concretetype] - inputargtypes = [PRIMITIVES_TO_C[arg.concretetype] - for arg in self.graph.startblock.inputargs] - result = "%s %s(%s)" % (returntype, self.funcname, - ", ".join(inputargtypes)) - return result - - def pyrex_wrapper(self): - inputargs = self.getllvmnames(self.graph.startblock.inputargs) - yield "cdef extern " + self.c_declaration() - yield "def %s_wrapper(%s):" % (self.funcname, ", ".join(inputargs)) - yield " return %s(%s)" % (self.funcname, ", ".join(inputargs)) - - def implementation(self): - graph = self.graph - log.gen("starting", graph.name) - nextblock = graph.startblock - args = graph.startblock.inputargs - l = [x for x in flatten(graph) if isinstance(x, Block)] - self.block_to_name = {} - for i, block in enumerate(l): - self.block_to_name[block] = "block%s" % i - for block in l: - for line in self.gen_block(block): - yield line - - def gen_block(self, block): - inputargs = self.getllvmnames(block.inputargs) - inputargtypes = self.getllvmtypes(block.inputargs) - yield self.block_to_name[block] + ":" - entrylinks = mkentrymap(self.graph)[block] - for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)): - line = [arg, " = phi ", type_] - for link in entrylinks: - line.append(" [%s, %%%s]" % (self.getllvmname(link.args[i]), - self.block_to_name[link.prevblock])) - yield "".join(line) - if block is self.graph.returnblock: - assert len(inputargs) == 1 - yield "ret %s %s" % (inputargtypes[0], inputargs[0]) - else: - #operations - #branches - assert len(block.exits) == 1 - yield "br label %%%s" % self.block_to_name[block.exits[0].target] - - def getllvmname(self, arg): - if isinstance(arg, Constant): - return str(arg.value).lower() #False --> false - elif isinstance(arg, Variable): - return "%" + str(arg) - else: - raise TypeError, arg - - def getllvmtype(self, arg): - log.type(arg) - return PRIMITIVES_TO_LLVM[arg.concretetype] - - def getllvmnames(self, args): - return [self.getllvmname(arg) for arg in args] - - def getllvmtypes(self, args): - return [self.getllvmtype(arg) for arg in args] - -py.log.setconsumer('genllvm', None) - Copied: pypy/dist/pypy/translator/llvm2/funcnode.py (from r13579, pypy/dist/pypy/translator/llvm2/funcgen.py) ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcgen.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jun 18 14:30:42 2005 @@ -1,78 +1,70 @@ import py -from pypy.translator.llvm2 import llvmbc from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable, flatten, mkentrymap - +from pypy.translator.llvm2.log import log +log = log.funcnode PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} -PRIMITIVES_TO_C = {lltype.Signed: "int"} -log = py.log.Producer('genllvm') +class FuncNode(object): + _issetup = False -class FunctionCodeGenerator(object): - def __init__(self, graph, func): - self.graph = graph + def __init__(self, db, func): + self.db = db self.func = func - self.funcname = self.func.func_name + self.ref = self.func.func_name + + def setup(self): + self.graph = self.db.getgraph(self.func) + self._issetup = True - def declaration(self): + def getdecl(self): + assert self._issetup startblock = self.graph.startblock returnblock = self.graph.returnblock inputargs = self.getllvmnames(startblock.inputargs) inputargtypes = self.getllvmtypes(startblock.inputargs) returntype = self.getllvmtype(self.graph.returnblock.inputargs[0]) - result = "%s %%%s" % (returntype, self.funcname) + result = "%s %%%s" % (returntype, self.ref) args = ["%s %s" % item for item in zip(inputargs, inputargtypes)] result += "(%s)" % ", ".join(args) - return result + return result - def c_declaration(self): - returntype = PRIMITIVES_TO_C[ - self.graph.returnblock.inputargs[0].concretetype] - inputargtypes = [PRIMITIVES_TO_C[arg.concretetype] - for arg in self.graph.startblock.inputargs] - result = "%s %s(%s)" % (returntype, self.funcname, - ", ".join(inputargtypes)) - return result - - def pyrex_wrapper(self): - inputargs = self.getllvmnames(self.graph.startblock.inputargs) - yield "cdef extern " + self.c_declaration() - yield "def %s_wrapper(%s):" % (self.funcname, ", ".join(inputargs)) - yield " return %s(%s)" % (self.funcname, ", ".join(inputargs)) + def writedecl(self, codewriter): + codewriter.declare(self.getdecl()) - def implementation(self): + def writeimpl(self, codewriter): + assert self._issetup graph = self.graph - log.gen("starting", graph.name) + log.writeimpl(graph.name) + codewriter.openfunc(self.getdecl()) nextblock = graph.startblock args = graph.startblock.inputargs l = [x for x in flatten(graph) if isinstance(x, Block)] self.block_to_name = {} for i, block in enumerate(l): self.block_to_name[block] = "block%s" % i - for block in l: - for line in self.gen_block(block): - yield line + for block in l: + self.write_block(codewriter, block) + codewriter.closefunc() - def gen_block(self, block): + def write_block(self, codewriter, block): inputargs = self.getllvmnames(block.inputargs) inputargtypes = self.getllvmtypes(block.inputargs) - yield self.block_to_name[block] + ":" + codewriter.label(self.block_to_name[block]) entrylinks = mkentrymap(self.graph)[block] for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)): - line = [arg, " = phi ", type_] - for link in entrylinks: - line.append(" [%s, %%%s]" % (self.getllvmname(link.args[i]), - self.block_to_name[link.prevblock])) - yield "".join(line) + names = self.getllvmnames([link.args[i] for link in entrylinks]) + blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] + codewriter.phi(arg, type_, names, blocknames) if block is self.graph.returnblock: assert len(inputargs) == 1 - yield "ret %s %s" % (inputargtypes[0], inputargs[0]) + codewriter.ret(inputargtypes[0], inputargs[0]) else: #operations #branches assert len(block.exits) == 1 - yield "br label %%%s" % self.block_to_name[block.exits[0].target] + codewriter.br_uncond(self.block_to_name[block.exits[0].target]) def getllvmname(self, arg): if isinstance(arg, Constant): @@ -83,7 +75,6 @@ raise TypeError, arg def getllvmtype(self, arg): - log.type(arg) return PRIMITIVES_TO_LLVM[arg.concretetype] def getllvmnames(self, args): @@ -91,6 +82,3 @@ def getllvmtypes(self, args): return [self.getllvmtype(arg) for arg in args] - -py.log.setconsumer('genllvm', None) - Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jun 18 14:30:42 2005 @@ -1,25 +1,35 @@ from pypy.translator.llvm2 import build_llvm_module -from pypy.translator.llvm2.funcgen import FunctionCodeGenerator +from pypy.translator.llvm2.database import Database +from pypy.translator.llvm2.pyxwrapper import write_pyx_wrapper +from pypy.translator.llvm2.log import log + from pypy.tool.udir import udir -import py +from pypy.translator.llvm2.codewriter import CodeWriter def genllvm(translator): func = translator.entrypoint - graph = translator.getflowgraph(func) + + db = Database(translator) + entrynode = db.getnode(func) + + while db.process(): + pass + + codewriter = CodeWriter() + dbobjects = db.getobjects() + for node in dbobjects: + node.writedecl(codewriter) + for node in dbobjects: + node.writeimpl(codewriter) + targetdir = udir - funcgen = FunctionCodeGenerator(graph, func) llvmsource = targetdir.join(func.func_name).new(ext='.ll') + content = str(codewriter) + llvmsource.write(content) + log.source(content) + pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+'.pyx') - f = llvmsource.open("w") - print >> f, funcgen.declaration() - print >> f, "{" - for line in funcgen.implementation(): - print >> f, line - print >> f, "}" - f.close() - f = pyxsource.open("w") - for line in funcgen.pyrex_wrapper(): - print >> f, line - f.close() + write_pyx_wrapper(entrynode, pyxsource) mod = build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) return getattr(mod, func.func_name + "_wrapper") + Deleted: /pypy/dist/pypy/translator/llvm2/llvmbc.py ============================================================================== --- /pypy/dist/pypy/translator/llvm2/llvmbc.py Sat Jun 18 14:30:42 2005 +++ (empty file) @@ -1,340 +0,0 @@ -""" -Some simple classes that output LLVM-assembler. Most functions here take -subclases of LLVMRepr as arguments. -""" - -import exceptions - -from pypy.objspace.flow.model import Variable, Constant, SpaceOperation - -class LLVMError(Exception): - pass - -class Function(object): - def __init__(self, funcdef, startbb): - self.funcdef = funcdef - self.startbb = startbb - self.blocks = {} - self.blocklist = [] - - def basic_block(self, block): - assert block.label != self.startbb.label, \ - "Block has same label as startblock!" - if block.label in self.blocks: - raise ValueError, "Can't add another block with the same name." - self.blocks[block.label] = block - self.blocklist.append(block) - - def __str__(self): - r = [self.funcdef, " {\n", str(self.startbb)] - r += [str(bb) for bb in self.blocklist] + ["}\n\n"] - return "".join(r) - -class BasicBlock(object): - def __init__(self, label): - self.label = label - self.instructions = [] - self.closed = False - #True after the first non-phi instruction has been added - self.phi_done = False - - def instruction(self, instr): #should not be used - self.instructions.append(instr) - - #Terminator instuctions - def ret(self, l_value): - self.phi_done = True - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - self.instructions.append("ret %s" % l_value.typed_name()) - - def uncond_branch(self, block): - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - self.phi_done = True - self.instructions.append("br label " + block) - - def cond_branch(self, l_switch, blocktrue, blockfalse): - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - self.phi_done = True - s = "br %s, label %s, label %s" % (l_switch.typed_name(), - blocktrue, blockfalse) - self.instructions.append(s) - - def switch(self, l_switch, default, rest=None): - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - self.phi_done = True - s = "switch %s, label %s " % (l_switch.typed_name(), default) - if rest is not None: - s += "[" + "\n\t".join(["%s %s, label %s" % (l_switch.llvmtype(), - c, l) - for c, l in rest]) + "]" - self.instructions.append(s) - - def unwind(self): - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - self.phi_done = True - self.instructions.append("unwind") - - #Arithmetic instructions - def binary_instruction(self, instr, l_target, l_a, l_b): - self.phi_done = True - assert l_a.llvmtype() == l_b.llvmtype() - s = "%s = %s %s, %s" % (l_target.llvmname(), instr, - l_a.typed_name(), l_b.llvmname()) - self.instructions.append(s) - - #Shift instructions - def shift_instruction(self, instr, l_target, l_a, l_b): - self.phi_done = True - # XXX hack: just assume that l_b is of the appropriate type - s = "%s = %s %s, ubyte %s" % (l_target.llvmname(), instr, - l_a.typed_name(), l_b.llvmname()) - self.instructions.append(s) - - #Memory access instructions - def load(self, l_target, l_pter): - self.phi_done = True - s = "%s = load %s %s" % (l_target.llvmname(), l_pter.llvmtype(), - l_pter.llvmname()) - self.instructions.append(s) - - def store(self, l_value, l_pter): - self.phi_done = True - s = "store %s, %s" % (l_value.typed_name(), l_pter.typed_name()) - self.instructions.append(s) - - def malloc(self, l_target, l_type=None, num=1): - self.phi_done = True - if l_type is None: - #XXX assuming that l_target.llvmtype() ends with an "*" here - s = "%s = malloc %s" % (l_target.llvmname(), - l_target.llvmtype()[:-1]) - else: - s = "%s = malloc %s" % (l_target.llvmname(), - l_type.typename_wo_pointer()) - if num > 1: - s += ", uint %i" % num - self.instructions.append(s) - - def getelementptr(self, l_target, l_ptr, adresses): - self.phi_done = True - s = "%s = getelementptr %s, " % (l_target.llvmname(), - l_ptr.typed_name()) - adr = [] - for a in adresses: - try: - t = a.typed_name() - adr.append(t) - except AttributeError: - if a >= 0: - adr.append("uint %i" % a) - else: - adr.append("int %i" % a) - self.instructions.append(s + ", ".join(adr)) - - #Function calls - def spaceop(self, l_target, opname, l_args): - self.phi_done = True - if l_target.llvmtype() == "void": - s = "call void %%std.%s(" % opname - else: - s = "%s = call %s %%std.%s(" % (l_target.llvmname(), - l_target.llvmtype(), opname) - self.instructions.append(s + - ", ".join([a.typed_name() for a in l_args]) + ")") - - def call(self, l_target, l_func, l_args): - self.phi_done = True - if l_target.llvmtype() == "void": - s = "call void %s(" % l_func.llvmname() - elif l_target.llvmtype() == "%std.void": - s = "call %std.void %s(" % l_func.llvmname() - else: - s = "%s = call %s %s(" % (l_target.llvmname(), l_target.llvmtype(), - l_func.llvmname()) - self.instructions.append(s + - ", ".join([a.typed_name() for a in l_args]) + ")") - - def call_void(self, l_func, l_args): - self.phi_done = True - s = "call %s %s(" % (l_func.rettype(), l_func.llvmname()) - self.instructions.append(s + - ", ".join([a.typed_name() for a in l_args]) + ")") - - #Other instructions - def select(self, l_arg, l_select, l_v1, l_v2): - self.phi_done = True - s = "%s = select bool %s, %s, %s" - s = s % (l_arg.llvmname(), l_select.llvmname(), l_v1.typed_name(), - l_v2.typed_name()) - self.instructions.append(s) - - def phi(self, l_arg, l_values, blocks): - assert len(l_values) == len(blocks) - if self.phi_done: - raise LLVMError, "Can't create phi node." - vars_string = [] - fd = "" + "%s = phi %s " % (l_arg.llvmname(), l_arg.llvmtype()) - fd += ", ".join(["[%s, %s]" % (v.llvmname(), b) - for v, b in zip(l_values, blocks)]) - self.instructions.append(fd) - - def cast(self, l_target, l_value): - self.phi_done = True - s = "%s = cast %s to %s" % (l_target.llvmname(), l_value.typed_name(), - l_target.llvmtype()) - self.instructions.append(s) - - #Non-instructions methods - def __str__(self): - s = [self.label + ":\n"] - for ins in self.instructions: - s += ["\t%s\n" % ins] - if not self.closed: - print "".join(s) - raise LLVMError, "Block lacks a terminator instruction." - return "".join(s) - -class TryBasicBlock(BasicBlock): - """A basic block for which the last operation is turned into an invoke. -Used for exception handling.""" - def __init__(self, label, regularblock, exceptblock): - BasicBlock.__init__(self, label) - self.exceptblock = exceptblock - self.regularblock = regularblock - self.pending_call = None - self.pending_args = None - #This is set to True before the last operation - #XXX Find a more elegant solution for this - self.last_op = False - - def spaceop(self, l_target, opname, l_args): - if not self.last_op: - return BasicBlock.spaceop(self, l_target, opname, l_args) - self.phi_done = True - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - if l_target.llvmtype() == "void": - s = "invoke void %%std.%s.exc(" % opname - else: - s = "%s = invoke %s %%std.%s.exc(" % (l_target.llvmname(), - l_target.llvmtype(), opname) - s += ", ".join([a.typed_name() for a in l_args]) + ")" - s += "\n\t\tto label %%%s\n\t\texcept label %%%s" % \ - (self.regularblock, self.exceptblock) - self.instructions.append(s) - - def call(self, l_target, l_func, l_args): - if not self.last_op: - return BasicBlock.call(self, l_target, l_func, l_args) - self.phi_done = True - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - if l_target.llvmtype() == "void": - s = "invoke void %s(" % l_func.llvmname() - elif l_target.llvmtype() == "%std.void": - s = "invoke %std.void %s(" % l_func.llvmname() - else: - s = "%s = invoke %s %s(" % (l_target.llvmname(), - l_target.llvmtype(), l_func.llvmname()) - s += ", ".join([a.typed_name() for a in l_args]) + ")" - s += "\n\t\tto label %%%s\n\t\texcept label %%%s" % \ - (self.regularblock, self.exceptblock) - self.instructions.append(s) - - def call_void(self, l_func, l_args): - if not self.last_op: - return BasicBlock.call_void(self, l_func, l_args) - self.phi_done = True - if self.closed: - raise LLVMError, "Can't add second terminator instruction." - self.closed = True - s = "invoke %s %s(" % (l_func.rettype(), l_func.llvmname()) - s += ", ".join([a.typed_name() for a in l_args]) + ")" - s += "\n\t\tto label %%%s\n\t\texcept label %%%s" % \ - (self.regularblock, self.exceptblock) - self.instructions.append(s) - -class TraceBasicBlock(BasicBlock): - """A basic block that will make it possible to create a sort of -'tracebacks' at some point in the future: Every call is turned into an invoke. -Then the corresponding exceptblock will have to append a string to a global -traceback object.""" - def __init__(self, label, regularblock, exceptblock): - self.label = label - self.exceptblock = exceptblock - self.regularblock = regularblock - self.llvmblocks = [] - self.instructions = [] - self.finalized = False - - def spaceop(self, l_target, opname, l_args): - if l_target.llvmtype() == "void": - s = "invoke void %%std.%s.exc(" % opname - else: - s = "%s = invoke %s %%std.%s.exc(" % (l_target.llvmname(), - l_target.llvmtype(), opname) - s += ", ".join([a.typed_name() for a in l_args]) + ")" - s += "\n\t\tto label %%%s.%i\n\t\texcept label %%%s" % \ - (self.label, len(self.llvmblocks), self.exceptblock) - self.instructions.append(s) - self.llvmblocks.append(self.instructions) - self.instructions = [] - - def invoke(self, l_target, l_func, l_args): - if l_target.llvmtype() == "void": - s = "invoke void %s(" % l_func.llvmname() - elif l_target.llvmtype() == "%std.void": - s = "invoke %std.void %s(" % l_func.llvmname() - else: - s = "%s = invoke %s %s(" % (l_target.llvmname(), - l_target.llvmtype(), l_func.llvmname()) - s += ", ".join([a.typed_name() for a in l_args]) + ")" - s += "\n\t\tto label %%%s.%i\n\t\texcept label %%%s" % \ - (self.label, len(self.llvmblocks), self.exceptblock) - self.instructions.append(s) - self.llvmblocks.append(self.instructions) - self.instructions = [] - - call = invoke - - def invoke_void(self, l_func, l_args): - s = "invoke %s %s(" % (l_func.rettype(), l_func.llvmname()) - s += ", ".join([a.typed_name() for a in l_args]) + ")" - s += "\n\t\tto label %%%s.%i\n\t\texcept label %%%s" % \ - (self.label, len(self.llvmblocks), self.exceptblock) - self.instructions.append(s) - self.llvmblocks.append(self.instructions) - self.instructions = [] - - call_void = invoke_void - - def __str__(self): - if not self.finalized: - if len(self.instructions) != 0: - self.llvmblocks.append(self.instructions) - self.instructions = [] - self.finalized = True - s = [] - for i, instrs in enumerate(self.llvmblocks): - if i == 0: - label = self.label - else: - label = "%s.%i" % (self.label, i - 1) - s.append(label + ":\n") - for ins in instrs: - s.append("\t%s\n" % ins) - return "".join(s) - - Added: pypy/dist/pypy/translator/llvm2/log.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/log.py Sat Jun 18 14:30:42 2005 @@ -0,0 +1,4 @@ +import py +log = py.log.Producer('genllvm') +py.log.setconsumer('genllvm', None) + Added: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sat Jun 18 14:30:42 2005 @@ -0,0 +1,25 @@ +from pypy.translator.llvm2.log import log +from pypy.rpython import lltype +log = log.pyrex + +PRIMITIVES_TO_C = {lltype.Signed: "int"} + +def write_pyx_wrapper(funcgen, targetpath): + def c_declaration(): + returntype = PRIMITIVES_TO_C[ + funcgen.graph.returnblock.inputargs[0].concretetype] + inputargtypes = [PRIMITIVES_TO_C[arg.concretetype] + for arg in funcgen.graph.startblock.inputargs] + result = "%s %s(%s)" % (returntype, funcgen.ref, + ", ".join(inputargtypes)) + return result + lines = [] + append = lines.append + inputargs = funcgen.getllvmnames(funcgen.graph.startblock.inputargs) + append("cdef extern " + c_declaration()) + append("") + append("def %s_wrapper(%s):" % (funcgen.ref, ", ".join(inputargs))) + append(" return %s(%s)" % (funcgen.ref, ", ".join(inputargs))) + append("") + targetpath.write("\n".join(lines)) + From cfbolz at codespeak.net Sat Jun 18 16:39:10 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 18 Jun 2005 16:39:10 +0200 (CEST) Subject: [pypy-svn] r13581 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050618143910.80ACA27B57@code1.codespeak.net> Author: cfbolz Date: Sat Jun 18 16:39:10 2005 New Revision: 13581 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py Log: moved some methods to database Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jun 18 16:39:10 2005 @@ -1,8 +1,12 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.funcnode import FuncNode +from pypy.rpython import lltype +from pypy.objspace.flow.model import Block, Constant, Variable log = log.database +PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} + class Database(object): def __init__(self, translator): self._translator = translator @@ -31,4 +35,21 @@ def getobjects(self): return self.obj2node.values() - + def getref(self, arg): + if isinstance(arg, Constant): + if isinstance(arg.concretetype, lltype.Primitive): + return str(arg.value).lower() #False --> false + raise TypeError, "can't handle the Constant %s" % arg + elif isinstance(arg, Variable): + return "%" + str(arg) + else: + raise TypeError, arg + + def gettyperef(self, arg): + return PRIMITIVES_TO_LLVM[arg.concretetype] + + def multi_getref(self, args): + return [self.getref(arg) for arg in args] + + def multi_gettyperef(self, args): + return [self.gettyperef(arg) for arg in args] Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jun 18 16:39:10 2005 @@ -1,11 +1,8 @@ import py -from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable, flatten, mkentrymap from pypy.translator.llvm2.log import log log = log.funcnode -PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} - class FuncNode(object): _issetup = False @@ -22,9 +19,9 @@ assert self._issetup startblock = self.graph.startblock returnblock = self.graph.returnblock - inputargs = self.getllvmnames(startblock.inputargs) - inputargtypes = self.getllvmtypes(startblock.inputargs) - returntype = self.getllvmtype(self.graph.returnblock.inputargs[0]) + inputargs = self.db.multi_getref(startblock.inputargs) + inputargtypes = self.db.multi_gettyperef(startblock.inputargs) + returntype = self.db.gettyperef(self.graph.returnblock.inputargs[0]) result = "%s %%%s" % (returntype, self.ref) args = ["%s %s" % item for item in zip(inputargs, inputargtypes)] result += "(%s)" % ", ".join(args) @@ -49,12 +46,12 @@ codewriter.closefunc() def write_block(self, codewriter, block): - inputargs = self.getllvmnames(block.inputargs) - inputargtypes = self.getllvmtypes(block.inputargs) + inputargs = self.db.multi_getref(block.inputargs) + inputargtypes = self.db.multi_gettyperef(block.inputargs) codewriter.label(self.block_to_name[block]) entrylinks = mkentrymap(self.graph)[block] for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)): - names = self.getllvmnames([link.args[i] for link in entrylinks]) + names = self.db.multi_getref([link.args[i] for link in entrylinks]) blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] codewriter.phi(arg, type_, names, blocknames) if block is self.graph.returnblock: @@ -66,19 +63,3 @@ assert len(block.exits) == 1 codewriter.br_uncond(self.block_to_name[block.exits[0].target]) - def getllvmname(self, arg): - if isinstance(arg, Constant): - return str(arg.value).lower() #False --> false - elif isinstance(arg, Variable): - return "%" + str(arg) - else: - raise TypeError, arg - - def getllvmtype(self, arg): - return PRIMITIVES_TO_LLVM[arg.concretetype] - - def getllvmnames(self, args): - return [self.getllvmname(arg) for arg in args] - - def getllvmtypes(self, args): - return [self.getllvmtype(arg) for arg in args] Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sat Jun 18 16:39:10 2005 @@ -15,7 +15,7 @@ return result lines = [] append = lines.append - inputargs = funcgen.getllvmnames(funcgen.graph.startblock.inputargs) + inputargs = funcgen.db.multi_getref(funcgen.graph.startblock.inputargs) append("cdef extern " + c_declaration()) append("") append("def %s_wrapper(%s):" % (funcgen.ref, ", ".join(inputargs))) From arigo at codespeak.net Sat Jun 18 18:24:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 18:24:58 +0200 (CEST) Subject: [pypy-svn] r13582 - pypy/dist/pypy/documentation Message-ID: <20050618162458.EF15427B53@code1.codespeak.net> Author: arigo Date: Sat Jun 18 18:24:57 2005 New Revision: 13582 Modified: pypy/dist/pypy/documentation/misc.txt Log: A _csv replacement could be based on this project. Modified: pypy/dist/pypy/documentation/misc.txt ============================================================================== --- pypy/dist/pypy/documentation/misc.txt (original) +++ pypy/dist/pypy/documentation/misc.txt Sat Jun 18 18:24:57 2005 @@ -138,7 +138,7 @@ _codecsmodule -_csv - already exists? +_csv - already exists? See http://python-dsv.sourceforge.net/ _heapqmodule - already exists From cfbolz at codespeak.net Sat Jun 18 18:28:30 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 18 Jun 2005 18:28:30 +0200 (CEST) Subject: [pypy-svn] r13583 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050618162830.4D67427B54@code1.codespeak.net> Author: cfbolz Date: Sat Jun 18 18:28:29 2005 New Revision: 13583 Added: pypy/dist/pypy/translator/llvm2/cfgtransform.py Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz,hpk) - added flow graph transform remove_same_as, because same_as is incompatible with SSA in LLVM. - refactored and extended functions (branches work) Added: pypy/dist/pypy/translator/llvm2/cfgtransform.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/cfgtransform.py Sat Jun 18 18:28:29 2005 @@ -0,0 +1,34 @@ +from pypy.objspace.flow.model import traverse, Block, checkgraph + +def remove_same_as(graph): + same_as_positions = [] + def visit(node): + if isinstance(node, Block): + for i, op in enumerate(node.operations): + if op.opname == 'same_as': + same_as_positions.append((node, i)) + traverse(visit, graph) + while same_as_positions: + block, index = same_as_positions.pop() + same_as_result = block.operations[index].result + same_as_arg = block.operations[index].args[0] + # replace the new variable (same_as_result) with the old variable + # (from all subsequent positions) + for op in block.operations[index:]: + for i in range(len(op.args)): + if op.args[i] == same_as_result: + op.args[i] = same_as_arg + for link in block.exits: + for i in range(len(link.args)): + if link.args[i] == same_as_result: + link.args[i] = same_as_arg + if block.exitswitch == same_as_result: + block.exitswitch = same_as_arg + block.operations[index] = None + + # remove all same_as operations + def visit(node): + if isinstance(node, Block) and node.operations: + node.operations[:] = filter(None, node.operations) + traverse(visit, graph) + checkgraph(graph) Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jun 18 18:28:29 2005 @@ -23,6 +23,10 @@ def br_uncond(self, blockname): self.indent("br label %%%s" %(blockname,)) + def br(self, switch, blockname_false, blockname_true): + self.indent("br bool %s, label %%%s, label %%%s" + % (switch, blockname_true, blockname_false)) + def openfunc(self, decl): self.append("%s {" % (decl,)) @@ -34,6 +38,7 @@ def phi(self, targetvar, type_, refs, blocknames): assert targetvar.startswith('%') + assert refs and len(refs) == len(blocknames), "phi node requires blocks" mergelist = ", ".join( ["[%s, %%%s]" % item for item in zip(refs, blocknames)]) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jun 18 18:28:29 2005 @@ -2,10 +2,13 @@ from pypy.translator.llvm2.funcnode import FuncNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable +from pypy.translator.unsimplify import remove_double_links +from pypy.translator.llvm2.cfgtransform import remove_same_as log = log.database -PRIMITIVES_TO_LLVM = {lltype.Signed: "int"} +PRIMITIVES_TO_LLVM = {lltype.Signed: "int", + lltype.Bool: "bool"} class Database(object): def __init__(self, translator): @@ -13,9 +16,12 @@ self.obj2node = {} self._pendingsetup = [] - def getgraph(self, func): - return self._translator.flowgraphs[func] - + def getgraph(self, func): + graph = self._translator.flowgraphs[func] + remove_same_as(graph) + remove_double_links(self._translator, graph) + return graph + def getnode(self, obj): assert hasattr(obj, 'func_code') try: @@ -25,7 +31,7 @@ self.obj2node[obj] = node log("add pending setup", node.ref) self._pendingsetup.append(node) - return node + return node def process(self): if self._pendingsetup: Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jun 18 18:28:29 2005 @@ -23,7 +23,7 @@ inputargtypes = self.db.multi_gettyperef(startblock.inputargs) returntype = self.db.gettyperef(self.graph.returnblock.inputargs[0]) result = "%s %%%s" % (returntype, self.ref) - args = ["%s %s" % item for item in zip(inputargs, inputargtypes)] + args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] result += "(%s)" % ", ".join(args) return result @@ -42,24 +42,60 @@ for i, block in enumerate(l): self.block_to_name[block] = "block%s" % i for block in l: - self.write_block(codewriter, block) - codewriter.closefunc() + codewriter.label(self.block_to_name[block]) + for name in 'startblock returnblock exceptblock'.split(): + if block is getattr(graph, name): + getattr(self, 'write_' + name)(codewriter, block) + break + else: + self.write_block(codewriter, block) + codewriter.closefunc() def write_block(self, codewriter, block): + self.write_block_phi_nodes(codewriter, block) + self.write_block_operations(codewriter, block) + self.write_block_branches(codewriter, block) + + + def write_block_phi_nodes(self, codewriter, block): + entrylinks = mkentrymap(self.graph)[block] + entrylinks = [x for x in entrylinks if x.prevblock is not None] inputargs = self.db.multi_getref(block.inputargs) inputargtypes = self.db.multi_gettyperef(block.inputargs) - codewriter.label(self.block_to_name[block]) - entrylinks = mkentrymap(self.graph)[block] for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)): names = self.db.multi_getref([link.args[i] for link in entrylinks]) - blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] + blocknames = [self.block_to_name[link.prevblock] + for link in entrylinks] codewriter.phi(arg, type_, names, blocknames) - if block is self.graph.returnblock: - assert len(inputargs) == 1 - codewriter.ret(inputargtypes[0], inputargs[0]) - else: - #operations - #branches - assert len(block.exits) == 1 + + def write_block_branches(self, codewriter, block): + if len(block.exits) == 1: codewriter.br_uncond(self.block_to_name[block.exits[0].target]) + elif len(block.exits) == 2: + switch = self.db.getref(block.exitswitch) + codewriter.br(switch, self.block_to_name[block.exits[0].target], + self.block_to_name[block.exits[1].target]) + + def write_block_operations(self, codewriter, block): + opwriter = OpWriter(self.db, codewriter) + for op in block.operations: + meth = getattr(opwriter, op.opname, None) + assert meth is not None, "operation %r not found" %(op.opname,) + meth(op) + + + def write_startblock(self, codewriter, block): + self.write_block_operations(codewriter, block) + self.write_block_branches(codewriter, block) + + def write_returnblock(self, codewriter, block): + assert len(block.inputargs) == 1 + self.write_block_phi_nodes(codewriter, block) + inputargtype = self.db.gettyperef(block.inputargs[0]) + inputarg = self.db.getref(block.inputargs[0]) + codewriter.ret(inputargtype, inputarg) +class OpWriter(object): + def __init__(self, db, codewriter): + self.db = db + self.codewriter = codewriter Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sat Jun 18 18:28:29 2005 @@ -2,7 +2,8 @@ from pypy.rpython import lltype log = log.pyrex -PRIMITIVES_TO_C = {lltype.Signed: "int"} +PRIMITIVES_TO_C = {lltype.Signed: "int", + lltype.Bool: "char"} def write_pyx_wrapper(funcgen, targetpath): def c_declaration(): @@ -16,10 +17,11 @@ lines = [] append = lines.append inputargs = funcgen.db.multi_getref(funcgen.graph.startblock.inputargs) + inputargs = [x.strip("%") for x in inputargs] append("cdef extern " + c_declaration()) append("") - append("def %s_wrapper(%s):" % (funcgen.ref, ", ".join(inputargs))) - append(" return %s(%s)" % (funcgen.ref, ", ".join(inputargs))) + append("def %s_wrapper(%s):" % (funcgen.ref.strip("%"), ", ".join(inputargs))) + append(" return %s(%s)" % (funcgen.ref.strip("%"), ", ".join(inputargs))) append("") targetpath.write("\n".join(lines)) - + Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jun 18 18:28:29 2005 @@ -1,7 +1,5 @@ #function snippets -def simple1(): - return 1 def simple2(): return False @@ -13,12 +11,6 @@ def simple4(): return 3 + simple1() -def simple5(b): - if b: - x = 12 - else: - x = 13 - return x def simple6(): simple4() Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jun 18 18:28:29 2005 @@ -23,6 +23,20 @@ a.simplify() return genllvm(t) -def test_genllvm(): - f = compile_function(llvmsnippet.simple1, []) + +def test_return1(): + def simple1(): + return 1 + f = compile_function(simple1, []) assert f() == 1 + +def test_simple_branching(): + def simple5(b): + if b: + x = 12 + else: + x = 13 + return x + f = compile_function(simple5, [bool]) + assert f(True) == 12 + assert f(False) == 13 From hpk at codespeak.net Sat Jun 18 18:40:36 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 18 Jun 2005 18:40:36 +0200 (CEST) Subject: [pypy-svn] r13584 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050618164036.AB71F27B59@code1.codespeak.net> Author: hpk Date: Sat Jun 18 18:40:36 2005 New Revision: 13584 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) added some integer operations and tests Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jun 18 18:40:36 2005 @@ -44,5 +44,8 @@ for item in zip(refs, blocknames)]) self.indent("%s = phi %s %s" %(targetvar, type_, mergelist)) + def binaryop(self, name, targetvar, type_, ref1, ref2): + self.indent("%s = %s %s %s, %s" % (targetvar, name, type_, ref1, ref2)) + def __str__(self): return "\n".join(self._lines) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jun 18 18:40:36 2005 @@ -99,3 +99,23 @@ def __init__(self, db, codewriter): self.db = db self.codewriter = codewriter + + def binaryop(self, name, op): + assert len(op.args) == 2 + self.codewriter.binaryop(name, + self.db.getref(op.result), + self.db.gettyperef(op.result), + self.db.getref(op.args[0]), + self.db.getref(op.args[1])) + def int_mul(self, op): + self.binaryop('mul', op) + + def int_floordiv(self, op): + self.binaryop('div', op) + + def int_add(self, op): + self.binaryop('add', op) + + def int_sub(self, op): + self.binaryop('sub', op) + Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jun 18 18:40:36 2005 @@ -40,3 +40,11 @@ f = compile_function(simple5, [bool]) assert f(True) == 12 assert f(False) == 13 + +def test_int_ops(): + def ops(i): + return i + 1 * i // i - 1 + f = compile_function(ops, [int]) + assert f(1) == 1 + assert f(2) == 2 + From arigo at codespeak.net Sat Jun 18 20:41:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 20:41:55 +0200 (CEST) Subject: [pypy-svn] r13585 - in pypy/dist/pypy/rpython: . test Message-ID: <20050618184155.473E827B52@code1.codespeak.net> Author: arigo Date: Sat Jun 18 20:41:53 2005 New Revision: 13585 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: simple_call adding default arguments. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 18 20:41:53 2005 @@ -250,7 +250,25 @@ def rtype_simple_call(self, hop): f, rinputs, rresult = self.function_signatures.itervalues().next() - vlist = hop.inputargs(self, *rinputs) + defaultclist = [] + if len(rinputs) != hop.nb_args-1: # argument count mismatch + assert not getattr(f._obj.graph, 'normalized_for_calls', False), ( + "normalization bug") + assert len(self.function_signatures) == 1, "normalization bug too" + func, = self.function_signatures.keys() + defaults = func.func_defaults or () + if len(rinputs) - len(defaults) <= hop.nb_args-1 <= len(rinputs): + rinputs = list(rinputs) + defaults = list(defaults) + while len(rinputs) != hop.nb_args-1: + c = hop.inputconst(rinputs.pop(), defaults.pop()) + defaultclist.insert(0, c) + else: + if hop.nb_args-1 > len(rinputs): + raise RTyperError("too many arguments in function call") + else: + raise RTyperError("not enough arguments in function call") + vlist = hop.inputargs(self, *rinputs) + defaultclist if self.lowleveltype == Void: assert len(self.function_signatures) == 1 vlist[0] = hop.inputconst(typeOf(f), f) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sat Jun 18 20:41:53 2005 @@ -127,3 +127,19 @@ return MyBase.m(inst, 2) res = interpret(f, []) assert res == 42 + +def test_call_defaults(): + def g(a, b=2, c=3): + return a+b+c + def f1(): + return g(1) + def f2(): + return g(1, 10) + def f3(): + return g(1, 10, 100) + res = interpret(f1, []) + assert res == 1+2+3 + res = interpret(f2, []) + assert res == 1+10+3 + res = interpret(f3, []) + assert res == 1+10+100 From arigo at codespeak.net Sat Jun 18 20:56:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 20:56:13 +0200 (CEST) Subject: [pypy-svn] r13586 - pypy/dist/pypy/translator/goal Message-ID: <20050618185613.9A96D27B52@code1.codespeak.net> Author: arigo Date: Sat Jun 18 20:56:12 2005 New Revision: 13586 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: We need the rtyper to get attached to the translator, otherwise some features of genc won't work. Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sat Jun 18 20:56:12 2005 @@ -106,8 +106,7 @@ a.simplify() if a and not options['-no-t']: print 'Specializing...' - typer = RPythonTyper(a) - typer.specialize() + t.specialize() t.frozen = True # cannot freeze if we don't have annotations if not options['-no-mark-some-objects']: options['-no-mark-some-objects'] = True # Do not do this again From arigo at codespeak.net Sat Jun 18 21:07:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 21:07:32 +0200 (CEST) Subject: [pypy-svn] r13587 - pypy/dist/pypy/translator/c Message-ID: <20050618190732.5F76827B53@code1.codespeak.net> Author: arigo Date: Sat Jun 18 21:07:29 2005 New Revision: 13587 Modified: pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/float_include.h pypy/dist/pypy/translator/c/node.py Log: Progress! targetrpystone2 appears to run. More inspection is needed to be sure that it really does what it's supposed to. Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sat Jun 18 21:07:29 2005 @@ -112,6 +112,8 @@ def cincrefstmt(self, expr, T): if isinstance(T, Ptr) and T._needsgc(): + if expr == 'NULL': # hum + return '' if T.TO == PyObject: return 'Py_XINCREF(%s);' % expr else: Modified: pypy/dist/pypy/translator/c/float_include.h ============================================================================== --- pypy/dist/pypy/translator/c/float_include.h (original) +++ pypy/dist/pypy/translator/c/float_include.h Sat Jun 18 21:07:29 2005 @@ -28,7 +28,7 @@ #define OP_FLOAT_ADD(x,y,r,err) r = x + y; #define OP_FLOAT_SUB(x,y,r,err) r = x - y; #define OP_FLOAT_MUL(x,y,r,err) r = x * y; - +#define OP_FLOAT_DIV(x,y,r,err) r = x / y; /*** conversions ***/ Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sat Jun 18 21:07:29 2005 @@ -109,6 +109,8 @@ line = '/* %s */' % line yield '\t' + line yield '};' + if self.deallocator: + yield 'void %s(struct %s *);' % (self.deallocator, self.name) elif phase == 2: if self.static_deallocator: From cfbolz at codespeak.net Sat Jun 18 21:51:54 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 18 Jun 2005 21:51:54 +0200 (CEST) Subject: [pypy-svn] r13589 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050618195154.E9CC827B57@code1.codespeak.net> Author: cfbolz Date: Sat Jun 18 21:51:54 2005 New Revision: 13589 Modified: pypy/dist/pypy/translator/llvm2/cfgtransform.py pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) made directcalls (recursive and non-recursive) work. the setup() phase for FunctionNodes now traverses the graph and adds any pending nodes so that references can be used without having looked at the function. improved logging and code output added a cfg transformation to remove same_as operations (only tested implicitely) Modified: pypy/dist/pypy/translator/llvm2/cfgtransform.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/cfgtransform.py (original) +++ pypy/dist/pypy/translator/llvm2/cfgtransform.py Sat Jun 18 21:51:54 2005 @@ -1,4 +1,6 @@ from pypy.objspace.flow.model import traverse, Block, checkgraph +from pypy.translator.unsimplify import remove_double_links + def remove_same_as(graph): same_as_positions = [] @@ -32,3 +34,10 @@ node.operations[:] = filter(None, node.operations) traverse(visit, graph) checkgraph(graph) + + +def prepare_graph(graph, translator): + remove_same_as(graph) + remove_double_links(translator, graph) + return graph + Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sat Jun 18 21:51:54 2005 @@ -12,10 +12,10 @@ log(line) def indent(self, line): - self.append(" " + line) + self.append(" " + line) def label(self, name): - self.append("%s:" % name) + self.append(" %s:" % name) def declare(self, decl): self.append("declare %s" %(decl,)) @@ -47,5 +47,10 @@ def binaryop(self, name, targetvar, type_, ref1, ref2): self.indent("%s = %s %s %s, %s" % (targetvar, name, type_, ref1, ref2)) + def call(self, targetvar, returntype, functionref, argrefs, argtypes): + arglist = ["%s %s" % item for item in zip(argtypes, argrefs)] + self.indent("%s = call %s %s(%s)" % (targetvar, returntype, functionref, + ", ".join(arglist))) + def __str__(self): return "\n".join(self._lines) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sat Jun 18 21:51:54 2005 @@ -2,8 +2,6 @@ from pypy.translator.llvm2.funcnode import FuncNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable -from pypy.translator.unsimplify import remove_double_links -from pypy.translator.llvm2.cfgtransform import remove_same_as log = log.database @@ -13,27 +11,32 @@ class Database(object): def __init__(self, translator): self._translator = translator - self.obj2node = {} + self.obj2node = {} self._pendingsetup = [] - def getgraph(self, func): - graph = self._translator.flowgraphs[func] - remove_same_as(graph) - remove_double_links(self._translator, graph) - return graph - - def getnode(self, obj): - assert hasattr(obj, 'func_code') - try: - return self.obj2node[obj] - except KeyError: - node = FuncNode(self, obj) - self.obj2node[obj] = node - log("add pending setup", node.ref) - self._pendingsetup.append(node) - return node + def prepare_ref(self, const_or_var): + if const_or_var in self.obj2node: + return + if isinstance(const_or_var, Constant): + if isinstance(const_or_var.concretetype, lltype.Primitive): + pass + else: + node = FuncNode(self, const_or_var) + self.obj2node[const_or_var] = node + log("added to pending nodes:", node) + self._pendingsetup.append(node) + + def prepare_typeref(self, type_): + if not isinstance(type_, lltype.Primitive): + log.XXX("need to prepare typeref") + + def prepare_arg(self, const_or_var): + log.prepare(const_or_var) + self.prepare_ref(const_or_var) + self.prepare_typeref(const_or_var.concretetype) - def process(self): + + def process(self): if self._pendingsetup: self._pendingsetup.pop().setup() return bool(self._pendingsetup) @@ -42,14 +45,12 @@ return self.obj2node.values() def getref(self, arg): - if isinstance(arg, Constant): - if isinstance(arg.concretetype, lltype.Primitive): - return str(arg.value).lower() #False --> false - raise TypeError, "can't handle the Constant %s" % arg + if (isinstance(arg, Constant) and + isinstance(arg.concretetype, lltype.Primitive)): + return str(arg.value).lower() #False --> false elif isinstance(arg, Variable): return "%" + str(arg) - else: - raise TypeError, arg + return self.obj2node[arg].ref def gettyperef(self, arg): return PRIMITIVES_TO_LLVM[arg.concretetype] Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sat Jun 18 21:51:54 2005 @@ -1,18 +1,33 @@ import py -from pypy.objspace.flow.model import Block, Constant, Variable, flatten, mkentrymap +from pypy.objspace.flow.model import Block, Constant, Variable, Link +from pypy.objspace.flow.model import flatten, mkentrymap, traverse +from pypy.translator.llvm2.cfgtransform import prepare_graph from pypy.translator.llvm2.log import log log = log.funcnode class FuncNode(object): _issetup = False - def __init__(self, db, func): + def __init__(self, db, const_ptr_func): self.db = db - self.func = func - self.ref = self.func.func_name - - def setup(self): - self.graph = self.db.getgraph(self.func) + self.ref = "%" + const_ptr_func.value._obj._name + self.graph = prepare_graph(const_ptr_func.value._obj.graph, + db._translator) + + def __str__(self): + return "" %(self.ref,) + + def setup(self): + log("setup", self) + def visit(node): + if isinstance(node, Link): + map(self.db.prepare_arg, node.args) + elif isinstance(node, Block): + map(self.db.prepare_arg, node.inputargs) + for op in node.operations: + map(self.db.prepare_arg, op.args) + self.db.prepare_arg(op.result) + traverse(visit, self.graph) self._issetup = True def getdecl(self): @@ -22,7 +37,7 @@ inputargs = self.db.multi_getref(startblock.inputargs) inputargtypes = self.db.multi_gettyperef(startblock.inputargs) returntype = self.db.gettyperef(self.graph.returnblock.inputargs[0]) - result = "%s %%%s" % (returntype, self.ref) + result = "%s %s" % (returntype, self.ref) args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] result += "(%s)" % ", ".join(args) return result @@ -104,7 +119,7 @@ assert len(op.args) == 2 self.codewriter.binaryop(name, self.db.getref(op.result), - self.db.gettyperef(op.result), + self.db.gettyperef(op.args[0]), self.db.getref(op.args[0]), self.db.getref(op.args[1])) def int_mul(self, op): @@ -118,4 +133,16 @@ def int_sub(self, op): self.binaryop('sub', op) + + def int_eq(self, op): + self.binaryop('seteq', op) + def direct_call(self, op): + assert len(op.args) >= 1 + targetvar = self.db.getref(op.result) + returntype = self.db.gettyperef(op.result) + functionref = self.db.getref(op.args[0]) + argrefs = self.db.multi_getref(op.args[1:]) + argtypes = self.db.multi_gettyperef(op.args[1:]) + self.codewriter.call(targetvar, returntype, functionref, argrefs, + argtypes) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jun 18 21:51:54 2005 @@ -1,7 +1,10 @@ from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database from pypy.translator.llvm2.pyxwrapper import write_pyx_wrapper -from pypy.translator.llvm2.log import log +from pypy.translator.llvm2.log import log +from pypy.objspace.flow.model import Constant +from pypy.rpython.rmodel import inputconst, getfunctionptr +from pypy.rpython import lltype from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter @@ -10,13 +13,17 @@ func = translator.entrypoint db = Database(translator) - entrynode = db.getnode(func) - + ptr = getfunctionptr(translator, func) + c = inputconst(lltype.typeOf(ptr), ptr) + db.prepare_ref(c) + assert c in db.obj2node while db.process(): pass - + entrynode = db.obj2node[c] codewriter = CodeWriter() dbobjects = db.getobjects() + log.debug(dbobjects) + log.debug(db.obj2node) for node in dbobjects: node.writedecl(codewriter) for node in dbobjects: Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sat Jun 18 21:51:54 2005 @@ -11,7 +11,7 @@ funcgen.graph.returnblock.inputargs[0].concretetype] inputargtypes = [PRIMITIVES_TO_C[arg.concretetype] for arg in funcgen.graph.startblock.inputargs] - result = "%s %s(%s)" % (returntype, funcgen.ref, + result = "%s %s(%s)" % (returntype, funcgen.ref.lstrip("%"), ", ".join(inputargtypes)) return result lines = [] Modified: pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py (original) +++ pypy/dist/pypy/translator/llvm2/test/llvmsnippet.py Sat Jun 18 21:51:54 2005 @@ -1,27 +1,7 @@ #function snippets -def simple2(): - return False -def simple3(i): - c = "Hello, Stars!" - return c[i] - -def simple4(): - return 3 + simple1() - - -def simple6(): - simple4() - return 1 - -def ackermann(n, m): - if n == 0: - return m + 1 - if m == 0: - return ackermann(n - 1, 1) - return ackermann(n - 1, ackermann(n, m - 1)) def calling1(m): if m > 1: Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sat Jun 18 21:51:54 2005 @@ -11,6 +11,8 @@ from pypy.rpython.rtyper import RPythonTyper py.log.setconsumer("genllvm", py.log.STDOUT) +py.log.setconsumer("genllvm database prepare", None) + ## def setup_module(mod): ## mod.llvm_found = is_on_path("llvm-as") @@ -18,8 +20,7 @@ def compile_function(function, annotate): t = Translator(function) a = t.annotate(annotate) - rt = RPythonTyper(a) - rt.specialize() + t.specialize() a.simplify() return genllvm(t) @@ -47,4 +48,24 @@ f = compile_function(ops, [int]) assert f(1) == 1 assert f(2) == 2 + +def test_function_call(): + def callee(): + return 1 + def caller(): + return 3 + callee() + f = compile_function(caller, []) + assert f() == 4 + +def test_recursive_call(): + def call_ackermann(n, m): + return ackermann(n, m) + def ackermann(n, m): + if n == 0: + return m + 1 + if m == 0: + return ackermann(n - 1, 1) + return ackermann(n - 1, ackermann(n, m - 1)) + f = compile_function(call_ackermann, [int, int]) + assert f(0, 2) == 3 From arigo at codespeak.net Sat Jun 18 22:20:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 18 Jun 2005 22:20:53 +0200 (CEST) Subject: [pypy-svn] r13590 - in pypy/dist/pypy: rpython rpython/test translator/c Message-ID: <20050618202053.B388A27B5A@code1.codespeak.net> Author: arigo Date: Sat Jun 18 22:20:50 2005 New Revision: 13590 Modified: pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/test/test_lltype.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/node.py Log: Made _ptr objects unhashable. Hashing them wouldn't be compatible with the __eq__. The __eq__ itself raises a TypeError if we compare pointers of mixed low-level types. So there is no sane way to allow _ptr's as dictionary keys. Some small clean-ups needed here and there to accomodate for this change :-( Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sat Jun 18 22:20:50 2005 @@ -163,7 +163,7 @@ def _attach_runtime_type_info_funcptr(self, funcptr): if self._runtime_type_info is None: - self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self) + self._runtime_type_info = opaqueptr(RuntimeTypeInfo, name=self._name, about=self)._obj if funcptr is not None: T = typeOf(funcptr) if (not isinstance(T, Ptr) or @@ -173,7 +173,7 @@ castable(T.TO.ARGS[0], Ptr(self)) < 0): raise TypeError("expected a runtime type info function " "implementation, got: %s" % funcptr) - self._runtime_type_info._obj.query_funcptr = funcptr + self._runtime_type_info.query_funcptr = funcptr class Array(ContainerType): __name__ = 'array' @@ -459,6 +459,9 @@ def __ne__(self, other): return not (self == other) + def __hash__(self): + raise TypeError("pointer objects are not hashable") + def __nonzero__(self): return self._obj is not None @@ -766,14 +769,14 @@ if not isinstance(GCSTRUCT, GcStruct): raise TypeError, "expected a GcStruct: %s" % GCSTRUCT GCSTRUCT._attach_runtime_type_info_funcptr(funcptr) - return GCSTRUCT._runtime_type_info + return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info) def getRuntimeTypeInfo(GCSTRUCT): if not isinstance(GCSTRUCT, GcStruct): raise TypeError, "expected a GcStruct: %s" % GCSTRUCT if GCSTRUCT._runtime_type_info is None: - raise TypeError, "no attached runtime type info for %s" % GCSTRUCT - return GCSTRUCT._runtime_type_info + raise ValueError, "no attached runtime type info for %s" % GCSTRUCT + return _ptr(Ptr(RuntimeTypeInfo), GCSTRUCT._runtime_type_info) def runtime_type_info(p): T = typeOf(p) Modified: pypy/dist/pypy/rpython/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/test/test_lltype.py Sat Jun 18 22:20:50 2005 @@ -341,7 +341,7 @@ def test_getRuntimeTypeInfo(): S = GcStruct('s', ('x', Signed)) - py.test.raises(TypeError, "getRuntimeTypeInfo(S)") + py.test.raises(ValueError, "getRuntimeTypeInfo(S)") pinf0 = attachRuntimeTypeInfo(S) assert pinf0._obj.about == S pinf = getRuntimeTypeInfo(S) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sat Jun 18 22:20:50 2005 @@ -28,7 +28,7 @@ # NOTE: cannot use dictionaries with Constants has keys, because # Constants may hash and compare equal but have different lltypes mix = [] - self.more_ll_values = {} + self.more_ll_values = [] def visit(block): if isinstance(block, Block): mix.extend(block.inputargs) @@ -40,7 +40,7 @@ mix.extend(link.args) mix.append(Constant(link.exitcase)) if hasattr(link, 'llexitcase'): - self.more_ll_values[link.llexitcase] = True + self.more_ll_values.append(link.llexitcase) traverse(visit, graph) resultvar = graph.getreturnvar() Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sat Jun 18 22:20:50 2005 @@ -70,11 +70,16 @@ # are two deallocators needed (a dynamic one for DECREF, which checks # the real type of the structure and calls the static deallocator) ? - if (isinstance(STRUCT, GcStruct) and - STRUCT._runtime_type_info is not None): + rtti = None + if isinstance(STRUCT, GcStruct): + try: + rtti = getRuntimeTypeInfo(STRUCT) + except ValueError: + pass + if rtti is not None: self.static_deallocator = db.namespace.uniquename( 'staticdealloc_'+self.name) - fnptr = STRUCT._runtime_type_info._obj.query_funcptr + fnptr = rtti._obj.query_funcptr if fnptr is None: raise NotImplementedError( "attachRuntimeTypeInfo(): please provide a function") From cfbolz at codespeak.net Sat Jun 18 23:39:45 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 18 Jun 2005 23:39:45 +0200 (CEST) Subject: [pypy-svn] r13591 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050618213945.5BD3A27B5A@code1.codespeak.net> Author: cfbolz Date: Sat Jun 18 23:39:45 2005 New Revision: 13591 Modified: pypy/dist/pypy/translator/llvm2/genllvm.py Log: skip/fail if genllvm() is called with a 'llvm-as' on the path. Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sat Jun 18 23:39:45 2005 @@ -1,3 +1,4 @@ +import py from pypy.translator.llvm2 import build_llvm_module from pypy.translator.llvm2.database import Database from pypy.translator.llvm2.pyxwrapper import write_pyx_wrapper @@ -5,7 +6,6 @@ from pypy.objspace.flow.model import Constant from pypy.rpython.rmodel import inputconst, getfunctionptr from pypy.rpython import lltype - from pypy.tool.udir import udir from pypy.translator.llvm2.codewriter import CodeWriter @@ -34,9 +34,20 @@ content = str(codewriter) llvmsource.write(content) log.source(content) - + + if not llvm_is_on_path(): + py.test.skip("llvm not found") # XXX not good to call py.test.skip here + pyxsource = llvmsource.new(basename=llvmsource.purebasename+'_wrapper'+'.pyx') write_pyx_wrapper(entrynode, pyxsource) + mod = build_llvm_module.make_module_from_llvm(llvmsource, pyxsource) return getattr(mod, func.func_name + "_wrapper") +def llvm_is_on_path(): + try: + py.path.local.sysfind("llvm-as") + except py.error.ENOENT: + return False + return True + From hpk at codespeak.net Sun Jun 19 00:05:11 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 19 Jun 2005 00:05:11 +0200 (CEST) Subject: [pypy-svn] r13592 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050618220511.5715D27B69@code1.codespeak.net> Author: hpk Date: Sun Jun 19 00:05:11 2005 New Revision: 13592 Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz,hpk,N.N) added some operations (thanks to whoever) and some tests for those Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jun 19 00:05:11 2005 @@ -52,5 +52,9 @@ self.indent("%s = call %s %s(%s)" % (targetvar, returntype, functionref, ", ".join(arglist))) + def cast(self, targetvar, fromtype, fromvar, targettype): + self.indent("%(targetvar)s = cast %(fromtype)s " + "%(fromvar)s to %(targettype)s" % locals()) + def __str__(self): return "\n".join(self._lines) Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jun 19 00:05:11 2005 @@ -136,6 +136,29 @@ def int_eq(self, op): self.binaryop('seteq', op) + + def int_ne(self, op): + self.binaryop('setne', op) + + def int_lt(self, op): + self.binaryop('setlt', op) + + def int_le(self, op): + self.binaryop('setle', op) + + def int_gt(self, op): + self.binaryop('setgt', op) + + def int_ge(self, op): + self.binaryop('setge', op) + + def cast_bool_to_int(self, op): + assert len(op.args) == 1 + targetvar = self.db.getref(op.result) + targettype = self.db.gettyperef(op.result) + fromvar = self.db.getref(op.args[0]) + fromtype = self.db.gettyperef(op.args[0]) + self.codewriter.cast(targetvar, fromtype, fromvar, targettype) def direct_call(self, op): assert len(op.args) >= 1 Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jun 19 00:05:11 2005 @@ -44,6 +44,15 @@ def test_int_ops(): def ops(i): + x = 0 + x += i < i + x += i <= i + x += i == i + x += i != i + x += i >= i + x += i > i + #x += i is not None + #x += i is None return i + 1 * i // i - 1 f = compile_function(ops, [int]) assert f(1) == 1 From cfbolz at codespeak.net Sun Jun 19 00:20:43 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 19 Jun 2005 00:20:43 +0200 (CEST) Subject: [pypy-svn] r13593 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050618222043.E929527B5F@code1.codespeak.net> Author: cfbolz Date: Sun Jun 19 00:20:43 2005 New Revision: 13593 Modified: pypy/dist/pypy/translator/llvm2/cfgtransform.py Log: fix situations where multiple same_as operations exist in one block Modified: pypy/dist/pypy/translator/llvm2/cfgtransform.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/cfgtransform.py (original) +++ pypy/dist/pypy/translator/llvm2/cfgtransform.py Sun Jun 19 00:20:43 2005 @@ -17,9 +17,10 @@ # replace the new variable (same_as_result) with the old variable # (from all subsequent positions) for op in block.operations[index:]: - for i in range(len(op.args)): - if op.args[i] == same_as_result: - op.args[i] = same_as_arg + if op is not None: + for i in range(len(op.args)): + if op.args[i] == same_as_result: + op.args[i] = same_as_arg for link in block.exits: for i in range(len(link.args)): if link.args[i] == same_as_result: From hpk at codespeak.net Sun Jun 19 12:29:04 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 19 Jun 2005 12:29:04 +0200 (CEST) Subject: [pypy-svn] r13595 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050619102904.720A127B6D@code1.codespeak.net> Author: hpk Date: Sun Jun 19 12:29:04 2005 New Revision: 13595 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) added disabled tuple tests and some dummy operations Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jun 19 12:29:04 2005 @@ -34,7 +34,6 @@ log.prepare(const_or_var) self.prepare_ref(const_or_var) self.prepare_typeref(const_or_var.concretetype) - def process(self): if self._pendingsetup: Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jun 19 12:29:04 2005 @@ -169,3 +169,12 @@ argtypes = self.db.multi_gettyperef(op.args[1:]) self.codewriter.call(targetvar, returntype, functionref, argrefs, argtypes) + + def malloc(self, op): + log.XXX("malloc not emitted") + + def getfield(self, op): + log.XXX("getfield not emitted") + + def setfield(self, op): + log.XXX("setfield not emitted") Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jun 19 12:29:04 2005 @@ -78,3 +78,9 @@ f = compile_function(call_ackermann, [int, int]) assert f(0, 2) == 3 +def XXXtest_tuple_getitem(): + def list_getitem(i): + l = (1,2,i) + return l[1] + f = compile_function(list_getitem, [int]) + assert f(1) == 2 From hpk at codespeak.net Sun Jun 19 12:34:34 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 19 Jun 2005 12:34:34 +0200 (CEST) Subject: [pypy-svn] r13596 - pypy/dist/pypy/translator/llvm2 Message-ID: <20050619103434.7F81127B6E@code1.codespeak.net> Author: hpk Date: Sun Jun 19 12:34:34 2005 New Revision: 13596 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/pyxwrapper.py Log: (cfbolz, hpk) some renamings to make usages more obvious Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jun 19 12:34:34 2005 @@ -14,7 +14,7 @@ self.obj2node = {} self._pendingsetup = [] - def prepare_ref(self, const_or_var): + def prepare_repr_arg(self, const_or_var): if const_or_var in self.obj2node: return if isinstance(const_or_var, Constant): @@ -26,14 +26,14 @@ log("added to pending nodes:", node) self._pendingsetup.append(node) - def prepare_typeref(self, type_): + def prepare_repr_arg_type(self, type_): if not isinstance(type_, lltype.Primitive): log.XXX("need to prepare typeref") def prepare_arg(self, const_or_var): log.prepare(const_or_var) - self.prepare_ref(const_or_var) - self.prepare_typeref(const_or_var.concretetype) + self.prepare_repr_arg(const_or_var) + self.prepare_repr_arg_type(const_or_var.concretetype) def process(self): if self._pendingsetup: @@ -43,7 +43,7 @@ def getobjects(self): return self.obj2node.values() - def getref(self, arg): + def repr_arg(self, arg): if (isinstance(arg, Constant) and isinstance(arg.concretetype, lltype.Primitive)): return str(arg.value).lower() #False --> false @@ -51,11 +51,11 @@ return "%" + str(arg) return self.obj2node[arg].ref - def gettyperef(self, arg): + def repr_arg_type(self, arg): return PRIMITIVES_TO_LLVM[arg.concretetype] - def multi_getref(self, args): - return [self.getref(arg) for arg in args] + def repr_arg_multi(self, args): + return [self.repr_arg(arg) for arg in args] - def multi_gettyperef(self, args): - return [self.gettyperef(arg) for arg in args] + def repr_arg_type_multi(self, args): + return [self.repr_arg_type(arg) for arg in args] Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jun 19 12:34:34 2005 @@ -34,9 +34,9 @@ assert self._issetup startblock = self.graph.startblock returnblock = self.graph.returnblock - inputargs = self.db.multi_getref(startblock.inputargs) - inputargtypes = self.db.multi_gettyperef(startblock.inputargs) - returntype = self.db.gettyperef(self.graph.returnblock.inputargs[0]) + inputargs = self.db.repr_arg_multi(startblock.inputargs) + inputargtypes = self.db.repr_arg_type_multi(startblock.inputargs) + returntype = self.db.repr_arg_type(self.graph.returnblock.inputargs[0]) result = "%s %s" % (returntype, self.ref) args = ["%s %s" % item for item in zip(inputargtypes, inputargs)] result += "(%s)" % ", ".join(args) @@ -75,10 +75,10 @@ def write_block_phi_nodes(self, codewriter, block): entrylinks = mkentrymap(self.graph)[block] entrylinks = [x for x in entrylinks if x.prevblock is not None] - inputargs = self.db.multi_getref(block.inputargs) - inputargtypes = self.db.multi_gettyperef(block.inputargs) + inputargs = self.db.repr_arg_multi(block.inputargs) + inputargtypes = self.db.repr_arg_type_multi(block.inputargs) for i, (arg, type_) in enumerate(zip(inputargs, inputargtypes)): - names = self.db.multi_getref([link.args[i] for link in entrylinks]) + names = self.db.repr_arg_multi([link.args[i] for link in entrylinks]) blocknames = [self.block_to_name[link.prevblock] for link in entrylinks] codewriter.phi(arg, type_, names, blocknames) @@ -87,7 +87,7 @@ if len(block.exits) == 1: codewriter.br_uncond(self.block_to_name[block.exits[0].target]) elif len(block.exits) == 2: - switch = self.db.getref(block.exitswitch) + switch = self.db.repr_arg(block.exitswitch) codewriter.br(switch, self.block_to_name[block.exits[0].target], self.block_to_name[block.exits[1].target]) @@ -106,8 +106,8 @@ def write_returnblock(self, codewriter, block): assert len(block.inputargs) == 1 self.write_block_phi_nodes(codewriter, block) - inputargtype = self.db.gettyperef(block.inputargs[0]) - inputarg = self.db.getref(block.inputargs[0]) + inputargtype = self.db.repr_arg_type(block.inputargs[0]) + inputarg = self.db.repr_arg(block.inputargs[0]) codewriter.ret(inputargtype, inputarg) class OpWriter(object): @@ -118,10 +118,10 @@ def binaryop(self, name, op): assert len(op.args) == 2 self.codewriter.binaryop(name, - self.db.getref(op.result), - self.db.gettyperef(op.args[0]), - self.db.getref(op.args[0]), - self.db.getref(op.args[1])) + self.db.repr_arg(op.result), + self.db.repr_arg_type(op.args[0]), + self.db.repr_arg(op.args[0]), + self.db.repr_arg(op.args[1])) def int_mul(self, op): self.binaryop('mul', op) @@ -154,19 +154,19 @@ def cast_bool_to_int(self, op): assert len(op.args) == 1 - targetvar = self.db.getref(op.result) - targettype = self.db.gettyperef(op.result) - fromvar = self.db.getref(op.args[0]) - fromtype = self.db.gettyperef(op.args[0]) + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + fromvar = self.db.repr_arg(op.args[0]) + fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) def direct_call(self, op): assert len(op.args) >= 1 - targetvar = self.db.getref(op.result) - returntype = self.db.gettyperef(op.result) - functionref = self.db.getref(op.args[0]) - argrefs = self.db.multi_getref(op.args[1:]) - argtypes = self.db.multi_gettyperef(op.args[1:]) + targetvar = self.db.repr_arg(op.result) + returntype = self.db.repr_arg_type(op.result) + functionref = self.db.repr_arg(op.args[0]) + argrefs = self.db.repr_arg_multi(op.args[1:]) + argtypes = self.db.repr_arg_type_multi(op.args[1:]) self.codewriter.call(targetvar, returntype, functionref, argrefs, argtypes) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jun 19 12:34:34 2005 @@ -15,7 +15,7 @@ db = Database(translator) ptr = getfunctionptr(translator, func) c = inputconst(lltype.typeOf(ptr), ptr) - db.prepare_ref(c) + db.prepare_repr_arg(c) assert c in db.obj2node while db.process(): pass Modified: pypy/dist/pypy/translator/llvm2/pyxwrapper.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/pyxwrapper.py (original) +++ pypy/dist/pypy/translator/llvm2/pyxwrapper.py Sun Jun 19 12:34:34 2005 @@ -16,7 +16,7 @@ return result lines = [] append = lines.append - inputargs = funcgen.db.multi_getref(funcgen.graph.startblock.inputargs) + inputargs = funcgen.db.repr_arg_multi(funcgen.graph.startblock.inputargs) inputargs = [x.strip("%") for x in inputargs] append("cdef extern " + c_declaration()) append("") From arigo at codespeak.net Sun Jun 19 12:50:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 12:50:55 +0200 (CEST) Subject: [pypy-svn] r13597 - in pypy/dist/pypy: annotation rpython Message-ID: <20050619105055.68B5727B75@code1.codespeak.net> Author: arigo Date: Sun Jun 19 12:50:53 2005 New Revision: 13597 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/rpython/rlist.py Log: Details. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sun Jun 19 12:50:53 2005 @@ -273,8 +273,8 @@ elif tp is float: result = SomeFloat() elif tp is list: + key = Constant(x) try: - key = Constant(x) return self.immutable_cache[key] except KeyError: result = SomeList(ListDef(self, SomeImpossibleValue())) @@ -282,8 +282,8 @@ for e in x: result.listdef.generalize(self.immutablevalue(e)) elif tp is dict: # exactly a dict + key = Constant(x) try: - key = Constant(x) return self.immutable_cache[key] except KeyError: result = SomeDict(DictDef(self, Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Jun 19 12:50:53 2005 @@ -60,11 +60,11 @@ raise TyperError("expected a list: %r" % (listobj,)) try: key = Constant(listobj) - return self.list_cache[key][1] + return self.list_cache[key] except KeyError: self.setup() result = malloc(self.LIST, immortal=True) - self.list_cache[key] = listobj, result + self.list_cache[key] = result result.items = malloc(self.LIST.items.TO, len(listobj)) r_item = self.item_repr for i in range(len(listobj)): From arigo at codespeak.net Sun Jun 19 13:16:32 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 13:16:32 +0200 (CEST) Subject: [pypy-svn] r13598 - in pypy/dist/pypy: rpython translator/c/test Message-ID: <20050619111632.4489727B69@code1.codespeak.net> Author: arigo Date: Sun Jun 19 13:16:29 2005 New Revision: 13598 Modified: pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/translator/c/test/test_annotated.py Log: Bug fix. Conversions from/to pyobj_repr should not use gendirectcall(), because translator/c/wrapper.py cannot cope with new graphs suddenly appearing. Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Sun Jun 19 13:16:29 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, pyobjectptr from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, BoolRepr -from pypy.rpython.robject import PyObjRepr +from pypy.rpython.robject import PyObjRepr, pyobj_repr debug = False @@ -48,31 +48,15 @@ return llops.genop('cast_bool_to_int', [v], resulttype=Signed) return NotImplemented -pyobj_true = pyobjectptr(True) -pyobj_false = pyobjectptr(False) - -def ll_pyobj2bool(pyobjptr): - if pyobjptr == pyobj_true: - return True - elif pyobjptr == pyobj_false: - return False - else: - raise TypeError - -def ll_bool2pyobj(boolval): - if boolval: - return pyobj_true - else: - return pyobj_false - class __extend__(pairtype(PyObjRepr, BoolRepr)): def convert_from_to((r_from, r_to), v, llops): if r_to.lowleveltype == Bool: - return llops.gendirectcall(ll_pyobj2bool, v) + return llops.gencapicall('PyObject_IsTrue', [v], resulttype=Bool) return NotImplemented class __extend__(pairtype(BoolRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from.lowleveltype == Bool: - return llops.gendirectcall(ll_bool2pyobj, v) + return llops.gencapicall('PyBool_FromLong', [v], + resulttype = pyobj_repr) return NotImplemented Modified: pypy/dist/pypy/translator/c/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/c/test/test_annotated.py Sun Jun 19 13:16:29 2005 @@ -128,3 +128,9 @@ for n in [-1,0,1,2]: result.append(fn(n)) assert result == [-1,0,1,2] + + def test_is_perfect_number(self): + fn = self.getcompiled(snippet.is_perfect_number) + for i in range(1, 33): + perfect = fn(i) + assert perfect is (i in (6,28)) From arigo at codespeak.net Sun Jun 19 13:17:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 13:17:55 +0200 (CEST) Subject: [pypy-svn] r13599 - pypy/dist/pypy/translator Message-ID: <20050619111755.5B23627B72@code1.codespeak.net> Author: arigo Date: Sun Jun 19 13:17:53 2005 New Revision: 13599 Added: pypy/dist/pypy/translator/lltransform.py - copied, changed from r13590, pypy/dist/pypy/translator/llvm2/cfgtransform.py Log: Started a module to regroup post-rtyper optimizations on low-level graphs. Contains llvm2's remove_same_as() and an experimental transformation that turns the graphs from SSI to SSA (see docstring). Copied: pypy/dist/pypy/translator/lltransform.py (from r13590, pypy/dist/pypy/translator/llvm2/cfgtransform.py) ============================================================================== --- pypy/dist/pypy/translator/llvm2/cfgtransform.py (original) +++ pypy/dist/pypy/translator/lltransform.py Sun Jun 19 13:17:53 2005 @@ -1,8 +1,12 @@ -from pypy.objspace.flow.model import traverse, Block, checkgraph -from pypy.translator.unsimplify import remove_double_links +import autopath +from pypy.translator.translator import Translator +from pypy.objspace.flow.model import Variable, Constant, Block, Link +from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph -def remove_same_as(graph): +def remove_same_as(graph): + """Remove all 'same_as' operations. + """ same_as_positions = [] def visit(node): if isinstance(node, Block): @@ -33,11 +37,87 @@ if isinstance(node, Block) and node.operations: node.operations[:] = filter(None, node.operations) traverse(visit, graph) - checkgraph(graph) -def prepare_graph(graph, translator): - remove_same_as(graph) - remove_double_links(translator, graph) - return graph +def SSI_to_SSA(graph): + """Rename the variables in a flow graph as much as possible without + violating the SSA rule. 'SSI' means that each Variable in a flow graph is + defined only once in the whole graph; all our graphs are SSI. This + function does not break that rule, but changes the 'name' of some + Variables to give them the same 'name' as other Variables. The result + looks like an SSA graph. 'SSA' means that each var name appears as the + result of an operation only once in the whole graph, but it can be + passed to other blocks across links. + """ + entrymap = mkentrymap(graph) + consider_blocks = entrymap + + while consider_blocks: + blocklist = consider_blocks.keys() + consider_blocks = {} + for block in blocklist: + if block is graph.startblock: + continue + links = entrymap[block] + assert links + mapping = {} + for i in range(len(block.inputargs)): + # list of possible vars that can arrive in i'th position + v1 = block.inputargs[i] + names = {v1.name: True} + key = [] + for link in links: + v = link.args[i] + if not isinstance(v, Variable): + break + names[v.name] = True + else: + if len(names) == 2: + del names[v1.name] + v1._name, = names.keys() + # mark all the following block as subject to + # possible further optimization + for link in block.exits: + consider_blocks[link.target] = True + # sanity-check that the same name is never used several times in a block + variables_by_name = {} + for block in entrymap: + vars = [op.result for op in block.operations] + for link in block.exits: + vars += link.getextravars() + assert len(dict.fromkeys([v.name for v in vars])) == len(vars), ( + "duplicate variable name in %r" % (block,)) + for v in vars: + variables_by_name.setdefault(v.name, []).append(v) + # sanity-check that variables with the same name have the same concretetype + for vname, vlist in variables_by_name.items(): + vct = [getattr(v, 'concretetype', None) for v in vlist] + assert vct == vct[:1] * len(vct), ( + "variables called %s have mixed concretetypes: %r" % (vname, vct)) + +# ____________________________________________________________ + +if __name__ == '__main__': + + def is_perfect_number(n=int): + div = 1 + sum = 0 + while div < n: + if n % div == 0: + sum += div + div += 1 + return n == sum + + t = Translator(is_perfect_number) + a = t.annotate([int]) + a.simplify() + t.specialize() + graph = t.getflowgraph() + remove_same_as(graph) + SSI_to_SSA(graph) + checkgraph(graph) + t.view() + f = t.ccompile() + for i in range(1, 33): + print '%3d' % i, is_perfect_number(i) From arigo at codespeak.net Sun Jun 19 13:40:41 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 13:40:41 +0200 (CEST) Subject: [pypy-svn] r13600 - pypy/dist/pypy/translator Message-ID: <20050619114041.EAAB327B7D@code1.codespeak.net> Author: arigo Date: Sun Jun 19 13:40:40 2005 New Revision: 13600 Modified: pypy/dist/pypy/translator/lltransform.py Log: Backport fix to llvm2/cfgtransform.py. Modified: pypy/dist/pypy/translator/lltransform.py ============================================================================== --- pypy/dist/pypy/translator/lltransform.py (original) +++ pypy/dist/pypy/translator/lltransform.py Sun Jun 19 13:40:40 2005 @@ -21,9 +21,10 @@ # replace the new variable (same_as_result) with the old variable # (from all subsequent positions) for op in block.operations[index:]: - for i in range(len(op.args)): - if op.args[i] == same_as_result: - op.args[i] = same_as_arg + if op is not None: + for i in range(len(op.args)): + if op.args[i] == same_as_result: + op.args[i] = same_as_arg for link in block.exits: for i in range(len(link.args)): if link.args[i] == same_as_result: From hpk at codespeak.net Sun Jun 19 14:28:28 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 19 Jun 2005 14:28:28 +0200 (CEST) Subject: [pypy-svn] r13601 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050619122828.4C56627B44@code1.codespeak.net> Author: hpk Date: Sun Jun 19 14:28:27 2005 New Revision: 13601 Added: pypy/dist/pypy/translator/llvm2/structnode.py Modified: pypy/dist/pypy/translator/llvm2/codewriter.py pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/genllvm.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) - added StructNode for - guess what -struct handling - added getfield/setfield and malloc support - simple tuple test passes - some minor improvements and refactorings Modified: pypy/dist/pypy/translator/llvm2/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm2/codewriter.py Sun Jun 19 14:28:27 2005 @@ -14,12 +14,20 @@ def indent(self, line): self.append(" " + line) - def label(self, name): + def label(self, name): self.append(" %s:" % name) - def declare(self, decl): + def structdef(self, name, typereprs): + self.append("%s = type { %s }" %(name, ", ".join(typereprs))) + + def declare(self, decl): self.append("declare %s" %(decl,)) + def startimpl(self): + self.append("") + self.append("implementation") + self.append("") + def br_uncond(self, blockname): self.indent("br label %%%s" %(blockname,)) @@ -56,5 +64,19 @@ self.indent("%(targetvar)s = cast %(fromtype)s " "%(fromvar)s to %(targettype)s" % locals()) + def malloc(self, targetvar, type): + self.indent("%(targetvar)s = malloc %(type)s" % locals()) + + def getelementptr(self, targetvar, type, typevar, index): + self.indent("%(targetvar)s = getelementptr " + "%(type)s %(typevar)s, int 0, uint %(index)s" % locals()) + + def load(self, targetvar, targettype, ptr): + self.indent("%(targetvar)s = load %(targettype)s* %(ptr)s" % locals()) + + def store(self, valuetype, valuevar, ptr): + self.indent("store %(valuetype)s %(valuevar)s, " + "%(valuetype)s* %(ptr)s" % locals()) + def __str__(self): return "\n".join(self._lines) Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Sun Jun 19 14:28:27 2005 @@ -1,5 +1,6 @@ from pypy.translator.llvm2.log import log from pypy.translator.llvm2.funcnode import FuncNode +from pypy.translator.llvm2.structnode import StructNode from pypy.rpython import lltype from pypy.objspace.flow.model import Block, Constant, Variable @@ -13,6 +14,14 @@ self._translator = translator self.obj2node = {} self._pendingsetup = [] + self._tmpcount = 1 + + def addpending(self, key, node): + assert key not in self.obj2node, ( + "node with key %r already known!" %(key,)) + self.obj2node[key] = node + log("added to pending nodes:", node) + self._pendingsetup.append(node) def prepare_repr_arg(self, const_or_var): if const_or_var in self.obj2node: @@ -20,15 +29,23 @@ if isinstance(const_or_var, Constant): if isinstance(const_or_var.concretetype, lltype.Primitive): pass + #log.prepare(const_or_var, "(is primitive)") else: - node = FuncNode(self, const_or_var) - self.obj2node[const_or_var] = node - log("added to pending nodes:", node) - self._pendingsetup.append(node) + self.addpending(const_or_var, FuncNode(self, const_or_var)) + else: + log.prepare.ignore(const_or_var) def prepare_repr_arg_type(self, type_): - if not isinstance(type_, lltype.Primitive): - log.XXX("need to prepare typeref") + if type_ in self.obj2node: + return + if isinstance(type_, lltype.Primitive): + pass + elif isinstance(type_, lltype.Ptr): + self.prepare_repr_arg_type(type_.TO) + elif isinstance(type_, lltype.Struct): + self.addpending(type_, StructNode(self, type_)) + else: + log.XXX("need to prepare typerepr", type_) def prepare_arg(self, const_or_var): log.prepare(const_or_var) @@ -52,10 +69,26 @@ return self.obj2node[arg].ref def repr_arg_type(self, arg): - return PRIMITIVES_TO_LLVM[arg.concretetype] + if isinstance(arg, (Constant, Variable)): + arg = arg.concretetype + try: + return self.obj2node[arg].ref + except KeyError: + if isinstance(arg, lltype.Primitive): + return PRIMITIVES_TO_LLVM[arg] + elif isinstance(arg, lltype.Ptr): + return self.repr_arg_type(arg.TO) + '*' + else: + raise TypeError("cannot represent %r" %(arg,)) def repr_arg_multi(self, args): return [self.repr_arg(arg) for arg in args] def repr_arg_type_multi(self, args): return [self.repr_arg_type(arg) for arg in args] + + def repr_tmpvar(self): + count = self._tmpcount + self._tmpcount += 1 + return "%tmp." + str(count) + Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jun 19 14:28:27 2005 @@ -1,6 +1,7 @@ import py from pypy.objspace.flow.model import Block, Constant, Variable, Link from pypy.objspace.flow.model import flatten, mkentrymap, traverse +from pypy.rpython import lltype from pypy.translator.llvm2.cfgtransform import prepare_graph from pypy.translator.llvm2.log import log log = log.funcnode @@ -15,7 +16,7 @@ db._translator) def __str__(self): - return "" %(self.ref,) + return "" %(self.ref,) def setup(self): log("setup", self) @@ -42,6 +43,8 @@ result += "(%s)" % ", ".join(args) return result + # ______________________________________________________________________ + # main entry points from genllvm def writedecl(self, codewriter): codewriter.declare(self.getdecl()) @@ -66,6 +69,9 @@ self.write_block(codewriter, block) codewriter.closefunc() + # ______________________________________________________________________ + # writing helpers for entry points + def write_block(self, codewriter, block): self.write_block_phi_nodes(codewriter, block) self.write_block_operations(codewriter, block) @@ -171,10 +177,33 @@ argtypes) def malloc(self, op): - log.XXX("malloc not emitted") + targetvar = self.db.repr_arg(op.result) + arg = op.args[0] + assert (isinstance(arg, Constant) and + isinstance(arg.value, lltype.Struct)) + type = "%" + arg.value._name + self.codewriter.malloc(targetvar, type) def getfield(self, op): - log.XXX("getfield not emitted") + tmpvar = self.db.repr_tmpvar() + type = self.db.repr_arg_type(op.args[0]) + typevar = self.db.repr_arg(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + self.codewriter.getelementptr(tmpvar, type, typevar, index) + + targetvar = self.db.repr_arg(op.result) + targettype = self.db.repr_arg_type(op.result) + self.codewriter.load(targetvar, targettype, tmpvar) def setfield(self, op): - log.XXX("setfield not emitted") + tmpvar = self.db.repr_tmpvar() + type = self.db.repr_arg_type(op.args[0]) + typevar = self.db.repr_arg(op.args[0]) + fieldnames = list(op.args[0].concretetype.TO._names) + index = fieldnames.index(op.args[1].value) + self.codewriter.getelementptr(tmpvar, type, typevar, index) + + valuevar = self.db.repr_arg(op.args[2]) + valuetype = self.db.repr_arg_type(op.args[2]) + self.codewriter.store(valuetype, valuevar, tmpvar) Modified: pypy/dist/pypy/translator/llvm2/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/genllvm.py Sun Jun 19 14:28:27 2005 @@ -26,6 +26,7 @@ log.debug(db.obj2node) for node in dbobjects: node.writedecl(codewriter) + codewriter.startimpl() for node in dbobjects: node.writeimpl(codewriter) Added: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sun Jun 19 14:28:27 2005 @@ -0,0 +1,34 @@ +import py +from pypy.objspace.flow.model import Block, Constant, Variable, Link +from pypy.translator.llvm2.log import log +log = log.structnode + +class StructNode(object): + _issetup = False + + def __init__(self, db, struct): + self.db = db + self.struct = struct + self.ref = "%" + struct._name + + def __str__(self): + return "" %(self.ref,) + + def setup(self): + log.XXX("setup", self) + self._issetup = True + + # ______________________________________________________________________ + # entry points from genllvm + # + def writedecl(self, codewriter): + assert self._issetup + struct = self.struct + l = [] + for fieldname in struct._names: + type_ = getattr(struct, fieldname) + l.append(self.db.repr_arg_type(type_)) + codewriter.structdef(self.ref, l) + + def writeimpl(self, codewriter): + assert self._issetup Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jun 19 14:28:27 2005 @@ -78,7 +78,7 @@ f = compile_function(call_ackermann, [int, int]) assert f(0, 2) == 3 -def XXXtest_tuple_getitem(): +def test_tuple_getitem(): def list_getitem(i): l = (1,2,i) return l[1] From cfbolz at codespeak.net Sun Jun 19 14:38:23 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 19 Jun 2005 14:38:23 +0200 (CEST) Subject: [pypy-svn] r13602 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050619123823.6563627B44@code1.codespeak.net> Author: cfbolz Date: Sun Jun 19 14:38:23 2005 New Revision: 13602 Modified: pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/structnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: (cfbolz, hpk) make nested tuples work + test Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Sun Jun 19 14:38:23 2005 @@ -181,7 +181,8 @@ arg = op.args[0] assert (isinstance(arg, Constant) and isinstance(arg.value, lltype.Struct)) - type = "%" + arg.value._name + #XXX unclean + type = self.db.obj2node[arg.value].ref self.codewriter.malloc(targetvar, type) def getfield(self, op): Modified: pypy/dist/pypy/translator/llvm2/structnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/structnode.py (original) +++ pypy/dist/pypy/translator/llvm2/structnode.py Sun Jun 19 14:38:23 2005 @@ -5,12 +5,14 @@ class StructNode(object): _issetup = False + struct_counter = 0 def __init__(self, db, struct): self.db = db self.struct = struct - self.ref = "%" + struct._name - + self.ref = "%%st.%s.%s" % (struct._name, StructNode.struct_counter) + StructNode.struct_counter += 1 + def __str__(self): return "" %(self.ref,) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Sun Jun 19 14:38:23 2005 @@ -79,8 +79,15 @@ assert f(0, 2) == 3 def test_tuple_getitem(): - def list_getitem(i): + def tuple_getitem(i): l = (1,2,i) return l[1] - f = compile_function(list_getitem, [int]) + f = compile_function(tuple_getitem, [int]) assert f(1) == 2 + +def test_nested_tuple(): + def nested_tuple(i): + l = (1,(1,2,i),i) + return l[1][2] + f = compile_function(nested_tuple, [int]) + assert f(4) == 4 From arigo at codespeak.net Sun Jun 19 15:17:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 15:17:43 +0200 (CEST) Subject: [pypy-svn] r13603 - pypy/dist/pypy/translator Message-ID: <20050619131743.4988227B82@code1.codespeak.net> Author: arigo Date: Sun Jun 19 15:17:41 2005 New Revision: 13603 Modified: pypy/dist/pypy/translator/lltransform.py Log: Bug fix. Modified: pypy/dist/pypy/translator/lltransform.py ============================================================================== --- pypy/dist/pypy/translator/lltransform.py (original) +++ pypy/dist/pypy/translator/lltransform.py Sun Jun 19 15:17:41 2005 @@ -52,6 +52,7 @@ """ entrymap = mkentrymap(graph) consider_blocks = entrymap + renamed = {} while consider_blocks: blocklist = consider_blocks.keys() @@ -74,9 +75,18 @@ names[v.name] = True else: if len(names) == 2: - del names[v1.name] - v1._name, = names.keys() - # mark all the following block as subject to + oldname = v1.name + del names[oldname] + newname, = names.keys() + while oldname in renamed: + oldname = renamed[oldname] + while newname in renamed: + newname = renamed[newname] + if oldname == newname: + continue + renamed[oldname] = newname + v1._name = newname + # mark all the following blocks as subject to # possible further optimization for link in block.exits: consider_blocks[link.target] = True From arigo at codespeak.net Sun Jun 19 15:34:29 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 15:34:29 +0200 (CEST) Subject: [pypy-svn] r13604 - in pypy/dist/pypy/translator: . c c/test Message-ID: <20050619133429.8011427B7D@code1.codespeak.net> Author: arigo Date: Sun Jun 19 15:34:24 2005 New Revision: 13604 Added: pypy/dist/pypy/translator/backendoptimization.py - copied unchanged from r13603, pypy/dist/pypy/translator/lltransform.py pypy/dist/pypy/translator/c/test/test_backendoptimized.py (contents, props changed) pypy/dist/pypy/translator/c/test/test_support.py (contents, props changed) Removed: pypy/dist/pypy/translator/lltransform.py Modified: pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/support.py pypy/dist/pypy/translator/c/test/test_typed.py Log: Renamed lltransform.py to backendoptimization.py. Support for the SSI_to_SSA optimization in genc. (This is fun for copying variables along links; see the new test_support.) All in all, with this optimization genc produces functions that looks (very roughly) sane. Good! Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sun Jun 19 15:34:24 2005 @@ -1,11 +1,10 @@ from __future__ import generators from pypy.translator.c.support import cdecl, ErrorValue -from pypy.translator.c.support import llvalue_from_constant +from pypy.translator.c.support import llvalue_from_constant, gen_assignments from pypy.objspace.flow.model import Variable, Constant, Block from pypy.objspace.flow.model import traverse, last_exception from pypy.rpython.lltype import Ptr, PyObject, Void, Bool from pypy.rpython.lltype import pyobjectptr, Struct, Array -from pypy.translator.unsimplify import remove_direct_loops PyObjPtr = Ptr(PyObject) @@ -18,7 +17,6 @@ def __init__(self, graph, db, cpython_exc=False): self.graph = graph - remove_direct_loops(None, graph) self.db = db self.cpython_exc = cpython_exc # @@ -110,14 +108,16 @@ def cfunction_declarations(self): # declare the local variables, excluding the function arguments - inputargset = {} + seen = {} for a in self.graph.getargs(): - inputargset[a] = True + seen[a.name] = True result_by_name = [] for v in self.allvariables(): - if v not in inputargset: - result = cdecl(self.lltypename(v), v.name) + ';' + name = v.name + if name not in seen: + seen[name] = True + result = cdecl(self.lltypename(v), name) + ';' if self.lltypemap(v) == Void: result = '/*%s*/' % result result_by_name.append((v._name, result)) @@ -145,6 +145,8 @@ for v in to_release: linklocalvars[v] = self.expr(v) has_ref = linklocalvars.copy() + assignments = [] + increfs = [] for a1, a2 in zip(link.args, link.target.inputargs): if self.lltypemap(a2) == Void: continue @@ -152,17 +154,27 @@ src = linklocalvars[a1] else: src = self.expr(a1) - line = '%s = %s;' % (self.expr(a2), src) + dest = self.expr(a2) + assignments.append((self.lltypename(a2), dest, src)) if a1 in has_ref: del has_ref[a1] else: assert self.lltypemap(a1) == self.lltypemap(a2) - line += '\t' + self.cincref(a2) - yield line + line = self.cincref(a2) + if line: + increfs.append(line) + # warning, the order below is delicate to get right: + # 1. decref the old variables that are not passed over for v in has_ref: line = self.cdecref(v, linklocalvars[v]) if line: yield line + # 2. perform the assignments with collision-avoidance + for line in gen_assignments(assignments): + yield line + # 3. incref the new variables if needed + for line in increfs: + yield line yield 'goto block%d;' % blocknum[link.target] # collect all blocks Modified: pypy/dist/pypy/translator/c/support.py ============================================================================== --- pypy/dist/pypy/translator/c/support.py (original) +++ pypy/dist/pypy/translator/c/support.py Sun Jun 19 15:34:24 2005 @@ -59,3 +59,43 @@ double long typedef else register union ''') + + +def gen_assignments(assignments): + # Generate a sequence of assignments that is possibly reordered + # to avoid clashes -- i.e. do the equivalent of a tuple assignment, + # reading all sources first, writing all targets next, but optimized + + allsources = [] + src2dest = {} + types = {} + assignments = list(assignments) + for typename, dest, src in assignments: + if src != dest: # ignore 'v=v;' + allsources.append(src) + src2dest.setdefault(src, []).append(dest) + types[dest] = typename + + for starting in allsources: + # starting from some starting variable, follow a chain of assignments + # 'vn=vn-1; ...; v3=v2; v2=v1; v1=starting;' + v = starting + srcchain = [] + while src2dest.get(v): + srcchain.append(v) + v = src2dest[v].pop(0) + if v == starting: + break # loop + if not srcchain: + continue # already done in a previous chain + srcchain.reverse() # ['vn-1', ..., 'v2', 'v1', 'starting'] + code = [] + for pair in zip([v] + srcchain[:-1], srcchain): + code.append('%s = %s;' % pair) + if v == starting: + # assignment loop 'starting=vn-1; ...; v2=v1; v1=starting;' + typename = types[starting] + tmpdecl = cdecl(typename, 'tmp') + code.insert(0, '{ %s = %s;' % (tmpdecl, starting)) + code[-1] = '%s = tmp; }' % (srcchain[-2],) + yield ' '.join(code) Added: pypy/dist/pypy/translator/c/test/test_backendoptimized.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/test_backendoptimized.py Sun Jun 19 15:34:24 2005 @@ -0,0 +1,27 @@ +import autopath +from pypy.translator.tool.buildpyxmodule import skip_missing_compiler +from pypy.translator.translator import Translator +from pypy.translator import backendoptimization + +from pypy.translator.c.test.test_typed import TestTypedTestCase as _TestTypedTestCase + + +class TestTypedOptimizedTestCase(_TestTypedTestCase): + + def getcompiled(self, func): + t = Translator(func, simplifying=True) + # builds starting-types from func_defs + argstypelist = [] + if func.func_defaults: + for spec in func.func_defaults: + if isinstance(spec, tuple): + spec = spec[0] # use the first type only for the tests + argstypelist.append(spec) + a = t.annotate(argstypelist) + a.simplify() + t.specialize() + for graph in t.flowgraphs.values(): + backendoptimization.remove_same_as(graph) + backendoptimization.SSI_to_SSA(graph) + t.checkgraphs() + return skip_missing_compiler(t.ccompile) Added: pypy/dist/pypy/translator/c/test/test_support.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/test_support.py Sun Jun 19 15:34:24 2005 @@ -0,0 +1,20 @@ +from pypy.translator.c.support import gen_assignments + + +def gen_assign(input, expected): + assert ' '.join(gen_assignments(input)) == expected + +def test_gen_assignments(): + yield gen_assign, [('int @', 'a', 'a')], '' + yield gen_assign, [('int @', 'a', 'b')], 'a = b;' + yield gen_assign, [('int @', 'a', 'b'), + ('int @', 'c', 'b')], 'a = b; c = b;' + yield gen_assign, [('int @', 'a', 'b'), + ('int @', 'b', 'c')], 'a = b; b = c;' + yield gen_assign, [('int @', 'b', 'c'), + ('int @', 'a', 'b')], 'a = b; b = c;' + yield gen_assign, [('int @', 'a', 'b'), + ('int @', 'b', 'a')], '{ int tmp = b; b = a; a = tmp; }' + yield gen_assign, [('int @', 'a', 'b'), + ('int @', 'b', 'c'), + ('int @', 'd', 'b')], 'a = b; d = b; b = c;' Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sun Jun 19 15:34:24 2005 @@ -1,6 +1,6 @@ import autopath import sys -import py.test +from py.test import raises from pypy.translator.translator import Translator from pypy.translator.test import snippet from pypy.translator.tool.buildpyxmodule import skip_missing_compiler Deleted: /pypy/dist/pypy/translator/lltransform.py ============================================================================== --- /pypy/dist/pypy/translator/lltransform.py Sun Jun 19 15:34:24 2005 +++ (empty file) @@ -1,134 +0,0 @@ -import autopath -from pypy.translator.translator import Translator -from pypy.objspace.flow.model import Variable, Constant, Block, Link -from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph - - -def remove_same_as(graph): - """Remove all 'same_as' operations. - """ - same_as_positions = [] - def visit(node): - if isinstance(node, Block): - for i, op in enumerate(node.operations): - if op.opname == 'same_as': - same_as_positions.append((node, i)) - traverse(visit, graph) - while same_as_positions: - block, index = same_as_positions.pop() - same_as_result = block.operations[index].result - same_as_arg = block.operations[index].args[0] - # replace the new variable (same_as_result) with the old variable - # (from all subsequent positions) - for op in block.operations[index:]: - if op is not None: - for i in range(len(op.args)): - if op.args[i] == same_as_result: - op.args[i] = same_as_arg - for link in block.exits: - for i in range(len(link.args)): - if link.args[i] == same_as_result: - link.args[i] = same_as_arg - if block.exitswitch == same_as_result: - block.exitswitch = same_as_arg - block.operations[index] = None - - # remove all same_as operations - def visit(node): - if isinstance(node, Block) and node.operations: - node.operations[:] = filter(None, node.operations) - traverse(visit, graph) - - -def SSI_to_SSA(graph): - """Rename the variables in a flow graph as much as possible without - violating the SSA rule. 'SSI' means that each Variable in a flow graph is - defined only once in the whole graph; all our graphs are SSI. This - function does not break that rule, but changes the 'name' of some - Variables to give them the same 'name' as other Variables. The result - looks like an SSA graph. 'SSA' means that each var name appears as the - result of an operation only once in the whole graph, but it can be - passed to other blocks across links. - """ - entrymap = mkentrymap(graph) - consider_blocks = entrymap - renamed = {} - - while consider_blocks: - blocklist = consider_blocks.keys() - consider_blocks = {} - for block in blocklist: - if block is graph.startblock: - continue - links = entrymap[block] - assert links - mapping = {} - for i in range(len(block.inputargs)): - # list of possible vars that can arrive in i'th position - v1 = block.inputargs[i] - names = {v1.name: True} - key = [] - for link in links: - v = link.args[i] - if not isinstance(v, Variable): - break - names[v.name] = True - else: - if len(names) == 2: - oldname = v1.name - del names[oldname] - newname, = names.keys() - while oldname in renamed: - oldname = renamed[oldname] - while newname in renamed: - newname = renamed[newname] - if oldname == newname: - continue - renamed[oldname] = newname - v1._name = newname - # mark all the following blocks as subject to - # possible further optimization - for link in block.exits: - consider_blocks[link.target] = True - # sanity-check that the same name is never used several times in a block - variables_by_name = {} - for block in entrymap: - vars = [op.result for op in block.operations] - for link in block.exits: - vars += link.getextravars() - assert len(dict.fromkeys([v.name for v in vars])) == len(vars), ( - "duplicate variable name in %r" % (block,)) - for v in vars: - variables_by_name.setdefault(v.name, []).append(v) - # sanity-check that variables with the same name have the same concretetype - for vname, vlist in variables_by_name.items(): - vct = [getattr(v, 'concretetype', None) for v in vlist] - assert vct == vct[:1] * len(vct), ( - "variables called %s have mixed concretetypes: %r" % (vname, vct)) - - -# ____________________________________________________________ - -if __name__ == '__main__': - - def is_perfect_number(n=int): - div = 1 - sum = 0 - while div < n: - if n % div == 0: - sum += div - div += 1 - return n == sum - - t = Translator(is_perfect_number) - a = t.annotate([int]) - a.simplify() - t.specialize() - graph = t.getflowgraph() - remove_same_as(graph) - SSI_to_SSA(graph) - checkgraph(graph) - t.view() - f = t.ccompile() - for i in range(1, 33): - print '%3d' % i, is_perfect_number(i) From arigo at codespeak.net Sun Jun 19 18:50:14 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 18:50:14 +0200 (CEST) Subject: [pypy-svn] r13605 - in pypy/dist/pypy: tool translator translator/c/test Message-ID: <20050619165014.F1C3427B82@code1.codespeak.net> Author: arigo Date: Sun Jun 19 18:50:12 2005 New Revision: 13605 Modified: pypy/dist/pypy/tool/unionfind.py pypy/dist/pypy/translator/backendoptimization.py pypy/dist/pypy/translator/c/test/test_backendoptimized.py Log: Sanitized SSI_to_SSA by using the union finder. I'm more confident that this is doing the right thing now. Modified: pypy/dist/pypy/tool/unionfind.py ============================================================================== --- pypy/dist/pypy/tool/unionfind.py (original) +++ pypy/dist/pypy/tool/unionfind.py Sun Jun 19 18:50:12 2005 @@ -4,7 +4,7 @@ class UnionFind(object): - def __init__(self, info_factory): + def __init__(self, info_factory=None): self.link_to_parent = {} self.weight = {} self.info_factory = info_factory @@ -15,9 +15,9 @@ if obj not in self.link_to_parent: raise KeyError, obj - ignore, rep, access = self.find(obj) + ignore, rep, info = self.find(obj) - return access + return info def __contains__(self, obj): return obj in self.link_to_parent @@ -31,9 +31,17 @@ def infos(self): return self.root_info.values() + def find_rep(self, obj): + ignore, rep, info = self.find(obj) + return rep + def find(self, obj): # -> new_root, obj, info if obj not in self.link_to_parent: - info = self.root_info[obj] = self.info_factory(obj) + if self.info_factory: + info = self.info_factory(obj) + else: + info = None + self.root_info[obj] = info self.weight[obj] = 1 self.link_to_parent[obj] = obj return True, obj, info @@ -66,7 +74,8 @@ if w1 < w2: rep1, rep2, info1, info2, = rep2, rep1, info2, info1 - info1.update(info2) + if info1 is not None: + info1.update(info2) self.link_to_parent[rep2] = rep1 Modified: pypy/dist/pypy/translator/backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/backendoptimization.py (original) +++ pypy/dist/pypy/translator/backendoptimization.py Sun Jun 19 18:50:12 2005 @@ -2,6 +2,7 @@ from pypy.translator.translator import Translator from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph +from pypy.tool.unionfind import UnionFind def remove_same_as(graph): @@ -52,8 +53,9 @@ """ entrymap = mkentrymap(graph) consider_blocks = entrymap - renamed = {} + variable_families = UnionFind() + # group variables by families; a family of variables will be identified. while consider_blocks: blocklist = consider_blocks.keys() consider_blocks = {} @@ -66,30 +68,28 @@ for i in range(len(block.inputargs)): # list of possible vars that can arrive in i'th position v1 = block.inputargs[i] - names = {v1.name: True} + v1 = variable_families.find_rep(v1) + inputs = {v1: True} key = [] for link in links: v = link.args[i] if not isinstance(v, Variable): break - names[v.name] = True + v = variable_families.find_rep(v) + inputs[v] = True else: - if len(names) == 2: - oldname = v1.name - del names[oldname] - newname, = names.keys() - while oldname in renamed: - oldname = renamed[oldname] - while newname in renamed: - newname = renamed[newname] - if oldname == newname: - continue - renamed[oldname] = newname - v1._name = newname + if len(inputs) == 2: + variable_families.union(*inputs) # mark all the following blocks as subject to # possible further optimization for link in block.exits: consider_blocks[link.target] = True + # rename variables to give them the name of their familiy representant + for v in variable_families.keys(): + v1 = variable_families.find_rep(v) + if v1 != v: + v._name = v1.name + # sanity-check that the same name is never used several times in a block variables_by_name = {} for block in entrymap: Modified: pypy/dist/pypy/translator/c/test/test_backendoptimized.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_backendoptimized.py (original) +++ pypy/dist/pypy/translator/c/test/test_backendoptimized.py Sun Jun 19 18:50:12 2005 @@ -25,3 +25,13 @@ backendoptimization.SSI_to_SSA(graph) t.checkgraphs() return skip_missing_compiler(t.ccompile) + + def test_remove_same_as(self): + def f(n=bool): + if bool(bool(bool(n))): + return 123 + else: + return 456 + fn = self.getcompiled(f) + assert f(True) == 123 + assert f(False) == 456 From arigo at codespeak.net Sun Jun 19 19:07:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 19:07:33 +0200 (CEST) Subject: [pypy-svn] r13606 - pypy/dist/pypy/translator Message-ID: <20050619170733.D2D9A27B88@code1.codespeak.net> Author: arigo Date: Sun Jun 19 19:07:32 2005 New Revision: 13606 Modified: pypy/dist/pypy/translator/geninterplevel.py Log: Use the SSI_to_SSA optimization in geninterplevel. This allows the generated functions to look nicer, with less copying around all over the place the same value. Modified: pypy/dist/pypy/translator/geninterplevel.py ============================================================================== --- pypy/dist/pypy/translator/geninterplevel.py (original) +++ pypy/dist/pypy/translator/geninterplevel.py Sun Jun 19 19:07:32 2005 @@ -57,6 +57,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.argument import Arguments from pypy.rpython.rarithmetic import r_int, r_uint +from pypy.translator.backendoptimization import SSI_to_SSA from pypy.translator.translator import Translator from pypy.objspace.flow import FlowObjSpace @@ -77,7 +78,7 @@ import pypy # __path__ import py.path -GI_VERSION = '1.1.1' # bump this for substantial changes +GI_VERSION = '1.1.2' # bump this for substantial changes # ____________________________________________________________ def eval_helper(self, typename, expr): @@ -302,8 +303,10 @@ src = linklocalvars[a1] else: src = self.expr(a1, localscope) - left.append(self.expr(a2, localscope)) - right.append(src) + dest = self.expr(a2, localscope) + if src != dest: + left.append(dest) + right.append(src) if left: # anything at all? txt = "%s = %s" % (", ".join(left), ", ".join(right)) if len(txt) <= 65: # arbitrary @@ -1000,6 +1003,14 @@ return name # no success def gen_rpyfunction(self, func): + try: + graph = self.translator.getflowgraph(func) + except Exception, e: + print 20*"*", e + print func + raise + SSI_to_SSA(graph) + checkgraph(graph) f = self.f print >> f, "##SECTION##" # simple to split, afterwards @@ -1011,7 +1022,7 @@ func.func_code.co_firstlineno) print >> f, "##SECTION##" localscope = self.namespace.localScope() - body = list(self.rpyfunction_body(func, localscope)) + body = list(self.rpyfunction_body(graph, localscope)) name_of_defaults = [self.nameof(x, debug=('Default argument of', func)) for x in (func.func_defaults or ())] self.gen_global_declarations() @@ -1022,14 +1033,14 @@ assert cname.startswith('gfunc_') f_name = 'f_' + cname[6:] - # collect all the local variables - graph = self.translator.getflowgraph(func) - localslst = [] - def visit(node): - if isinstance(node, Block): - localslst.extend(node.getvariables()) - traverse(visit, graph) - localnames = [self.expr(a, localscope) for a in uniqueitems(localslst)] +## # collect all the local variables +## graph = self.translator.getflowgraph(func) +## localslst = [] +## def visit(node): +## if isinstance(node, Block): +## localslst.extend(node.getvariables()) +## traverse(visit, graph) +## localnames = [self.expr(a, localscope) for a in uniqueitems(localslst)] # collect all the arguments vararg = varkw = None @@ -1110,7 +1121,7 @@ if docstr is not None: print >> f, docstr - fast_locals = [arg for arg in localnames if arg not in fast_set] +## fast_locals = [arg for arg in localnames if arg not in fast_set] ## # if goto is specialized, the false detection of ## # uninitialized variables goes away. ## if fast_locals and not self.specialize_goto: @@ -1134,25 +1145,7 @@ pass # del self.translator.flowgraphs[func] # got duplicate flowgraphs when doing this! - def rpyfunction_body(self, func, localscope): - try: - graph = self.translator.getflowgraph(func) - except Exception, e: - print 20*"*", e - print func - raise - # not needed, we use tuple assignment! - # remove_direct_loops(graph) - checkgraph(graph) - - allblocks = [] - - f = self.f - t = self.translator - #t.simplify(func) - graph = t.getflowgraph(func) - - + def rpyfunction_body(self, graph, localscope): start = graph.startblock allblocks = ordered_blocks(graph) nblocks = len(allblocks) From arigo at codespeak.net Sun Jun 19 19:30:03 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 19 Jun 2005 19:30:03 +0200 (CEST) Subject: [pypy-svn] r13607 - in pypy/dist/pypy/translator: . goal Message-ID: <20050619173003.1CA5C27B5E@code1.codespeak.net> Author: arigo Date: Sun Jun 19 19:30:00 2005 New Revision: 13607 Modified: pypy/dist/pypy/translator/backendoptimization.py pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/translator.py Log: Use the backendoptimizer at the end of translate_pypy. Modified: pypy/dist/pypy/translator/backendoptimization.py ============================================================================== --- pypy/dist/pypy/translator/backendoptimization.py (original) +++ pypy/dist/pypy/translator/backendoptimization.py Sun Jun 19 19:30:00 2005 @@ -107,6 +107,11 @@ "variables called %s have mixed concretetypes: %r" % (vname, vct)) +def backend_optimizations(graph): + remove_same_as(graph) + SSI_to_SSA(graph) + checkgraph(graph) + # ____________________________________________________________ if __name__ == '__main__': Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sun Jun 19 19:30:00 2005 @@ -15,11 +15,10 @@ -no-a Don't infer annotations, just translate everything -no-s Don't simplify the graph after annotation -no-t Don't type-specialize the graph operations with the C typer + -no-o Don't do backend-oriented optimizations -no-c Don't generate the C code -c Generate the C code, but don't compile it -o Generate and compile the C code, but don't run it - -no-mark-some-objects - Do not mark functions that have SomeObject in their signature. -tcc Equivalent to the envvar PYPY_CC='tcc -shared -o "%s.so" "%s.c"' -- http://fabrice.bellard.free.fr/tcc/ -no-d Disable recording of debugging information @@ -100,17 +99,19 @@ print 'Annotating...' a = t.annotate(inputtypes, policy=PyPyAnnotatorPolicy()) sanity_check_exceptblocks(t) - worstblocks_topten(a) + worstblocks_topten(a, 3) + find_someobjects(t) if a and not options['-no-s']: print 'Simplifying...' a.simplify() if a and not options['-no-t']: print 'Specializing...' t.specialize() - t.frozen = True # cannot freeze if we don't have annotations - if not options['-no-mark-some-objects']: - options['-no-mark-some-objects'] = True # Do not do this again - find_someobjects(t) + if not options['-no-o']: + print 'Back-end optimizations...' + t.backend_optimizations() + if a: + t.frozen = True # cannot freeze if we don't have annotations def sanity_check_exceptblocks(translator): annotator = translator.annotator @@ -251,6 +252,7 @@ '-no-a': False, '-no-s': False, '-no-t': False, + '-no-o': False, '-tcc': False, '-no-d': False, '-load': False, @@ -487,7 +489,7 @@ targetspec_dic = loaded_dic['targetspec_dic'] targetspec = loaded_dic['targetspec'] old_options = loaded_dic['options'] - for name in '-no-a -no-s -no-t'.split(): + for name in '-no-a -no-s -no-t -no-o'.split(): # if one of these options has not been set, before, # then the action has been done and must be prevented, now. if not old_options[name]: Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Sun Jun 19 19:30:00 2005 @@ -147,6 +147,11 @@ self.rtyper = RPythonTyper(self.annotator) self.rtyper.specialize() + def backend_optimizations(self): + from pypy.translator.backendoptimization import backend_optimizations + for graph in self.flowgraphs.values(): + backend_optimizations(graph) + def source(self, func=None): """Returns original Python source. From pedronis at codespeak.net Mon Jun 20 00:48:54 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 20 Jun 2005 00:48:54 +0200 (CEST) Subject: [pypy-svn] r13608 - in pypy/dist/pypy: annotation translator/goal Message-ID: <20050619224854.1813627B61@code1.codespeak.net> Author: pedronis Date: Mon Jun 20 00:48:53 2005 New Revision: 13608 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/translator/goal/query.py Log: stats over list comparisons Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Mon Jun 20 00:48:53 2005 @@ -83,7 +83,12 @@ def consider_newslice(self, s_start, s_stop, s_step): return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)]) + def consider_list_list_eq(self, obj1, obj2): + return obj1, obj2 + def consider_non_int_eq(self, obj1, obj2): + if obj1.knowntype == obj2.knowntype == list: + self.count("list_list_eq", obj1, obj2) return obj1.knowntype.__name__, obj2.knowntype.__name__ def consider_non_int_comp(self, obj1, obj2): Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Mon Jun 20 00:48:53 2005 @@ -337,12 +337,43 @@ for bm_fam in plural_bm_families: print pretty_els(bm_fam.objects) return plural_bm_families - + +class Counters(dict): + + def __getitem__(self, outcome): + if (isinstance(outcome, annmodel.SomeObject) or + isinstance(outcome, tuple) and outcome and + isinstance(outcome[0], annmodel.SomeObject)): + for k in self.iterkeys(): + if k == outcome: + outcome = k + break + else: + raise KeyError + return dict.__getitem__(self, outcome) + + def get(self, outcome, defl): + try: + return self[outcome] + except KeyError: + return defl + + def __setitem__(self, outcome, c): + if (isinstance(outcome, annmodel.SomeObject) or + isinstance(outcome, tuple) and outcome and + isinstance(outcome[0], annmodel.SomeObject)): + for k in self.iterkeys(): + if k == outcome: + outcome = k + break + return dict.__setitem__(self, outcome, c) + + def statsfor(t, category): stats = t.annotator.bookkeeper.stats for_category = stats.classify[category] print "%s total = %d" % (category, len(for_category)) - counters = {} + counters = Counters() for pos, outcome in for_category.iteritems(): counters[outcome] = counters.get(outcome, 0) + 1 def keyrepr(k): From arigo at codespeak.net Mon Jun 20 13:42:56 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Jun 2005 13:42:56 +0200 (CEST) Subject: [pypy-svn] r13613 - in pypy/dist/pypy/rpython: . test Message-ID: <20050620114256.87E4327B5B@code1.codespeak.net> Author: arigo Date: Mon Jun 20 13:42:53 2005 New Revision: 13613 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rlist.py Log: - fix SomeBuiltin.rtyper_makekey() - don't hack the 'hop' object but a copy in BuiltinMethodRepr.rtype_simple_call() - keyword arg 'viewbefore' in interpret() to see the flow graph before the typer modifies it -- useful to debug the typer - support bound methods of prebuilt objects of built-in types (list and str for now) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jun 20 13:42:53 2005 @@ -24,10 +24,12 @@ return BuiltinMethodRepr(rtyper.getrepr(self.s_self), self.methodname) def rtyper_makekey(self): - key = (getattr(self, 'const', None), self.methodname) - if self.s_self is not None: - key += (self.s_self.rtyper_makekey(),) - return key + if self.s_self is None: + # built-in function case + return getattr(self, 'const', None) + else: + # built-in method case + return (self.methodname, self.s_self.rtyper_makekey()) class BuiltinFunctionRepr(Repr): @@ -64,9 +66,10 @@ raise TyperError("missing %s.%s" % ( self.self_repr.__class__.__name__, name)) # hack based on the fact that 'lowleveltype == self_repr.lowleveltype' - assert hop.args_r[0] is self - hop.args_r[0] = self.self_repr - return bltintyper(hop) + hop2 = hop.copy() + assert hop2.args_r[0] is self + hop2.args_r[0] = self.self_repr + return bltintyper(hop2) ##class __extend__(pairtype(SomeBuiltin, SomeObject)): Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon Jun 20 13:42:53 2005 @@ -56,6 +56,7 @@ self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY)))) def convert_const(self, listobj): + listobj = getattr(listobj, '__self__', listobj) # for bound list methods if not isinstance(listobj, list): raise TyperError("expected a list: %r" % (listobj,)) try: Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Mon Jun 20 13:42:53 2005 @@ -44,6 +44,7 @@ def convert_const(self, value): if value is None: return nullptr(STR) + value = getattr(value, '__self__', value) # for bound string methods if not isinstance(value, str): raise TyperError("not a str: %r" % (value,)) try: Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Mon Jun 20 13:42:53 2005 @@ -26,10 +26,11 @@ if func(pyobjectptr(cls)).typeptr == klass: return cls -def gengraph(func, argtypes=[]): +def gengraph(func, argtypes=[], viewbefore=False): t = Translator(func) t.annotate(argtypes) - #t.view() + if viewbefore: + t.view() global typer # we need it for find_exception typer = RPythonTyper(t.annotator) typer.specialize() @@ -37,8 +38,9 @@ t.checkgraphs() return t, typer -def interpret(func, values, view=False): - t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) for x in values]) +def interpret(func, values, view=False, viewbefore=False): + t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) for x in values], + viewbefore) if view: t.view() interp = LLInterpreter(t.flowgraphs, typer) Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Mon Jun 20 13:42:53 2005 @@ -163,3 +163,10 @@ assert res == 'k' res = interpret(dummyfn, [-2]) assert res == 'z' + +def test_bound_list_method(): + klist = [1,2,3] + # for testing constant methods without actually mutating the constant + def dummyfn(n): + klist.extend([]) + interpret(dummyfn, [7]) From arigo at codespeak.net Mon Jun 20 13:52:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Jun 2005 13:52:09 +0200 (CEST) Subject: [pypy-svn] r13614 - pypy/dist/pypy/translator/c/test Message-ID: <20050620115209.C18F227B60@code1.codespeak.net> Author: arigo Date: Mon Jun 20 13:52:08 2005 New Revision: 13614 Modified: pypy/dist/pypy/translator/c/test/test_annotated.py Log: Test for list comprehension. Modified: pypy/dist/pypy/translator/c/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/c/test/test_annotated.py Mon Jun 20 13:52:08 2005 @@ -134,3 +134,10 @@ for i in range(1, 33): perfect = fn(i) assert perfect is (i in (6,28)) + + def test_prime(self): + fn = self.getcompiled(snippet.prime) + result = [fn(i) for i in range(1, 21)] + assert result == [False, True, True, False, True, False, True, False, + False, False, True, False, True, False, False, False, + True, False, True, False] From arigo at codespeak.net Mon Jun 20 14:06:26 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Jun 2005 14:06:26 +0200 (CEST) Subject: [pypy-svn] r13615 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050620120626.2202427B60@code1.codespeak.net> Author: arigo Date: Mon Jun 20 14:06:21 2005 New Revision: 13615 Added: pypy/dist/pypy/translator/c/g_debuginfo.h (contents, props changed) pypy/dist/pypy/translator/c/symboltable.py (contents, props changed) pypy/dist/pypy/translator/c/test/test_symboltable.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/g_module.h pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/node.py Log: Enable insepction of the global variable's state in a GenC-generated C module. The SymbolTable class provides a way to access each global by C name, and presents a lltype-compatible read-only interface on the pointers. Implemented by generating all struct offsets in the C source so that the SymbolTable can find out where each structure field actually is in memory. Then it uses the C function debuginfo_peek() to read raw data, and the 'struct' module to convert it to Python integers. Added: pypy/dist/pypy/translator/c/g_debuginfo.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/g_debuginfo.h Mon Jun 20 14:06:21 2005 @@ -0,0 +1,42 @@ + +/************************************************************/ + /*** C header subsection: debugging info ***/ + +/* NOTE: this is not included by . + The #include is generated manually if needed. */ + +#undef METHODDEF_DEBUGINFO +#define METHODDEF_DEBUGINFO \ + { "debuginfo_offset", debuginfo_offset, METH_VARARGS }, \ + { "debuginfo_global", debuginfo_global, METH_VARARGS }, \ + { "debuginfo_peek", debuginfo_peek, METH_VARARGS }, + + +static PyObject *debuginfo_offset(PyObject *self, PyObject *args) +{ + int index; + if (!PyArg_ParseTuple(args, "i", &index)) + return NULL; + return PyInt_FromLong(debuginfo_offsets[index]); +} + +static PyObject *debuginfo_global(PyObject *self, PyObject *args) +{ + int index; + if (!PyArg_ParseTuple(args, "i", &index)) + return NULL; + return PyLong_FromVoidPtr(debuginfo_globals[index]); +} + +static PyObject *debuginfo_peek(PyObject *self, PyObject *args) +{ + PyObject *o; + int size; + void *start; + if (!PyArg_ParseTuple(args, "Oi", &o, &size)) + return NULL; + start = PyLong_AsVoidPtr(o); + if (PyErr_Occurred()) + return NULL; + return PyString_FromStringAndSize((char *)start, size); +} Modified: pypy/dist/pypy/translator/c/g_module.h ============================================================================== --- pypy/dist/pypy/translator/c/g_module.h (original) +++ pypy/dist/pypy/translator/c/g_module.h Mon Jun 20 14:06:21 2005 @@ -2,19 +2,22 @@ /************************************************************/ /*** C header subsection: CPython-extension-module-ness ***/ - -#ifndef COUNT_OP_MALLOCS -# define MODULE_INITFUNC(modname) \ - static PyMethodDef my_methods[] = { (char *)NULL, (PyCFunction)NULL }; \ - PyMODINIT_FUNC init##modname(void) +#ifdef COUNT_OP_MALLOCS +# define METHODDEF_MALLOC_COUNTERS \ + { "malloc_counters", malloc_counters, METH_VARARGS }, #else -# define MODULE_INITFUNC(modname) \ - static PyMethodDef my_methods[] = { \ - { "malloc_counters", malloc_counters }, \ - { (char *)NULL, (PyCFunction)NULL } }; \ - PyMODINIT_FUNC init##modname(void) +# define METHODDEF_MALLOC_COUNTERS /* nothing */ #endif +#define METHODDEF_DEBUGINFO /* nothing, unless overridden by g_debuginfo.h */ + +#define MODULE_INITFUNC(modname) \ + static PyMethodDef my_methods[] = { \ + METHODDEF_MALLOC_COUNTERS \ + METHODDEF_DEBUGINFO \ + { (char *)NULL, (PyCFunction)NULL } }; \ + PyMODINIT_FUNC init##modname(void) + #define SETUP_MODULE(modname) \ PyObject *m = Py_InitModule(#modname, my_methods); \ PyModule_AddStringConstant(m, "__sourcefile__", __FILE__); \ @@ -26,7 +29,7 @@ if (RPythonError == NULL) \ return; \ PyModule_AddObject(m, "RPythonError", RPythonError); \ - if (setup_globalfunctions(globalfunctiondefs) < 0) \ + if (setup_globalfunctions(globalfunctiondefs, #modname) < 0) \ return; \ if (setup_initcode(frozen_initcode, FROZEN_INITCODE_SIZE) < 0) \ return; \ @@ -67,12 +70,15 @@ return 0; } -static int setup_globalfunctions(globalfunctiondef_t* def) +static int setup_globalfunctions(globalfunctiondef_t* def, char* modname) { PyObject* fn; + PyObject* modname_o = PyString_FromString(modname); + if (modname_o == NULL) + return -1; for (; def->p != NULL; def++) { - fn = PyCFunction_New(&def->ml, NULL); + fn = PyCFunction_NewEx(&def->ml, NULL, modname_o); if (fn == NULL) return -1; fn->ob_type = &PyGenCFunction_Type; Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Mon Jun 20 14:06:21 2005 @@ -16,7 +16,8 @@ return db, pf -def genc(translator, targetdir=None, modulename=None, compile=True): +def genc(translator, targetdir=None, modulename=None, compile=True, + symtable=True): """Generate C code starting at the translator's entry point. The files are written to the targetdir if specified. If 'compile' is True, compile and return the new module. @@ -31,12 +32,19 @@ elif isinstance(targetdir, str): targetdir = py.path.local(targetdir) targetdir.ensure(dir=1) + if symtable: + from pypy.translator.c.symboltable import SymbolTable + symboltable = SymbolTable() + else: + symboltable = None cfile = gen_source(db, modulename, targetdir, # defines={'COUNT_OP_MALLOCS': 1}, - exports = {translator.entrypoint.func_name: pf}) + exports = {translator.entrypoint.func_name: pf}, + symboltable = symboltable) if not compile: return cfile m = make_module_from_c(cfile, include_dirs = [autopath.this_dir]) + symboltable.attach(m) # hopefully temporary hack return m @@ -87,7 +95,8 @@ blank = True -def gen_source(database, modulename, targetdir, defines={}, exports={}): +def gen_source(database, modulename, targetdir, defines={}, exports={}, + symboltable=None): if isinstance(targetdir, str): targetdir = py.path.local(targetdir) filename = targetdir.join(modulename + '.c') @@ -107,6 +116,27 @@ gen_readable_parts_of_main_c_file(f, database) # + # Debugging info + # + if symboltable: + print >> f + print >> f, '/*******************************************************/' + print >> f, '/*** Debugging info ***/' + print >> f + print >> f, 'static int debuginfo_offsets[] = {' + for node in database.structdeflist: + for expr in symboltable.generate_type_info(database, node): + print >> f, '\t%s,' % expr + print >> f, '\t0 };' + print >> f, 'static void *debuginfo_globals[] = {' + for node in database.globalcontainers(): + if not isinstance(node, PyObjectNode): + result = symboltable.generate_global_info(database, node) + print >> f, '\t%s,' % (result,) + print >> f, '\tNULL };' + print >> f, '#include "g_debuginfo.h"' + + # # PyObject support (strange) code # pyobjmaker = database.pyobjmaker Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Mon Jun 20 14:06:21 2005 @@ -26,6 +26,7 @@ def __init__(self, db, STRUCT, varlength=1): self.db = db self.STRUCT = STRUCT + self.LLTYPE = STRUCT self.varlength = varlength def setup(self): @@ -148,6 +149,11 @@ FIELD_T): yield line + def debug_offsets(self): + # generate number exprs giving the offset of the elements in the struct + for name, typename in self.fields: + yield 'offsetof(struct %s, %s)' % (self.name, name) + class ArrayDefNode: refcount = None @@ -156,6 +162,7 @@ def __init__(self, db, ARRAY, varlength=1): self.db = db self.ARRAY = ARRAY + self.LLTYPE = ARRAY self.varlength = varlength def setup(self): @@ -225,6 +232,16 @@ yield '\t}' yield '}' + def debug_offsets(self): + # generate three offsets for debugging inspection + yield 'offsetof(struct %s, length)' % (self.name,) + if self.ARRAY.OF != Void: + yield 'offsetof(struct %s, items[0])' % (self.name,) + yield 'offsetof(struct %s, items[1])' % (self.name,) + else: + yield '-1' + yield '-1' + def generic_dealloc(db, expr, T): if isinstance(T, Ptr) and T._needsgc(): @@ -446,6 +463,7 @@ assert T == RuntimeTypeInfo assert isinstance(obj.about, GcStruct) self.db = db + self.T = T self.obj = obj defnode = db.gettypedefnode(obj.about) self.implementationtypename = 'void (@)(struct %s *)' % ( Added: pypy/dist/pypy/translator/c/symboltable.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/symboltable.py Mon Jun 20 14:06:21 2005 @@ -0,0 +1,143 @@ +from pypy.rpython.lltype import * + + +class SymbolTable: + """For debugging purposes only. This collects the information + needed to know the byte-layout of the data structures generated in + a C source. + """ + + def __init__(self): + self.next_number = 0 + self.next_pointer = 0 + self.lltypes = {} + self.globals = {} + self.module = None + + def attach(self, module): + self.module = module + module.__symboltable__ = self + + def generate_type_info(self, db, defnode): + self.lltypes[defnode.LLTYPE] = self.next_number + for number_expr in defnode.debug_offsets(): + self.next_number += 1 + yield number_expr + + def generate_global_info(self, db, node): + self.globals[node.name] = self.next_pointer, node.T + self.next_pointer += 1 + return node.ptrname + + # __________ public interface (mapping-like) __________ + + def keys(self): + return self.globals.keys() + + def __getitem__(self, globalname): + ptrindex, T = self.globals[globalname] + address = self.module.debuginfo_global(ptrindex) + return debugptr(Ptr(T), address, self) + + def __iter__(self): + return self.globals.iterkeys() + +def getsymboltable(module): + if isinstance(module, str): + module = __import__(module) + return module.__symboltable__ + +# ____________________________________________________________ + +import struct + +PrimitiveTag = { + Signed: 'l', + Unsigned: 'L', + Float: 'd', + Char: 'c', + Bool: 'b', + } +ptr_size = struct.calcsize('P') + + +class debugptr: + + def __init__(self, PTRTYPE, address, symtable): + self._TYPE = PTRTYPE + self._address = address + self._symtable = symtable + + def __eq__(self, other): + return self._address == other._address + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + raise TypeError("pointer objects are not hashable") + + def __repr__(self): + addr = self._address + if addr < 0: + addr += 256 ** ptr_size + return '' % (self._TYPE.TO, addr) + + def __nonzero__(self): + return self._address != 0 + + def _nth_offset(self, n): + index = self._symtable.lltypes[self._TYPE.TO] + return self._symtable.module.debuginfo_offset(index + n) + + def _read(self, FIELD_TYPE, offset): + if not self: # NULL + raise ValueError, 'dereferencing NULL pointer' + module = self._symtable.module + address = self._address + offset + if isinstance(FIELD_TYPE, ContainerType): + return debugptr(Ptr(FIELD_TYPE), address, self._symtable) + elif isinstance(FIELD_TYPE, Primitive): + if FIELD_TYPE == Void: + return None + tag = PrimitiveTag[FIELD_TYPE] + size = struct.calcsize(tag) + data = module.debuginfo_peek(address, size) + result, = struct.unpack(tag, data) + return result + elif isinstance(FIELD_TYPE, Ptr): + data = module.debuginfo_peek(address, ptr_size) + result, = struct.unpack('P', data) + return debugptr(FIELD_TYPE, result, self._symtable) + else: + raise TypeError("unknown type %r" % (FIELD_TYPE,)) + + def __getattr__(self, name): + STRUCT = self._TYPE.TO + if not name.startswith('_') and isinstance(STRUCT, Struct): + try: + field_index = list(STRUCT._names).index(name) + except ValueError: + raise AttributeError, name + FIELD_TYPE = STRUCT._flds[name] + offset = self._nth_offset(field_index) + return self._read(FIELD_TYPE, offset) + raise AttributeError, name + + def __len__(self): + ARRAY = self._TYPE.TO + if isinstance(ARRAY, Array): + length_offset = self._nth_offset(0) + return self._read(Signed, length_offset) + raise TypeError, "not an array: %r" % (ARRAY,) + + def __getitem__(self, index): + ARRAY = self._TYPE.TO + if isinstance(ARRAY, Array): + if not (0 <= index < len(self)): + raise IndexError("array index out of bounds") + item0_offset = self._nth_offset(1) + item1_offset = self._nth_offset(2) + offset = item0_offset + (item1_offset-item0_offset) * index + return self._read(ARRAY.OF, offset) + raise TypeError, "not an array: %r" % (ARRAY,) Added: pypy/dist/pypy/translator/c/test/test_symboltable.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/test_symboltable.py Mon Jun 20 14:06:21 2005 @@ -0,0 +1,21 @@ +from pypy.translator.translator import Translator +from pypy.translator.c.symboltable import getsymboltable + +def test_simple(): + glist = [4, 5, 6] + def f(x): + return glist[x] + t = Translator(f) + t.annotate([int]) + t.specialize() + + f = t.ccompile() + assert f(1) == 5 + assert f(2) == 6 + + symtable = getsymboltable(f.__module__) + debug_list = symtable['g_list'] # XXX find a way to find this name + assert len(debug_list.items) == 3 + assert debug_list.items[0] == 4 + assert debug_list.items[1] == 5 + assert debug_list.items[2] == 6 From ac at codespeak.net Mon Jun 20 14:26:35 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 14:26:35 +0200 (CEST) Subject: [pypy-svn] r13616 - pypy/extradoc/sprintinfo Message-ID: <20050620122635.58BEE27B60@code1.codespeak.net> Author: ac Date: Mon Jun 20 14:26:35 2005 New Revision: 13616 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: I will attend. Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Mon Jun 20 14:26:35 2005 @@ -14,6 +14,7 @@ Beatrice D?ring visiting private Anders Lehmann 22nd-26th SGS Michael Hudson 23rd- private +Anders Chrigstr?m 23rd- private =================== ============== ===================== @@ -36,6 +37,7 @@ Christian Tismer ? ? Adrien Di Mascio 1st-5th July Nice Hotel Ludovic Aubry 1st-5th July Nice Hotel +Anders Chrigstr?m 1st-7th July private =================== ============== ===================== @@ -54,4 +56,5 @@ Lene Wagner 8th July ? Christian Tismer 8th July ? Stephan Busemann 8th July ? +Anders Chrigstr?m 8th July private =================== ============== ===================== From arigo at codespeak.net Mon Jun 20 14:30:50 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Jun 2005 14:30:50 +0200 (CEST) Subject: [pypy-svn] r13617 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050620123050.11F7927B5B@code1.codespeak.net> Author: arigo Date: Mon Jun 20 14:30:46 2005 New Revision: 13617 Modified: pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/symboltable.py pypy/dist/pypy/translator/c/test/test_symboltable.py Log: Implement id() in rtyper and genc. Use it to return from small examples the address of global structures. From this address, the SymbolTable can inspect the global structures and recursively everything reachable from them. Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Mon Jun 20 14:30:46 2005 @@ -72,6 +72,14 @@ else: return hop.genop('int_is_true', [vlen], resulttype=Bool) + def rtype_id(self, hop): + if not isinstance(self.lowleveltype, Ptr): + raise TyperError('id() of an instance of the non-pointer %r' % ( + self,)) + vobj, = hop.inputargs(self) + # XXX + return hop.genop('cast_ptr_to_int', [vobj], resulttype=Signed) + def rtype_iter(self, hop): r_iter = self.make_iterator_repr() return r_iter.newiter(hop) Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Mon Jun 20 14:30:46 2005 @@ -143,6 +143,7 @@ #define OP_CAST_INT_TO_UINT(x,r,err) r = (unsigned long)(x); #define OP_CAST_CHAR_TO_INT(x,r,err) r = (long)(x); #define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); +#define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ /* _________________ certain implementations __________________ */ Modified: pypy/dist/pypy/translator/c/symboltable.py ============================================================================== --- pypy/dist/pypy/translator/c/symboltable.py (original) +++ pypy/dist/pypy/translator/c/symboltable.py Mon Jun 20 14:30:46 2005 @@ -34,9 +34,18 @@ def keys(self): return self.globals.keys() - def __getitem__(self, globalname): - ptrindex, T = self.globals[globalname] - address = self.module.debuginfo_global(ptrindex) + def __getitem__(self, globalname_or_address): + if isinstance(globalname_or_address, str): + ptrindex, T = self.globals[globalname] + address = self.module.debuginfo_global(ptrindex) + else: + for ptrindex, T in self.globals.values(): + address = self.module.debuginfo_global(ptrindex) + if address == globalname_or_address: + break + else: + raise KeyError("no global object at 0x%x" % + (globalname_or_address,)) return debugptr(Ptr(T), address, self) def __iter__(self): Modified: pypy/dist/pypy/translator/c/test/test_symboltable.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_symboltable.py (original) +++ pypy/dist/pypy/translator/c/test/test_symboltable.py Mon Jun 20 14:30:46 2005 @@ -4,17 +4,17 @@ def test_simple(): glist = [4, 5, 6] def f(x): - return glist[x] + return glist[x], id(glist) t = Translator(f) t.annotate([int]) t.specialize() f = t.ccompile() - assert f(1) == 5 - assert f(2) == 6 + res, addr = f(1) + assert res == 5 symtable = getsymboltable(f.__module__) - debug_list = symtable['g_list'] # XXX find a way to find this name + debug_list = symtable[addr] assert len(debug_list.items) == 3 assert debug_list.items[0] == 4 assert debug_list.items[1] == 5 From arigo at codespeak.net Mon Jun 20 14:48:18 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Jun 2005 14:48:18 +0200 (CEST) Subject: [pypy-svn] r13618 - pypy/dist/pypy/translator/goal Message-ID: <20050620124818.6E45527B5B@code1.codespeak.net> Author: arigo Date: Mon Jun 20 14:48:16 2005 New Revision: 13618 Modified: pypy/dist/pypy/translator/goal/targetrpystone2.py Log: Checking that rpystone2 appears to do its job: the global variables are the same after running it through GenC than after running it over Python. Modified: pypy/dist/pypy/translator/goal/targetrpystone2.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone2.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone2.py Mon Jun 20 14:48:16 2005 @@ -1,6 +1,7 @@ import buildcache2 from pypy.objspace.std.objspace import StdObjSpace from pypy.translator.test import rpystone +from pypy.translator.c.symboltable import getsymboltable # __________ Entry point __________ @@ -9,7 +10,7 @@ rpystone.setslow(False) def entry_point(): - return rpystone.pystones(LOOPS) + return rpystone.pystones(LOOPS), id(rpystone.g) # _____ Define and setup target _____ def target(): @@ -19,7 +20,7 @@ def run(c_entry_point): res = c_entry_point() - benchtime, stones = res + (benchtime, stones), g_addr = res print "translated rpystone.pystones/fast time for %d passes = %g" % \ (LOOPS, benchtime) print "This machine benchmarks at %g translated rpystone/fast pystones/second" % stones @@ -28,8 +29,54 @@ print "rpystone.pystones/fast time for %d passes = %g" % \ (50000, benchtime) print "This machine benchmarks at %g rpystone/fast pystones/second" % stones + symtable = getsymboltable(c_entry_point.__module__) + check_g_results(symtable, g_addr) +def check_g_results(symtable, g_addr): + try: + g_ptr = symtable[g_addr] + except KeyError: + print "No low-level equivalent of structure 'g' found." + else: + assert g_ptr.inst_BoolGlob == rpystone.g.BoolGlob + assert g_ptr.inst_Char1Glob == rpystone.g.Char1Glob + assert g_ptr.inst_Char2Glob == rpystone.g.Char2Glob + compare_array_of_array(g_ptr.inst_Array2Glob, rpystone.g.Array2Glob) + compare_record(g_ptr.inst_PtrGlb, rpystone.g.PtrGlb) + compare_record(g_ptr.inst_PtrGlbNext, rpystone.g.PtrGlbNext) + + +def compare_array_of_array(array, pylist): + assert len(array.items) == len(pylist) + for i in range(len(pylist)): + x1 = array.items[i] + x2 = pylist[i] + compare_array(x1, x2) + +def compare_array(array, pylist): + assert len(array.items) == len(pylist) + for i in range(len(pylist)): + x1 = array.items[i] + x2 = pylist[i] + assert x1 == x2 + +def compare_record(struct, pyrecord): + if pyrecord is None: + assert not struct + else: + assert struct + compare_record(struct.inst_PtrComp, pyrecord.PtrComp) + assert struct.inst_Discr == pyrecord.Discr + assert struct.inst_EnumComp == pyrecord.EnumComp + assert struct.inst_IntComp == pyrecord.IntComp + compare_string(struct.inst_StringComp, pyrecord.StringComp) + +def compare_string(str, pystr): + assert len(str.chars) == len(pystr) + for i in range(len(pystr)): + assert str.chars[i] == pystr[i] + #if __name__ == "__main__": # # just run it without translation # LOOPS = 50000 From ac at codespeak.net Mon Jun 20 15:08:40 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 15:08:40 +0200 (CEST) Subject: [pypy-svn] r13619 - pypy/dist/pypy/objspace/std Message-ID: <20050620130840.74A0027B62@code1.codespeak.net> Author: ac Date: Mon Jun 20 15:08:40 2005 New Revision: 13619 Modified: pypy/dist/pypy/objspace/std/unicodetype.py Log: Minor fix to temporary hack. ;) Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Mon Jun 20 15:08:40 2005 @@ -48,7 +48,7 @@ def unicode_from_encoded_object(obj, encoding, errors): # Fix later for buffer if type(obj).__name__ == 'buffer': - obj = obj.buf + obj = str(obj) if encoding is None: encoding = sys.getdefaultencoding() decoder = codecs.getdecoder(encoding) From arigo at codespeak.net Mon Jun 20 16:07:35 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 20 Jun 2005 16:07:35 +0200 (CEST) Subject: [pypy-svn] r13623 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050620140735.5AF0E27B5B@code1.codespeak.net> Author: arigo Date: Mon Jun 20 16:07:33 2005 New Revision: 13623 Modified: pypy/dist/pypy/translator/c/ll_include.h pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_annotated.py Log: Generate more correct reference counters for immortal global GcStructs... Well, more correct, but not exactly elegant: officially, we need a value equal to the number of references to this global from other globals, plus one. The following upper bound "approximation" will do... #define REFCOUNT_IMMORTAL (INT_MAX/2) Modified: pypy/dist/pypy/translator/c/ll_include.h ============================================================================== --- pypy/dist/pypy/translator/c/ll_include.h (original) +++ pypy/dist/pypy/translator/c/ll_include.h Mon Jun 20 16:07:33 2005 @@ -3,6 +3,11 @@ /*** C header subsection: operations on LowLevelTypes ***/ +/* XXX hack to initialize the refcount of global structures: officially, + we need a value equal to the number of references to this global from + other globals, plus one. This upper bound "approximation" will do... */ +#define REFCOUNT_IMMORTAL (INT_MAX/2) + #define OP_ZERO_MALLOC(size, r, err) { \ r = (void*) PyObject_Malloc(size); \ if (r == NULL) FAIL_EXCEPTION(err, Exc_MemoryError, "out of memory")\ Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Mon Jun 20 16:07:33 2005 @@ -314,7 +314,7 @@ def initializationexpr(self, decoration=''): yield '{' if needs_refcount(self.T): - yield '\t1,' + yield '\tREFCOUNT_IMMORTAL,' defnode = self.db.gettypedefnode(self.T) for name in self.T._names: value = getattr(self.obj, name) @@ -340,7 +340,7 @@ def initializationexpr(self, decoration=''): yield '{' if needs_refcount(self.T): - yield '\t1,' + yield '\tREFCOUNT_IMMORTAL,' if self.T.OF == Void or len(self.obj.items) == 0: yield '\t%d' % len(self.obj.items) yield '}' Modified: pypy/dist/pypy/translator/c/test/test_annotated.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_annotated.py (original) +++ pypy/dist/pypy/translator/c/test/test_annotated.py Mon Jun 20 16:07:33 2005 @@ -141,3 +141,20 @@ assert result == [False, True, True, False, True, False, True, False, False, False, True, False, True, False, False, False, True, False, True, False] + + def test_mutate_global(self): + class Stuff: + pass + g1 = Stuff(); g1.value = 1 + g2 = Stuff(); g2.value = 2 + g3 = Stuff(); g3.value = 3 + g1.next = g3 + g2.next = g3 + g3.next = g3 + def do_things(): + g1.next = g1 + g2.next = g1 + g3.next = g2 + return g3.next.next.value + fn = self.getcompiled(do_things) + assert fn() == 1 From ac at codespeak.net Mon Jun 20 16:44:53 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 16:44:53 +0200 (CEST) Subject: [pypy-svn] r13626 - pypy/dist/pypy/translator/c Message-ID: <20050620144453.4C85D27B62@code1.codespeak.net> Author: ac Date: Mon Jun 20 16:44:53 2005 New Revision: 13626 Modified: pypy/dist/pypy/translator/c/node.py Log: skip void fields in debuf offset table Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Mon Jun 20 16:44:53 2005 @@ -151,8 +151,14 @@ def debug_offsets(self): # generate number exprs giving the offset of the elements in the struct - for name, typename in self.fields: - yield 'offsetof(struct %s, %s)' % (self.name, name) + STRUCT = self.STRUCT + for name in STRUCT._names: + FIELD_T = self.c_struct_field_type(name) + if FIELD_T == Void: + yield '-1' + else: + cname = self.c_struct_field_name(name) + yield 'offsetof(struct %s, %s)' % (self.name, cname) class ArrayDefNode: From ac at codespeak.net Mon Jun 20 16:46:32 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 16:46:32 +0200 (CEST) Subject: [pypy-svn] r13627 - in pypy/dist/pypy/rpython: . test Message-ID: <20050620144632.A026827B5B@code1.codespeak.net> Author: ac Date: Mon Jun 20 16:46:32 2005 New Revision: 13627 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/test/test_rint.py Log: Implement builtin chr(). Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Jun 20 16:46:32 2005 @@ -217,6 +217,10 @@ assert type(b) is bool return int(b) + def op_cast_int_to_chr(self, b): + assert type(b) is int + return chr(b) + def op_cast_bool_to_float(self, b): assert type(b) is bool return float(b) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon Jun 20 16:46:32 2005 @@ -95,6 +95,10 @@ assert hop.nb_args == 1 return hop.args_r[0].rtype_float(hop) +def rtype_builtin_chr(hop): + assert hop.nb_args == 1 + return hop.args_r[0].rtype_chr(hop) + #def rtype_builtin_range(hop): see rrange.py def rtype_intmask(hop): Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Mon Jun 20 16:46:32 2005 @@ -1,8 +1,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.objspace import op_appendices -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -195,6 +195,10 @@ vlist = hop.inputargs(Float) return vlist[0] + def rtype_chr(_, hop): + vlist = hop.inputargs(Char) + return vlist[0] + def rtype_is_true(self, hop): if self.lowleveltype == Unsigned: vlist = hop.inputargs(Unsigned) @@ -282,3 +286,9 @@ return llops.gencapicall('PyInt_FromLong', [v], resulttype=pyobj_repr) return NotImplemented + +class __extend__(pairtype(IntegerRepr, CharRepr)): + def convert_from_to((r_from, r_to), v, llops): + if r_from.lowleveltype == Signed: + return llops.genop('cast_int_to_chr', [v], resulttype=Char) + return NotImplemented Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Mon Jun 20 16:46:32 2005 @@ -2,6 +2,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet +from pypy.rpython.test.test_llinterp import interpret class TestSnippet(object): @@ -36,3 +37,15 @@ # XXX TODO test if all binary operations are implemented for opname in annmodel.BINARY_OPERATIONS: print 'BINARY_OPERATIONS:', opname + + +def test_char_constant(): + def dummyfn(i): + return chr(i) + res = interpret(dummyfn, [ord(' ')]) + assert res == ' ' + res = interpret(dummyfn, [0]) + assert res == '\0' + res = interpret(dummyfn, [ord('a')]) + assert res == 'a' + From ac at codespeak.net Mon Jun 20 18:05:44 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 18:05:44 +0200 (CEST) Subject: [pypy-svn] r13629 - in pypy/dist/pypy: rpython rpython/test translator/c translator/c/test Message-ID: <20050620160544.3BC7427B5B@code1.codespeak.net> Author: ac Date: Mon Jun 20 18:05:43 2005 New Revision: 13629 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/test/test_typed.py Log: Implement 'is'. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Jun 20 18:05:43 2005 @@ -209,6 +209,24 @@ # well, actually this is what's now in the globals. return cast_pointer(tp, obj) + def op_ptr_eq(self, ptr1, ptr2): + assert isinstance(ptr1, _ptr) + assert isinstance(ptr2, _ptr) + return ptr1 == ptr2 + + def op_ptr_ne(self, ptr1, ptr2): + assert isinstance(ptr1, _ptr) + assert isinstance(ptr2, _ptr) + return ptr1 != ptr2 + + def op_ptr_nonzero(self, ptr1): + assert isinstance(ptr1, _ptr) + return bool(ptr1) + + def op_ptr_iszero(self, ptr1): + assert isinstance(ptr1, _ptr) + return not bool(ptr1) + def op_cast_int_to_float(self, i): assert type(i) is int return float(i) @@ -224,6 +242,7 @@ def op_cast_bool_to_float(self, b): assert type(b) is bool return float(b) + # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Mon Jun 20 18:05:43 2005 @@ -101,6 +101,23 @@ def rtyper_makekey(self): return None +# ____ generic binary operations _____________________________ + + +class __extend__(pairtype(Repr, Repr)): + + def rtype_is_((robj1, robj2), hop): + if (not isinstance(robj1.lowleveltype, Ptr) or + not isinstance(robj2.lowleveltype, Ptr)): + raise TyperError('is of instances of the non-pointers: %r, %r' % ( + robj1, robj2)) + if robj1.lowleveltype != robj2.lowleveltype: + raise TyperError('is of instances of different pointer types: %r, %r' % ( + robj1, robj2)) + + v_list = hop.inputargs(robj1, robj2) + return hop.genop('ptr_eq', v_list, resulttype=Bool) + # ____________________________________________________________ class TyperError(Exception): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Mon Jun 20 18:05:43 2005 @@ -1,9 +1,9 @@ import types -from pypy.annotation.pairtype import pairtype +from pypy.annotation.pairtype import pairtype, pair from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct +from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct, Bool from pypy.rpython.lltype import Ptr, malloc, nullptr from pypy.rpython.rmodel import Repr, TyperError from pypy.rpython import rclass @@ -67,6 +67,8 @@ def getFrozenPBCRepr(rtyper, s_pbc): if len(s_pbc.prebuiltinstances) <= 1: + if s_pbc.const is None: + return none_frozen_pbc_repr return single_frozen_pbc_repr else: pbcs = [pbc for pbc in s_pbc.prebuiltinstances.keys() @@ -95,6 +97,31 @@ single_frozen_pbc_repr = SingleFrozenPBCRepr() +# __ None ____________________________________________________ +class NoneFrozenPBCRepr(SingleFrozenPBCRepr): + pass + +none_frozen_pbc_repr = NoneFrozenPBCRepr() + + +def rtype_is_None(robj1, rnone2, hop, pos=0): + if not isinstance(robj1.lowleveltype, Ptr): + raise TyperError('is None of instance of the non-pointer: %r' % (robj1)) + v1 = hop.inputarg(robj1, pos) + return hop.genop('ptr_iszero', [v1], resulttype=Bool) + +class __extend__(pairtype(Repr, NoneFrozenPBCRepr)): + + def rtype_is_((robj1, rnone2), hop): + return rtype_is_None(robj1, rnone2, hop) + +class __extend__(pairtype(NoneFrozenPBCRepr, Repr)): + + def rtype_is_((rnone1, robj2), hop): + return rtype_is_None(robj2, rnone1, hop, pos=1) + + +# ____________________________________________________________ class MultipleFrozenPBCRepr(Repr): """Representation selected for multiple non-callable pre-built constants.""" Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Mon Jun 20 18:05:43 2005 @@ -170,3 +170,34 @@ def dummyfn(n): klist.extend([]) interpret(dummyfn, [7]) + +def test_list_is(): + def dummyfn(): + l1 = [] + return l1 is l1 + res = interpret(dummyfn, []) + assert res is True + def dummyfn(): + l2 = [1, 2] + return l2 is l2 + res = interpret(dummyfn, []) + assert res is True + def dummyfn(): + l1 = [2] + l2 = [1, 2] + return l1 is l2 + res = interpret(dummyfn, []) + assert res is False + def dummyfn(): + l1 = [1, 2] + l2 = [1, 2] + return l1 is l2 + res = interpret(dummyfn, []) + assert res is False + + def dummyfn(): + l1 = None + l2 = [1, 2] + return l1 is l2 + res = interpret(dummyfn, []) + assert res is False Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Mon Jun 20 18:05:43 2005 @@ -438,7 +438,10 @@ def OP_PTR_NONZERO(self, op, err): return '%s = (%s != NULL);' % (self.expr(op.result), self.expr(op.args[0])) - + def OP_PTR_ISZERO(self, op, err): + return '%s = (%s == NULL);' % (self.expr(op.result), + self.expr(op.args[0])) + def OP_PTR_EQ(self, op, err): return '%s = (%s == %s);' % (self.expr(op.result), self.expr(op.args[0]), Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Mon Jun 20 18:05:43 2005 @@ -64,6 +64,20 @@ 1, 9, 2, 11, 'h') + def test_is(self): + def testfn(): + l1 = [] + return l1 is l1 + fn = self.getcompiled(testfn) + result = fn() + assert result is True + def testfn(): + l1 = [] + return l1 is None + fn = self.getcompiled(testfn) + result = fn() + assert result is False + def test_slice_long(self): "the parent's test_slice_long() makes no sense here" From ac at codespeak.net Mon Jun 20 18:31:54 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 18:31:54 +0200 (CEST) Subject: [pypy-svn] r13631 - in pypy/dist/pypy: rpython translator/c Message-ID: <20050620163154.AD01127B5B@code1.codespeak.net> Author: ac Date: Mon Jun 20 18:31:54 2005 New Revision: 13631 Added: pypy/dist/pypy/translator/c/char_include.h (contents, props changed) Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/primitive.py Log: Make rpystone work. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon Jun 20 18:31:54 2005 @@ -235,7 +235,7 @@ assert type(b) is bool return int(b) - def op_cast_int_to_chr(self, b): + def op_cast_int_to_char(self, b): assert type(b) is int return chr(b) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Mon Jun 20 18:31:54 2005 @@ -290,5 +290,5 @@ class __extend__(pairtype(IntegerRepr, CharRepr)): def convert_from_to((r_from, r_to), v, llops): if r_from.lowleveltype == Signed: - return llops.genop('cast_int_to_chr', [v], resulttype=Char) + return llops.genop('cast_int_to_char', [v], resulttype=Char) return NotImplemented Added: pypy/dist/pypy/translator/c/char_include.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/char_include.h Mon Jun 20 18:31:54 2005 @@ -0,0 +1,15 @@ +/************************************************************/ +/*** C header subsection: operations between chars ***/ + +/*** unary operations ***/ + +/*** binary operations ***/ + + +#define OP_CHAR_EQ(x,y,r,err) r = ((x) == (y)); +#define OP_CHAR_NE(x,y,r,err) r = ((x) != (y)); +#define OP_CHAR_LE(x,y,r,err) r = ((x) <= (y)); +#define OP_CHAR_GT(x,y,r,err) r = ((x) > (y)); +#define OP_CHAR_LT(x,y,r,err) r = ((x) < (y)); +#define OP_CHAR_GE(x,y,r,err) r = ((x) >= (y)); + Modified: pypy/dist/pypy/translator/c/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/g_include.h (original) +++ pypy/dist/pypy/translator/c/g_include.h Mon Jun 20 18:31:54 2005 @@ -16,6 +16,7 @@ #include "g_module.h" #include "int_include.h" +#include "char_include.h" #include "float_include.h" #include "ll_include.h" #include "pyobj_include.h" Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Mon Jun 20 18:31:54 2005 @@ -21,7 +21,7 @@ def name_char(value): assert type(value) is str and len(value) == 1 if ' ' <= value < '\x7f': - return "'%s'" % (value.replace("'", r"\'").replace("\\", r"\\"),) + return "'%s'" % (value.replace("\\", r"\\").replace("'", r"\'"),) else: return '%d' % ord(value) From ac at codespeak.net Mon Jun 20 19:06:56 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Mon, 20 Jun 2005 19:06:56 +0200 (CEST) Subject: [pypy-svn] r13632 - pypy/dist/pypy/translator/goal Message-ID: <20050620170656.7B88C27B51@code1.codespeak.net> Author: ac Date: Mon Jun 20 19:06:55 2005 New Revision: 13632 Added: pypy/dist/pypy/translator/goal/targetrpystonex.py - copied, changed from r13624, pypy/dist/pypy/translator/goal/targetrpystone2.py Modified: pypy/dist/pypy/translator/goal/targetrpystone.py pypy/dist/pypy/translator/goal/targetrpystone2.py Log: Refactor the targetrpythone files. Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Mon Jun 20 19:06:55 2005 @@ -1,37 +1,14 @@ -from pypy.objspace.std.objspace import StdObjSpace -from pypy.translator.test import rpystone - -# __________ Entry point __________ +import targetrpystonex LOOPS = 150000 -# rpystone.setslow(False) +# targetrpystonex.rpystone.setslow(False) -def entry_point(): - return rpystone.pystones(LOOPS) - -# _____ Define and setup target _____ -def target(): - return entry_point, [] +# __________ Entry point __________ +# _____ Define and setup target _____ # _____ Run translated _____ -def run(c_entry_point): - res = c_entry_point() - benchtime, stones = res - print "translated rpystone.pystones time for %d passes = %g" % \ - (LOOPS, benchtime) - print "This machine benchmarks at %g translated rpystone pystones/second" % stones - print "CPython:" - benchtime, stones = rpystone.pystones(50000) - print "rpystone.pystones time for %d passes = %g" % \ - (50000, benchtime) - print "This machine benchmarks at %g rpystone pystones/second" % stones - - -#if __name__ == "__main__": -# # just run it without translation -# LOOPS = 50000 -# target() -# run(entry_point) - +(entry_point, + target, + run) = targetrpystonex.make_target_definition(LOOPS, "normal") Modified: pypy/dist/pypy/translator/goal/targetrpystone2.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone2.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone2.py Mon Jun 20 19:06:55 2005 @@ -1,85 +1,15 @@ -import buildcache2 -from pypy.objspace.std.objspace import StdObjSpace -from pypy.translator.test import rpystone -from pypy.translator.c.symboltable import getsymboltable +import targetrpystonex -# __________ Entry point __________ LOOPS = 1000000 -rpystone.setslow(False) +targetrpystonex.rpystone.setslow(False) -def entry_point(): - return rpystone.pystones(LOOPS), id(rpystone.g) - -# _____ Define and setup target _____ -def target(): - return entry_point, [] +# __________ Entry point __________ +# _____ Define and setup target _____ # _____ Run translated _____ -def run(c_entry_point): - res = c_entry_point() - (benchtime, stones), g_addr = res - print "translated rpystone.pystones/fast time for %d passes = %g" % \ - (LOOPS, benchtime) - print "This machine benchmarks at %g translated rpystone/fast pystones/second" % stones - print "CPython:" - benchtime, stones = rpystone.pystones(50000) - print "rpystone.pystones/fast time for %d passes = %g" % \ - (50000, benchtime) - print "This machine benchmarks at %g rpystone/fast pystones/second" % stones - symtable = getsymboltable(c_entry_point.__module__) - check_g_results(symtable, g_addr) - - -def check_g_results(symtable, g_addr): - try: - g_ptr = symtable[g_addr] - except KeyError: - print "No low-level equivalent of structure 'g' found." - else: - assert g_ptr.inst_BoolGlob == rpystone.g.BoolGlob - assert g_ptr.inst_Char1Glob == rpystone.g.Char1Glob - assert g_ptr.inst_Char2Glob == rpystone.g.Char2Glob - compare_array_of_array(g_ptr.inst_Array2Glob, rpystone.g.Array2Glob) - compare_record(g_ptr.inst_PtrGlb, rpystone.g.PtrGlb) - compare_record(g_ptr.inst_PtrGlbNext, rpystone.g.PtrGlbNext) - - -def compare_array_of_array(array, pylist): - assert len(array.items) == len(pylist) - for i in range(len(pylist)): - x1 = array.items[i] - x2 = pylist[i] - compare_array(x1, x2) - -def compare_array(array, pylist): - assert len(array.items) == len(pylist) - for i in range(len(pylist)): - x1 = array.items[i] - x2 = pylist[i] - assert x1 == x2 - -def compare_record(struct, pyrecord): - if pyrecord is None: - assert not struct - else: - assert struct - compare_record(struct.inst_PtrComp, pyrecord.PtrComp) - assert struct.inst_Discr == pyrecord.Discr - assert struct.inst_EnumComp == pyrecord.EnumComp - assert struct.inst_IntComp == pyrecord.IntComp - compare_string(struct.inst_StringComp, pyrecord.StringComp) - -def compare_string(str, pystr): - assert len(str.chars) == len(pystr) - for i in range(len(pystr)): - assert str.chars[i] == pystr[i] - -#if __name__ == "__main__": -# # just run it without translation -# LOOPS = 50000 -# target() -# run(entry_point) - +(entry_point, + target, + run) = targetrpystonex.make_target_definition(LOOPS, "fast") Copied: pypy/dist/pypy/translator/goal/targetrpystonex.py (from r13624, pypy/dist/pypy/translator/goal/targetrpystone2.py) ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone2.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystonex.py Mon Jun 20 19:06:55 2005 @@ -1,36 +1,43 @@ -import buildcache2 -from pypy.objspace.std.objspace import StdObjSpace from pypy.translator.test import rpystone from pypy.translator.c.symboltable import getsymboltable -# __________ Entry point __________ -LOOPS = 1000000 +def make_target_definition(LOOPS, version): + def entry_point(loops): + g = rpystone.g + g.IntGlob = 0 + g.BoolGlob = 0 + g.Char1Glob = '\0' + g.Char2Glob = '\0' + for i in range(51): + g.Array1Glob[i] = 0 + for i in range(51): + for j in range(51): + g.Array2Glob[i][j] = 0 + g.PtrGlb = None + g.PtrGlbNext = None + return rpystone.pystones(loops), id(g) -rpystone.setslow(False) - -def entry_point(): - return rpystone.pystones(LOOPS), id(rpystone.g) + def target(): + return entry_point, [int] -# _____ Define and setup target _____ -def target(): - return entry_point, [] - -# _____ Run translated _____ - -def run(c_entry_point): - res = c_entry_point() - (benchtime, stones), g_addr = res - print "translated rpystone.pystones/fast time for %d passes = %g" % \ - (LOOPS, benchtime) - print "This machine benchmarks at %g translated rpystone/fast pystones/second" % stones - print "CPython:" - benchtime, stones = rpystone.pystones(50000) - print "rpystone.pystones/fast time for %d passes = %g" % \ - (50000, benchtime) - print "This machine benchmarks at %g rpystone/fast pystones/second" % stones - symtable = getsymboltable(c_entry_point.__module__) - check_g_results(symtable, g_addr) + def run(c_entry_point): + res = c_entry_point(LOOPS) + (benchtime, stones), _ = res + print "translated rpystone.pystones/%s time for %d passes = %g" % \ + (version, LOOPS, benchtime) + print "This machine benchmarks at %g translated rpystone/%s pystones/second" % (stones, version) + res = c_entry_point(50000) + _, g_addr = res + print "CPython:" + benchtime, stones = rpystone.pystones(50000) + print "rpystone.pystones/%s time for %d passes = %g" % \ + (version, 50000, benchtime) + print "This machine benchmarks at %g rpystone/%s pystones/second" % (stones, version) + symtable = getsymboltable(c_entry_point.__module__) + check_g_results(symtable, g_addr) + + return entry_point, target, run def check_g_results(symtable, g_addr): @@ -42,6 +49,7 @@ assert g_ptr.inst_BoolGlob == rpystone.g.BoolGlob assert g_ptr.inst_Char1Glob == rpystone.g.Char1Glob assert g_ptr.inst_Char2Glob == rpystone.g.Char2Glob + compare_array(g_ptr.inst_Array1Glob, rpystone.g.Array1Glob) compare_array_of_array(g_ptr.inst_Array2Glob, rpystone.g.Array2Glob) compare_record(g_ptr.inst_PtrGlb, rpystone.g.PtrGlb) compare_record(g_ptr.inst_PtrGlbNext, rpystone.g.PtrGlbNext) From pedronis at codespeak.net Mon Jun 20 23:56:27 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 20 Jun 2005 23:56:27 +0200 (CEST) Subject: [pypy-svn] r13638 - pypy/dist/pypy/rpython Message-ID: <20050620215627.988BC27B51@code1.codespeak.net> Author: pedronis Date: Mon Jun 20 23:56:25 2005 New Revision: 13638 Modified: pypy/dist/pypy/rpython/rint.py Log: oops, in the end, we don't want int->char as a generic conversion Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Mon Jun 20 23:56:25 2005 @@ -196,8 +196,8 @@ return vlist[0] def rtype_chr(_, hop): - vlist = hop.inputargs(Char) - return vlist[0] + vlist = hop.inputargs(Signed) + return hop.genop('cast_int_to_char', vlist, resulttype=Char) def rtype_is_true(self, hop): if self.lowleveltype == Unsigned: @@ -286,9 +286,3 @@ return llops.gencapicall('PyInt_FromLong', [v], resulttype=pyobj_repr) return NotImplemented - -class __extend__(pairtype(IntegerRepr, CharRepr)): - def convert_from_to((r_from, r_to), v, llops): - if r_from.lowleveltype == Signed: - return llops.genop('cast_int_to_char', [v], resulttype=Char) - return NotImplemented From tismer at codespeak.net Tue Jun 21 00:14:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 21 Jun 2005 00:14:26 +0200 (CEST) Subject: [pypy-svn] r13639 - pypy/dist/pypy/translator/goal Message-ID: <20050620221426.3B5B827B62@code1.codespeak.net> Author: tismer Date: Tue Jun 21 00:14:25 2005 New Revision: 13639 Modified: pypy/dist/pypy/translator/goal/targetrpystone.py pypy/dist/pypy/translator/goal/targetrpystone2.py Log: did some testing with the newly generated code. At first glance, it looks great, if we can trust the timing. For "slow" mode, I get a factor of 43. For "fast"mode, I get 250 or more, and I bumped the iterations to 10**9. But real run-time seems to be several seconds, so I think we can't trust these results. Something must be wrong with the dry-running. Will look abit deeper when on the train. Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Tue Jun 21 00:14:25 2005 @@ -1,6 +1,6 @@ import targetrpystonex -LOOPS = 150000 +LOOPS = 2000000 # targetrpystonex.rpystone.setslow(False) Modified: pypy/dist/pypy/translator/goal/targetrpystone2.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone2.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone2.py Tue Jun 21 00:14:25 2005 @@ -1,7 +1,7 @@ import targetrpystonex -LOOPS = 1000000 +LOOPS = 1000000000 #10**9 targetrpystonex.rpystone.setslow(False) From busemann at codespeak.net Tue Jun 21 10:33:33 2005 From: busemann at codespeak.net (busemann at codespeak.net) Date: Tue, 21 Jun 2005 10:33:33 +0200 (CEST) Subject: [pypy-svn] r13647 - pypy/extradoc/sprintinfo Message-ID: <20050621083333.BF5D127B50@code1.codespeak.net> Author: busemann Date: Tue Jun 21 10:33:33 2005 New Revision: 13647 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: Stephan's details Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Tue Jun 21 10:33:33 2005 @@ -55,6 +55,6 @@ Laura Creighton 8th July private Lene Wagner 8th July ? Christian Tismer 8th July ? -Stephan Busemann 8th July ? +Stephan Busemann 7+8th July Hotel Lilton Anders Chrigstr?m 8th July private -=================== ============== ===================== +=================== ============== ===================== \ No newline at end of file From arigo at codespeak.net Tue Jun 21 12:54:21 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 21 Jun 2005 12:54:21 +0200 (CEST) Subject: [pypy-svn] r13650 - pypy/dist/pypy/translator Message-ID: <20050621105421.3D77427B69@code1.codespeak.net> Author: arigo Date: Tue Jun 21 12:54:19 2005 New Revision: 13650 Modified: pypy/dist/pypy/translator/transform.py Log: For '[a]*b': make transform_allocate() detect cases where between 'newlist' and 'mul' there are other operations, like 'getattr' to compute the expression 'b'. Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Tue Jun 21 12:54:19 2005 @@ -32,20 +32,19 @@ def transform_allocate(self, block_subset): """Transforms [a] * b to alloc_and_set(b, a) where b is int.""" for block in block_subset: - operations = block.operations[:] - n_op = len(operations) - for i in range(0, n_op-1): - op1 = operations[i] - op2 = operations[i+1] - if (op1.opname == 'newlist' and - len(op1.args) == 1 and - op2.opname == 'mul' and - op1.result is op2.args[0] and - self.gettype(op2.args[1]) is int): + length1_lists = {} # maps 'c' to 'a', in the above notation + for i in range(len(block.operations)): + op = block.operations[i] + if (op.opname == 'newlist' and + len(op.args) == 1): + length1_lists[op.result] = op.args[0] + elif (op.opname == 'mul' and + op.args[0] in length1_lists and + self.gettype(op.args[1]) is int): new_op = SpaceOperation('alloc_and_set', - (op2.args[1], op1.args[0]), - op2.result) - block.operations[i+1:i+2] = [new_op] + (op.args[1], length1_lists[op.args[0]]), + op.result) + block.operations[i] = new_op # a[b:c] # --> From arigo at codespeak.net Tue Jun 21 13:48:42 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 21 Jun 2005 13:48:42 +0200 (CEST) Subject: [pypy-svn] r13653 - pypy/dist/pypy/rpython Message-ID: <20050621114842.F30C227B69@code1.codespeak.net> Author: arigo Date: Tue Jun 21 13:48:41 2005 New Revision: 13653 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py Log: - Method calls sanitization, by falling back to function calls code. - Nicer error message for hop.inputarg() argument count mismatch. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Tue Jun 21 13:48:41 2005 @@ -355,30 +355,26 @@ "methods can be found: %r" % ( s_pbc.prebuiltinstances,)) # the low-level representation is just the bound 'self' argument. - self.r_instance = rclass.getinstancerepr(rtyper, self.classdef) - self.lowleveltype = self.r_instance.lowleveltype + self.s_im_self = annmodel.SomeInstance(self.classdef) + self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef) + self.lowleveltype = self.r_im_self.lowleveltype def rtype_simple_call(self, hop): - # XXX the graph of functions used as methods may need to be hacked - # XXX so that its 'self' argument accepts a pointer to an instance of - # XXX the common base class. This is needed to make the direct_call - # XXX below well-typed. - r_class = self.r_instance.rclass + r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] assert isinstance(r_func, FunctionsPBCRepr) - # - # XXX try to unify with FunctionsPBCRepr.rtype_simple_call() - f, rinputs, rresult = r_func.function_signatures.itervalues().next() - vlist = hop.inputargs(self, *rinputs[1:]) # ignore the self from r_func - if r_func.lowleveltype == Void: - assert len(r_func.function_signatures) == 1 - vfunc = hop.inputconst(typeOf(f), f) - else: - vinst = vlist[0] - vcls = self.r_instance.getfield(vinst, '__class__', hop.llops) - vfunc = r_class.getclsfield(vcls, self.methodname, hop.llops) - vlist.insert(0, vfunc) - return hop.genop('direct_call', vlist, resulttype = rresult) + s_func = r_func.s_pbc + + hop2 = hop.copy() + hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' + hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') + + v_im_self = hop.inputarg(self, arg=0) + v_cls = self.r_im_self.getfield(v_im_self, '__class__', hop.llops) + v_func = r_class.getclsfield(v_cls, self.methodname, hop.llops) + hop2.v_s_insertfirstarg(v_func, s_func) # insert 'function' + # now hop2 looks like simple_call(function, self, args...) + return hop2.dispatch() # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jun 21 13:48:41 2005 @@ -417,9 +417,10 @@ inputconst = staticmethod(inputconst) # export via the HighLevelOp class def inputargs(self, *converted_to): - assert len(converted_to) == self.nb_args, ( - "operation argument count mismatch: '%s' has %d arguments" % ( - self.spaceop.opname, self.nb_args)) + if len(converted_to) != self.nb_args: + raise TyperError("operation argument count mismatch:\n" + "'%s' has %d arguments, rtyper wants %d" % ( + self.spaceop.opname, self.nb_args, len(converted_to))) vars = [] for i in range(len(converted_to)): vars.append(self.inputarg(converted_to[i], i)) From ale at codespeak.net Tue Jun 21 14:54:30 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 21 Jun 2005 14:54:30 +0200 (CEST) Subject: [pypy-svn] r13654 - in pypy/dist/pypy/rpython: . test Message-ID: <20050621125430.48F5027B68@code1.codespeak.net> Author: ale Date: Tue Jun 21 14:54:29 2005 New Revision: 13654 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_llinterp.py Log: added added .reverse and .pop .pop is not finished yet ( and maybe not right - ll operations cant call each other, right ? ) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Tue Jun 21 14:54:29 2005 @@ -84,7 +84,17 @@ def rtype_method_extend(self, hop): v_lst1, v_lst2 = hop.inputargs(self, self) hop.gendirectcall(ll_extend, v_lst1, v_lst2) - + + def rtype_method_reverse(self, hop): + v_lst, = hop.inputargs(self) + hop.gendirectcall(ll_reverse,v_lst) + + def rtype_method_pop(self,hop): + v_list,v_index = hop.inputargs(self,Signed) + #v_index = hop.inputconst(Signed,-1) + assert hasattr(v_index,'concretetype') + return hop.gendirectcall(ll_pop,v_list,v_index) + def make_iterator_repr(self): return ListIteratorRepr(self) @@ -98,7 +108,11 @@ else: llfn = ll_getitem return hop.gendirectcall(llfn, v_lst, v_index) - + +## def rtype_method_pop((r_list,r_int),hop): +## v_lst, v_index = hop.inputargs(r_lst, Signed) +## return hop.gendirectcall(ll_pop,v_list,v_index) + def rtype_setitem((r_lst, r_int), hop): v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr) if hop.args_s[1].nonneg: @@ -173,6 +187,20 @@ newitems[length] = newitem l.items = newitems +def ll_pop(l,index): + res = ll_getitem(l,index) + ll_delitem(l,index) + return res + +def ll_reverse(l): + length = len(l.items) + i=0 + while i Author: arigo Date: Tue Jun 21 16:10:27 2005 New Revision: 13655 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/g_support.h pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_genc.py Log: Hacked support for math.exp(). We will soon need a cleaner approach for this. Conversion from PyObject* to rstring, needed by the 'str' operation when applied to PyObjRepr. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Tue Jun 21 16:10:27 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.rpython import lltype from pypy.rpython import rarithmetic -from pypy.rpython.lltype import Void, Signed, Ptr, RuntimeTypeInfo +from pypy.rpython.lltype import Void, Signed, Float, Ptr, RuntimeTypeInfo from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range from pypy.rpython.rmodel import Repr, TyperError @@ -161,5 +161,12 @@ BUILTIN_TYPER[time.clock] = rtype_time_clock +import math +def rtype_math_exp(hop): + vlist = hop.inputargs(Float) + # XXX need PyFPE_START_PROTECT/PyFPE_END_PROTECT/Py_SET_ERRNO_ON_MATH_ERROR + return hop.llops.gencapicall('exp', vlist, resulttype=Float, + includes=["math.h"]) # XXX clean up needed +BUILTIN_TYPER[math.exp] = rtype_math_exp Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jun 21 16:10:27 2005 @@ -146,9 +146,17 @@ return llops.gendirectcall(ll_stritem_nonneg, v, c_zero) return NotImplemented -##class __extend__(pairtype(PyObjRepr, StringRepr)): -## def convert_from_to((r_from, r_to), v, llops): -## XXX +class __extend__(pairtype(PyObjRepr, StringRepr)): + def convert_from_to((r_from, r_to), v, llops): + v_len = llops.gencapicall('PyString_Size', [v], resulttype=Signed) + cstr = inputconst(Void, STR) + v_result = llops.genop('malloc_varsize', [cstr, v_len], + resulttype=Ptr(STR)) + cchars = inputconst(Void, "chars") + v_chars = llops.genop('getsubstruct', [v_result, cchars], + resulttype=Ptr(STR.chars)) + llops.gencapicall('PyString_ToLLCharArray', [v, v_chars]) + return v_result class __extend__(pairtype(StringRepr, PyObjRepr)): def convert_from_to((r_from, r_to), v, llops): @@ -158,7 +166,7 @@ resulttype=Ptr(STR.chars)) v_size = llops.genop('getarraysize', [v_chars], resulttype=Signed) - return llops.gencapicall('PyString_FromRPythonCharArrayAndSize', + return llops.gencapicall('PyString_FromLLCharArrayAndSize', [v_chars, v_size], resulttype=pyobj_repr) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jun 21 16:10:27 2005 @@ -508,12 +508,12 @@ return self.genop('direct_call', [c]+list(args_v), resulttype = typeOf(f).TO.RESULT) - def gencapicall(self, cfnname, args_v, resulttype=None): + def gencapicall(self, cfnname, args_v, resulttype=None, **flags): if isinstance(resulttype, Repr): resulttype = resulttype.lowleveltype argtypes = [v.concretetype for v in args_v] FUNCTYPE = FuncType(argtypes, resulttype or Void) - f = functionptr(FUNCTYPE, cfnname, external="C") + f = functionptr(FUNCTYPE, cfnname, external="C", **flags) cf = inputconst(typeOf(f), f) return self.genop('direct_call', [cf]+list(args_v), resulttype) Modified: pypy/dist/pypy/translator/c/g_support.h ============================================================================== --- pypy/dist/pypy/translator/c/g_support.h (original) +++ pypy/dist/pypy/translator/c/g_support.h Tue Jun 21 16:10:27 2005 @@ -369,5 +369,9 @@ return PyTuple_SetItem(tuple, index, o); } -#define PyString_FromRPythonCharArrayAndSize(itemsarray, size) \ +#define PyString_FromLLCharArrayAndSize(itemsarray, size) \ PyString_FromStringAndSize(itemsarray->items, size) + +#define PyString_ToLLCharArray(s, itemsarray) \ + memcpy(itemsarray->items, PyString_AS_STRING(s), \ + itemsarray->length) Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Tue Jun 21 16:10:27 2005 @@ -108,6 +108,14 @@ for key, value in defines.items(): print >> f, '#define %s %s' % (key, value) print >> f, '#include "Python.h"' + includes = {} + for node in database.globalcontainers(): + for include in node.includes: + includes[include] = True + includes = includes.keys() + includes.sort() + for include in includes: + print >> f, '#include <%s>' % (include,) # # 1) All declarations Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue Jun 21 16:10:27 2005 @@ -263,6 +263,7 @@ class ContainerNode: + includes = () def __init__(self, db, T, obj): self.db = db @@ -396,10 +397,13 @@ self.obj = obj #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) - argnames = self.funcgen.argnames() - self.implementationtypename = db.gettype(T, argnames=argnames) + if self.funcgen: + argnames = self.funcgen.argnames() + self.implementationtypename = db.gettype(T, argnames=argnames) self.name = db.namespace.uniquename('g_' + self.basename()) self.ptrname = self.name + if hasattr(obj, 'includes'): + self.includes = obj.includes def basename(self): return self.obj._name @@ -407,8 +411,16 @@ def enum_dependencies(self): return self.funcgen.allconstantvalues() + def forward_declaration(self): + if self.funcgen: + return ContainerNode.forward_declaration(self) + else: + return [] + def implementation(self): funcgen = self.funcgen + if funcgen is None: + return yield '%s {' % cdecl(self.implementationtypename, self.name) # # declare the local variables @@ -456,7 +468,10 @@ cpython_exc = getattr(fnptr, 'exception_policy', None) == "CPython" return FunctionCodeGenerator(fnptr.graph, db, cpython_exc) elif getattr(fnptr, 'external', None) == 'C': - return CExternalFunctionCodeGenerator(fnptr, db) + if getattr(fnptr, 'includes', None): + return None # assume no wrapper needed + else: + return CExternalFunctionCodeGenerator(fnptr, db) else: raise ValueError, "don't know how to generate code for %r" % (fnptr,) Modified: pypy/dist/pypy/translator/c/test/test_genc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_genc.py (original) +++ pypy/dist/pypy/translator/c/test/test_genc.py Tue Jun 21 16:10:27 2005 @@ -206,3 +206,24 @@ assert t0 <= t1 <= t2 mallocs, frees = module.malloc_counters() assert mallocs == frees + +def test_str(): + def call_str(o): + return str(o) + t = Translator(call_str) + t.annotate([object]) + t.specialize() + #t.view() + + db = LowLevelDatabase(t) + entrypoint = db.get(pyobjectptr(call_str)) + db.complete() + + module = compile_db(db) + + f1 = getattr(module, entrypoint) + lst = (1, [5], "'hello'", lambda x: x+1) + res = f1(lst) + assert res == str(lst) + mallocs, frees = module.malloc_counters() + assert mallocs == frees From ac at codespeak.net Tue Jun 21 16:18:08 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 16:18:08 +0200 (CEST) Subject: [pypy-svn] r13656 - pypy/dist/pypy/translator/c Message-ID: <20050621141808.DEF0E27B68@code1.codespeak.net> Author: ac Date: Tue Jun 21 16:18:08 2005 New Revision: 13656 Modified: pypy/dist/pypy/translator/c/funcgen.py Log: Fix commenting out void generic get/set. Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Tue Jun 21 16:18:08 2005 @@ -77,9 +77,9 @@ v, T, typename = self.lltypes[id(v)] return typename - def expr(self, v): + def expr(self, v, special_case_void=True): if isinstance(v, Variable): - if self.lltypemap(v) == Void: + if self.lltypemap(v) == Void and special_case_void: return '/* nothing */' else: return v.name @@ -366,10 +366,11 @@ # low-level operations def generic_get(self, op, sourceexpr): - newvalue = self.expr(op.result) + T = self.lltypemap(op.result) + newvalue = self.expr(op.result, special_case_void=False) result = ['%s = %s;' % (newvalue, sourceexpr)] # need to adjust the refcount of the result - T = self.lltypemap(op.result) + increfstmt = self.db.cincrefstmt(newvalue, T) if increfstmt: result.append(increfstmt) @@ -379,7 +380,7 @@ return result def generic_set(self, op, targetexpr): - newvalue = self.expr(op.args[2]) + newvalue = self.expr(op.args[2], special_case_void=False) result = ['%s = %s;' % (targetexpr, newvalue)] # need to adjust some refcounts T = self.lltypemap(op.args[2]) From ac at codespeak.net Tue Jun 21 16:19:37 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 16:19:37 +0200 (CEST) Subject: [pypy-svn] r13657 - in pypy/dist/pypy: rpython rpython/test translator/c translator/c/test Message-ID: <20050621141937.8188C27B68@code1.codespeak.net> Author: ac Date: Tue Jun 21 16:19:37 2005 New Revision: 13657 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/test/test_typed.py Log: Add == and != for rpython strings. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue Jun 21 16:19:37 2005 @@ -231,17 +231,21 @@ assert type(i) is int return float(i) - def op_cast_bool_to_int(self, b): - assert type(b) is bool - return int(b) - def op_cast_int_to_char(self, b): assert type(b) is int return chr(b) + def op_cast_bool_to_int(self, b): + assert type(b) is bool + return int(b) + def op_cast_bool_to_float(self, b): assert type(b) is bool return float(b) + + def op_bool_not(self, b): + assert type(b) is bool + return not b # __________________________________________________________ # primitive operations Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jun 21 16:19:37 2005 @@ -97,6 +97,15 @@ return hop.gendirectcall(ll_strconcat, v_str1, v_str2) rtype_inplace_add = rtype_add + def rtype_eq(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_streq, v_str1, v_str2) + + def rtype_ne(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_streq, v_str1, v_str2) + return hop.genop('bool_not', [vres], resulttype=Bool) + class __extend__(CharRepr): def convert_const(self, value): @@ -233,3 +242,17 @@ return newstr +def ll_streq(s1, s2): + len1 = len(s1.chars) + len2 = len(s2.chars) + if len1 != len2: + return False + j = 0 + chars1 = s1.chars + chars2 = s2.chars + while j < len1: + if chars1[j] != chars2[j]: + return False + j += 1 + + return True Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Tue Jun 21 16:19:37 2005 @@ -70,3 +70,23 @@ assert res is True res = interpret(lambda c1, c2: c1 <= c2, ['z', 'a']) assert res is False + +def test_str_compare(): + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] == s2[j] + for i in range(2): + for j in range(6): + res = interpret(fn, [i, j]) + assert res is fn(i, j) + + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] != s2[j] + for i in range(2): + for j in range(6): + res = interpret(fn, [i, j]) + assert res is fn(i, j) + Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Tue Jun 21 16:19:37 2005 @@ -145,6 +145,10 @@ #define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); #define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ +/* bool operations */ + +#define OP_BOOL_NOT(x, r, err) r = !(x); + /* _________________ certain implementations __________________ */ #ifndef HAVE_LONG_LONG Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Tue Jun 21 16:19:37 2005 @@ -77,7 +77,27 @@ fn = self.getcompiled(testfn) result = fn() assert result is False - + + def test_str_compare(self): + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] == s2[j] + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res is testfn(i, j) + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] != s2[j] + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res is testfn(i, j) + def test_slice_long(self): "the parent's test_slice_long() makes no sense here" From ac at codespeak.net Tue Jun 21 17:58:28 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 17:58:28 +0200 (CEST) Subject: [pypy-svn] r13658 - pypy/dist/pypy/annotation Message-ID: <20050621155828.24E6327B51@code1.codespeak.net> Author: ac Date: Tue Jun 21 17:58:27 2005 New Revision: 13658 Modified: pypy/dist/pypy/annotation/unaryop.py Log: in the case of a empty list .join returns an empty string constant Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Tue Jun 21 17:58:27 2005 @@ -291,6 +291,9 @@ def method_join(str, s_list): getbookkeeper().count("str_join", str) + s_item = s_list.listdef.read_item() + if s_item == SomeImpossibleValue(): + return immutablevalue("") return SomeString() def iter(str): From ac at codespeak.net Tue Jun 21 17:59:41 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 17:59:41 +0200 (CEST) Subject: [pypy-svn] r13659 - pypy/dist/pypy/rpython Message-ID: <20050621155941.5CCBB27B60@code1.codespeak.net> Author: ac Date: Tue Jun 21 17:59:41 2005 New Revision: 13659 Modified: pypy/dist/pypy/rpython/rtyper.py Log: allow hl->ll translation to return a bit more than just primitive values (xxx not fully general, we do not a general equality among constant ll objects) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue Jun 21 17:59:41 2005 @@ -265,7 +265,10 @@ if not hop.s_result.is_constant(): raise TyperError("the annotator doesn't agree that '%s' " "returns a constant" % op.opname) - if resultvar.value != hop.s_result.const: + # xxx allow not only primitive const to be returned, but we don't have + # general equality for non-primitive ll constant objects; + # works for strings tough + if resultvar.value != inputconst(hop.r_result, hop.s_result.const).value: raise TyperError("constant mismatch: %r vs %r" % ( resultvar.value, hop.s_result.const)) resulttype = resultvar.concretetype From ac at codespeak.net Tue Jun 21 18:01:00 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 18:01:00 +0200 (CEST) Subject: [pypy-svn] r13660 - in pypy/dist/pypy: rpython rpython/test translator/c/test Message-ID: <20050621160100.A4BC927B60@code1.codespeak.net> Author: ac Date: Tue Jun 21 18:01:00 2005 New Revision: 13660 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/translator/c/test/test_typed.py Log: implemented startswith, endswith, and join for rstrings Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jun 21 18:01:00 2005 @@ -80,7 +80,24 @@ v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strhash, v_str) - + def rtype_method_startswith(_, hop): + v_str, v_value = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_startswith, v_str, v_value) + + def rtype_method_endswith(_, hop): + v_str, v_value = hop.inputargs(string_repr, string_repr) + return hop.gendirectcall(ll_endswith, v_str, v_value) + + def rtype_method_join(_, hop): + r_lst = hop.args_r[1] + s_item = r_lst.listitem.s_value + if s_item == annmodel.SomeImpossibleValue(): + return inputconst(string_repr, "") + elif not s_item.__class__ == annmodel.SomeString: + raise TyperError("join of non-string list: %r" % r_lst) + v_str, v_lst = hop.inputargs(string_repr, r_lst) + return hop.gendirectcall(ll_join, v_str, v_lst) + class __extend__(pairtype(StringRepr, IntegerRepr)): def rtype_getitem(_, hop): v_str, v_index = hop.inputargs(string_repr, Signed) @@ -241,7 +258,6 @@ j += 1 return newstr - def ll_streq(s1, s2): len1 = len(s1.chars) len2 = len(s2.chars) @@ -256,3 +272,77 @@ j += 1 return True + +def ll_startswith(s1, s2): + len1 = len(s1.chars) + len2 = len(s2.chars) + if len1 < len2: + return False + j = 0 + chars1 = s1.chars + chars2 = s2.chars + while j < len2: + if chars1[j] != chars2[j]: + return False + j += 1 + + return True + +def ll_endswith(s1, s2): + len1 = len(s1.chars) + len2 = len(s2.chars) + if len1 < len2: + return False + j = 0 + chars1 = s1.chars + chars2 = s2.chars + offset = len1 - len2 + while j < len2: + if chars1[offset + j] != chars2[j]: + return False + j += 1 + + return True + +emptystr = string_repr.convert_const("") + +def ll_join(s, l): + s_chars = s.chars + s_len = len(s_chars) + items = l.items + num_items = len(items) + if num_items == 0: + return emptystr + itemslen = 0 + i = 0 + while i < num_items: + itemslen += len(items[i].chars) + i += 1 + result = malloc(STR, itemslen + s_len * (num_items - 1)) + res_chars = result.chars + res_index = 0 + i = 0 + item_chars = items[i].chars + item_len = len(item_chars) + j = 0 + while j < item_len: + res_chars[res_index] = item_chars[j] + j += 1 + res_index += 1 + i += 1 + while i < num_items: + j = 0 + while j < s_len: + res_chars[res_index] = s_chars[j] + j += 1 + res_index += 1 + + item_chars = items[i].chars + item_len = len(item_chars) + j = 0 + while j < item_len: + res_chars[res_index] = item_chars[j] + j += 1 + res_index += 1 + i += 1 + return result Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Tue Jun 21 18:01:00 2005 @@ -90,3 +90,36 @@ res = interpret(fn, [i, j]) assert res is fn(i, j) +def test_startswith(): + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] + return s1[i].startswith(s2[j]) + for i in range(2): + for j in range(9): + res = interpret(fn, [i, j]) + assert res is fn(i, j) + +def test_endswith(): + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] + return s1[i].endswith(s2[j]) + for i in range(2): + for j in range(9): + res = interpret(fn, [i, j]) + assert res is fn(i, j) + +def test_join(): + res = interpret(lambda: ''.join([]), []) + assert ''.join(res.chars) == "" + + def fn(i, j): + s1 = [ '', ',', ' and '] + s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']] + return s1[i].join(s2[j]) + + for i in range(3): + for j in range(3): + res = interpret(fn, [i, j]) + assert ''.join(res.chars) == fn(i, j) Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Tue Jun 21 18:01:00 2005 @@ -98,6 +98,37 @@ res = fn(i, j) assert res is testfn(i, j) + def test_str_methods(self): + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] + return s1[i].startswith(s2[j]) + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(9): + res = fn(i, j) + assert res is testfn(i, j) + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] + return s1[i].endswith(s2[j]) + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(9): + res = fn(i, j) + assert res is testfn(i, j) + + def test_str_join(self): + def testfn(i=int, j=int): + s1 = [ '', ',', ' and '] + s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']] + return s1[i].join(s2[j]) + fn = self.getcompiled(testfn) + for i in range(3): + for j in range(3): + res = fn(i, j) + assert res == fn(i, j) + def test_slice_long(self): "the parent's test_slice_long() makes no sense here" From ac at codespeak.net Tue Jun 21 18:24:50 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 18:24:50 +0200 (CEST) Subject: [pypy-svn] r13662 - pypy/dist/pypy/rpython/test Message-ID: <20050621162450.DB51727B51@code1.codespeak.net> Author: ac Date: Tue Jun 21 18:24:50 2005 New Revision: 13662 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rstr.py Log: Extend the testsuite for rstring. Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Tue Jun 21 18:24:50 2005 @@ -48,6 +48,17 @@ res = interp.eval_function(func, values) return res +def make_interpreter(func, example_values, view=False, viewbefore=False): + t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) for x in example_values], + viewbefore) + if view: + t.view() + interp = LLInterpreter(t.flowgraphs, typer) + def evaluate(*values): + return interp.eval_function(func, values) + + return evaluate + #__________________________________________________________________ # tests Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Tue Jun 21 18:24:50 2005 @@ -1,64 +1,62 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, make_interpreter def test_simple(): - def dummyfn(i): + def fn(i): s = 'hello' return s[i] - - t = Translator(dummyfn) - t.annotate([int]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + ev_fn = make_interpreter(fn, [0]) + for i in range(5): + res = ev_fn(i) + assert res == 'hello'[i] def test_nonzero(): - def dummyfn(i, s): + def fn(i, j): + s = ['', 'xx'][j] if i < 0: s = None if i > -2: return bool(s) else: return False - - t = Translator(dummyfn) - t.annotate([int, str]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + ev_fn = make_interpreter(fn, [0, 0]) + for i in [-2, -1, 0]: + for j in range(2): + res = ev_fn(i, j) + assert res is fn(i, j) def test_hash(): - def dummyfn(s): + def fn(i): + if i == 0: + s = '' + else: + s = "xxx" return hash(s) - - t = Translator(dummyfn) - t.annotate([str]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + ev_fn = make_interpreter(fn, [0]) + res = ev_fn(0) + assert res == -1 + res = ev_fn(1) + assert typeOf(res) == Signed def test_concat(): - def dummyfn(s1, s2): - return s1 + s2 - - t = Translator(dummyfn) - t.annotate([str, str]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() + def fn(i, j): + s1 = ['', 'a', 'ab'] + s2 = ['', 'x', 'xy'] + return s1[i] + s2[j] + ev_fn = make_interpreter(fn, [0,0]) + for i in range(3): + for j in range(3): + res = ev_fn(i, j) + assert ''.join(res.chars) == fn(i, j) def test_char_constant(): - def dummyfn(s): + def fn(s): return s + '.' - res = interpret(dummyfn, ['x']) + res = interpret(fn, ['x']) assert len(res.chars) == 2 assert res.chars[0] == 'x' assert res.chars[1] == '.' @@ -76,18 +74,20 @@ s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] == s2[j] + ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = interpret(fn, [i, j]) + res = ev_fn(i, j) assert res is fn(i, j) def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] != s2[j] + ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = interpret(fn, [i, j]) + res = ev_fn(i, j) assert res is fn(i, j) def test_startswith(): @@ -95,9 +95,10 @@ s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] return s1[i].startswith(s2[j]) + ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(9): - res = interpret(fn, [i, j]) + res = ev_fn(i, j) assert res is fn(i, j) def test_endswith(): @@ -105,9 +106,10 @@ s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] return s1[i].endswith(s2[j]) + ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(9): - res = interpret(fn, [i, j]) + res = ev_fn(i, j) assert res is fn(i, j) def test_join(): @@ -118,8 +120,8 @@ s1 = [ '', ',', ' and '] s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']] return s1[i].join(s2[j]) - + ev_fn = make_interpreter(fn, [0,0]) for i in range(3): for j in range(3): - res = interpret(fn, [i, j]) + res = ev_fn(i, j) assert ''.join(res.chars) == fn(i, j) From ac at codespeak.net Tue Jun 21 19:34:57 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 21 Jun 2005 19:34:57 +0200 (CEST) Subject: [pypy-svn] r13665 - in pypy/dist/pypy: rpython rpython/test translator/c/test Message-ID: <20050621173457.528B427B6A@code1.codespeak.net> Author: ac Date: Tue Jun 21 19:34:56 2005 New Revision: 13665 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/translator/c/test/test_typed.py Log: Added <, <=, >=, > and iteration for rstrings. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue Jun 21 19:34:56 2005 @@ -247,6 +247,10 @@ assert type(b) is bool return not b + def op_cast_char_to_int(self, b): + assert type(b) is str and len(b) == 1 + return ord(b) + # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Tue Jun 21 19:34:56 2005 @@ -98,6 +98,9 @@ v_str, v_lst = hop.inputargs(string_repr, r_lst) return hop.gendirectcall(ll_join, v_str, v_lst) + def make_iterator_repr(self): + return string_iterator_repr + class __extend__(pairtype(StringRepr, IntegerRepr)): def rtype_getitem(_, hop): v_str, v_index = hop.inputargs(string_repr, Signed) @@ -122,7 +125,31 @@ v_str1, v_str2 = hop.inputargs(string_repr, string_repr) vres = hop.gendirectcall(ll_streq, v_str1, v_str2) return hop.genop('bool_not', [vres], resulttype=Bool) - + + def rtype_lt(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_lt', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_le(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_le', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_ge(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_ge', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + + def rtype_gt(_, hop): + v_str1, v_str2 = hop.inputargs(string_repr, string_repr) + vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2) + return hop.genop('int_gt', [vres, hop.inputconst(Signed, 0)], + resulttype=Bool) + class __extend__(CharRepr): def convert_const(self, value): @@ -258,6 +285,24 @@ j += 1 return newstr +def ll_strcmp(s1, s2): + chars1 = s1.chars + chars2 = s2.chars + len1 = len(chars1) + len2 = len(chars2) + + if len1 < len2: + cmplen = len1 + else: + cmplen = len2 + i = 0 + while i < cmplen: + diff = ord(chars1[i]) - ord(chars2[i]) + if diff != 0: + return diff + i += 1 + return len1 - len2 + def ll_streq(s1, s2): len1 = len(s1.chars) len2 = len(s2.chars) @@ -346,3 +391,35 @@ res_index += 1 i += 1 return result + +# ____________________________________________________________ +# +# Iteration. + +class StringIteratorRepr(Repr): + lowleveltype = Ptr(GcStruct('stringiter', + ('string', string_repr.lowleveltype), + ('index', Signed))) + def newiter(self, hop): + v_str, = hop.inputargs(string_repr) + return hop.gendirectcall(ll_striter, v_str) + + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) + return hop.gendirectcall(ll_strnext, v_iter) + +string_iterator_repr = StringIteratorRepr() + +def ll_striter(string): + iter = malloc(string_iterator_repr.lowleveltype.TO) + iter.string = string + iter.index = 0 + return iter + +def ll_strnext(iter): + chars = iter.string.chars + index = iter.index + if index >= len(chars): + raise StopIteration + iter.index = index + 1 + return chars[index] Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Tue Jun 21 19:34:56 2005 @@ -53,6 +53,23 @@ res = ev_fn(i, j) assert ''.join(res.chars) == fn(i, j) +def test_iter(): + def fn(i): + s = ['', 'a', 'hello'][i] + i = 0 + for c in s: + if c != s[i]: + return False + i += 1 + if i == len(s): + return True + return False + + ev_fn = make_interpreter(fn, [0]) + for i in range(3): + res = ev_fn(i) + assert res is True + def test_char_constant(): def fn(s): return s + '.' @@ -90,6 +107,47 @@ res = ev_fn(i, j) assert res is fn(i, j) + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] < s2[j] + ev_fn = make_interpreter(fn, [0,0]) + for i in range(2): + for j in range(6): + res = ev_fn(i, j) + assert res is fn(i, j) + + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] <= s2[j] + ev_fn = make_interpreter(fn, [0,0]) + for i in range(2): + for j in range(6): + res = ev_fn(i, j) + assert res is fn(i, j) + + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] >= s2[j] + ev_fn = make_interpreter(fn, [0,0]) + for i in range(2): + for j in range(6): + res = ev_fn(i, j) + assert res is fn(i, j) + + def fn(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] > s2[j] + ev_fn = make_interpreter(fn, [0,0]) + for i in range(2): + for j in range(6): + res = ev_fn(i, j) + assert res is fn(i, j) + + def test_startswith(): def fn(i, j): s1 = ['one', 'two'] Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Tue Jun 21 19:34:56 2005 @@ -88,6 +88,7 @@ for j in range(6): res = fn(i, j) assert res is testfn(i, j) + def testfn(i=int, j=int): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] @@ -98,6 +99,46 @@ res = fn(i, j) assert res is testfn(i, j) + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] < s2[j] + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res is testfn(i, j) + + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] <= s2[j] + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res is testfn(i, j) + + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] > s2[j] + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res is testfn(i, j) + + def testfn(i=int, j=int): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] >= s2[j] + fn = self.getcompiled(testfn) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res is testfn(i, j) + def test_str_methods(self): def testfn(i=int, j=int): s1 = ['one', 'two'] From pedronis at codespeak.net Tue Jun 21 22:31:12 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 21 Jun 2005 22:31:12 +0200 (CEST) Subject: [pypy-svn] r13668 - pypy/dist/pypy/translator/goal Message-ID: <20050621203112.C13DC27B5A@code1.codespeak.net> Author: pedronis Date: Tue Jun 21 22:31:11 2005 New Revision: 13668 Added: pypy/dist/pypy/translator/goal/richards.py - copied unchanged from r13667, user/pedronis/richards.py pypy/dist/pypy/translator/goal/targetrichards.py - copied, changed from r13665, pypy/dist/pypy/translator/goal/targetrpystonex.py Log: a target based on a (R)Python port of the classic richards benchmark Copied: pypy/dist/pypy/translator/goal/targetrichards.py (from r13665, pypy/dist/pypy/translator/goal/targetrpystonex.py) ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystonex.py (original) +++ pypy/dist/pypy/translator/goal/targetrichards.py Tue Jun 21 22:31:11 2005 @@ -1,93 +1,17 @@ -from pypy.translator.test import rpystone -from pypy.translator.c.symboltable import getsymboltable +import richards +entry_point = richards.entry_point -def make_target_definition(LOOPS, version): - def entry_point(loops): - g = rpystone.g - g.IntGlob = 0 - g.BoolGlob = 0 - g.Char1Glob = '\0' - g.Char2Glob = '\0' - for i in range(51): - g.Array1Glob[i] = 0 - for i in range(51): - for j in range(51): - g.Array2Glob[i][j] = 0 - g.PtrGlb = None - g.PtrGlbNext = None - return rpystone.pystones(loops), id(g) +# _____ Define and setup target ___ - def target(): - return entry_point, [int] - - def run(c_entry_point): - res = c_entry_point(LOOPS) - (benchtime, stones), _ = res - print "translated rpystone.pystones/%s time for %d passes = %g" % \ - (version, LOOPS, benchtime) - print "This machine benchmarks at %g translated rpystone/%s pystones/second" % (stones, version) - res = c_entry_point(50000) - _, g_addr = res - print "CPython:" - benchtime, stones = rpystone.pystones(50000) - print "rpystone.pystones/%s time for %d passes = %g" % \ - (version, 50000, benchtime) - print "This machine benchmarks at %g rpystone/%s pystones/second" % (stones, version) - symtable = getsymboltable(c_entry_point.__module__) - check_g_results(symtable, g_addr) - - return entry_point, target, run - - -def check_g_results(symtable, g_addr): - try: - g_ptr = symtable[g_addr] - except KeyError: - print "No low-level equivalent of structure 'g' found." - else: - assert g_ptr.inst_BoolGlob == rpystone.g.BoolGlob - assert g_ptr.inst_Char1Glob == rpystone.g.Char1Glob - assert g_ptr.inst_Char2Glob == rpystone.g.Char2Glob - compare_array(g_ptr.inst_Array1Glob, rpystone.g.Array1Glob) - compare_array_of_array(g_ptr.inst_Array2Glob, rpystone.g.Array2Glob) - compare_record(g_ptr.inst_PtrGlb, rpystone.g.PtrGlb) - compare_record(g_ptr.inst_PtrGlbNext, rpystone.g.PtrGlbNext) - - -def compare_array_of_array(array, pylist): - assert len(array.items) == len(pylist) - for i in range(len(pylist)): - x1 = array.items[i] - x2 = pylist[i] - compare_array(x1, x2) - -def compare_array(array, pylist): - assert len(array.items) == len(pylist) - for i in range(len(pylist)): - x1 = array.items[i] - x2 = pylist[i] - assert x1 == x2 - -def compare_record(struct, pyrecord): - if pyrecord is None: - assert not struct - else: - assert struct - compare_record(struct.inst_PtrComp, pyrecord.PtrComp) - assert struct.inst_Discr == pyrecord.Discr - assert struct.inst_EnumComp == pyrecord.EnumComp - assert struct.inst_IntComp == pyrecord.IntComp - compare_string(struct.inst_StringComp, pyrecord.StringComp) +def target(): + return entry_point, [] -def compare_string(str, pystr): - assert len(str.chars) == len(pystr) - for i in range(len(pystr)): - assert str.chars[i] == pystr[i] +# _____ Run translated _____ +def run(c_entry_point): + print "Translated:" + richards.main(c_entry_point) + print "CPython:" + richards.main() -#if __name__ == "__main__": -# # just run it without translation -# LOOPS = 50000 -# target() -# run(entry_point) From tismer at codespeak.net Wed Jun 22 00:42:24 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 22 Jun 2005 00:42:24 +0200 (CEST) Subject: [pypy-svn] r13671 - pypy/dist/pypy/translator/test Message-ID: <20050621224224.AB8F527B60@code1.codespeak.net> Author: tismer Date: Wed Jun 22 00:42:23 2005 New Revision: 13671 Modified: pypy/dist/pypy/translator/test/rpystone.py Log: removed range, because it made measures very flaky. On my machine, I get around a factor of 40 for slow mode and some unbelievable 1600 for fast mode. The latter is probably due to code removal. But that's fine, too. For real testing, we should use something that produces a result that cannot be ignored by optimizatiion, tho. Modified: pypy/dist/pypy/translator/test/rpystone.py ============================================================================== --- pypy/dist/pypy/translator/test/rpystone.py (original) +++ pypy/dist/pypy/translator/test/rpystone.py Wed Jun 22 00:42:23 2005 @@ -110,8 +110,13 @@ #global PtrGlbNext starttime = clock() - for i in range(loops): - pass + #for i in range(loops): + # this is bad with very large values of loops + # XXX xrange support? + i = 0 + while i < loops: + i += 1 + # the above is most likely to vanish in C :-( nulltime = clock() - starttime g.PtrGlbNext = Record() @@ -127,7 +132,11 @@ EnumLoc = None # addition for flow space starttime = clock() - for i in range(loops): + #for i in range(loops): + # this is bad with very large values of loops + # XXX xrange support? + i = 0 + while i < loops: if XP5:Proc5() if XP4:Proc4() IntLoc1 = 2 @@ -150,6 +159,7 @@ IntLoc2 = IntLoc3 / IntLoc1 IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 if XP2:IntLoc1 = Proc2(IntLoc1) + i += 1 benchtime = clock() - starttime - nulltime return benchtime, (loops / benchtime) From hpk at codespeak.net Wed Jun 22 10:23:46 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 22 Jun 2005 10:23:46 +0200 (CEST) Subject: [pypy-svn] r13682 - pypy/dist/pypy/documentation/website Message-ID: <20050622082346.48F7327B70@code1.codespeak.net> Author: hpk Date: Wed Jun 22 10:23:45 2005 New Revision: 13682 Modified: pypy/dist/pypy/documentation/website/news.txt Log: add a link to the attendees list in the news page Modified: pypy/dist/pypy/documentation/website/news.txt ============================================================================== --- pypy/dist/pypy/documentation/website/news.txt (original) +++ pypy/dist/pypy/documentation/website/news.txt Wed Jun 22 10:23:45 2005 @@ -12,17 +12,20 @@ Next Sprint after EuroPython 2005 1st-7th July ====================================================== -The next sprint is scheduled right after EuroPython_ 2005 in G?teborg, Sweden. -We take a day of break after the conference and start sprinting from 1st-7th -of July 2005. See the `sprint announcement`_. The sprint theme is related -strongly to `translation`_ and working towards getting a first self-contained -PyPy version. Additionally there will be a four day Pre-EuroPython sprint for -people who already are familiar with the PyPy code base. *(05/04/2005, -12/06/2005)* +The next sprint is scheduled right after EuroPython_ 2005 in +G?teborg, Sweden. We take a day of break after the conference +and start sprinting from 1st-7th of July 2005. See the +`sprint announcement`_ and the `list of people coming`_. The +sprint theme is related strongly to `translation`_ and working +towards getting a first self-contained PyPy version. +Additionally there will be a four day Pre-EuroPython sprint +for people who already are familiar with the PyPy code base. +*(05/04/2005, 12/06/2005, 22/06/2005)* .. _EuroPython: http://europython.org .. _`translation`: ../translation.html .. _`sprint announcement`: EP2005-announcement.html +.. _`list of people coming`: http://codespeak.net/pypy/index.cgi?extradoc/sprintinfo/EP2005-people.html First PyPy release! =================== From arigo at codespeak.net Wed Jun 22 12:11:41 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 22 Jun 2005 12:11:41 +0200 (CEST) Subject: [pypy-svn] r13684 - in pypy/dist/pypy/rpython: . test Message-ID: <20050622101141.D3C6927B70@code1.codespeak.net> Author: arigo Date: Wed Jun 22 12:11:39 2005 New Revision: 13684 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rrange.py pypy/dist/pypy/rpython/test/test_rrange.py Log: More tests for rrange. Supports floordiv and truediv in llinterp. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Wed Jun 22 12:11:39 2005 @@ -259,8 +259,8 @@ for typ in (float, int): typname = typ.__name__ - for opname in ('add', 'sub', 'mul', 'div', 'gt', 'lt', - 'ge', 'ne', 'le', 'eq'): + for opname in ('add', 'sub', 'mul', 'div', 'floordiv', 'truediv', + 'gt', 'lt', 'ge', 'ne', 'le', 'eq'): assert opname in opimpls exec py.code.Source(""" def %(typname)s_%(opname)s(x, y): Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Wed Jun 22 12:11:39 2005 @@ -59,12 +59,7 @@ def ll_rangeitem(l, i, step): if i<0: - # XXX ack. cannot call ll_rangelen() here for now :-( - if step > 0: - length = (l.stop - l.start + (step-1)) // step - else: - length = (l.start - l.stop - (step+1)) // (-step) - #assert length >= 0 + length = ll_rangelen(l, step) i += length return l.start + i*step Modified: pypy/dist/pypy/rpython/test/test_rrange.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rrange.py (original) +++ pypy/dist/pypy/rpython/test/test_rrange.py Wed Jun 22 12:11:39 2005 @@ -1,6 +1,6 @@ from pypy.translator.translator import Translator -from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.rrange import * +from pypy.rpython.test.test_llinterp import interpret def test_rlist_range(): def test1(start, stop, step): @@ -22,20 +22,31 @@ # ____________________________________________________________ -def rtype(fn, argtypes=[]): - t = Translator(fn) - t.annotate(argtypes) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - return t - - def test_range(): def dummyfn(N): total = 0 for i in range(N): total += i return total - rtype(dummyfn, [int]) + res = interpret(dummyfn, [10]) + assert res == 45 + +def test_range_is_lazy(): + def dummyfn(N, M): + total = 0 + for i in range(M): + if i == N: + break + total += i + return total + res = interpret(dummyfn, [10, 2147418112]) + assert res == 45 + +def test_range_item(): + def dummyfn(start, stop, i): + r = range(start, stop) + return r[i] + res = interpret(dummyfn, [10, 17, 4]) + assert res == 14 + res = interpret(dummyfn, [10, 17, -2]) + assert res == 15 From tismer at codespeak.net Wed Jun 22 12:20:14 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 22 Jun 2005 12:20:14 +0200 (CEST) Subject: [pypy-svn] r13685 - pypy/extradoc/sprintinfo Message-ID: <20050622102014.0579E27B70@code1.codespeak.net> Author: tismer Date: Wed Jun 22 12:20:13 2005 New Revision: 13685 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: added my info Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Wed Jun 22 12:20:13 2005 @@ -15,6 +15,7 @@ Anders Lehmann 22nd-26th SGS Michael Hudson 23rd- private Anders Chrigstr?m 23rd- private +Christian Tismer 23rd- ? =================== ============== ===================== @@ -38,6 +39,7 @@ Adrien Di Mascio 1st-5th July Nice Hotel Ludovic Aubry 1st-5th July Nice Hotel Anders Chrigstr?m 1st-7th July private +Christian Tismer 1st-8th July ? =================== ============== ===================== From tismer at codespeak.net Wed Jun 22 12:24:52 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Wed, 22 Jun 2005 12:24:52 +0200 (CEST) Subject: [pypy-svn] r13686 - pypy/extradoc/sprintinfo Message-ID: <20050622102452.6781427B70@code1.codespeak.net> Author: tismer Date: Wed Jun 22 12:24:51 2005 New Revision: 13686 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: update Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Wed Jun 22 12:24:51 2005 @@ -35,11 +35,10 @@ Beatrice D?ring visiting private Jacob Hallen ? private Laura Creighton ? private -Christian Tismer ? ? Adrien Di Mascio 1st-5th July Nice Hotel Ludovic Aubry 1st-5th July Nice Hotel Anders Chrigstr?m 1st-7th July private -Christian Tismer 1st-8th July ? +Christian Tismer 1st-7th July ? =================== ============== ===================== @@ -56,7 +55,7 @@ Jacob Hallen 8th July private Laura Creighton 8th July private Lene Wagner 8th July ? -Christian Tismer 8th July ? Stephan Busemann 7+8th July Hotel Lilton Anders Chrigstr?m 8th July private +Christian Tismer 8th July ? =================== ============== ===================== \ No newline at end of file From arigo at codespeak.net Wed Jun 22 12:54:49 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 22 Jun 2005 12:54:49 +0200 (CEST) Subject: [pypy-svn] r13689 - pypy/dist/pypy/documentation Message-ID: <20050622105449.054BD27B70@code1.codespeak.net> Author: arigo Date: Wed Jun 22 12:54:47 2005 New Revision: 13689 Modified: pypy/dist/pypy/documentation/translation.txt Log: Low-level types documentation: * mention Float * an attempt at documenting OpaqueType and RuntimeTypeInfo -- pretty obscure Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Wed Jun 22 12:54:47 2005 @@ -571,6 +571,9 @@ Unsigned a non-signed integer in one machine word (``unsigned long``) +Float + a 64-bit float (``double``) + Char a single character (``char``) @@ -578,8 +581,8 @@ a boolean value Void - a constant. Meant for variables and function arguments that should - disappear from the generated code. + a constant. Meant for variables, function arguments, structure fields, etc. + which should disappear from the generated code. Structure Types @@ -654,6 +657,16 @@ The testing implementation allows you to "create" PyObjects by calling ``pyobjectptr(obj)``. +Opaque Types +++++++++++++ + +Opaque types represent data implemented in a back-end specific way. This data cannot be inspected or manipulated. + +There is a predefined opaque type ``RuntimeTypeInfo``; at run-time, a value of type ``RuntimeTypeInfo`` represents a low-level type. In practice it is probably enough to be able to represent GcStruct and GcArray types. This is useful if we have a pointer of type ``Ptr(S)`` which can at run-time point either to a malloc'ed ``S`` alone, or to the ``S`` first field of a larger malloc'ed structure. The information about the exact larger type that it points to can be computed or passed around as a ``Ptr(RuntimeTypeInfo)``. Pointer equality on ``Ptr(RuntimeTypeInfo)`` can be used to check the type at run-time. + +At the moment, for memory management purposes, some back-ends actually require such information to be available at run-time in the following situation: when a GcStruct has another GcStruct as its first field. A reference-counting back-end needs to be able to know when a pointer to the smaller structure actually points to the larger one, so that it can also decref the extra fields. Depending on the situation, it is possible to reconstruct this information without having to store a flag in each and every instance of the smaller GcStruct. For example, the instances of a class hierarchy can be implemented by nested GcStructs, with instances of subclasses extending instances of parent classes by embedding the parent part of the instance as the first field. In this case, there is probably already a way to know the run-time class of the instance (e.g. a vtable pointer), but the back-end cannot guess this. This is the reason for which ``RuntimeTypeInfo`` was originally introduced: just after the GcStruct is created, the function attachRuntimeTypeInfo() should be called to attach to the GcStruct a low-level function of signature ``Ptr(GcStruct) -> Ptr(RuntimeTypeInfo)``. This function will be compiled by the back-end and automatically called at run-time. In the above example, it would follow the vtable pointer and fetch the opaque ``Ptr(RuntimeTypeInfo)`` from the vtable itself. (The reference-counting GenC back-end uses a pointer to the deallocation function as the opaque ``RuntimeTypeInfo``.) + + Implementing RPython types -------------------------- From hpk at codespeak.net Thu Jun 23 11:43:26 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 11:43:26 +0200 (CEST) Subject: [pypy-svn] r13695 - in pypy/dist/pypy: rpython rpython/test tool translator Message-ID: <20050623094326.2EDD127B83@code1.codespeak.net> Author: hpk Date: Thu Jun 23 11:43:24 2005 New Revision: 13695 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rtyper.py pypy/dist/pypy/tool/ansi_print.py pypy/dist/pypy/translator/annrpython.py Log: - use py.log instead of directly printing to stdout/stderr - one can define from tests or other entry points if logging information is actually shown (see test_rtyper.py for an initial example) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 23 11:43:24 2005 @@ -13,6 +13,7 @@ from __future__ import generators import sys +import py from pypy.annotation.pairtype import pair from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Variable, Constant, Block, Link @@ -28,11 +29,10 @@ from pypy.rpython.annlowlevel import annotate_lowlevel_helper from pypy.rpython.exceptiondata import ExceptionData - -debug = False +log = py.log.Producer("rtyper") +py.log.setconsumer("rtyper", None) crash_on_first_typeerror = True - class RPythonTyper: def __init__(self, annotator): @@ -246,8 +246,7 @@ yield HighLevelOp(self, block.operations[-1], exclinks, llops) def translate_hl_to_ll(self, hop, varmapping): - if debug: - print hop.spaceop.opname, hop.args_s + log.translating(hop.spaceop.opname, hop.args_s) resultvar = hop.dispatch() op = hop.spaceop if resultvar is None: Modified: pypy/dist/pypy/rpython/test/test_rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtyper.py (original) +++ pypy/dist/pypy/rpython/test/test_rtyper.py Thu Jun 23 11:43:24 2005 @@ -1,20 +1,24 @@ from pypy.annotation import model as annmodel from pypy.translator.translator import Translator from pypy.rpython.lltype import * +from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.rtyper import RPythonTyper +import py +def setup_module(mod): + mod.logstate = py.log._getstate() + py.log.setconsumer("rtyper", py.log.STDOUT) + py.log.setconsumer("annrpython", None) + +def teardown_module(mod): + py.log._setstate(mod.logstate) def test_simple(): def dummyfn(x): return x+1 - t = Translator(dummyfn) - t.annotate([int]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - + res = interpret(dummyfn, [7]) + assert res == 8 def test_function_call(): def g(x, y): @@ -22,13 +26,8 @@ def f(x): return g(1, x) - t = Translator(f) - t.annotate([int]) - typer = RPythonTyper(t.annotator) - typer.specialize() - #t.view() - t.checkgraphs() - + res = interpret(f, [4]) + assert res == -3 def test_retval(): def f(x): Modified: pypy/dist/pypy/tool/ansi_print.py ============================================================================== --- pypy/dist/pypy/tool/ansi_print.py (original) +++ pypy/dist/pypy/tool/ansi_print.py Thu Jun 23 11:43:24 2005 @@ -7,8 +7,21 @@ def ansi_print(text, esc, file=None): if file is None: file = sys.stderr text = text.rstrip() - if sys.platform != "win32" and file.isatty(): + if esc and sys.platform != "win32" and file.isatty(): text = ('\x1b[%sm' % esc + text + '\x1b[0m') # ANSI color code "reset" file.write(text + '\n') + +def ansi_log(msg): + keywords = list(msg.keywords) + if 'bold' in keywords: + keywords.remove('bold') + esc = "1" + elif 'red' in keywords: + keywords.remove('red') + esc = "31" + else: + esc = None + ansi_print("[%s] %s" %(":".join(keywords), msg.content()), esc) + Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Thu Jun 23 11:43:24 2005 @@ -1,13 +1,16 @@ from __future__ import generators from types import FunctionType, ClassType -from pypy.tool.ansi_print import ansi_print +from pypy.tool.ansi_print import ansi_log from pypy.annotation import model as annmodel from pypy.annotation.model import pair from pypy.annotation.bookkeeper import Bookkeeper from pypy.objspace.flow.model import Variable, Constant from pypy.objspace.flow.model import SpaceOperation, FunctionGraph from pypy.objspace.flow.model import last_exception, checkgraph +import py +log = py.log.Producer("annrpython") +py.log.setconsumer("annrpython", ansi_log) class AnnotatorError(Exception): pass @@ -233,15 +236,13 @@ self.bindings[arg] = s_value if annmodel.DEBUG: if arg in self.return_bindings: - ansi_print("%s -> %s" % (self.whereami((self.return_bindings[arg], - None, None)), - s_value), - esc="1") # bold + log.bold("%s -> %s" % + (self.whereami((self.return_bindings[arg], None, None)), + s_value)) if arg in self.return_bindings and s_value == annmodel.SomeObject(): - ansi_print("*** WARNING: %s result degenerated to SomeObject" % - self.whereami((self.return_bindings[arg],None, None)), - esc="31") # RED + log.red("*** WARNING: %s result degenerated to SomeObject" % + self.whereami((self.return_bindings[arg],None, None))) self.binding_caused_by[arg] = called_from From arigo at codespeak.net Thu Jun 23 12:00:30 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Jun 2005 12:00:30 +0200 (CEST) Subject: [pypy-svn] r13697 - pypy/dist/pypy/rpython Message-ID: <20050623100030.CB16B27B8D@code1.codespeak.net> Author: arigo Date: Thu Jun 23 12:00:28 2005 New Revision: 13697 Modified: pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rpbc.py Log: Normalize calls for return values too. Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Thu Jun 23 12:00:28 2005 @@ -115,6 +115,9 @@ args_s.append(bindings[j]) s_value = unionof(*args_s) generalizedargs.append(s_value) + result_s = [annotator.binding(graph.getreturnvar()) + for graph in graph_bindings] + generalizedresult = unionof(*result_s) for func in functions: graph = annotator.translator.getflowgraph(func) @@ -158,7 +161,8 @@ checkgraph(graph) annotator.annotated[newblock] = annotator.annotated[oldblock] graph.normalized_for_calls = True - # XXX convert the return value too + # convert the return value too + annotator.setbinding(graph.getreturnvar(), generalizedresult) def perform_normalizations(annotator): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Thu Jun 23 12:00:28 2005 @@ -299,7 +299,8 @@ if self.lowleveltype == Void: assert len(self.function_signatures) == 1 vlist[0] = hop.inputconst(typeOf(f), f) - return hop.genop('direct_call', vlist, resulttype = rresult) + v = hop.genop('direct_call', vlist, resulttype = rresult) + return hop.llops.convertvar(v, rresult, hop.r_result) def rtype_call_args(self, hop): f, rinputs, rresult = self.function_signatures.itervalues().next() From mwh at codespeak.net Thu Jun 23 13:34:01 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 13:34:01 +0200 (CEST) Subject: [pypy-svn] r13698 - pypy/dist/pypy/objspace/std Message-ID: <20050623113401.180A727B83@code1.codespeak.net> Author: mwh Date: Thu Jun 23 13:34:00 2005 New Revision: 13698 Modified: pypy/dist/pypy/objspace/std/mro.py Log: avoid the use of index Modified: pypy/dist/pypy/objspace/std/mro.py ============================================================================== --- pypy/dist/pypy/objspace/std/mro.py (original) +++ pypy/dist/pypy/objspace/std/mro.py Thu Jun 23 13:34:00 2005 @@ -37,7 +37,13 @@ cycle.append(candidate) nextblockinglist = blockinglist(candidate, orderlists) candidate = nextblockinglist[0] - del cycle[:cycle.index(candidate)] + # avoid the only use of list.index in the PyPy code base: + i = 0 + for c in cycle: + if c == candidate: + break + i += 1 + del cycle[:i] cycle.append(candidate) cycle.reverse() names = [cls.__name__ for cls in cycle] From mwh at codespeak.net Thu Jun 23 13:51:30 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 13:51:30 +0200 (CEST) Subject: [pypy-svn] r13699 - pypy/dist/pypy/annotation Message-ID: <20050623115130.11D2C27B83@code1.codespeak.net> Author: mwh Date: Thu Jun 23 13:51:25 2005 New Revision: 13699 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py Log: count some more stuff (untested, checking in to get stuff on samuele's machine...) Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 23 13:51:25 2005 @@ -47,7 +47,7 @@ def count(self, category, *args): for_category = self.classify.setdefault(category, {}) - classifier = getattr(self, 'consider_%s' % category) + classifier = getattr(self, 'consider_%s' % category, self.consider_generic) outcome = classifier(*args) for_category[self.bookkeeper.position_key] = outcome @@ -79,6 +79,8 @@ else: return 'non-const-step %s' % self.typerepr(stp) + def consider_generic(self, *args): + return tuple([self.typerepr(x) for x in args]) def consider_newslice(self, s_start, s_stop, s_step): return ':'.join([self.indexrepr(s_start), self.indexrepr(s_stop), self.steprepr(s_step)]) @@ -129,7 +131,7 @@ return "NON-CONSTANT" def consider_str_getitem(self, idx): - return self.indexrepr(idx) + return self.indexrepr(idx) class Bookkeeper: """The log of choices that have been made while analysing the operations. Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Thu Jun 23 13:51:25 2005 @@ -83,9 +83,20 @@ return SomeInteger() def str(obj): + getbookkeeper().count('str', obj) return SomeString() - repr = hex = oct = str + def repr(obj): + getbookkeeper().count('repr', obj) + return SomeString() + + def hex(obj): + getbookkeeper().count('hex', obj) + return SomeString() + + def oct(obj): + getbookkeeper().count('oct', obj) + return SomeString() def id(obj): # xxx return SomeInteger() From hpk at codespeak.net Thu Jun 23 13:57:33 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 13:57:33 +0200 (CEST) Subject: [pypy-svn] r13700 - pypy/extradoc/sprintinfo Message-ID: <20050623115733.3AFFB27B83@code1.codespeak.net> Author: hpk Date: Thu Jun 23 13:57:32 2005 New Revision: 13700 Added: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: add some brainstorming/planning information regarding the work of the pre-EP sprint. Added: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 13:57:32 2005 @@ -0,0 +1,61 @@ + +Open areas in translation +------------------------------------- + +Still missing are: + +* GenC knows little about float operations. Need to complete + translator/c/float_include.h. + +* Almost all the topics from the rtyper, from the previous + status report: + + - (hard) prebuilt constants -- PBCs -- and dicts with PBC keys + tasks: 1. call to memoized functions, at first with a single PBC arg + 2. find out if we really have visible dicts with PBC keys + + - (medium) dicts with non-wrapped string keys to any object, and + iterators over them + tasks: do it (iterators in a second step) + + - (medium) iterators over tuples + task: the built-in list() should convert from homogenous tuples + to lists + + - (varying) all built-in functions listed in annotation/builtin.py + task: write them into rpython/rbuiltin.py + possibly remove support for some of them + + - (mostly easy) a few more operations: issubtype, str(?) + task: go through them one by one and decide if they should + be supported + + - (easy) list methods reverse, pop, insert, index(?) + task: only left: remove the single index() call in PyPy (typeobject.py) + + - (easy) tuple concatenation + task: do it + + - (easy) string slices + task: do it (see rlist) + + - (easy) equality and non-equality are generally missing + task: 1. missing for lists of primitives, and lists of strings + 2. annotator fix: unify lists when they are compared + 3. for instances, 'eq' is 'is' + + - (medium) limited form of string formatting: 'constant template' only + which should only generate a sequence of simple ll-function + invocations like concatenation and str() on integers + task: 1. figure out what kind of formatting we use in PyPy + 2. implement them + +* lltype will also need to grow a new primitive type, UnicodeChar. + +* convert each file that does 'from ... import *' to use explicit + imports (e.g. from pypy.rpython import lltype and then use lltype.*) + +* progress on translation of example targets: + python demo/bpnn.py + python pypy/translator/goal/translate_pypy.py targetrichards.py + From tismer at codespeak.net Thu Jun 23 14:03:02 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 14:03:02 +0200 (CEST) Subject: [pypy-svn] r13701 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623120302.75CBB27B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 14:03:01 2005 New Revision: 13701 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: just a bit of sanitization Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 14:03:01 2005 @@ -89,11 +89,11 @@ v_lst, = hop.inputargs(self) hop.gendirectcall(ll_reverse,v_lst) - def rtype_method_pop(self,hop): - v_list,v_index = hop.inputargs(self,Signed) + def rtype_method_pop(self, hop): + v_list, v_index = hop.inputargs(self, Signed) #v_index = hop.inputconst(Signed,-1) - assert hasattr(v_index,'concretetype') - return hop.gendirectcall(ll_pop,v_list,v_index) + assert hasattr(v_index, 'concretetype') + return hop.gendirectcall(ll_pop, v_list, v_index) def make_iterator_repr(self): return ListIteratorRepr(self) @@ -181,31 +181,31 @@ length = len(l.items) newitems = malloc(typeOf(l).TO.items.TO, length+1) i = 0 - while i Author: tismer Date: Thu Jun 23 14:05:49 2005 New Revision: 13702 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: support for insert and pop. special-cased pop with or without arguments. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 14:05:49 2005 @@ -81,6 +81,14 @@ v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) + def rtype_method_insert(self, hop): + v_lst, v_index, v_value = hop.inputargs(self, Signed, self.item_repr) + if hop.args_s[1].nonneg: + llfn = ll_insert_nonneg + else: + llfn = ll_insert + hop.gendirectcall(llfn, v_lst, v_index, v_value) + def rtype_method_extend(self, hop): v_lst1, v_lst2 = hop.inputargs(self, self) hop.gendirectcall(ll_extend, v_lst1, v_lst2) @@ -90,11 +98,19 @@ hop.gendirectcall(ll_reverse,v_lst) def rtype_method_pop(self, hop): - v_list, v_index = hop.inputargs(self, Signed) - #v_index = hop.inputconst(Signed,-1) + if hop.nb_args == 2: + v_list, v_index = hop.inputargs(self, Signed) + if hop.args_s[1].nonneg: + llfn = ll_pop_nonneg + else: + llfn = ll_pop + else: + v_list, = hop.inputargs(self) + v_index = hop.inputconst(Signed, -1) + llfn = ll_pop assert hasattr(v_index, 'concretetype') - return hop.gendirectcall(ll_pop, v_list, v_index) - + return hop.gendirectcall(llfn, v_list, v_index) + def make_iterator_repr(self): return ListIteratorRepr(self) @@ -187,15 +203,52 @@ newitems[length] = newitem l.items = newitems +<<<<<<< .mine +def ll_insert_nonneg(l, index, newitem): + length = len(l.items) + newitems = malloc(typeOf(l).TO.items.TO, length+1) + i = 0 + while i < index: + newitems[i] = l.items[i] + i += 1 + newitems[i] = newitem + i += 1 + while i <= length: + newitems[i] = l.items[i-1] + i += 1 + l.items = newitems + +def ll_insert(l, index, newitem): + if index < 0: + index += len(l.items) + ll_insert_nonneg(l, index, newitem) + +def ll_pop_nonneg(l, index): + res = ll_getitem_nonneg(l, index) + ll_delitem_nonneg(l, index) +======= def ll_pop(l, index): res = ll_getitem(l, index) ll_delitem(l, index) +>>>>>>> .r13701 + return res + +def ll_pop(l, index): + if index < 0: + index += len(l.items) + res = ll_getitem_nonneg(l, index) + ll_delitem_nonneg(l, index) return res def ll_reverse(l): length = len(l.items) +<<<<<<< .mine + i = 0 + while i < length / 2: +======= i = 0 while i < length // 2: +>>>>>>> .r13701 tmp = l.items[i] l.items[i] = l.items[length-1-i] l.items[length-1-i] = tmp @@ -217,20 +270,6 @@ i += len(l.items) l.items[i] = newitem -def ll_delitem(l, i): - if i < 0: - i += len(l.items) - newlength = len(l.items) - 1 - newitems = malloc(typeOf(l).TO.items.TO, newlength) - j = 0 - while j < i: - newitems[j] = l.items[j] - j += 1 - while j < newlength: - newitems[j] = l.items[j+1] - j += 1 - l.items = newitems - def ll_delitem_nonneg(l, i): newlength = len(l.items) - 1 newitems = malloc(typeOf(l).TO.items.TO, newlength) @@ -243,6 +282,11 @@ j += 1 l.items = newitems +def ll_delitem(l, i): + if i < 0: + i += len(l.items) + ll_delitem_nonneg(l, i) + def ll_concat(l1, l2): len1 = len(l1.items) len2 = len(l2.items) Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 14:05:49 2005 @@ -153,6 +153,20 @@ del l[:] rtype(dummyfn) +def test_insert_pop(): + def dummyfn(): + l = [] + l.append(5) + l.append(6) + l.append(7) + l.insert(1, 42) + l.pop(2) + del l[0] + l.pop() + return l[-1] + res = interpret(dummyfn, ()) + assert res == 42 + def test_prebuilt_list(): klist = ['a', 'd', 'z', 'k'] def dummyfn(n): From ale at codespeak.net Thu Jun 23 14:09:05 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 14:09:05 +0200 (CEST) Subject: [pypy-svn] r13703 - pypy/dist/pypy/tool Message-ID: <20050623120905.E0D9027B83@code1.codespeak.net> Author: ale Date: Thu Jun 23 14:09:03 2005 New Revision: 13703 Modified: pypy/dist/pypy/tool/_enum_exceptions.py Log: Fixed a bug that made SyntaxError raise TypeError (Christian please review) Modified: pypy/dist/pypy/tool/_enum_exceptions.py ============================================================================== --- pypy/dist/pypy/tool/_enum_exceptions.py (original) +++ pypy/dist/pypy/tool/_enum_exceptions.py Thu Jun 23 14:09:03 2005 @@ -177,7 +177,7 @@ return tuple(res) def findAllArgs(exc, maxprobe): - minargs, maxargs = probeArgCount(exc, maxprobe=20) + minargs, maxargs = probeArgCount(exc, maxprobe) res = [] # for minargs args, we need to try combinations arglist = tuple([genArgsToTry(i) for i in range(minargs)]) @@ -231,11 +231,11 @@ txt = br[0] + ", ".join(stuff) + br[-1] names[obj] = txt else: - names[obj] = "%r # default, hopefully" % obj + names[obj] = "%r" % obj return names[obj] res = [] for i,(name, obj) in enumerate(assigned): - if isinstance(obj,ProbeObject) or name == 'args': + if isinstance(obj,ProbeObject) or name == 'args' or obj==None: res.append("self.%s = %s" % (name, nameof(obj))) else: res.append("if type(%s) == %s:"%(nameof(obj),repr(type(obj))[7:-2])) @@ -284,8 +284,10 @@ dense = tuple(range(argcounts[0], argcounts[-1]+1)) == argcounts if len(argcounts) == 1: yield " if argc == %d:" % argcounts - trailer = [" else:"] - trailer += [" raise TypeError('function takes exactly 5 arguments (%d given)'%argc)"] + if maxargs == minargs: + trailer = [" else:"] + err_msg = "" + trailer += [" raise TypeError('function takes exactly "+str(argcounts[0])+" arguments (%d given)'%argc)"] elif dense and argcounts[0] == 0: yield " if argc <= %d:" % argcounts[-1] elif dense and argcounts[-1] == maxprobe-1: @@ -294,8 +296,11 @@ yield " if %d <= argc <= %d:" % (argcounts[0], argcounts[-1]) else: yield " if argc in %r:" % (argcounts, ) - for order, line in ordered_statements: - yield indent * " " + line + if len(ordered_statements)>0: + for order, line in ordered_statements: + yield indent * " " + line + else: + yield indent * " " + "pass" if trailer: for line in trailer : yield line From mwh at codespeak.net Thu Jun 23 14:15:04 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 14:15:04 +0200 (CEST) Subject: [pypy-svn] r13704 - pypy/extradoc/sprintinfo Message-ID: <20050623121504.79FB427B83@code1.codespeak.net> Author: mwh Date: Thu Jun 23 14:15:04 2005 New Revision: 13704 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: refinement of operations task Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 14:15:04 2005 @@ -26,9 +26,13 @@ task: write them into rpython/rbuiltin.py possibly remove support for some of them - - (mostly easy) a few more operations: issubtype, str(?) + - (mostly easy) a few more operations: issubtype, ...? task: go through them one by one and decide if they should be supported + + - (probably easy): operations: str for ints, instances (only something + very simple for the latter). all other uses are cheating, as + are all uses of hex, oct, repr. - (easy) list methods reverse, pop, insert, index(?) task: only left: remove the single index() call in PyPy (typeobject.py) From tismer at codespeak.net Thu Jun 23 14:15:14 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 14:15:14 +0200 (CEST) Subject: [pypy-svn] r13705 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623121514.15D8627B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 14:15:12 2005 New Revision: 13705 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: support for floordiv/truediv optimized reverse a bit and used floordiv Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 14:15:12 2005 @@ -259,8 +259,10 @@ for typ in (float, int): typname = typ.__name__ - for opname in ('add', 'sub', 'mul', 'div', 'floordiv', 'truediv', - 'gt', 'lt', 'ge', 'ne', 'le', 'eq'): + optup = ('add', 'sub', 'mul', 'div', 'gt', 'lt', 'ge', 'ne', 'le', 'eq') + if typ is int: + optup += 'truediv', 'floordiv' + for opname in optup: assert opname in opimpls exec py.code.Source(""" def %(typname)s_%(opname)s(x, y): Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 14:15:12 2005 @@ -203,7 +203,6 @@ newitems[length] = newitem l.items = newitems -<<<<<<< .mine def ll_insert_nonneg(l, index, newitem): length = len(l.items) newitems = malloc(typeOf(l).TO.items.TO, length+1) @@ -224,31 +223,21 @@ ll_insert_nonneg(l, index, newitem) def ll_pop_nonneg(l, index): - res = ll_getitem_nonneg(l, index) + res = l.items[index] ll_delitem_nonneg(l, index) -======= -def ll_pop(l, index): - res = ll_getitem(l, index) - ll_delitem(l, index) ->>>>>>> .r13701 - return res def ll_pop(l, index): if index < 0: index += len(l.items) - res = ll_getitem_nonneg(l, index) + res = l.items[index] ll_delitem_nonneg(l, index) return res def ll_reverse(l): length = len(l.items) -<<<<<<< .mine + len2 = length // 2 # moved this out of the loop i = 0 - while i < length / 2: -======= - i = 0 - while i < length // 2: ->>>>>>> .r13701 + while i < len2: tmp = l.items[i] l.items[i] = l.items[length-1-i] l.items[length-1-i] = tmp Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 14:15:12 2005 @@ -167,6 +167,14 @@ res = interpret(dummyfn, ()) assert res == 42 +def test_reverse(): + def dummyfn(): + l = [5, 3, 2] + l.reverse() + return l[0]*100 + l[1]*10 + l[2] + res = interpret(dummyfn, ()) + assert res == 235 + def test_prebuilt_list(): klist = ['a', 'd', 'z', 'k'] def dummyfn(n): From mwh at codespeak.net Thu Jun 23 14:16:12 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 14:16:12 +0200 (CEST) Subject: [pypy-svn] r13706 - pypy/dist/pypy/annotation Message-ID: <20050623121612.DCFB227B83@code1.codespeak.net> Author: mwh Date: Thu Jun 23 14:16:11 2005 New Revision: 13706 Modified: pypy/dist/pypy/annotation/binaryop.py Log: Count string formatting operations. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 23 14:16:11 2005 @@ -306,6 +306,7 @@ class __extend__(pairtype(SomeString, SomeObject)): def mod((str, args)): + getbookkeeper().count('strformat', str, args) return SomeString() From ale at codespeak.net Thu Jun 23 14:18:32 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 14:18:32 +0200 (CEST) Subject: [pypy-svn] r13707 - pypy/dist/pypy/documentation Message-ID: <20050623121832.2823327B83@code1.codespeak.net> Author: ale Date: Thu Jun 23 14:18:31 2005 New Revision: 13707 Modified: pypy/dist/pypy/documentation/translation.txt Log: typos and Modified: pypy/dist/pypy/documentation/translation.txt ============================================================================== --- pypy/dist/pypy/documentation/translation.txt (original) +++ pypy/dist/pypy/documentation/translation.txt Thu Jun 23 14:18:31 2005 @@ -24,7 +24,7 @@ Here are the steps we follow to translate a given program: 1. The complete program is imported. If needed, extra initialization is - performed. Once this is done, the program must be present in memory is + performed. Once this is done, the program must be present in memory as a form that is "static enough" in the sense of RPython_. 2. The `Flow Object Space`_ processes the input program, turning each @@ -362,7 +362,7 @@ The distinction between instance-level and class-level attributes is thin; class-level attributes are essentially considered as initial values for instance-level attributes. Methods are not special in this -respect, expect that they are bound to the instance (i.e. ``self = +respect, except that they are bound to the instance (i.e. ``self = SomeInstance(cls)``) when considered as the initial value for the instance. @@ -443,9 +443,25 @@ Overview -------- -The RPython Typer is the bridge between the Annotator_ and the low-level code generators. The annotator computes types (or "annotations") that are high-level, in the sense that they describe RPython types like lists or instances of user-defined classes. In general, though, to emit code we need to represent these high-level annotations into the low-level model of the target language; for C, this means structures and pointers and arrays. The Typer both determines the appropriate low-level type for each annotation, and tries to replace *all* operations in the control flow graphs with one or a few low-level operations. Just like low-level types, there is only a fairly restricted set of low-level operations, along the lines of reading or writing from or to a field of a structure. - -In theory, this step is optional; some code generators might be able to read directly the high-level types. However, we expect that case to be the exception. "Compiling" high-level types into low-level ones is rather more messy than one would expect. This was the motivation for making this step explicit and isolated in a single place. After Typing, the graphs can only contain very few operations, which makes the job of the code generators much simpler. +The RPython Typer is the bridge between the Annotator_ and the low-level code +generators. The annotator computes types (or "annotations") that are +high-level, in the sense that they describe RPython types like lists or +instances of user-defined classes. In general, though, to emit code we need +to represent these high-level annotations into the low-level model of the +target language; for C, this means structures and pointers and arrays. The +Typer both determines the appropriate low-level type for each annotation, and +tries to replace *all* operations in the control flow graphs with one or a few +low-level operations. Just like low-level types, there is only a fairly +restricted set of low-level operations, along the lines of reading or writing +from or to a field of a structure. + +In theory, this step is optional; some code generators might be able to read +directly the high-level types. However, we expect that case to be the +exception. "Compiling" high-level types into low-level ones is rather more +messy than one would expect. This was the motivation for making this step +explicit and isolated in a single place. After Typing, the graphs can only +contain very few operations, which makes the job of the code generators much +simpler. Example: Integer operations @@ -465,33 +481,78 @@ v3 = int_add(v1, v2) -where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 (which might be instances of Variable or possibly Constant). In our model, this ``concretetype`` is ``pypy.rpython.lltype.Signed``. Of course, the purpose of replacing the operation called ``add`` with ``int_add`` is that code generators no longer have to worry about what kind of addition (or concatenation maybe?) it means. +where -- in C notation -- all three variables v1, v2 and v3 are typed ``int``. +This is done by attaching an attribute ``concretetype`` to v1, v2 and v3 +(which might be instances of Variable or possibly Constant). In our model, +this ``concretetype`` is ``pypy.rpython.lltype.Signed``. Of course, the +purpose of replacing the operation called ``add`` with ``int_add`` is that +code generators no longer have to worry about what kind of addition (or +concatenation maybe?) it means. The process in more details --------------------------- -The RPython Typer has a structure similar to that of the Annotator_: both consider each block of the flow graphs in turn, and perform some analysis on each operation. In both cases the analysis of an operation depends on the annotations of its input arguments. This is reflected in the usage of the same ``__extend__`` syntax in the source files (compare e.g. `annotation/binaryop.py`_ and `rpython/rint.py`_). - -The analogy stops here, though: while it runs, the Annotator is in the middle of computing the annotations, so it might need to reflow and generalize until a fixpoint is reached. The Typer, by contrast, works on the final annotations that the Annotator computed, without changing them, assuming that they are globally consistent. There is no need to reflow: the Typer considers each block only once. And unlike the Annotator, the Typer completely modifies the flow graph, by replacing each operation with some low-level operations. - -In addition to replacing operations, the RTyper creates a ``concretetype`` attribute on all Variables and Constants in the flow graphs, which tells code generators which type to use for each of them. This attribute is a `low-level type`_, as described below. +The RPython Typer has a structure similar to that of the Annotator_: both +consider each block of the flow graphs in turn, and perform some analysis on +each operation. In both cases the analysis of an operation depends on the +annotations of its input arguments. This is reflected in the usage of the same +``__extend__`` syntax in the source files (compare e.g. +`annotation/binaryop.py`_ and `rpython/rint.py`_). + +The analogy stops here, though: while it runs, the Annotator is in the middle +of computing the annotations, so it might need to reflow and generalize until +a fixpoint is reached. The Typer, by contrast, works on the final annotations +that the Annotator computed, without changing them, assuming that they are +globally consistent. There is no need to reflow: the Typer considers each +block only once. And unlike the Annotator, the Typer completely modifies the +flow graph, by replacing each operation with some low-level operations. + +In addition to replacing operations, the RTyper creates a ``concretetype`` +attribute on all Variables and Constants in the flow graphs, which tells code +generators which type to use for each of them. This attribute is a +`low-level type`_, as described below. Representations --------------- -Representations -- the Repr classes -- are the most important internal classes used by the RTyper. (They are internal in the sense that they are an "implementation detail" and their instances just go away after the RTyper is finished; the code generators should only use the ``concretetype`` attributes, which are not Repr instances but `low-level types`_.) - -A representation contains all the logic about mapping a specific SomeXxx() annotation to a specific low-level type. For the time being, the RTyper assumes that each SomeXxx() instance needs only one "canonical" representation. For example, all variables annotated with SomeInteger() will correspond to the ``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, variables annotated SomeList() can correspond either to a structure holding an array of items of the correct type, or -- if the list in question is just a range() with a constant step -- a structure with just start and stop fields. - -This example shows that two representations may need very different low-level implementations for the same high-level operations. This is the reason for turning representations into explicit objects. - -The base Repr class is defined in `rpython/rmodel.py`_. Most of the ``rpython/r*.py`` files define one or a few subclasses of Repr. The method getrepr() of the RTyper will build and cache a single Repr instance per SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the same Repr instance. - -The key attribute of a Repr instance is called ``lowleveltype``, which is what gets copied into the attribute ``concretetype`` of the Variables that have been given this representation. The RTyper also computes a ``concretetype`` for Constants, to match the way they are used in the low-level operations (for example, ``int_add(x, 1)`` requires a ``Constant(1)`` with ``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a ``Constant(1)`` that must actually be a PyObject at run-time). - -In addition to ``lowleveltype``, each Repr subclass provides a set of methods called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` is turned into low-level operations. +Representations -- the Repr classes -- are the most important internal classes +used by the RTyper. (They are internal in the sense that they are an +"implementation detail" and their instances just go away after the RTyper is +finished; the code generators should only use the ``concretetype`` attributes, +which are not Repr instances but `low-level types`_.) + +A representation contains all the logic about mapping a specific SomeXxx() +annotation to a specific low-level type. For the time being, the RTyper +assumes that each SomeXxx() instance needs only one "canonical" representation. +For example, all variables annotated with SomeInteger() will correspond to the +``Signed`` low-level type via the ``IntegerRepr`` representation. More subtly, +variables annotated SomeList() can correspond either to a structure holding an +array of items of the correct type, or -- if the list in question is just a +range() with a constant step -- a structure with just start and stop fields. + +This example shows that two representations may need very different low-level +implementations for the same high-level operations. This is the reason for +turning representations into explicit objects. + +The base Repr class is defined in `rpython/rmodel.py`_. Most of the +``rpython/r*.py`` files define one or a few subclasses of Repr. The method +getrepr() of the RTyper will build and cache a single Repr instance per +SomeXxx() instance; moreover, two SomeXxx() instances that are equal get the +same Repr instance. + +The key attribute of a Repr instance is called ``lowleveltype``, which is what +gets copied into the attribute ``concretetype`` of the Variables that have been +given this representation. The RTyper also computes a ``concretetype`` for +Constants, to match the way they are used in the low-level operations (for +example, ``int_add(x, 1)`` requires a ``Constant(1)`` with +``concretetype=Signed``, but an untyped ``add(x, 1)`` works with a +``Constant(1)`` that must actually be a PyObject at run-time). + +In addition to ``lowleveltype``, each Repr subclass provides a set of methods +called ``rtype_op_xxx()`` which define how each high-level operation ``op_xxx`` +is turned into low-level operations. .. _`low-level type`: @@ -499,17 +560,30 @@ Low-Level Types --------------- -The RPython Typer uses a standard low-level model which we believe can correspond rather directly to various target languages from C to LLVM to Java. This model is implemented in the first part of `rpython/lltype.py`_. - -The second part of `rpython/lltype.py`_ is a runnable implementation of these types, for testing purposes. It allows us to write and test plain Python code using a malloc() function to obtain and manipulate structures and arrays. This is useful for example to implement and test RPython types like 'list' with its operations and methods. - -The basic assumption is that Variables (i.e. local variables and function arguments and return value) all contain "simple" values: basically, just integers or pointers. All the "container" data structures (struct and array) are allocated in the heap, and they are always manipulated via pointers. (There is no equivalent to the C notion of local variable of a ``struct`` type.) - -Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you have some older version, the ``lltype`` module might be called ``lltypes`` and you may need to add or remove a few ``Gc`` prefixes here and there):: +The RPython Typer uses a standard low-level model which we believe can +correspond rather directly to various target languages from C to LLVM to Java. +This model is implemented in the first part of `rpython/lltype.py`_. + +The second part of `rpython/lltype.py`_ is a runnable implementation of these +types, for testing purposes. It allows us to write and test plain Python code +using a malloc() function to obtain and manipulate structures and arrays. +This is useful for example to implement and test RPython types like 'list' with +its operations and methods. + +The basic assumption is that Variables (i.e. local variables and function +arguments and return value) all contain "simple" values: basically, just +integers or pointers. All the "container" data structures (struct and array) +are allocated in the heap, and they are always manipulated via pointers. +(There is no equivalent to the C notion of local variable of a ``struct`` type.) + +Here is a quick tour (NOTE: this is up-to-date with the Subversion head. If you +have some older version, the ``lltype`` module might be called ``lltypes`` and +you may need to add or remove a few ``Gc`` prefixes here and there):: >>> from pypy.rpython.lltype import * -Here are a few primitive low-level types, and the typeOf() function to figure them out:: +Here are a few primitive low-level types, and the typeOf() function to figure +them out:: >>> Signed @@ -520,15 +594,20 @@ >>> typeOf('x') -Let's say that we want to build a type "point", which is a structure with two integer fields "x" and "y":: +Let's say that we want to build a type "point", which is a structure with two +integer fields "x" and "y":: >>> POINT = GcStruct('point', ('x', Signed), ('y', Signed)) >>> POINT -The structure is a ``GcStruct``, which means a structure that can be allocated in the heap and eventually freed by some garbage collector. (For platforms where we use reference counting, think about ``GcStruct`` as a struct with an additional reference counter field.) +The structure is a ``GcStruct``, which means a structure that can be allocated +in the heap and eventually freed by some garbage collector. (For platforms +where we use reference counting, think about ``GcStruct`` as a struct with an +additional reference counter field.) -Giving a name ('point') to the GcStruct is only for clarity: it is used in the representation. +Giving a name ('point') to the GcStruct is only for clarity: it is used in the +representation. >>> p = malloc(POINT) >>> p @@ -539,14 +618,23 @@ >>> p -``malloc()`` allocates a structure from the heap, initalizes it to 0 (currently), and returns a pointer to it. The point of all this is to work with a very limited, easily controllable set of types, and define implementations of types like list in this elementary world. The ``malloc()`` function is a kind of placeholder, which must eventually be provided by the code generator for the target platform; but as we have just seen its Python implementation in `rpython/lltype.py`_ works too, which is primarily useful for testing, interactive exploring, etc. +``malloc()`` allocates a structure from the heap, initalizes it to 0 +(currently), and returns a pointer to it. The point of all this is to work with +a very limited, easily controllable set of types, and define implementations of +types like list in this elementary world. The ``malloc()`` function is a kind +of placeholder, which must eventually be provided by the code generator for the +target platform; but as we have just seen its Python implementation in ` +rpython/lltype.py`_ works too, which is primarily useful for testing, +interactive exploring, etc. -The argument to ``malloc()`` is the structure type directly, but it returns a pointer to the structure, as ``typeOf()`` tells you:: +The argument to ``malloc()`` is the structure type directly, but it returns a +pointer to the structure, as ``typeOf()`` tells you:: >>> typeOf(p) -For the purpose of creating structures with pointers to other structures, we can declare pointer types explicitely:: +For the purpose of creating structures with pointers to other structures, we can +declare pointer types explicitely:: >>> typeOf(p) == Ptr(POINT) True @@ -559,7 +647,8 @@ >>> b.p2.y 42 -The world of low-level types is more complicated than integers and GcStructs, though. The next pages are a reference guide. +The world of low-level types is more complicated than integers and GcStructs, +though. The next pages are a reference guide. Primitive Types @@ -593,13 +682,27 @@ MyStructType = Struct('somename', ('field1', Type1), ('field2', Type2)...) MyStructType = GcStruct('somename', ('field1', Type1), ('field2', Type2)...) -This declares a structure (or a Pascal ``record``) containing the specified named fields with the given types. The field names cannot start with an underscore. As noted above, you cannot directly manipulate structure objects, but only pointer to structures living in the heap. - -By contrast, the fields themselves can be of primitive, pointer or container type. When a structure contains another structure as a field we say that the latter is "inlined" in the former: the bigger structure contains the smaller one as part of its memory layout. - -A structure can also contain an inlined array (see below), but only as its last field: in this case it is a "variable-sized" structure, whose memory layout starts with the non-variable fields and ends with a variable number of array items. This number is determined when a structure is allocated in the heap. Variable-sized structures cannot be inlined in other structures. - -GcStructs have a platform-specific GC header (e.g. a reference counter); only these can be dynamically malloc()ed. The non-GC version of Struct does not have any header, and is suitable for being embedded ("inlined") inside other structures. As an exception, a GcStruct can be embedded as the first field of a GcStruct: the parent structure uses the same GC header as the substructure. +This declares a structure (or a Pascal ``record``) containing the specified +named fields with the given types. The field names cannot start with an +underscore. As noted above, you cannot directly manipulate structure objects, +but only pointer to structures living in the heap. + +By contrast, the fields themselves can be of primitive, pointer or container +type. When a structure contains another structure as a field we say that the +latter is "inlined" in the former: the bigger structure contains the smaller one +as part of its memory layout. + +A structure can also contain an inlined array (see below), but only as its last +field: in this case it is a "variable-sized" structure, whose memory layout +starts with the non-variable fields and ends with a variable number of array +items. This number is determined when a structure is allocated in the heap. +Variable-sized structures cannot be inlined in other structures. + +GcStructs have a platform-specific GC header (e.g. a reference counter); only +these can be dynamically malloc()ed. The non-GC version of Struct does not have +any header, and is suitable for being embedded ("inlined") inside other +structures. As an exception, a GcStruct can be embedded as the first field of a +GcStruct: the parent structure uses the same GC header as the substructure. Array Types @@ -615,23 +718,48 @@ MyArrayType = Array(('field1', Type1), ('field2', Type2)...) -You can build arrays whose items are either primitive or pointer types, or (non-GC non-varsize) structures. - -GcArrays can be malloc()ed. The length must be specified when malloc() is called, and arrays cannot be resized; this length is stored explicitely in a header. +You can build arrays whose items are either primitive or pointer types, or +(non-GC non-varsize) structures. -The non-GC version of Array can be used as the last field of a structure, to make a variable-sized structure. The whole structure can then be malloc()ed, and the length of the array is specified at this time. +GcArrays can be malloc()ed. The length must be specified when malloc() is +called, and arrays cannot be resized; this length is stored explicitely in a +header. + +The non-GC version of Array can be used as the last field of a structure, to +make a variable-sized structure. The whole structure can then be malloc()ed, +and the length of the array is specified at this time. Pointer Types +++++++++++++ -As in C, pointers provide the indirection needed to make a reference modifiable or sharable. Pointers can only point to a structure, an array, a function (see below) or a PyObject (see below). Pointers to primitive types, if needed, must be done by pointing to a structure with a single field of the required type. Pointer types are declared by:: +As in C, pointers provide the indirection needed to make a reference modifiable +or sharable. Pointers can only point to a structure, an array, a function +(see below) or a PyObject (see below). Pointers to primitive types, if needed, +must be done by pointing to a structure with a single field of the required +type. Pointer types are declared by:: Ptr(TYPE) -At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a reference to what they are pointing to. Pointers to non-GC structures that can go away when their container is deallocated (Struct, Array) must be handled with care: the bigger structure of which they are part of could be freed while the Ptr to the substructure is still in use. In general, it is a good idea to avoid passing around pointers to inlined substructures of malloc()ed structures. (The testing implementation of `rpython/lltype.py`_ checks to some extend that you are not trying to use a pointer to a structure after its container has been freed, using weak references. But pointers to non-GC structures are not officially meant to be weak references: using them after what they point to has been freed just crashes.) - -The malloc() operation allocates and returns a Ptr to a new GC structure or array. In a refcounting implementation, malloc() would allocate enough space for a reference counter before the actual structure, and initialize it to 1. Note that the testing implementation also allows malloc() to allocate a non-GC structure or array with a keyword argument ``immortal=True``. Its purpose is to declare and initialize prebuilt data structures which the code generators will turn into static immortal non-GC'ed data. +At run-time, pointers to GC structures (GcStruct, GcArray and PyObject) hold a +reference to what they are pointing to. Pointers to non-GC structures that can +go away when their container is deallocated (Struct, Array) must be handled +with care: the bigger structure of which they are part of could be freed while +the Ptr to the substructure is still in use. In general, it is a good idea to +avoid passing around pointers to inlined substructures of malloc()ed structures. +(The testing implementation of `rpython/lltype.py`_ checks to some extend that +you are not trying to use a pointer to a structure after its container has been +freed, using weak references. But pointers to non-GC structures are not +officially meant to be weak references: using them after what they point to has +been freed just crashes.) + +The malloc() operation allocates and returns a Ptr to a new GC structure or +array. In a refcounting implementation, malloc() would allocate enough space +for a reference counter before the actual structure, and initialize it to 1. +Note that the testing implementation also allows malloc() to allocate a non-GC +structure or array with a keyword argument ``immortal=True``. Its purpose is to +declare and initialize prebuilt data structures which the code generators will +turn into static immortal non-GC'ed data. Function Types @@ -641,9 +769,16 @@ MyFuncType = FuncType([Type1, Type2, ...], ResultType) -declares a function type taking arguments of the given types and returning a result of the given type. All these types must be primitives or pointers. The function type itself is considered to be a "container" type: if you wish, a function contains the bytes that make up its executable code. As with structures and arrays, they can only be manipulated through pointers. - -The testing implementation allows you to "create" functions by calling ``functionptr(TYPE, name, **attrs)``. The extra attributes describe the function in a way that isn't fully specified now, but the following attributes *might* be present: +declares a function type taking arguments of the given types and returning a +result of the given type. All these types must be primitives or pointers. The +function type itself is considered to be a "container" type: if you wish, a +function contains the bytes that make up its executable code. As with +structures and arrays, they can only be manipulated through pointers. + +The testing implementation allows you to "create" functions by calling +``functionptr(TYPE, name, **attrs)``. The extra attributes describe the +function in a way that isn't fully specified now, but the following attributes +*might* be present: :_callable: a Python callable, typically a function object. :graph: the flow graph of the function. @@ -652,9 +787,17 @@ The PyObject Type +++++++++++++++++ -This is a special type, for compatibility with CPython: it stands for a structure compatible with PyObject. This is also a "container" type (thinking about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated via a Ptr. A typed graph can still contain generic space operations (add, getitem, etc.) provided they are applied on objects whose low-level type is ``Ptr(PyObject)``. In fact, code generators that support this should consider that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. In this way, they can generate the correct code for fully-untyped flow graphs. +This is a special type, for compatibility with CPython: it stands for a +structure compatible with PyObject. This is also a "container" type (thinking +about C, this is ``PyObject``, not ``PyObject*``), so it is usually manipulated +via a Ptr. A typed graph can still contain generic space operations (add, +getitem, etc.) provided they are applied on objects whose low-level type is +``Ptr(PyObject)``. In fact, code generators that support this should consider +that the default type of a variable, if none is specified, is ``Ptr(PyObject)``. +In this way, they can generate the correct code for fully-untyped flow graphs. -The testing implementation allows you to "create" PyObjects by calling ``pyobjectptr(obj)``. +The testing implementation allows you to "create" PyObjects by calling +``pyobjectptr(obj)``. Opaque Types @@ -670,9 +813,22 @@ Implementing RPython types -------------------------- -As hinted above, the RPython types (e.g. 'list') are implemented in some "restricted-restricted Python" format by manipulating only low-level types, as provided by the testing implementation of malloc() and friends. What occurs then is that the same (tested!) very-low-level Python code -- which looks really just like C -- is then transformed into a flow graph and integrated with the rest of the user program. In other words, we replace an operation like ``add`` between two variables annotated as SomeList, with a ``direct_call`` operation invoking this very-low-level list concatenation. - -This list concatenation flow graph is then annotated as usual, with one difference: the annotator has to be taught about malloc() and the way the pointer thus obtained can be manipulated. This generates a flow graph which is hopefully completely annotated with SomePtr() annotation. Introduced just for this case, SomePtr maps directly to a low-level pointer type. This is the only change needed to the Annotator to allow it to perform type inference of our very-low-level snippets of code. +As hinted above, the RPython types (e.g. 'list') are implemented in some +"restricted-restricted Python" format by manipulating only low-level types, as +provided by the testing implementation of malloc() and friends. What occurs +then is that the same (tested!) very-low-level Python code -- which looks really +just like C -- is then transformed into a flow graph and integrated with the +rest of the user program. In other words, we replace an operation like ``add`` +between two variables annotated as SomeList, with a ``direct_call`` operation +invoking this very-low-level list concatenation. + +This list concatenation flow graph is then annotated as usual, with one +difference: the annotator has to be taught about malloc() and the way the +pointer thus obtained can be manipulated. This generates a flow graph which is +hopefully completely annotated with SomePtr() annotation. Introduced just for +this case, SomePtr maps directly to a low-level pointer type. This is the only +change needed to the Annotator to allow it to perform type inference of our +very-low-level snippets of code. See for example `rpython/rlist.py`_. @@ -690,9 +846,16 @@ Overview -------- -The task of GenC is to convert a flow graph into C code. By itself, GenC does not use the annotations in the graph. It can actually convert unannotated graphs to C. However, to make use of the annotations if they are present, an extra pass is needed: the `RPython Typer`_, whose task is to modify the flow graph according to the annotations, replacing operations with lower-level C-ish equivalents. - -XXX GenC is currently in the process of being updated to use the RPython Typer. more documentation needed when this is done. But the basic principle of creating code from flowgraphs is similar to the `Python back-end`_. +The task of GenC is to convert a flow graph into C code. By itself, GenC does +not use the annotations in the graph. It can actually convert unannotated +graphs to C. However, to make use of the annotations if they are present, an +extra pass is needed: the `RPython Typer`_, whose task is to modify the flow +graph according to the annotations, replacing operations with lower-level C-ish +equivalents. + +XXX GenC is currently in the process of being updated to use the RPython Typer. +More documentation needed when this is done. But the basic principle of creating +code from flowgraphs is similar to the `Python back-end`_. @@ -742,9 +905,9 @@ ``FuncRepr`` of the appropriate ``__init__`` method to generate the code for the call to it. -Every representation object has a some other representations it depends on: A +Every representation object has some other representations it depends on: A ``ListRepr`` of lists instances of a class depends on the ``ClassRepr`` of -that class. To ensure that the typedef of of the class is written to the llvm +that class. To ensure that the typedef of the class is written to the llvm file before the typedef of the list, the dependency tree of representations traversed depth first when the LLVM code is written to a file. From ale at codespeak.net Thu Jun 23 14:20:27 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 14:20:27 +0200 (CEST) Subject: [pypy-svn] r13708 - pypy/dist/pypy/objspace/std Message-ID: <20050623122027.1429527B83@code1.codespeak.net> Author: ale Date: Thu Jun 23 14:20:26 2005 New Revision: 13708 Modified: pypy/dist/pypy/objspace/std/unicodeobject.py Log: wrong error message Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Thu Jun 23 14:20:26 2005 @@ -782,7 +782,7 @@ else: retval, length = encoder(unistr, errors) if not isinstance(retval,str): - raise TypeError("encoder did not return an unicode object (type=%s)" % + raise TypeError("encoder did not return a string object (type=%s)" % type(retval).__name__) return retval From tismer at codespeak.net Thu Jun 23 14:20:43 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 14:20:43 +0200 (CEST) Subject: [pypy-svn] r13709 - pypy/dist/pypy/rpython Message-ID: <20050623122043.E1BD527B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 14:20:42 2005 New Revision: 13709 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rlist.py Log: small cleanup, and correcting check-in mess Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 14:20:42 2005 @@ -157,10 +157,10 @@ # obj should be pointer setattr(obj, fieldname, fieldvalue) - def op_getarrayitem(self,array,index): + def op_getarrayitem(self, array, index): return array[index] - def op_setarrayitem(self,array,index,item): + def op_setarrayitem(self, array, index, item): array[index] = item def op_direct_call(self, f, *args): Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 14:20:42 2005 @@ -225,6 +225,7 @@ def ll_pop_nonneg(l, index): res = l.items[index] ll_delitem_nonneg(l, index) + return res def ll_pop(l, index): if index < 0: From mwh at codespeak.net Thu Jun 23 14:20:46 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 14:20:46 +0200 (CEST) Subject: [pypy-svn] r13710 - pypy/dist/pypy/annotation Message-ID: <20050623122046.AC06327B88@code1.codespeak.net> Author: mwh Date: Thu Jun 23 14:20:44 2005 New Revision: 13710 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/bookkeeper.py Log: oops, need to be a little more clever. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 23 14:20:44 2005 @@ -306,6 +306,7 @@ class __extend__(pairtype(SomeString, SomeObject)): def mod((str, args)): + assert str.is_constant() getbookkeeper().count('strformat', str, args) return SomeString() Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 23 14:20:44 2005 @@ -133,6 +133,13 @@ def consider_str_getitem(self, idx): return self.indexrepr(idx) + def consider_strformat(self, str, args): + if isinstance(args, SomeTuple): + return (str.const, tuple([self.typerepr(x) for x in args.items])) + else: + return (str.const, self.typerepr(args)) + + class Bookkeeper: """The log of choices that have been made while analysing the operations. It ensures that the same 'choice objects' will be returned if we ask From tismer at codespeak.net Thu Jun 23 14:21:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 14:21:20 +0200 (CEST) Subject: [pypy-svn] r13711 - pypy/dist/pypy/translator/c/test Message-ID: <20050623122120.677BE27B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 14:21:18 2005 New Revision: 13711 Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py Log: small cleanup Modified: pypy/dist/pypy/translator/c/test/test_lltyped.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_lltyped.py (original) +++ pypy/dist/pypy/translator/c/test/test_lltyped.py Thu Jun 23 14:21:18 2005 @@ -31,6 +31,6 @@ s = malloc(S2) s.a.v = 6 s.b.v = 12 - return s.a.v+s.b.v + return s.a.v + s.b.v fn = self.getcompiled(llf) assert fn() == 18 From tismer at codespeak.net Thu Jun 23 14:25:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 14:25:26 +0200 (CEST) Subject: [pypy-svn] r13712 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623122526.5F5CA27B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 14:25:25 2005 New Revision: 13712 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: some pop refinements. Going do to more of these: pop() and pop(0) are most common, also insert(0) should get special treatment (a "prepend") Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 14:25:25 2005 @@ -99,17 +99,16 @@ def rtype_method_pop(self, hop): if hop.nb_args == 2: - v_list, v_index = hop.inputargs(self, Signed) + args = hop.inputargs(self, Signed) if hop.args_s[1].nonneg: llfn = ll_pop_nonneg else: llfn = ll_pop + assert hasattr(args[1], 'concretetype') else: - v_list, = hop.inputargs(self) - v_index = hop.inputconst(Signed, -1) - llfn = ll_pop - assert hasattr(v_index, 'concretetype') - return hop.gendirectcall(llfn, v_list, v_index) + args = hop.inputargs(self) + llfn = ll_pop_default + return hop.gendirectcall(llfn, *args) def make_iterator_repr(self): return ListIteratorRepr(self) @@ -125,10 +124,6 @@ llfn = ll_getitem return hop.gendirectcall(llfn, v_lst, v_index) -## def rtype_method_pop((r_list,r_int),hop): -## v_lst, v_index = hop.inputargs(r_lst, Signed) -## return hop.gendirectcall(ll_pop,v_list,v_index) - def rtype_setitem((r_lst, r_int), hop): v_lst, v_index, v_item = hop.inputargs(r_lst, Signed, r_lst.item_repr) if hop.args_s[1].nonneg: @@ -227,6 +222,18 @@ ll_delitem_nonneg(l, index) return res +def ll_pop_default(l): + index = len(l.items) - 1 + res = l.items[index] + newlength = index + newitems = malloc(typeOf(l).TO.items.TO, newlength) + j = 0 + while j < newlength: + newitems[j] = l.items[j] + j += 1 + l.items = newitems + return res + def ll_pop(l, index): if index < 0: index += len(l.items) Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 14:25:25 2005 @@ -155,13 +155,11 @@ def test_insert_pop(): def dummyfn(): - l = [] - l.append(5) - l.append(6) - l.append(7) + l = [5, 6, 7, 8] l.insert(1, 42) l.pop(2) del l[0] + l.pop(-1) l.pop() return l[-1] res = interpret(dummyfn, ()) From mwh at codespeak.net Thu Jun 23 15:30:33 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 15:30:33 +0200 (CEST) Subject: [pypy-svn] r13713 - pypy/dist/pypy/interpreter Message-ID: <20050623133033.9547F27B83@code1.codespeak.net> Author: mwh Date: Thu Jun 23 15:30:32 2005 New Revision: 13713 Modified: pypy/dist/pypy/interpreter/nestedscope.py Log: yikes, don't do (non-const-string)%stuff Modified: pypy/dist/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/dist/pypy/interpreter/nestedscope.py (original) +++ pypy/dist/pypy/interpreter/nestedscope.py Thu Jun 23 15:30:32 2005 @@ -140,13 +140,13 @@ except ValueError: varname = f.getfreevarname(varindex) if f.iscellvar(varindex): - message = "local variable '%s' referenced before assignment" + message = "local variable '%s' referenced before assignment"%varname w_exc_type = f.space.w_UnboundLocalError else: message = ("free variable '%s' referenced before assignment" - " in enclosing scope") + " in enclosing scope"%varname) w_exc_type = f.space.w_NameError - raise OperationError(w_exc_type, f.space.wrap(message % varname)) + raise OperationError(w_exc_type, f.space.wrap(message)) else: f.valuestack.push(w_value) From mwh at codespeak.net Thu Jun 23 15:35:27 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 15:35:27 +0200 (CEST) Subject: [pypy-svn] r13714 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050623133527.31AC927B85@code1.codespeak.net> Author: mwh Date: Thu Jun 23 15:35:26 2005 New Revision: 13714 Modified: pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py Log: merge fix to pypy-translation-snapshot Modified: pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py Thu Jun 23 15:35:26 2005 @@ -140,13 +140,13 @@ except ValueError: varname = f.getfreevarname(varindex) if f.iscellvar(varindex): - message = "local variable '%s' referenced before assignment" + message = "local variable '%s' referenced before assignment"%varname w_exc_type = f.space.w_UnboundLocalError else: message = ("free variable '%s' referenced before assignment" - " in enclosing scope") + " in enclosing scope"%varname) w_exc_type = f.space.w_NameError - raise OperationError(w_exc_type, f.space.wrap(message % varname)) + raise OperationError(w_exc_type, f.space.wrap(message)) else: f.valuestack.push(w_value) From tismer at codespeak.net Thu Jun 23 15:42:47 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 15:42:47 +0200 (CEST) Subject: [pypy-svn] r13715 - pypy/dist/pypy/rpython Message-ID: <20050623134247.692E827B88@code1.codespeak.net> Author: tismer Date: Thu Jun 23 15:42:46 2005 New Revision: 13715 Modified: pypy/dist/pypy/rpython/rmodel.py Log: typo Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Thu Jun 23 15:42:46 2005 @@ -10,7 +10,7 @@ """ An instance of Repr is associated with each instance of SomeXxx. It defines the chosen representation for the SomeXxx. The Repr subclasses generally follows the SomeXxx subclass hierarchy, but there are numerous - exceptions. For example, the anotator uses SomeIter for any iterator, but + exceptions. For example, the annotator uses SomeIter for any iterator, but we need different representations according to the type of container we are iterating over. """ From ale at codespeak.net Thu Jun 23 15:43:10 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 15:43:10 +0200 (CEST) Subject: [pypy-svn] r13716 - pypy/dist/pypy/lib Message-ID: <20050623134310.2060727B88@code1.codespeak.net> Author: ale Date: Thu Jun 23 15:43:09 2005 New Revision: 13716 Modified: pypy/dist/pypy/lib/_exceptions.py Log: The generated exceptions with the changes from the last check-in. It sometimes makes py.py, run on top of 2.4.1, crash on exit with: pypy.interpreter.error.OperationError: [: >] Modified: pypy/dist/pypy/lib/_exceptions.py ============================================================================== --- pypy/dist/pypy/lib/_exceptions.py (original) +++ pypy/dist/pypy/lib/_exceptions.py Thu Jun 23 15:43:09 2005 @@ -131,10 +131,24 @@ argc = len(args) self.args = args # modified: always assign args, no error check if argc == 4: - self.object = args[0] - self.start = args[1] - self.end = args[2] - self.reason = args[3] + if type(args[0]) == unicode: + self.object = args[0] + else: + raise TypeError('argument 0 must be unicode, not %s'%type(args[0])) + if type(args[1]) == int: + self.start = args[1] + else: + raise TypeError('argument 1 must be int, not %s'%type(args[1])) + if type(args[2]) == int: + self.end = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == str: + self.reason = args[3] + else: + raise TypeError('argument 3 must be str, not %s'%type(args[3])) + else: + raise TypeError('function takes exactly 4 arguments (%d given)'%argc) # auto-generated code, please check carefully! def __str__(self): @@ -181,9 +195,9 @@ def __init__(self, *args): argc = len(args) self.args = args - self.errno = None # default, hopefully - self.strerror = None # default, hopefully - self.filename = None # default, hopefully + self.errno = None + self.strerror = None + self.filename = None if 2 <= argc <= 3: self.errno = args[0] self.strerror = args[1] @@ -207,6 +221,50 @@ class DeprecationWarning(Warning): """Base class for warnings about deprecated features.""" +class UnicodeEncodeError(UnicodeError): + """Unicode encoding error.""" + + # auto-generated code, please check carefully! + def __init__(self, *args): + argc = len(args) + self.args = args # modified: always assign args, no error check + if argc == 5: + if type(args[0]) == str: + self.encoding = args[0] + else: + raise TypeError('argument 0 must be str, not %s'%type(args[0])) + if type(args[1]) == unicode: + self.object = args[1] + else: + raise TypeError('argument 1 must be unicode, not %s'%type(args[1])) + if type(args[2]) == int: + self.start = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == int: + self.end = args[3] + else: + raise TypeError('argument 3 must be int, not %s'%type(args[3])) + if type(args[4]) == str: + self.reason = args[4] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[4])) + else: + raise TypeError('function takes exactly 5 arguments (%d given)'%argc) + + # auto-generated code, please check carefully! + def __str__(self): + # this is a bad hack, please supply an implementation + res = ' '.join([ + 'object=' + str(getattr(self, 'object', None)), + 'end=' + str(getattr(self, 'end', None)), + 'encoding=' + str(getattr(self, 'encoding', None)), + 'args=' + str(getattr(self, 'args', None)), + 'start=' + str(getattr(self, 'start', None)), + 'reason=' + str(getattr(self, 'reason', None)), + ]) + return res + class ArithmeticError(StandardError): """Base class for arithmetic errors.""" @@ -241,10 +299,22 @@ if argc >= 1: self.msg = args[0] if argc == 2: - self.filename = args[1][0] - self.lineno = args[1][1] - self.offset = args[1][2] - self.text = args[1][3] + if type(args[1][0]) == str: + self.filename = args[1][0] + else: + raise TypeError('argument 1 must be str, not %s'%type(args[1][0])) + if type(args[1][1]) == str: + self.lineno = args[1][1] + else: + raise TypeError('argument 2 must be str, not %s'%type(args[1][1])) + if type(args[1][2]) == str: + self.offset = args[1][2] + else: + raise TypeError('argument 3 must be str, not %s'%type(args[1][2])) + if type(args[1][3]) == str: + self.text = args[1][3] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[1][3])) def __str__(self): if type(self.msg) is not str: @@ -275,12 +345,15 @@ def __init__(self, *args): argc = len(args) if argc == 0: - self.code = None # default, hopefully + self.code = None self.args = args if argc == 1: self.code = args[0] if argc >= 2: - self.code = args + if type(args) == tuple: + self.code = args + else: + raise TypeError('argument 0 must be tuple, not %s'%type(args)) class EOFError(StandardError): """Read beyond end of file.""" @@ -311,11 +384,28 @@ argc = len(args) self.args = args # modified: always assign args, no error check if argc == 5: - self.encoding = args[0] - self.object = args[1] - self.start = args[2] - self.end = args[3] - self.reason = args[4] + if type(args[0]) == str: + self.encoding = args[0] + else: + raise TypeError('argument 0 must be str, not %s'%type(args[0])) + if type(args[1]) == str: + self.object = args[1] + else: + raise TypeError('argument 1 must be str, not %s'%type(args[1])) + if type(args[2]) == int: + self.start = args[2] + else: + raise TypeError('argument 2 must be int, not %s'%type(args[2])) + if type(args[3]) == int: + self.end = args[3] + else: + raise TypeError('argument 3 must be int, not %s'%type(args[3])) + if type(args[4]) == str: + self.reason = args[4] + else: + raise TypeError('argument 4 must be str, not %s'%type(args[4])) + else: + raise TypeError('function takes exactly 5 arguments (%d given)'%argc) # auto-generated code, please check carefully! def __str__(self): @@ -363,29 +453,5 @@ class OverflowError(ArithmeticError): """Result too large to be represented.""" -class UnicodeEncodeError(UnicodeError): - """Unicode encoding error.""" - - # auto-generated code, please check carefully! - def __init__(self, *args): - argc = len(args) - self.args = args # modified: always assign args, no error check - if argc == 5: - self.encoding = args[0] - self.object = args[1] - self.start = args[2] - self.end = args[3] - self.reason = args[4] - - # auto-generated code, please check carefully! - def __str__(self): - # this is a bad hack, please supply an implementation - res = ' '.join([ - 'object=' + str(getattr(self, 'object', None)), - 'end=' + str(getattr(self, 'end', None)), - 'encoding=' + str(getattr(self, 'encoding', None)), - 'args=' + str(getattr(self, 'args', None)), - 'start=' + str(getattr(self, 'start', None)), - 'reason=' + str(getattr(self, 'reason', None)), - ]) - return res +class WindowsError(OSError): + """MS-Windows OS system call failed.""" From pedronis at codespeak.net Thu Jun 23 15:53:14 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 15:53:14 +0200 (CEST) Subject: [pypy-svn] r13717 - pypy/dist/pypy/annotation Message-ID: <20050623135314.97C6D27B85@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 15:53:13 2005 New Revision: 13717 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/bookkeeper.py Log: stats for formatting % change Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 23 15:53:13 2005 @@ -306,7 +306,6 @@ class __extend__(pairtype(SomeString, SomeObject)): def mod((str, args)): - assert str.is_constant() getbookkeeper().count('strformat', str, args) return SomeString() Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 23 15:53:13 2005 @@ -134,6 +134,10 @@ return self.indexrepr(idx) def consider_strformat(self, str, args): + if str.is_constant(): + s = repr(str.const) + else: + s = "?!!!!!!" if isinstance(args, SomeTuple): return (str.const, tuple([self.typerepr(x) for x in args.items])) else: From tismer at codespeak.net Thu Jun 23 16:14:13 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 16:14:13 +0200 (CEST) Subject: [pypy-svn] r13718 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050623141413.3383227B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 16:14:11 2005 New Revision: 13718 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: list comparison works (just eq and ne needed) Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Thu Jun 23 16:14:11 2005 @@ -333,6 +333,11 @@ lst1.listdef.union(lst2.listdef) return lst1 + def eq((lst1, lst2)): + lst1.listdef.union(lst2.listdef) + return SomeBool() + ne = eq + class __extend__(pairtype(SomeList, SomeObject)): Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 16:14:11 2005 @@ -179,6 +179,16 @@ hop.gendirectcall(ll_extend, v_lst1, v_lst2) return v_lst1 + def rtype_eq((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + return hop.gendirectcall(ll_listeq, v_lst1, v_lst2) + + def rtype_ne((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + flag = hop.gendirectcall(ll_listeq, v_lst1, v_lst2) + return hop.genop('bool_not', [flag], resulttype=Bool) + + # ____________________________________________________________ # # Low-level methods. These can be run for testing, but are meant to @@ -366,6 +376,25 @@ # ____________________________________________________________ # +# Comparison. + +def ll_listeq(l1, l2): + len1 = len(l1.items) + len2 = len(l2.items) + if len1 != len2: + return False + j = 0 + items1 = l1.items + items2 = l2.items + while j < len1: + if items1[j] != items2[j]: + return False + j += 1 + return True + + +# ____________________________________________________________ +# # Irregular operations. def ll_newlist(LISTPTR, length): Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 16:14:11 2005 @@ -4,7 +4,7 @@ from pypy.rpython.rlist import * from pypy.rpython.rslice import ll_newslice from pypy.rpython.rint import signed_repr -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, make_interpreter def sample_list(): @@ -221,3 +221,16 @@ return l1 is l2 res = interpret(dummyfn, []) assert res is False + +def test_list_compare(): + def fn(i, j, neg=False): + s1 = [[1, 2, 3], [4, 5, 1]] + s2 = [[1, 2, 3], [4, 5, 1], [1], [1, 2], [4, 5, 1, 6], [7, 1, 1, 8, 9, 10]] + if neg: return s1[i] != s2[i] + return s1[i] == s2[j] + ev_fn = make_interpreter(fn, [0, 0, False]) + for i in range(2): + for j in range(6): + for case in False, True: + res = ev_fn(i, j, case) + assert res is fn(i, j, case) From mwh at codespeak.net Thu Jun 23 16:39:24 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 16:39:24 +0200 (CEST) Subject: [pypy-svn] r13719 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623143924.6D14C27B83@code1.codespeak.net> Author: mwh Date: Thu Jun 23 16:39:21 2005 New Revision: 13719 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/test/test_rint.py Log: implementation of str for ints. also, a little more llinterp. (mwh, pedronis) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 16:39:21 2005 @@ -259,7 +259,7 @@ for typ in (float, int): typname = typ.__name__ - optup = ('add', 'sub', 'mul', 'div', 'gt', 'lt', 'ge', 'ne', 'le', 'eq') + optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq') if typ is int: optup += 'truediv', 'floordiv' for opname in optup: @@ -271,7 +271,7 @@ func = opimpls[%(opname)r] return func(x, y) """ % locals()).compile() - for opname in 'is_true',: + for opname in 'is_true', 'neg': assert opname in opimpls exec py.code.Source(""" def %(typname)s_%(opname)s(x): Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Thu Jun 23 16:39:21 2005 @@ -1,7 +1,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.objspace import op_appendices -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char, \ + GcArray, malloc from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -264,6 +265,40 @@ vlist = hop.inputargs(Float) return vlist[0] + def rtype_str(_, hop): + varg = hop.inputarg(hop.args_r[0], 0) + return hop.gendirectcall(ll_int2str, varg) + +CHAR_ARRAY = GcArray(Char) + +def ll_int2str(i): + from pypy.rpython.rstr import STR + temp = malloc(CHAR_ARRAY, 20) + len = 0 + sign = 0 + if i < 0: + sign = 1 + i = -i + if i == 0: + len = 1 + temp[0] = '0' + else: + while i: + temp[len] = chr(i%10+ord('0')) + i /= 10 + len += 1 + len += sign + result = malloc(STR, len) + if sign: + result.chars[0] = '-' + j = 1 + else: + j = 0 + while j < len: + result.chars[j] = temp[len-j-1] + j += 1 + return result + # # _________________________ Conversions _________________________ Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Thu Jun 23 16:39:21 2005 @@ -2,7 +2,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, make_interpreter class TestSnippet(object): @@ -49,3 +49,18 @@ res = interpret(dummyfn, [ord('a')]) assert res == 'a' +def test_str_of_int(): + def dummy(i): + return str(i) + + ev_fun = make_interpreter(dummy, [0]) + + res = ev_fun(0) + assert ''.join(res.chars) == '0' + + res = ev_fun(1034) + assert ''.join(res.chars) == '1034' + + res = ev_fun(-123) + assert ''.join(res.chars) == '-123' + From hpk at codespeak.net Thu Jun 23 16:41:40 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 16:41:40 +0200 (CEST) Subject: [pypy-svn] r13720 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623144140.CC3D027B83@code1.codespeak.net> Author: hpk Date: Thu Jun 23 16:41:39 2005 New Revision: 13720 Added: pypy/dist/pypy/rpython/rdict.py (contents, props changed) pypy/dist/pypy/rpython/test/test_rdict.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rtyper.py Log: (hpk,arre,arigo) added machinery for rdict's which at the moment can only process exactly one key-value mapping. Added: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 16:41:39 2005 @@ -0,0 +1,183 @@ +from pypy.annotation.pairtype import pairtype +from pypy.annotation import model as annmodel +from pypy.objspace.flow.model import Constant +from pypy.rpython import rmodel, lltype +from pypy.rpython.rstr import STR, string_repr, ll_strhash + +# ____________________________________________________________ +# +# pseudo implementation of RPython dictionary (this is per +# dictvalue type): +# +# struct dictentry { +# struct STR *key; +# ### XXX? int state; +# DICTVALUE value; +# } +# +# struct dicttable { +# int num_used_entries; +# Array *entries; +# } +# +# + +class __extend__(annmodel.SomeDict): + def rtyper_makerepr(self, rtyper): + s_key = self.dictdef.dictkey.s_value + if isinstance(s_key, annmodel.SomeString): + dictvalue = self.dictdef.dictvalue + return StrDictRepr(lambda: rtyper.getrepr(dictvalue.s_value), + dictvalue) + else: + raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) + + def rtyper_makekey(self): + return (self.dictdef.dictkey, self.dictdef.dictvalue) + +class StrDictRepr(rmodel.Repr): + + def __init__(self, value_repr, dictvalue=None): + self.STRDICT = lltype.GcForwardReference() + self.lowleveltype = lltype.Ptr(self.STRDICT) + if not isinstance(value_repr, rmodel.Repr): # not computed yet, done by setup() + assert callable(value_repr) + self._value_repr_computer = value_repr + else: + self.value_repr = value_repr + self.dictvalue = dictvalue + #self.dict_cache = {} + # setup() needs to be called to finish this initialization + + def setup(self): + if 'value_repr' not in self.__dict__: + self.value_repr = self._value_repr_computer() + if isinstance(self.STRDICT, lltype.GcForwardReference): + self.DICTVALUE = self.value_repr.lowleveltype + self.DICTENTRY = lltype.Struct("dictentry", ("key", lltype.Ptr(STR)), + ('value', self.DICTVALUE)) + self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) + self.STRDICT.become(lltype.GcStruct("dicttable", + ("num_used_entries", lltype.Signed), + ("entries", lltype.Ptr(self.DICTENTRYARRAY)))) + + #def convert_const(self, dictobj): + # dictobj = getattr(dictobj, '__self__', dictobj) # for bound list methods + # if not isinstance(dictobj, list): + # raise TyperError("expected a list: %r" % (dictobj,)) + # try: + # key = Constant(dictobj) + # return self.list_cache[key] + # except KeyError: + # self.setup() + # result = malloc(self.STRDICT, immortal=True) + # self.list_cache[key] = result + # result.items = malloc(self.STRDICT.items.TO, len(dictobj)) + # r_item = self.value_repr + # for i in range(len(dictobj)): + # x = dictobj[i] + # result.items[i] = r_item.convert_const(x) + # return result + + #def rtype_len(self, hop): + # v_lst, = hop.inputargs(self) + # return hop.gendirectcall(ll_len, v_lst) + +class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): + + def rtype_getitem((r_dict, r_string), hop): + v_dict, v_key = hop.inputargs(r_dict, string_repr) + return hop.gendirectcall(ll_strdict_getitem, v_dict, v_key) + + def rtype_setitem((r_dict, r_string), hop): + v_dict, v_key, v_value = hop.inputargs(r_dict, string_repr, r_dict.value_repr) + hop.gendirectcall(ll_strdict_setitem, v_dict, v_key, v_value) + +class __extend__(pairtype(StrDictRepr, StrDictRepr)): + def convert_from_to((r_dict1, r_dict2), v, llops): + # check that we don't convert from StrDicts with + # different value types + if r_dict1.dictvalue is None or r_dict2.dictvalue is None: + return NotImplemented + if r_dict1.dictvalue is not r_dict2.dictvalue: + return NotImplemented + return v + + #def rtype_add((self, _), hop): + # v_lst1, v_lst2 = hop.inputargs(self, self) + # return hop.gendirectcall(ll_concat, v_lst1, v_lst2) +# +# def rtype_inplace_add((self, _), hop): +# v_lst1, v_lst2 = hop.inputargs(self, self) +# hop.gendirectcall(ll_extend, v_lst1, v_lst2) +# return v_lst1 + +# ____________________________________________________________ +# +# Low-level methods. These can be run for testing, but are meant to +# be direct_call'ed from rtyped flow graphs, which means that they will +# get flowed and annotated, mostly with SomePtr. + +def ll_strdict_len(d): + return d.num_used_entries + +def ll_strdict_getitem(d, key): + return d.entries[0].value + +def ll_strdict_setitem(d, key, value): + d.entries[0].key = key + d.entries[0].value = value + +# ____________________________________________________________ +# +# Irregular operations. + +def ll_newstrdict(DICTPTR): + d = lltype.malloc(DICTPTR.TO) + d.entries = lltype.malloc(DICTPTR.TO.entries.TO, 8) # everything is zeroed + d.num_used_entries = 0 # but still be explicit + return d + +def rtype_newdict(hop): + r_dict = hop.r_result + if not isinstance(r_dict, StrDictRepr): + raise rmodel.TyperError("cannot create non-StrDicts, got %r" %(r_dict,)) + c1 = hop.inputconst(lltype.Void, r_dict.lowleveltype) + v_result = hop.gendirectcall(ll_newstrdict, c1) + return v_result + +# ____________________________________________________________ +# +# Iteration. + +if 0: + class ListIteratorRepr(Repr): + + def __init__(self, r_list): + self.r_list = r_list + self.lowleveltype = lltype.Ptr(GcStruct('listiter', + ('list', r_list.lowleveltype), + ('index', Signed))) + + def newiter(self, hop): + v_lst, = hop.inputargs(self.r_list) + citerptr = hop.inputconst(Void, self.lowleveltype) + return hop.gendirectcall(ll_listiter, citerptr, v_lst) + + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) + return hop.gendirectcall(ll_listnext, v_iter) + + def ll_listiter(ITERPTR, lst): + iter = malloc(ITERPTR.TO) + iter.list = lst + iter.index = 0 + return iter + + def ll_listnext(iter): + l = iter.list + index = iter.index + if index >= len(l.items): + raise StopIteration + iter.index = index + 1 + return l.items[index] Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 23 16:41:39 2005 @@ -329,6 +329,9 @@ def translate_op_newlist(self, hop): return rlist.rtype_newlist(hop) + def translate_op_newdict(self, hop): + return rdict.rtype_newdict(hop) + def translate_op_alloc_and_set(self, hop): return rlist.rtype_alloc_and_set(hop) @@ -526,6 +529,6 @@ from pypy.rpython import robject from pypy.rpython import rint, rbool, rfloat from pypy.rpython import rslice -from pypy.rpython import rlist, rstr, rtuple +from pypy.rpython import rlist, rstr, rtuple, rdict from pypy.rpython import rclass, rbuiltin, rpbc from pypy.rpython import rptr Added: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 16:41:39 2005 @@ -0,0 +1,13 @@ + +from pypy.rpython import lltype +from pypy.rpython.test.test_llinterp import interpret + +import py + +def test_dict_creation(): + def createdict(i): + d = {'hello' : i} + return d['hello'] + + res = interpret(createdict, [42]) + assert res == 42 From hpk at codespeak.net Thu Jun 23 17:06:21 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 17:06:21 +0200 (CEST) Subject: [pypy-svn] r13721 - pypy/dist/pypy/rpython Message-ID: <20050623150621.161E427B83@code1.codespeak.net> Author: hpk Date: Thu Jun 23 17:06:20 2005 New Revision: 13721 Modified: pypy/dist/pypy/rpython/llinterp.py Log: (hpk,arre) add support for 'int_and' and 'int_or' Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 17:06:20 2005 @@ -259,13 +259,14 @@ for typ in (float, int): typname = typ.__name__ - optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq') + optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq', 'and_', 'or_') if typ is int: optup += 'truediv', 'floordiv' for opname in optup: assert opname in opimpls + pureopname = opname.rstrip('_') exec py.code.Source(""" - def %(typname)s_%(opname)s(x, y): + def %(typname)s_%(pureopname)s(x, y): assert isinstance(x, %(typname)s) assert isinstance(y, %(typname)s) func = opimpls[%(opname)r] From hpk at codespeak.net Thu Jun 23 17:07:36 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 17:07:36 +0200 (CEST) Subject: [pypy-svn] r13722 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623150736.A7B2827B85@code1.codespeak.net> Author: hpk Date: Thu Jun 23 17:07:35 2005 New Revision: 13722 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (hpk, arre) a slightly more clever implementation for StrDict's getitem/setitem Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 17:07:35 2005 @@ -1,8 +1,8 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython import rmodel, lltype -from pypy.rpython.rstr import STR, string_repr, ll_strhash +from pypy.rpython import rmodel, lltype, rstr +from pypy.rpython.rstr import STR, string_repr # ____________________________________________________________ # @@ -118,15 +118,38 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. +deleted_entry_marker = lltype.malloc(STR, 0, immortal=True) + def ll_strdict_len(d): return d.num_used_entries def ll_strdict_getitem(d, key): - return d.entries[0].value + entry = ll_strdict_lookup(d, key) + if entry.key: + return entry.value + else: + raise KeyError def ll_strdict_setitem(d, key, value): - d.entries[0].key = key - d.entries[0].value = value + entry = ll_strdict_lookup(d, key) + if not entry.key: + entry.key = key + entry.value = value + +def ll_strdict_lookup(d, key): + keyhash = rstr.ll_strhash(key) + n = len(d.entries) + index = keyhash & (n - 1) + while 1: + entry = d.entries[index] + if entry.key: + if rstr.ll_streq(entry.key, key): + break + # XXX check for delitem + index = (index + 1) & (n-1) + else: + break + return entry # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 17:07:35 2005 @@ -11,3 +11,11 @@ res = interpret(createdict, [42]) assert res == 42 + +def test_dict_getitem_setitem(): + def func(i): + d = {'hello' : i} + d['world'] = i + 1 + return d['hello'] * d['world'] + res = interpret(func, [6]) + assert res == 42 From mwh at codespeak.net Thu Jun 23 17:11:21 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 17:11:21 +0200 (CEST) Subject: [pypy-svn] r13723 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623151121.B74D627B88@code1.codespeak.net> Author: mwh Date: Thu Jun 23 17:11:20 2005 New Revision: 13723 Modified: pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/test/test_rint.py Log: converting ints to hex at low-level Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Thu Jun 23 17:11:20 2005 @@ -2,8 +2,9 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.objspace import op_appendices from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char, \ - GcArray, malloc -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr + GcArray, malloc, Array +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr, \ + inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -269,6 +270,11 @@ varg = hop.inputarg(hop.args_r[0], 0) return hop.gendirectcall(ll_int2str, varg) + def rtype_hex(_, hop): + varg = hop.inputarg(hop.args_r[0], 0) + true = inputconst(Bool, True) + return hop.gendirectcall(ll_int2hex, varg, true) + CHAR_ARRAY = GcArray(Char) def ll_int2str(i): @@ -299,6 +305,44 @@ j += 1 return result +hex_chars = malloc(Array(Char), 16, immortal=True) + +for i in range(16): + hex_chars[i] = "%x"%i + +def ll_int2hex(i, addPrefix): + from pypy.rpython.rstr import STR + temp = malloc(CHAR_ARRAY, 20) + len = 0 + sign = 0 + if i < 0: + sign = 1 + i = -i + if i == 0: + len = 1 + temp[0] = '0' + else: + while i: + temp[len] = hex_chars[i%16] + i /= 16 + len += 1 + len += sign + if addPrefix: + len += 2 + result = malloc(STR, len) + j = 0 + if sign: + result.chars[0] = '-' + j = 1 + if addPrefix: + result.chars[j] = '0' + result.chars[j+1] = 'x' + j += 2 + while j < len: + result.chars[j] = temp[len-j-1] + j += 1 + return result + # # _________________________ Conversions _________________________ Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Thu Jun 23 17:11:20 2005 @@ -64,3 +64,18 @@ res = ev_fun(-123) assert ''.join(res.chars) == '-123' +def test_hex_of_int(): + def dummy(i): + return hex(i) + + ev_fun = make_interpreter(dummy, [0]) + + res = ev_fun(0) + assert ''.join(res.chars) == '0x0' + + res = ev_fun(1034) + assert ''.join(res.chars) == '0x40a' + + res = ev_fun(-123) + assert ''.join(res.chars) == '-0x7b' + From arigo at codespeak.net Thu Jun 23 17:22:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Jun 2005 17:22:36 +0200 (CEST) Subject: [pypy-svn] r13724 - pypy/dist/pypy/rpython Message-ID: <20050623152236.7D93727B8B@code1.codespeak.net> Author: arigo Date: Thu Jun 23 17:22:34 2005 New Revision: 13724 Modified: pypy/dist/pypy/rpython/annlowlevel.py Log: Bug fix. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Thu Jun 23 17:22:34 2005 @@ -26,7 +26,7 @@ def __hash__(self): return hash(self.val) def __str__(self): - return getattr(self.val, '__name__', self.val) + 'Const' + return getattr(self.val, '__name__', repr(self.val)) + 'Const' class LowLevelAnnotatorPolicy(BasicAnnotatorPolicy): From arigo at codespeak.net Thu Jun 23 17:23:06 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Jun 2005 17:23:06 +0200 (CEST) Subject: [pypy-svn] r13725 - pypy/dist/pypy/translator/c Message-ID: <20050623152306.CF1D727B93@code1.codespeak.net> Author: arigo Date: Thu Jun 23 17:23:04 2005 New Revision: 13725 Modified: pypy/dist/pypy/translator/c/char_include.h Log: Compare characters unsignedly in C (credits: tismer) Modified: pypy/dist/pypy/translator/c/char_include.h ============================================================================== --- pypy/dist/pypy/translator/c/char_include.h (original) +++ pypy/dist/pypy/translator/c/char_include.h Thu Jun 23 17:23:04 2005 @@ -6,10 +6,10 @@ /*** binary operations ***/ -#define OP_CHAR_EQ(x,y,r,err) r = ((x) == (y)); -#define OP_CHAR_NE(x,y,r,err) r = ((x) != (y)); -#define OP_CHAR_LE(x,y,r,err) r = ((x) <= (y)); -#define OP_CHAR_GT(x,y,r,err) r = ((x) > (y)); -#define OP_CHAR_LT(x,y,r,err) r = ((x) < (y)); -#define OP_CHAR_GE(x,y,r,err) r = ((x) >= (y)); +#define OP_CHAR_EQ(x,y,r,err) r = ((x) == (y)); +#define OP_CHAR_NE(x,y,r,err) r = ((x) != (y)); +#define OP_CHAR_LE(x,y,r,err) r = ((unsigned char)(x) <= (unsigned char)(y)); +#define OP_CHAR_GT(x,y,r,err) r = ((unsigned char)(x) > (unsigned char)(y)); +#define OP_CHAR_LT(x,y,r,err) r = ((unsigned char)(x) < (unsigned char)(y)); +#define OP_CHAR_GE(x,y,r,err) r = ((unsigned char)(x) >= (unsigned char)(y)); From hpk at codespeak.net Thu Jun 23 17:32:33 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 17:32:33 +0200 (CEST) Subject: [pypy-svn] r13726 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623153233.4849527B8D@code1.codespeak.net> Author: hpk Date: Thu Jun 23 17:32:32 2005 New Revision: 13726 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (arre, hpk) added some delitem and len support (still no resizing is going on) Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 17:32:32 2005 @@ -79,9 +79,9 @@ # result.items[i] = r_item.convert_const(x) # return result - #def rtype_len(self, hop): - # v_lst, = hop.inputargs(self) - # return hop.gendirectcall(ll_len, v_lst) + def rtype_len(self, hop): + v_dict, = hop.inputargs(self) + return hop.gendirectcall(ll_strdict_len, v_dict) class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): @@ -89,6 +89,10 @@ v_dict, v_key = hop.inputargs(r_dict, string_repr) return hop.gendirectcall(ll_strdict_getitem, v_dict, v_key) + def rtype_delitem((r_dict, r_string), hop): + v_dict, v_key = hop.inputargs(r_dict, string_repr) + return hop.gendirectcall(ll_strdict_delitem, v_dict, v_key) + def rtype_setitem((r_dict, r_string), hop): v_dict, v_key, v_value = hop.inputargs(r_dict, string_repr, r_dict.value_repr) hop.gendirectcall(ll_strdict_setitem, v_dict, v_key, v_value) @@ -134,8 +138,17 @@ entry = ll_strdict_lookup(d, key) if not entry.key: entry.key = key + d.num_used_entries += 1 entry.value = value +def ll_strdict_delitem(d, key): + entry = ll_strdict_lookup(d, key) + if not entry.key or entry.key == deleted_entry_marker: + raise KeyError + entry.key = deleted_entry_marker + d.num_used_entries -= 1 + # XXX: entry.value = ??? + def ll_strdict_lookup(d, key): keyhash = rstr.ll_strhash(key) n = len(d.entries) Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 17:32:32 2005 @@ -19,3 +19,23 @@ return d['hello'] * d['world'] res = interpret(func, [6]) assert res == 42 + +def test_dict_getitem_keyerror(): + def func(i): + d = {'hello' : i} + try: + return d['world'] + except KeyError: + return 0 + res = interpret(func, [6]) + assert res == 0 + +def test_dict_del_simple(): + def func(i): + d = {'hello' : i} + d['world'] = i + 1 + del d['hello'] + return len(d) + res = interpret(func, [6]) + assert res == 1 + From tismer at codespeak.net Thu Jun 23 18:01:49 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 18:01:49 +0200 (CEST) Subject: [pypy-svn] r13727 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623160149.CDC9027B93@code1.codespeak.net> Author: tismer Date: Thu Jun 23 18:01:48 2005 New Revision: 13727 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: implemented comparison for string lists. checking if the list is neither primitive nor string. prematurely optimized pop() and insert(). I am guilty. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 18:01:48 2005 @@ -6,6 +6,7 @@ from pypy.rpython import rrange from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr +from pypy.rpython.rstr import string_repr, ll_streq # ____________________________________________________________ # @@ -83,11 +84,16 @@ def rtype_method_insert(self, hop): v_lst, v_index, v_value = hop.inputargs(self, Signed, self.item_repr) - if hop.args_s[1].nonneg: + arg1 = hop.args_s[1] + args = v_lst, v_index, v_value + if arg1.is_constant() and arg1.const == 0: + llfn = ll_prepend + args = v_lst, v_value + elif arg1.nonneg: llfn = ll_insert_nonneg else: llfn = ll_insert - hop.gendirectcall(llfn, v_lst, v_index, v_value) + hop.gendirectcall(llfn, *args) def rtype_method_extend(self, hop): v_lst1, v_lst2 = hop.inputargs(self, self) @@ -100,11 +106,15 @@ def rtype_method_pop(self, hop): if hop.nb_args == 2: args = hop.inputargs(self, Signed) - if hop.args_s[1].nonneg: + assert hasattr(args[1], 'concretetype') + arg1 = hop.args_s[1] + if arg1.is_constant() and arg1.const == 0: + llfn = ll_pop_zero + args = args[:1] + elif hop.args_s[1].nonneg: llfn = ll_pop_nonneg else: llfn = ll_pop - assert hasattr(args[1], 'concretetype') else: args = hop.inputargs(self) llfn = ll_pop_default @@ -181,11 +191,17 @@ def rtype_eq((self, _), hop): v_lst1, v_lst2 = hop.inputargs(self, self) - return hop.gendirectcall(ll_listeq, v_lst1, v_lst2) + if self.item_repr == string_repr: + func = ll_streq + elif isinstance(self.item_repr.lowleveltype, Primitive): + func = None + else: + raise TyperError, 'comparison not implemented for %r' % self + cmp = hop.inputconst(Void, func) + return hop.gendirectcall(ll_listeq, v_lst1, v_lst2, cmp) - def rtype_ne((self, _), hop): - v_lst1, v_lst2 = hop.inputargs(self, self) - flag = hop.gendirectcall(ll_listeq, v_lst1, v_lst2) + def rtype_ne(both, hop): + flag = both.rtype_eq(hop) return hop.genop('bool_not', [flag], resulttype=Bool) @@ -208,6 +224,17 @@ newitems[length] = newitem l.items = newitems +# this one is for the special case of insert(0, x) +def ll_prepend(l, newitem): + length = len(l.items) + newitems = malloc(typeOf(l).TO.items.TO, length+1) + i = 0 + while i < length: + newitems[i+1] = l.items[i] + i += 1 + newitems[0] = newitem + l.items = newitems + def ll_insert_nonneg(l, index, newitem): length = len(l.items) newitems = malloc(typeOf(l).TO.items.TO, length+1) @@ -244,6 +271,18 @@ l.items = newitems return res +def ll_pop_zero(l): + index = len(l.items) - 1 + res = l.items[0] + newlength = index + newitems = malloc(typeOf(l).TO.items.TO, newlength) + j = 0 + while j < newlength: + newitems[j] = l.items[j+1] + j += 1 + l.items = newitems + return res + def ll_pop(l, index): if index < 0: index += len(l.items) @@ -378,7 +417,7 @@ # # Comparison. -def ll_listeq(l1, l2): +def ll_listeq(l1, l2, eqfn): len1 = len(l1.items) len2 = len(l2.items) if len1 != len2: @@ -387,8 +426,12 @@ items1 = l1.items items2 = l2.items while j < len1: - if items1[j] != items2[j]: - return False + if eqfn is None: + if items1[j] != items2[j]: + return False + else: + if not eqfn(items1[j], items2[j]): + return False j += 1 return True Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 18:01:48 2005 @@ -155,14 +155,15 @@ def test_insert_pop(): def dummyfn(): - l = [5, 6, 7, 8] + l = [6, 7, 8] + l.insert(0, 5) l.insert(1, 42) l.pop(2) - del l[0] + l.pop(0) l.pop(-1) l.pop() return l[-1] - res = interpret(dummyfn, ()) + res = interpret(dummyfn, ())#, view=True) assert res == 42 def test_reverse(): @@ -234,3 +235,17 @@ for case in False, True: res = ev_fn(i, j, case) assert res is fn(i, j, case) + +def test_list_comparestr(): + def fn(i, j, neg=False): + s1 = [["hell"], ["hello", "world"]] + s1[0][0] += "o" # ensure no interning + s2 = [["hello"], ["world"]] + if neg: return s1[i] != s2[i] + return s1[i] == s2[j] + ev_fn = make_interpreter(fn, [0, 0, False])#, view=True) + for i in range(2): + for j in range(2): + for case in False, True: + res = ev_fn(i, j, case) + assert res is fn(i, j, case) From ale at codespeak.net Thu Jun 23 18:05:03 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 18:05:03 +0200 (CEST) Subject: [pypy-svn] r13728 - pypy/extradoc/sprintinfo Message-ID: <20050623160503.6FDBB27B97@code1.codespeak.net> Author: ale Date: Thu Jun 23 18:05:02 2005 New Revision: 13728 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: List eq done Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 18:05:02 2005 @@ -43,7 +43,7 @@ - (easy) string slices task: do it (see rlist) - - (easy) equality and non-equality are generally missing + - DONE (easy) equality and non-equality are generally missing task: 1. missing for lists of primitives, and lists of strings 2. annotator fix: unify lists when they are compared 3. for instances, 'eq' is 'is' From mwh at codespeak.net Thu Jun 23 18:40:12 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 18:40:12 +0200 (CEST) Subject: [pypy-svn] r13729 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623164012.6FA0627B6A@code1.codespeak.net> Author: mwh Date: Thu Jun 23 18:40:11 2005 New Revision: 13729 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: string formatting for rpython (samuele, mwh) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 23 18:40:11 2005 @@ -6,6 +6,8 @@ from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst from pypy.rpython.rarithmetic import intmask from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.rtuple import TupleRepr +from pypy.rpython import rint # ____________________________________________________________ # @@ -96,7 +98,10 @@ elif not s_item.__class__ == annmodel.SomeString: raise TyperError("join of non-string list: %r" % r_lst) v_str, v_lst = hop.inputargs(string_repr, r_lst) - return hop.gendirectcall(ll_join, v_str, v_lst) + cname = inputconst(Void, "items") + v_items = hop.genop("getfield", [v_lst, cname], + resulttype=Ptr(GcArray(Ptr(STR)))) + return hop.gendirectcall(ll_join, v_str, v_items) def make_iterator_repr(self): return string_iterator_repr @@ -150,6 +155,76 @@ return hop.genop('int_gt', [vres, hop.inputconst(Signed, 0)], resulttype=Bool) +def parse_fmt_string(fmt): + # we support x, d, s, [r] + + it = iter(fmt) + r = [] + curstr = '' + for c in it: + if c == '%': + f = it.next() + if f == '%': + curstr += '%' + continue + + if curstr: + r.append(curstr) + curstr = '' + assert f in 'xdsr' + + r.append((f,)) + else: + curstr += c + if curstr: + r.append(curstr) + return r + + + +class __extend__(pairtype(StringRepr, TupleRepr)): + def rtype_mod(_, hop): + s_str = hop.args_s[0] + assert s_str.is_constant() + s = s_str.const + things = parse_fmt_string(s) + size = inputconst(Void, len(things)) + TEMP = GcArray(Ptr(STR)) + cTEMP = inputconst(Void, TEMP) + vtemp = hop.genop("malloc_varsize", [cTEMP, size], + resulttype=Ptr(TEMP)) + r_tuple = hop.args_r[1] + v_tuple = hop.args_v[1] + + argsiter = iter(enumerate(r_tuple.items_r)) + for i, thing in enumerate(things): + if isinstance(thing, tuple): + code = thing[0] + argi, r_arg = argsiter.next() + fname = r_tuple.fieldnames[argi] + cname = hop.inputconst(Void, fname) + vitem = hop.genop("getfield", [v_tuple, cname], + resulttype=r_arg.lowleveltype) + if code == 's': + assert isinstance(r_arg, StringRepr) + vchunk = hop.llops.convertvar(vitem, r_arg, string_repr) + elif code == 'd': + assert isinstance(r_arg, IntegerRepr) + vchunk = hop.gendirectcall(rint.ll_int2str, vitem) + elif code == 'x': + assert isinstance(r_arg, IntegerRepr) + vchunk = hop.gendirectcall(rint.ll_int2hex, vitem, + inputconst(Bool, False)) + else: + assert 0 + else: + vchunk = inputconst(string_repr, thing) + i = inputconst(Signed, i) + hop.genop('setarrayitem', [vtemp, i, vchunk]) + + return hop.gendirectcall(ll_join, inputconst(string_repr, ""), vtemp) + + class __extend__(CharRepr): def convert_const(self, value): @@ -351,10 +426,9 @@ emptystr = string_repr.convert_const("") -def ll_join(s, l): +def ll_join(s, items): s_chars = s.chars s_len = len(s_chars) - items = l.items num_items = len(items) if num_items == 0: return emptystr Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Jun 23 18:40:11 2005 @@ -1,5 +1,6 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * +from pypy.rpython.rstr import parse_fmt_string from pypy.rpython.rtyper import RPythonTyper from pypy.rpython.test.test_llinterp import interpret, make_interpreter @@ -183,3 +184,27 @@ for j in range(3): res = ev_fn(i, j) assert ''.join(res.chars) == fn(i, j) + +def test_parse_fmt(): + assert parse_fmt_string('a') == ['a'] + assert parse_fmt_string('%s') == [('s',)] + assert parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"] + +def test_strformat(): + def percentS(s): + return "before %s after" % (s,) + + res = interpret(percentS, ['1']) + assert ''.join(res.chars) == 'before 1 after' + + def percentD(i): + return "bing %d bang" % (i,) + + res = interpret(percentD, [23]) + assert ''.join(res.chars) == 'bing 23 bang' + + def percentX(i): + return "bing %x bang" % (i,) + + res = interpret(percentX, [23]) + assert ''.join(res.chars) == 'bing 17 bang' From mwh at codespeak.net Thu Jun 23 18:45:01 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 18:45:01 +0200 (CEST) Subject: [pypy-svn] r13730 - pypy/dist/pypy/rpython/test Message-ID: <20050623164501.E0D0B27B86@code1.codespeak.net> Author: mwh Date: Thu Jun 23 18:45:01 2005 New Revision: 13730 Modified: pypy/dist/pypy/rpython/test/test_rstr.py Log: more string formatting tests (we don't handle non-tuples on the RHS, btw) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Jun 23 18:45:01 2005 @@ -206,5 +206,22 @@ def percentX(i): return "bing %x bang" % (i,) - res = interpret(percentX, [23]) + x_fn = make_interpreter(percentX, [0]) + + res = x_fn(23) assert ''.join(res.chars) == 'bing 17 bang' + + res = x_fn(-123) + assert ''.join(res.chars) == 'bing -7b bang' + + def moreThanOne(s, d, x): + return "string: %s decimal: %d hex: %x" % (s, d, x) + + m_fn = make_interpreter(moreThanOne, ['a', 2, 3]) + + args = 'a', 2, 3 + res = m_fn(*args) + assert ''.join(res.chars) == moreThanOne(*args) + + + From tismer at codespeak.net Thu Jun 23 18:59:01 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 18:59:01 +0200 (CEST) Subject: [pypy-svn] r13731 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623165901.C154327B8A@code1.codespeak.net> Author: tismer Date: Thu Jun 23 18:59:00 2005 New Revision: 13731 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rlist.py Log: made eq/ne work for instances. refactored comparison. next thing is to support "contains" and "index" Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 18:59:00 2005 @@ -2,11 +2,12 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import * -from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython import rrange from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr from pypy.rpython.rstr import string_repr, ll_streq +from pypy.rpython.rclass import InstanceRepr # ____________________________________________________________ # @@ -74,6 +75,17 @@ result.items[i] = r_item.convert_const(x) return result + def get_eqfunc(self): + if self.item_repr == string_repr: + func = ll_streq + elif isinstance(self.item_repr.lowleveltype, Primitive): + func = None + elif isinstance(self.item_repr, InstanceRepr): + func = None + else: + raise TyperError, 'comparison not implemented for %r' % self + return inputconst(Void, func) + def rtype_len(self, hop): v_lst, = hop.inputargs(self) return hop.gendirectcall(ll_len, v_lst) @@ -191,17 +203,11 @@ def rtype_eq((self, _), hop): v_lst1, v_lst2 = hop.inputargs(self, self) - if self.item_repr == string_repr: - func = ll_streq - elif isinstance(self.item_repr.lowleveltype, Primitive): - func = None - else: - raise TyperError, 'comparison not implemented for %r' % self - cmp = hop.inputconst(Void, func) - return hop.gendirectcall(ll_listeq, v_lst1, v_lst2, cmp) + return hop.gendirectcall(ll_listeq, v_lst1, v_lst2, self.get_eqfunc()) - def rtype_ne(both, hop): - flag = both.rtype_eq(hop) + def rtype_ne((self, _), hop): + v_lst1, v_lst2 = hop.inputargs(self, self) + flag = hop.gendirectcall(ll_listeq, v_lst1, v_lst2, self.get_eqfunc()) return hop.genop('bool_not', [flag], resulttype=Bool) Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 18:59:00 2005 @@ -249,3 +249,23 @@ for case in False, True: res = ev_fn(i, j, case) assert res is fn(i, j, case) + +class Foo: pass + +class Bar(Foo): pass + +def test_list_compareinst(): + def fn(i, j, neg=False): + foo1 = Foo() + foo2 = Foo() + bar1 = Bar() + s1 = [[foo1], [foo2], [bar1]] + s2 = s1[:] + if neg: return s1[i] != s2[i] + return s1[i] == s2[j] + ev_fn = make_interpreter(fn, [0, 0, False])#, view=True) + for i in range(3): + for j in range(3): + for case in False, True: + res = ev_fn(i, j, case) + assert res is fn(i, j, case) From mwh at codespeak.net Thu Jun 23 19:17:22 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 19:17:22 +0200 (CEST) Subject: [pypy-svn] r13732 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623171722.ACB8827B6A@code1.codespeak.net> Author: mwh Date: Thu Jun 23 19:17:21 2005 New Revision: 13732 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: rpython string formatting with non-tuple right hand sides. tests. (mwh, samuele) Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 23 19:17:21 2005 @@ -115,6 +115,9 @@ llfn = ll_stritem return hop.gendirectcall(llfn, v_str, v_index) + def rtype_mod(_, hop): + return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) + class __extend__(pairtype(StringRepr, StringRepr)): def rtype_add(_, hop): @@ -155,6 +158,9 @@ return hop.genop('int_gt', [vres, hop.inputconst(Signed, 0)], resulttype=Bool) + def rtype_mod(_, hop): + return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) + def parse_fmt_string(fmt): # we support x, d, s, [r] @@ -181,49 +187,59 @@ return r +def do_stringformat(hop, sourcevarsrepr): + s_str = hop.args_s[0] + assert s_str.is_constant() + s = s_str.const + things = parse_fmt_string(s) + size = inputconst(Void, len(things)) + TEMP = GcArray(Ptr(STR)) + cTEMP = inputconst(Void, TEMP) + vtemp = hop.genop("malloc_varsize", [cTEMP, size], + resulttype=Ptr(TEMP)) + r_tuple = hop.args_r[1] + v_tuple = hop.args_v[1] + + argsiter = iter(sourcevarsrepr) + + for i, thing in enumerate(things): + if isinstance(thing, tuple): + code = thing[0] + vitem, r_arg = argsiter.next() + if code == 's': + assert isinstance(r_arg, StringRepr) + vchunk = hop.llops.convertvar(vitem, r_arg, string_repr) + elif code == 'd': + assert isinstance(r_arg, IntegerRepr) + vchunk = hop.gendirectcall(rint.ll_int2str, vitem) + elif code == 'x': + assert isinstance(r_arg, IntegerRepr) + vchunk = hop.gendirectcall(rint.ll_int2hex, vitem, + inputconst(Bool, False)) + else: + assert 0 + else: + vchunk = inputconst(string_repr, thing) + i = inputconst(Signed, i) + hop.genop('setarrayitem', [vtemp, i, vchunk]) + + return hop.gendirectcall(ll_join, inputconst(string_repr, ""), vtemp) + class __extend__(pairtype(StringRepr, TupleRepr)): def rtype_mod(_, hop): - s_str = hop.args_s[0] - assert s_str.is_constant() - s = s_str.const - things = parse_fmt_string(s) - size = inputconst(Void, len(things)) - TEMP = GcArray(Ptr(STR)) - cTEMP = inputconst(Void, TEMP) - vtemp = hop.genop("malloc_varsize", [cTEMP, size], - resulttype=Ptr(TEMP)) r_tuple = hop.args_r[1] v_tuple = hop.args_v[1] - - argsiter = iter(enumerate(r_tuple.items_r)) - for i, thing in enumerate(things): - if isinstance(thing, tuple): - code = thing[0] - argi, r_arg = argsiter.next() - fname = r_tuple.fieldnames[argi] - cname = hop.inputconst(Void, fname) - vitem = hop.genop("getfield", [v_tuple, cname], - resulttype=r_arg.lowleveltype) - if code == 's': - assert isinstance(r_arg, StringRepr) - vchunk = hop.llops.convertvar(vitem, r_arg, string_repr) - elif code == 'd': - assert isinstance(r_arg, IntegerRepr) - vchunk = hop.gendirectcall(rint.ll_int2str, vitem) - elif code == 'x': - assert isinstance(r_arg, IntegerRepr) - vchunk = hop.gendirectcall(rint.ll_int2hex, vitem, - inputconst(Bool, False)) - else: - assert 0 - else: - vchunk = inputconst(string_repr, thing) - i = inputconst(Signed, i) - hop.genop('setarrayitem', [vtemp, i, vchunk]) - return hop.gendirectcall(ll_join, inputconst(string_repr, ""), vtemp) - + sourcevars = [] + for fname, r_arg in zip(r_tuple.fieldnames, r_tuple.items_r): + cname = hop.inputconst(Void, fname) + vitem = hop.genop("getfield", [v_tuple, cname], + resulttype=r_arg) + sourcevars.append((vitem, r_arg)) + + return do_stringformat(hop, sourcevars) + class __extend__(CharRepr): Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Jun 23 19:17:21 2005 @@ -224,4 +224,15 @@ assert ''.join(res.chars) == moreThanOne(*args) - +def test_strformat_nontuple(): + def percentD(i): + return "before %d after" % i + + res = interpret(percentD, [1]) + assert ''.join(res.chars) == 'before 1 after' + + def percentS(i): + return "before %s after" % i + + res = interpret(percentS, ['D']) + assert ''.join(res.chars) == 'before D after' From mwh at codespeak.net Thu Jun 23 19:20:35 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 19:20:35 +0200 (CEST) Subject: [pypy-svn] r13733 - pypy/extradoc/sprintinfo Message-ID: <20050623172035.E1ABB27B74@code1.codespeak.net> Author: mwh Date: Thu Jun 23 19:20:35 2005 New Revision: 13733 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: updates! Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 19:20:35 2005 @@ -33,6 +33,7 @@ - (probably easy): operations: str for ints, instances (only something very simple for the latter). all other uses are cheating, as are all uses of hex, oct, repr. + mostly DONE apart from instances which we're not sure we need anyway - (easy) list methods reverse, pop, insert, index(?) task: only left: remove the single index() call in PyPy (typeobject.py) @@ -53,6 +54,7 @@ invocations like concatenation and str() on integers task: 1. figure out what kind of formatting we use in PyPy 2. implement them + mostly DONE apart from possibly '%s' % some random instance * lltype will also need to grow a new primitive type, UnicodeChar. From arigo at codespeak.net Thu Jun 23 19:41:45 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Jun 2005 19:41:45 +0200 (CEST) Subject: [pypy-svn] r13734 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623174145.A8AC027B6A@code1.codespeak.net> Author: arigo Date: Thu Jun 23 19:41:41 2005 New Revision: 13734 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rarithmetic.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/test/test_rint.py Log: Unsigned arithmetic: basic support and bug fixes in the code that was already there but not tested. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 19:41:41 2005 @@ -3,6 +3,7 @@ from pypy.translator.translator import Translator from pypy.tool.sourcetools import compile2 from pypy.objspace.flow.model import Constant, Variable, last_exception +from pypy.rpython.rarithmetic import intmask, r_uint import py log = py.log.Producer('llinterp') @@ -251,22 +252,34 @@ assert type(b) is str and len(b) == 1 return ord(b) + def op_cast_int_to_uint(self, b): + assert type(b) is int + return r_uint(b) + + def op_cast_uint_to_int(self, b): + assert type(b) is r_uint + return intmask(b) + # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName opimpls = FunctionByName.copy() opimpls['is_true'] = bool -for typ in (float, int): +for typ in (float, int, r_uint): typname = typ.__name__ + if typ is r_uint: + opnameprefix = 'uint' + else: + opnameprefix = typname optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq', 'and_', 'or_') - if typ is int: + if typ in (int, r_uint): optup += 'truediv', 'floordiv' for opname in optup: assert opname in opimpls pureopname = opname.rstrip('_') exec py.code.Source(""" - def %(typname)s_%(pureopname)s(x, y): + def %(opnameprefix)s_%(pureopname)s(x, y): assert isinstance(x, %(typname)s) assert isinstance(y, %(typname)s) func = opimpls[%(opname)r] @@ -275,7 +288,7 @@ for opname in 'is_true', 'neg': assert opname in opimpls exec py.code.Source(""" - def %(typname)s_%(opname)s(x): + def %(opnameprefix)s_%(opname)s(x): assert isinstance(x, %(typname)s) func = opimpls[%(opname)r] return func(x) Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Thu Jun 23 19:41:41 2005 @@ -159,7 +159,7 @@ def intmask(n): if isinstance(n, int): - return n + return int(n) # possibly bool->int if isinstance(n, r_uint): n = long(n) n &= LONG_MASK Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Thu Jun 23 19:41:41 2005 @@ -2,7 +2,6 @@ from pypy.annotation import model as annmodel from pypy.rpython import lltype from pypy.rpython import rarithmetic -from pypy.rpython.lltype import Void, Signed, Float, Ptr, RuntimeTypeInfo from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range from pypy.rpython.rmodel import Repr, TyperError @@ -33,7 +32,7 @@ class BuiltinFunctionRepr(Repr): - lowleveltype = Void + lowleveltype = lltype.Void def __init__(self, builtinfunc): self.builtinfunc = builtinfunc @@ -102,7 +101,11 @@ #def rtype_builtin_range(hop): see rrange.py def rtype_intmask(hop): - vlist = hop.inputargs(Signed) + vlist = hop.inputargs(lltype.Signed) + return vlist[0] + +def rtype_r_uint(hop): + vlist = hop.inputargs(lltype.Unsigned) return vlist[0] @@ -119,11 +122,11 @@ def rtype_malloc(hop): assert hop.args_s[0].is_constant() if hop.nb_args == 1: - vlist = hop.inputargs(Void) + vlist = hop.inputargs(lltype.Void) return hop.genop('malloc', vlist, resulttype = hop.r_result.lowleveltype) else: - vlist = hop.inputargs(Void, Signed) + vlist = hop.inputargs(lltype.Void, lltype.Signed) return hop.genop('malloc_varsize', vlist, resulttype = hop.r_result.lowleveltype) @@ -133,7 +136,7 @@ def rtype_cast_pointer(hop): assert hop.args_s[0].is_constant() assert isinstance(hop.args_r[1], rptr.PtrRepr) - v_type, v_input = hop.inputargs(Void, hop.args_r[1]) + v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1]) return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result resulttype = hop.r_result.lowleveltype) @@ -141,7 +144,7 @@ assert isinstance(hop.args_r[0], rptr.PtrRepr) vlist = hop.inputargs(hop.args_r[0]) return hop.genop('runtime_type_info', vlist, - resulttype = rptr.PtrRepr(Ptr(RuntimeTypeInfo))) + resulttype = rptr.PtrRepr(lltype.Ptr(lltype.RuntimeTypeInfo))) BUILTIN_TYPER[lltype.malloc] = rtype_malloc @@ -151,6 +154,7 @@ BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask +BUILTIN_TYPER[rarithmetic.r_uint] = rtype_r_uint import time @@ -164,9 +168,9 @@ import math def rtype_math_exp(hop): - vlist = hop.inputargs(Float) + vlist = hop.inputargs(lltype.Float) # XXX need PyFPE_START_PROTECT/PyFPE_END_PROTECT/Py_SET_ERRNO_ON_MATH_ERROR - return hop.llops.gencapicall('exp', vlist, resulttype=Float, + return hop.llops.gencapicall('exp', vlist, resulttype=lltype.Float, includes=["math.h"]) # XXX clean up needed BUILTIN_TYPER[math.exp] = rtype_math_exp Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Thu Jun 23 19:41:41 2005 @@ -6,6 +6,7 @@ from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr, \ inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.rarithmetic import intmask, r_uint debug = False @@ -27,10 +28,10 @@ class __extend__(pairtype(IntegerRepr, IntegerRepr)): def convert_from_to((r_from, r_to), v, llops): - if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed: + if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned: if debug: print 'explicit cast_int_to_uint' return llops.genop('cast_int_to_uint', [v], resulttype=Unsigned) - if r_from.lowleveltype == Signed and r_to.lowleveltype == Unsigned: + if r_from.lowleveltype == Unsigned and r_to.lowleveltype == Signed: if debug: print 'explicit cast_uint_to_int' return llops.genop('cast_uint_to_int', [v], resulttype=Signed) return v @@ -189,9 +190,13 @@ class __extend__(IntegerRepr): def convert_const(self, value): - if not isinstance(value, int): # can be bool + if not isinstance(value, (int, r_uint)): # can be bool raise TyperError("not an integer: %r" % (value,)) - return int(value) + if self.lowleveltype == Signed: + return intmask(value) + if self.lowleveltype == Unsigned: + return r_uint(value) + raise NotImplementedError def rtype_float(_, hop): vlist = hop.inputargs(Float) Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Thu Jun 23 19:41:41 2005 @@ -3,6 +3,7 @@ from pypy.annotation import model as annmodel from pypy.rpython.test import snippet from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.rarithmetic import r_uint class TestSnippet(object): @@ -79,3 +80,16 @@ res = ev_fun(-123) assert ''.join(res.chars) == '-0x7b' +def test_unsigned(): + def dummy(i): + i = r_uint(i) + j = r_uint(12) + return i < j + + ev_fun = make_interpreter(dummy, [0]) + + res = ev_fun(0) + assert res is True + + res = ev_fun(-1) + assert res is False # -1 ==> 0xffffffff From hpk at codespeak.net Thu Jun 23 19:45:38 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 19:45:38 +0200 (CEST) Subject: [pypy-svn] r13735 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623174538.1CB4027B61@code1.codespeak.net> Author: hpk Date: Thu Jun 23 19:45:36 2005 New Revision: 13735 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (arre, hpk) - ported CPythonn's dict lookup function (ll_strdict_lookup) - added some operations to llinterp - still not resizing Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 19:45:36 2005 @@ -268,13 +268,13 @@ for typ in (float, int, r_uint): typname = typ.__name__ + optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq',) if typ is r_uint: opnameprefix = 'uint' else: opnameprefix = typname - optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq', 'and_', 'or_') if typ in (int, r_uint): - optup += 'truediv', 'floordiv' + optup += 'truediv', 'floordiv', 'and_', 'or_', 'lshift', 'rshift', 'xor' for opname in optup: assert opname in opimpls pureopname = opname.rstrip('_') Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 19:45:36 2005 @@ -3,6 +3,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython import rmodel, lltype, rstr from pypy.rpython.rstr import STR, string_repr +from pypy.rpython.rarithmetic import r_uint # ____________________________________________________________ # @@ -129,14 +130,14 @@ def ll_strdict_getitem(d, key): entry = ll_strdict_lookup(d, key) - if entry.key: + if entry.key and entry.key != deleted_entry_marker: return entry.value else: raise KeyError def ll_strdict_setitem(d, key, value): entry = ll_strdict_lookup(d, key) - if not entry.key: + if not entry.key or entry.key == deleted_entry_marker: entry.key = key d.num_used_entries += 1 entry.value = value @@ -149,20 +150,42 @@ d.num_used_entries -= 1 # XXX: entry.value = ??? + +# the below is a port of CPython's dictobject.c's lookdict implementation +PERTURB_SHIFT = 5 + def ll_strdict_lookup(d, key): - keyhash = rstr.ll_strhash(key) - n = len(d.entries) - index = keyhash & (n - 1) + hash = rstr.ll_strhash(key) + entries = d.entries + mask = len(entries) - 1 + i = r_uint(hash & mask) + + # do the first try before any looping + entry = entries[i] + if not entry.key or entry.key == key: + return entry + if entry.key == deleted_entry_marker: + freeslot = entry + else: + if entry.key.hash == hash and rstr.ll_streq(entry.key, key): + return entry + freeslot = lltype.nullptr(lltype.typeOf(entry).TO) + + # In the loop, key == deleted_entry_marker is by far (factor of 100s) the + # least likely outcome, so test for that last. + perturb = r_uint(hash) while 1: - entry = d.entries[index] - if entry.key: - if rstr.ll_streq(entry.key, key): - break - # XXX check for delitem - index = (index + 1) & (n-1) - else: - break - return entry + i = (i << 2) + i + perturb + 1 + entry = entries[i & mask] + if not entry.key: + return freeslot or entry + if entry.key == key or (entry.key.hash == hash and + entry.key != deleted_entry_marker and + rstr.ll_streq(entry.key, key)): + return entry + if entry.key == deleted_entry_marker and not freeslot: + freeslot = entry + perturb >>= PERTURB_SHIFT # ____________________________________________________________ # @@ -217,3 +240,17 @@ raise StopIteration iter.index = index + 1 return l.items[index] + + + keyhash = rstr.ll_strhash(key) + n = len(d.entries) + index = keyhash & (n - 1) + while 1: + entry = d.entries[index] + if not entry.key or en: + break + if entry.key != deleted_entry_marker and rstr.ll_streq(entry.key, key): + break + index = (index + 1) & (n-1) + #return entry + Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 19:45:36 2005 @@ -1,6 +1,7 @@ from pypy.rpython import lltype from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython import rstr, rdict import py @@ -39,3 +40,65 @@ res = interpret(func, [6]) assert res == 1 +def test_empty_strings(): + def func(i): + d = {'' : i} + del d[''] + try: + d[''] + return 0 + except KeyError: + pass + return 1 + res = interpret(func, [6]) + assert res == 1 + + def func(i): + d = {'' : i} + del d[''] + d[''] = i + 1 + return len(d) + res = interpret(func, [6]) + assert res == 1 + +def test_deleted_entry_reusage_with_colliding_hashes(): + def lowlevelhash(value): + p = lltype.malloc(rstr.STR, len(value)) + for i in range(len(value)): + p.chars[i] = value[i] + return rstr.ll_strhash(p) + + def func(c1, c2): + c1 = chr(c1) + c2 = chr(c2) + d = {} + d[c1] = 1 + d[c2] = 2 + del d[c1] + return d[c2] + + base = 8 + x = 'a' + xh = lowlevelhash(x) % base + for y in range(ord('b'), ord('z')): + if lowlevelhash(chr(y)) % base == xh: + break + else: + py.test.skip("XXX improve hash finding algo") + + res = interpret(func, [ord(x), y]) + assert res == 2 + + def func2(c1, c2): + c1 = chr(c1) + c2 = chr(c2) + d = {} + d[c1] = 1 + d[c2] = 2 + del d[c1] + d[c1] = 3 + return d + + res = interpret(func2, [ord(x), y]) + for i in range(len(res.entries)): + assert res.entries[i].key != rdict.deleted_entry_marker From tismer at codespeak.net Thu Jun 23 20:03:23 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 20:03:23 +0200 (CEST) Subject: [pypy-svn] r13736 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623180323.5300E27B74@code1.codespeak.net> Author: tismer Date: Thu Jun 23 20:03:22 2005 New Revision: 13736 Modified: pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rlist.py Log: implemented __contains__ and index augmented rtyper to support __contains__ Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu Jun 23 20:03:22 2005 @@ -94,6 +94,10 @@ v_lst, v_value = hop.inputargs(self, self.item_repr) hop.gendirectcall(ll_append, v_lst, v_value) + def rtype_method_index(self, hop): + v_lst, v_value = hop.inputargs(self, self.item_repr) + return hop.gendirectcall(ll_listindex, v_lst, v_value, self.get_eqfunc()) + def rtype_method_insert(self, hop): v_lst, v_index, v_value = hop.inputargs(self, Signed, self.item_repr) arg1 = hop.args_s[1] @@ -136,6 +140,13 @@ return ListIteratorRepr(self) +class __extend__(pairtype(ListRepr, Repr)): + + def rtype_contains((r_lst, _), hop): + v_lst, v_any = hop.inputargs(r_lst, r_lst.item_repr) + return hop.gendirectcall(ll_listcontains, v_lst, v_any, r_lst.get_eqfunc()) + + class __extend__(pairtype(ListRepr, IntegerRepr)): def rtype_getitem((r_lst, r_int), hop): @@ -441,6 +452,33 @@ j += 1 return True +def ll_listcontains(lst, obj, eqfn): + items = lst.items + lng = len(items) + j = 0 + while j < lng: + if eqfn is None: + if items[j] == obj: + return True + else: + if eqfn(items[j], obj): + return True + j += 1 + return False + +def ll_listindex(lst, obj, eqfn): + items = lst.items + lng = len(items) + j = 0 + while j < lng: + if eqfn is None: + if items[j] == obj: + return j + else: + if eqfn(items[j], obj): + return j + j += 1 + raise ValueError # can't say 'list.index(x): x not in list' # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Thu Jun 23 20:03:22 2005 @@ -324,6 +324,12 @@ _registeroperations(locals()) del _registeroperations + # this one is not in BINARY_OPERATIONS + def translate_op_contains(self, hop): + r_arg1 = hop.args_r[0] + r_arg2 = hop.args_r[1] + return pair(r_arg1, r_arg2).rtype_contains(hop) + # __________ irregular operations __________ def translate_op_newlist(self, hop): Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Thu Jun 23 20:03:22 2005 @@ -5,6 +5,7 @@ from pypy.rpython.rslice import ll_newslice from pypy.rpython.rint import signed_repr from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import find_exception def sample_list(): @@ -269,3 +270,40 @@ for case in False, True: res = ev_fn(i, j, case) assert res is fn(i, j, case) + +def test_list_contains(): + def fn(i, neg=False): + foo1 = Foo() + foo2 = Foo() + bar1 = Bar() + bar2 = Bar() + lis = [foo1, foo2, bar1] + args = lis + [bar2] + if neg : return args[i] not in lis + return args[i] in lis + ev_fn = make_interpreter(fn, [0, False]) + for i in range(4): + for case in False, True: + res = ev_fn(i, case) + assert res is fn(i, case) + +def test_list_index(): + def fn(i): + foo1 = Foo() + foo2 = Foo() + bar1 = Bar() + bar2 = Bar() + lis = [foo1, foo2, bar1] + args = lis + [bar2] + return lis.index(args[i]) + ev_fn = make_interpreter(fn, [0]) + for i in range(4): + try: + res = ev_fn(i) + except Exception, e: + res = find_exception(e) + try: + res2 = fn(i) + except Exception, e: + res2 = e.__class__ + assert res == res2 From tismer at codespeak.net Thu Jun 23 20:07:01 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 20:07:01 +0200 (CEST) Subject: [pypy-svn] r13737 - pypy/extradoc/sprintinfo Message-ID: <20050623180701.7650227B83@code1.codespeak.net> Author: tismer Date: Thu Jun 23 20:07:00 2005 New Revision: 13737 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: list stuff is done (ale + chris) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 20:07:00 2005 @@ -35,8 +35,8 @@ are all uses of hex, oct, repr. mostly DONE apart from instances which we're not sure we need anyway - - (easy) list methods reverse, pop, insert, index(?) - task: only left: remove the single index() call in PyPy (typeobject.py) + - DONE (easy) list methods reverse, pop, insert, index(!) + task: do it. also support contains - (easy) tuple concatenation task: do it From pedronis at codespeak.net Thu Jun 23 20:27:41 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 20:27:41 +0200 (CEST) Subject: [pypy-svn] r13738 - pypy/dist/pypy/annotation Message-ID: <20050623182741.44E8027B83@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 20:27:40 2005 New Revision: 13738 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: stats for contains Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 23 20:27:40 2005 @@ -88,6 +88,9 @@ def consider_list_list_eq(self, obj1, obj2): return obj1, obj2 + def consider_contains(self, seq): + return seq + def consider_non_int_eq(self, obj1, obj2): if obj1.knowntype == obj2.knowntype == list: self.count("list_list_eq", obj1, obj2) From pedronis at codespeak.net Thu Jun 23 20:29:04 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 20:29:04 +0200 (CEST) Subject: [pypy-svn] r13739 - in pypy/dist/pypy/translator: . goal Message-ID: <20050623182904.7383327B83@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 20:29:02 2005 New Revision: 13739 Modified: pypy/dist/pypy/translator/annrpython.py pypy/dist/pypy/translator/goal/query.py Log: ... contains stats pretty printing for query for string formatting Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Thu Jun 23 20:29:02 2005 @@ -596,6 +596,7 @@ # XXX "contains" clash with SomeObject method def consider_op_contains(self, seq, elem): + self.bookkeeper.count("contains", seq) return annmodel.SomeBool() def consider_op_newtuple(self, *args): Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 23 20:29:02 2005 @@ -1,5 +1,6 @@ # functions to query information out of the translator and annotator from the debug prompt of translate_pypy import types +import re import pypy.annotation.model as annmodel import pypy.objspace.flow.model as flowmodel @@ -369,6 +370,12 @@ return dict.__setitem__(self, outcome, c) +def keyrepr(k): + if isinstance(k, tuple): + return "(%s)" % ', '.join([keyrepr(x) for x in k]) + else: + return str(k) + def statsfor(t, category): stats = t.annotator.bookkeeper.stats for_category = stats.classify[category] @@ -376,15 +383,28 @@ counters = Counters() for pos, outcome in for_category.iteritems(): counters[outcome] = counters.get(outcome, 0) + 1 - def keyrepr(k): - if isinstance(k, tuple): - return "(%s)" % ', '.join([keyrepr(x) for x in k]) - else: - return str(k) w = max([len(keyrepr(o)) for o in counters.keys()])+1 - for outcome, n in counters.iteritems(): - print "%*s | %d" % (w, keyrepr(outcome), n) + if w < 60: + for outcome, n in counters.iteritems(): + print "%*s | %d" % (w, keyrepr(outcome), n) + else: + for outcome, n in counters.iteritems(): + print "%s | %d" % (keyrepr(outcome), n) + +def statsforstrformat(t): + stats = t.annotator.bookkeeper.stats + stats = stats.classify['strformat'] + result = {} + for fmt, args in stats.itervalues(): + fmts = re.findall("%l?.", fmt) + if not isinstance(args, tuple): + args = (args,) + for f, a in zip(fmts, args): + result[(f,a)] = result.get((f,a), 0) + 1 + for (f,a), c in result.iteritems(): + print "%s %s %d" % (f, keyrepr(a), c) + # debug helper def tryout(f, *args): From hpk at codespeak.net Thu Jun 23 20:43:01 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 20:43:01 +0200 (CEST) Subject: [pypy-svn] r13740 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623184301.B8F3A27B74@code1.codespeak.net> Author: hpk Date: Thu Jun 23 20:43:00 2005 New Revision: 13740 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (arre) added basic strdict resizing Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 20:43:00 2005 @@ -139,8 +139,13 @@ entry = ll_strdict_lookup(d, key) if not entry.key or entry.key == deleted_entry_marker: entry.key = key + entry.value = value d.num_used_entries += 1 - entry.value = value + if d.num_used_entries / 2 > len(d.entries) / 3: + ll_strdict_resize(d, len(d.entries) * 2) + + else: + entry.value = value def ll_strdict_delitem(d, key): entry = ll_strdict_lookup(d, key) @@ -150,6 +155,18 @@ d.num_used_entries -= 1 # XXX: entry.value = ??? +def ll_strdict_resize(d, new_size): + old_entries = d.entries + old_size = len(old_entries) + d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size) + i = 0 + while i < old_size: + entry = old_entries[i] + if entry.key and entry.key != deleted_entry_marker: + new_entry = ll_strdict_lookup(d, entry.key) + new_entry.key = entry.key + new_entry.value = entry.value + i += 1 # the below is a port of CPython's dictobject.c's lookdict implementation PERTURB_SHIFT = 5 Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 20:43:00 2005 @@ -102,3 +102,12 @@ res = interpret(func2, [ord(x), y]) for i in range(len(res.entries)): assert res.entries[i].key != rdict.deleted_entry_marker + +def test_dict_resize(): + def func(): + d = {} + for i in range(8): + d[chr(ord('a') + i)] = i + return d + res = interpret(func, []) + assert len(res.entries) > 8 From ale at codespeak.net Thu Jun 23 21:04:42 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 21:04:42 +0200 (CEST) Subject: [pypy-svn] r13741 - pypy/dist/pypy/rpython Message-ID: <20050623190442.24DC127B74@code1.codespeak.net> Author: ale Date: Thu Jun 23 21:04:41 2005 New Revision: 13741 Modified: pypy/dist/pypy/rpython/rtuple.py Log: Added tuple concatenation Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Thu Jun 23 21:04:41 2005 @@ -56,6 +56,16 @@ cname = hop.inputconst(Void, name) return hop.genop('getfield', [v_tuple, cname], resulttype = llresult) +class __extend__(pairtype(TupleRepr, TupleRepr)): + + def rtype_add((r_tup1, r_tup2), hop): + v_tuple, v_tuple1 = hop.inputargs(r_tup1.items_r, r_tup2.items_r) + items_r = r_tup1.items_r + r_tup2.items_r + res = TupleRepr(items_r) + vlist = v_tuple + v_tuple1 + return newtuple(hop.llops, res, vlist) + + # ____________________________________________________________ # # Irregular operations. From ale at codespeak.net Thu Jun 23 21:06:58 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 21:06:58 +0200 (CEST) Subject: [pypy-svn] r13742 - pypy/extradoc/sprintinfo Message-ID: <20050623190658.F3D2027B80@code1.codespeak.net> Author: ale Date: Thu Jun 23 21:06:58 2005 New Revision: 13742 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Tuple concatenation added (ale + chris) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 21:06:58 2005 @@ -38,7 +38,7 @@ - DONE (easy) list methods reverse, pop, insert, index(!) task: do it. also support contains - - (easy) tuple concatenation + - DONE (easy) tuple concatenation task: do it - (easy) string slices From ale at codespeak.net Thu Jun 23 21:16:11 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 21:16:11 +0200 (CEST) Subject: [pypy-svn] r13743 - pypy/dist/pypy/rpython/test Message-ID: <20050623191611.99BA227B61@code1.codespeak.net> Author: ale Date: Thu Jun 23 21:16:10 2005 New Revision: 13743 Modified: pypy/dist/pypy/rpython/test/test_rtuple.py Log: test for tuple concatenation Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Thu Jun 23 21:16:10 2005 @@ -4,7 +4,7 @@ from pypy.rpython.rtuple import * from pypy.rpython.rint import signed_repr from pypy.rpython.rbool import bool_repr - +from pypy.rpython.test.test_llinterp import interpret, make_interpreter def test_rtuple(): rtuple = TupleRepr([signed_repr, bool_repr]) @@ -49,3 +49,14 @@ def dummyfn(x, y): return (xy) rtype(dummyfn, [int, int]) + +def test_tuple_concatenation(): + def f(): + tup = (1,2) + tup1 = (3,) + res = tup + tup1 + return res[0]*100 + res[1]*10 + res[2] + fn = make_interpreter(f,[])#,view=True) + res = fn() + assert res == 123 + \ No newline at end of file From tismer at codespeak.net Thu Jun 23 21:22:50 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 21:22:50 +0200 (CEST) Subject: [pypy-svn] r13744 - pypy/dist/pypy/rpython/test Message-ID: <20050623192250.89FBB27B61@code1.codespeak.net> Author: tismer Date: Thu Jun 23 21:22:49 2005 New Revision: 13744 Modified: pypy/dist/pypy/rpython/test/test_rtuple.py Log: added a test for mixed tuples (int, str) Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Thu Jun 23 21:22:49 2005 @@ -54,9 +54,18 @@ def f(): tup = (1,2) tup1 = (3,) - res = tup + tup1 + res = tup + tup1 + () return res[0]*100 + res[1]*10 + res[2] fn = make_interpreter(f,[])#,view=True) res = fn() assert res == 123 - \ No newline at end of file + +def test_tuple_concatenation_mix(): + def f(): + tup = (1,2) + tup1 = ('3',) + res = tup + tup1 + return res[0]*100 + res[1]*10 + ord(res[2]) - ord('0') + fn = make_interpreter(f,[])#,view=True) + res = fn() + assert res == 123 From mwh at codespeak.net Thu Jun 23 21:23:56 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 21:23:56 +0200 (CEST) Subject: [pypy-svn] r13745 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050623192356.6015327B61@code1.codespeak.net> Author: mwh Date: Thu Jun 23 21:23:54 2005 New Revision: 13745 Modified: pypy/dist/pypy/interpreter/eval.py pypy/dist/pypy/interpreter/nestedscope.py pypy/dist/pypy/objspace/std/tupleobject.py Log: remove uses of zip (seemed easier than magicing them away in a transform or whatever) Modified: pypy/dist/pypy/interpreter/eval.py ============================================================================== --- pypy/dist/pypy/interpreter/eval.py (original) +++ pypy/dist/pypy/interpreter/eval.py Thu Jun 23 21:23:54 2005 @@ -107,7 +107,10 @@ if self.w_locals is None: self.w_locals = self.space.newdict([]) varnames = self.code.getvarnames() - for name, w_value in zip(varnames, self.getfastscope()): + fastscope_w = self.getfastscope() + for i in range(min(len(varnames), len(fastscope_w))): + name = varnames[i] + w_value = fastscope_w[i] if w_value is not None: w_name = self.space.wrap(name) self.space.setitem(self.w_locals, w_name, w_value) @@ -119,7 +122,7 @@ new_fastlocals_w = [None]*self.numlocals - for name, i in zip(varnames, range(self.numlocals)): + for i in range(min(len(varnames), self.numlocals)): w_name = self.space.wrap(varnames[i]) try: w_value = self.space.getitem(self.w_locals, w_name) Modified: pypy/dist/pypy/interpreter/nestedscope.py ============================================================================== --- pypy/dist/pypy/interpreter/nestedscope.py (original) +++ pypy/dist/pypy/interpreter/nestedscope.py Thu Jun 23 21:23:54 2005 @@ -73,7 +73,9 @@ # cellvars are values exported to inner scopes # freevars are values coming from outer scopes freevarnames = self.code.co_cellvars + self.code.co_freevars - for name, cell in zip(freevarnames, self.cells): + for i in range(len(freevarnames)): + name = freevarnames[i] + cell = self.cells[i] try: w_value = cell.get() except ValueError: @@ -85,7 +87,9 @@ def locals2fast(self): PyInterpFrame.locals2fast(self) freevarnames = self.code.co_cellvars + self.code.co_freevars - for name, cell in zip(freevarnames, self.cells): + for i in range(len(freevarnames)): + name = freevarnames[i] + cell = self.cells[i] w_name = self.space.wrap(name) try: w_value = self.space.getitem(self.w_locals, w_name) Modified: pypy/dist/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/tupleobject.py Thu Jun 23 21:23:54 2005 @@ -86,7 +86,9 @@ items2 = w_tuple2.wrappeditems if len(items1) != len(items2): return space.w_False - for item1, item2 in zip(items1, items2): + for i in range(len(items1)): + item1 = items1[i] + item2 = items2[i] if not space.is_true(space.eq(item1, item2)): return space.w_False return space.w_True From mwh at codespeak.net Thu Jun 23 21:25:26 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 23 Jun 2005 21:25:26 +0200 (CEST) Subject: [pypy-svn] r13746 - in pypy/branch/pypy-translation-snapshot: interpreter objspace/std Message-ID: <20050623192526.2E81527B61@code1.codespeak.net> Author: mwh Date: Thu Jun 23 21:25:24 2005 New Revision: 13746 Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py pypy/branch/pypy-translation-snapshot/objspace/std/tupleobject.py Log: port zip-removal to translation branch Modified: pypy/branch/pypy-translation-snapshot/interpreter/eval.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/eval.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/eval.py Thu Jun 23 21:25:24 2005 @@ -107,7 +107,10 @@ if self.w_locals is None: self.w_locals = self.space.newdict([]) varnames = self.code.getvarnames() - for name, w_value in zip(varnames, self.getfastscope()): + fastscope_w = self.getfastscope() + for i in range(min(len(varnames), len(fastscope_w))): + name = varnames[i] + w_value = fastscope_w[i] if w_value is not None: w_name = self.space.wrap(name) self.space.setitem(self.w_locals, w_name, w_value) @@ -119,7 +122,7 @@ new_fastlocals_w = [None]*self.numlocals - for name, i in zip(varnames, range(self.numlocals)): + for i in range(min(len(varnames), self.numlocals)): w_name = self.space.wrap(varnames[i]) try: w_value = self.space.getitem(self.w_locals, w_name) Modified: pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/nestedscope.py Thu Jun 23 21:25:24 2005 @@ -73,7 +73,9 @@ # cellvars are values exported to inner scopes # freevars are values coming from outer scopes freevarnames = self.code.co_cellvars + self.code.co_freevars - for name, cell in zip(freevarnames, self.cells): + for i in range(len(freevarnames)): + name = freevarnames[i] + cell = self.cells[i] try: w_value = cell.get() except ValueError: @@ -85,7 +87,9 @@ def locals2fast(self): PyInterpFrame.locals2fast(self) freevarnames = self.code.co_cellvars + self.code.co_freevars - for name, cell in zip(freevarnames, self.cells): + for i in range(len(freevarnames)): + name = freevarnames[i] + cell = self.cells[i] w_name = self.space.wrap(name) try: w_value = self.space.getitem(self.w_locals, w_name) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/tupleobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/tupleobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/tupleobject.py Thu Jun 23 21:25:24 2005 @@ -86,7 +86,9 @@ items2 = w_tuple2.wrappeditems if len(items1) != len(items2): return space.w_False - for item1, item2 in zip(items1, items2): + for i in range(len(items1)): + item1 = items1[i] + item2 = items2[i] if not space.is_true(space.eq(item1, item2)): return space.w_False return space.w_True From pedronis at codespeak.net Thu Jun 23 21:28:55 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 21:28:55 +0200 (CEST) Subject: [pypy-svn] r13747 - pypy/extradoc/sprintinfo Message-ID: <20050623192855.0A1D127B61@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 21:28:54 2005 New Revision: 13747 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: update Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 21:28:54 2005 @@ -18,13 +18,15 @@ iterators over them tasks: do it (iterators in a second step) - - (medium) iterators over tuples + - (mostly easy) tuple to list task: the built-in list() should convert from homogenous tuples to lists - (varying) all built-in functions listed in annotation/builtin.py task: write them into rpython/rbuiltin.py possibly remove support for some of them + + Done removing zip from PyPy codebase - (mostly easy) a few more operations: issubtype, ...? task: go through them one by one and decide if they should From pedronis at codespeak.net Thu Jun 23 21:41:40 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 21:41:40 +0200 (CEST) Subject: [pypy-svn] r13748 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623194140.7BB6827B61@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 21:41:39 2005 New Revision: 13748 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rint.py Log: rtyper support for min(int, int) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Thu Jun 23 21:41:39 2005 @@ -4,7 +4,7 @@ from pypy.rpython import rarithmetic from pypy.rpython.rtyper import TyperError from pypy.rpython.rrange import rtype_builtin_range -from pypy.rpython.rmodel import Repr, TyperError +from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr from pypy.rpython.rfloat import float_repr @@ -108,6 +108,19 @@ vlist = hop.inputargs(lltype.Unsigned) return vlist[0] +def rtype_builtin_min(hop): + rint1, rint2 = hop.args_r + assert isinstance(rint1, IntegerRepr) + assert isinstance(rint2, IntegerRepr) + assert rint1.lowleveltype == rint2.lowleveltype + v1, v2 = hop.inputargs(rint1, rint2) + return hop.gendirectcall(ll_min, v1, v2) + +def ll_min(i1, i2): + if i1 < i2: + return i1 + return i2 + # collect all functions import __builtin__ Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Thu Jun 23 21:41:39 2005 @@ -93,3 +93,12 @@ res = ev_fun(-1) assert res is False # -1 ==> 0xffffffff + +def test_int_min(): + def fn(i, j): + return min(i,j) + ev_fun = make_interpreter(fn, [0, 0]) + assert ev_fun(1, 2) == 1 + assert ev_fun(1, -1) == -1 + assert ev_fun(2, 2) == 2 + assert ev_fun(-1, -12) == -12 From pedronis at codespeak.net Thu Jun 23 21:42:31 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 21:42:31 +0200 (CEST) Subject: [pypy-svn] r13749 - in pypy/dist/pypy: annotation translator/goal Message-ID: <20050623194231.6944427B61@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 21:42:28 2005 New Revision: 13749 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/translator/goal/query.py Log: stats on builtin functions Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu Jun 23 21:42:28 2005 @@ -315,7 +315,7 @@ result.dictdef.generalize_key(self.immutablevalue(ek)) result.dictdef.generalize_value(self.immutablevalue(ev)) elif ishashable(x) and x in BUILTIN_ANALYZERS: - result = SomeBuiltin(BUILTIN_ANALYZERS[x]) + result = SomeBuiltin(BUILTIN_ANALYZERS[x], methodname="%s.%s" % (x.__module__, x.__name__)) elif isinstance(x, lltype._ptr): result = SomePtr(lltype.typeOf(x)) elif callable(x) or isinstance(x, staticmethod): # XXX Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Thu Jun 23 21:42:28 2005 @@ -379,6 +379,7 @@ if bltn.s_self is not None: return bltn.analyser(bltn.s_self, *args) else: + getbookkeeper().count(bltn.methodname.replace('.', '_'), *args) return bltn.analyser(*args) def call(bltn, args, implicit_init=False): Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Thu Jun 23 21:42:28 2005 @@ -405,6 +405,11 @@ for (f,a), c in result.iteritems(): print "%s %s %d" % (f, keyrepr(a), c) +def statbuiltins(t): + stats = t.annotator.bookkeeper.stats.classify + for k in stats: + if k.startswith('__builtin__'): + statsfor(t, k) # debug helper def tryout(f, *args): From tismer at codespeak.net Thu Jun 23 21:43:27 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 23 Jun 2005 21:43:27 +0200 (CEST) Subject: [pypy-svn] r13750 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623194327.BA7BC27B74@code1.codespeak.net> Author: tismer Date: Thu Jun 23 21:43:26 2005 New Revision: 13750 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: implemented string slicing Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 23 21:43:26 2005 @@ -8,6 +8,8 @@ from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.rtuple import TupleRepr from pypy.rpython import rint +from pypy.rpython.rslice import SliceRepr +from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr # ____________________________________________________________ # @@ -119,6 +121,18 @@ return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) +class __extend__(pairtype(StringRepr, SliceRepr)): + + def rtype_getitem((r_str, r_slic), hop): + if r_slic == startonly_slice_repr: + v_str, v_start = hop.inputargs(r_str, startonly_slice_repr) + return hop.gendirectcall(ll_stringslice_startonly, v_str, v_start) + if r_slic == startstop_slice_repr: + v_str, v_slice = hop.inputargs(r_str, startstop_slice_repr) + return hop.gendirectcall(ll_stringslice, v_str, v_slice) + raise TyperError(r_slic) + + class __extend__(pairtype(StringRepr, StringRepr)): def rtype_add(_, hop): v_str1, v_str2 = hop.inputargs(string_repr, string_repr) @@ -482,6 +496,27 @@ i += 1 return result +def ll_stringslice_startonly(s1, start): + len1 = len(s1.chars) + newstr = malloc(STR, len1 - start) + j = 0 + while start < len1: + newstr.chars[j] = s1.chars[start] + start += 1 + j += 1 + return newstr + +def ll_stringslice(s1, slice): + start = slice.start + stop = slice.stop + newstr = malloc(STR, stop - start) + j = 0 + while start < stop: + newstr.chars[j] = s1.chars[start] + start += 1 + j += 1 + return newstr + # ____________________________________________________________ # # Iteration. Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Thu Jun 23 21:43:26 2005 @@ -236,3 +236,12 @@ res = interpret(percentS, ['D']) assert ''.join(res.chars) == 'before D after' + +def test_str_slice(): + def fn(): + s = 'hello' + s1 = s[:3] + s2 = s[3:] + return s1+s2 == s and s2+s1 == 'lohel' + res = interpret(fn, ()) + assert res From ale at codespeak.net Thu Jun 23 21:44:50 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 23 Jun 2005 21:44:50 +0200 (CEST) Subject: [pypy-svn] r13751 - pypy/extradoc/sprintinfo Message-ID: <20050623194450.E752A27B7D@code1.codespeak.net> Author: ale Date: Thu Jun 23 21:44:50 2005 New Revision: 13751 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: String slices completed (ale + chris) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 21:44:50 2005 @@ -43,7 +43,7 @@ - DONE (easy) tuple concatenation task: do it - - (easy) string slices + - DONE (easy) string slices task: do it (see rlist) - DONE (easy) equality and non-equality are generally missing From pedronis at codespeak.net Thu Jun 23 21:46:05 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 23 Jun 2005 21:46:05 +0200 (CEST) Subject: [pypy-svn] r13752 - pypy/extradoc/sprintinfo Message-ID: <20050623194605.27F1527B7D@code1.codespeak.net> Author: pedronis Date: Thu Jun 23 21:46:04 2005 New Revision: 13752 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: update: - min (as far as used in Pypy) done - listing of the builtins that need to be done Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Thu Jun 23 21:46:04 2005 @@ -27,6 +27,14 @@ possibly remove support for some of them Done removing zip from PyPy codebase + DONE min + + to be done: + - list(list) + - list(tuple) + - isinstance + - float(int), int(float), float(str) (likely delegate to backend) + - (mostly easy) a few more operations: issubtype, ...? task: go through them one by one and decide if they should From arigo at codespeak.net Thu Jun 23 22:00:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 23 Jun 2005 22:00:05 +0200 (CEST) Subject: [pypy-svn] r13753 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623200005.3E95F27B74@code1.codespeak.net> Author: arigo Date: Thu Jun 23 22:00:03 2005 New Revision: 13753 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (arigo, arre, hpk) - CPython-style resizing of rdictionaries. - added support for r_uint and intmask in llinterp - fixed the hash for rstrings. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 23 22:00:03 2005 @@ -265,6 +265,10 @@ from pypy.objspace.flow.operation import FunctionByName opimpls = FunctionByName.copy() opimpls['is_true'] = bool +ops_returning_a_bool = {'gt': True, 'ge': True, + 'lt': True, 'le': True, + 'eq': True, 'ne': True, + 'is_true': True} for typ in (float, int, r_uint): typname = typ.__name__ @@ -277,21 +281,29 @@ optup += 'truediv', 'floordiv', 'and_', 'or_', 'lshift', 'rshift', 'xor' for opname in optup: assert opname in opimpls + if typ is int and opname not in ops_returning_a_bool: + adjust_result = 'intmask' + else: + adjust_result = '' pureopname = opname.rstrip('_') exec py.code.Source(""" def %(opnameprefix)s_%(pureopname)s(x, y): assert isinstance(x, %(typname)s) assert isinstance(y, %(typname)s) func = opimpls[%(opname)r] - return func(x, y) + return %(adjust_result)s(func(x, y)) """ % locals()).compile() for opname in 'is_true', 'neg': assert opname in opimpls + if typ is int and opname not in ops_returning_a_bool: + adjust_result = 'intmask' + else: + adjust_result = '' exec py.code.Source(""" def %(opnameprefix)s_%(opname)s(x): assert isinstance(x, %(typname)s) func = opimpls[%(opname)r] - return func(x) + return %(adjust_result)s(func(x)) """ % locals()).compile() for opname in ('gt', 'lt', 'ge', 'ne', 'le', 'eq'): Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 22:00:03 2005 @@ -17,7 +17,8 @@ # } # # struct dicttable { -# int num_used_entries; +# int num_items; +# int num_pristine_entries; # never used entries # Array *entries; # } # @@ -59,7 +60,8 @@ ('value', self.DICTVALUE)) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) self.STRDICT.become(lltype.GcStruct("dicttable", - ("num_used_entries", lltype.Signed), + ("num_items", lltype.Signed), + ("num_pristine_entries", lltype.Signed), ("entries", lltype.Ptr(self.DICTENTRYARRAY)))) #def convert_const(self, dictobj): @@ -126,7 +128,7 @@ deleted_entry_marker = lltype.malloc(STR, 0, immortal=True) def ll_strdict_len(d): - return d.num_used_entries + return d.num_items def ll_strdict_getitem(d, key): entry = ll_strdict_lookup(d, key) @@ -137,13 +139,17 @@ def ll_strdict_setitem(d, key, value): entry = ll_strdict_lookup(d, key) - if not entry.key or entry.key == deleted_entry_marker: + if not entry.key: + entry.key = key + entry.value = value + d.num_items += 1 + d.num_pristine_entries -= 1 + if d.num_pristine_entries <= len(d.entries) / 3: + ll_strdict_resize(d) + elif entry.key == deleted_entry_marker: entry.key = key entry.value = value - d.num_used_entries += 1 - if d.num_used_entries / 2 > len(d.entries) / 3: - ll_strdict_resize(d, len(d.entries) * 2) - + d.num_items += 1 else: entry.value = value @@ -152,13 +158,19 @@ if not entry.key or entry.key == deleted_entry_marker: raise KeyError entry.key = deleted_entry_marker - d.num_used_entries -= 1 + d.num_items -= 1 # XXX: entry.value = ??? -def ll_strdict_resize(d, new_size): +def ll_strdict_resize(d): old_entries = d.entries old_size = len(old_entries) + # make a 'new_size' estimate and shrink it if there are many + # deleted entry markers + new_size = old_size * 2 + while new_size >= 8 and d.num_items < new_size / 4: + new_size /= 2 d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size) + d.num_pristine_entries = new_size - d.num_items i = 0 while i < old_size: entry = old_entries[i] @@ -207,11 +219,13 @@ # ____________________________________________________________ # # Irregular operations. +STRDICT_INITSIZE = 8 def ll_newstrdict(DICTPTR): d = lltype.malloc(DICTPTR.TO) - d.entries = lltype.malloc(DICTPTR.TO.entries.TO, 8) # everything is zeroed - d.num_used_entries = 0 # but still be explicit + d.entries = lltype.malloc(DICTPTR.TO.entries.TO, STRDICT_INITSIZE) + d.num_items = 0 # but still be explicit + d.num_pristine_entries = STRDICT_INITSIZE return d def rtype_newdict(hop): @@ -222,52 +236,3 @@ v_result = hop.gendirectcall(ll_newstrdict, c1) return v_result -# ____________________________________________________________ -# -# Iteration. - -if 0: - class ListIteratorRepr(Repr): - - def __init__(self, r_list): - self.r_list = r_list - self.lowleveltype = lltype.Ptr(GcStruct('listiter', - ('list', r_list.lowleveltype), - ('index', Signed))) - - def newiter(self, hop): - v_lst, = hop.inputargs(self.r_list) - citerptr = hop.inputconst(Void, self.lowleveltype) - return hop.gendirectcall(ll_listiter, citerptr, v_lst) - - def rtype_next(self, hop): - v_iter, = hop.inputargs(self) - return hop.gendirectcall(ll_listnext, v_iter) - - def ll_listiter(ITERPTR, lst): - iter = malloc(ITERPTR.TO) - iter.list = lst - iter.index = 0 - return iter - - def ll_listnext(iter): - l = iter.list - index = iter.index - if index >= len(l.items): - raise StopIteration - iter.index = index + 1 - return l.items[index] - - - keyhash = rstr.ll_strhash(key) - n = len(d.entries) - index = keyhash & (n - 1) - while 1: - entry = d.entries[index] - if not entry.key or en: - break - if entry.key != deleted_entry_marker and rstr.ll_streq(entry.key, key): - break - index = (index + 1) & (n-1) - #return entry - Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Thu Jun 23 22:00:03 2005 @@ -365,7 +365,7 @@ x = -1 else: x = ord(s.chars[0]) << 7 - i = 1 + i = 0 while i < length: x = (1000003*x) ^ ord(s.chars[i]) i += 1 Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 22:00:03 2005 @@ -77,16 +77,16 @@ del d[c1] return d[c2] + char_by_hash = {} base = 8 - x = 'a' - xh = lowlevelhash(x) % base - for y in range(ord('b'), ord('z')): - if lowlevelhash(chr(y)) % base == xh: - break - else: - py.test.skip("XXX improve hash finding algo") + for y in range(0, 256): + y = chr(y) + y_hash = lowlevelhash(y) % base + char_by_hash.setdefault(y_hash, []).append(y) + + x, y = char_by_hash[0][:2] # find a collision - res = interpret(func, [ord(x), y]) + res = interpret(func, [ord(x), ord(y)]) assert res == 2 def func2(c1, c2): @@ -99,10 +99,29 @@ d[c1] = 3 return d - res = interpret(func2, [ord(x), y]) + res = interpret(func2, [ord(x), ord(y)]) for i in range(len(res.entries)): assert res.entries[i].key != rdict.deleted_entry_marker + def func3(c0, c1, c2, c3, c4, c5, c6, c7): + d = {} + c0 = chr(c0) ; d[c0] = 1; del d[c0] + c1 = chr(c1) ; d[c1] = 1; del d[c1] + c2 = chr(c2) ; d[c2] = 1; del d[c2] + c3 = chr(c3) ; d[c3] = 1; del d[c3] + c4 = chr(c4) ; d[c4] = 1; del d[c4] + c5 = chr(c5) ; d[c5] = 1; del d[c5] + c6 = chr(c6) ; d[c6] = 1; del d[c6] + c7 = chr(c7) ; d[c7] = 1; del d[c7] + return d + + res = interpret(func3, [ord(char_by_hash[i][0]) for i in range(8)]) + count_frees = 0 + for i in range(len(res.entries)): + if not res.entries[i].key: + count_frees += 1 + assert count_frees >= 3 + def test_dict_resize(): def func(): d = {} From hpk at codespeak.net Thu Jun 23 22:08:56 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Thu, 23 Jun 2005 22:08:56 +0200 (CEST) Subject: [pypy-svn] r13754 - in pypy/dist/pypy/rpython: . test Message-ID: <20050623200856.0181727B74@code1.codespeak.net> Author: hpk Date: Thu Jun 23 22:08:55 2005 New Revision: 13754 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: use STRDICT_INITSIZE instead of the 8 literal Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Thu Jun 23 22:08:55 2005 @@ -158,8 +158,11 @@ if not entry.key or entry.key == deleted_entry_marker: raise KeyError entry.key = deleted_entry_marker - d.num_items -= 1 # XXX: entry.value = ??? + d.num_items -= 1 + num_entries = len(d.entries) + if num_entries > STRDICT_INITSIZE and d.num_items < num_entries / 4: + ll_strdict_resize(d) def ll_strdict_resize(d): old_entries = d.entries @@ -167,7 +170,7 @@ # make a 'new_size' estimate and shrink it if there are many # deleted entry markers new_size = old_size * 2 - while new_size >= 8 and d.num_items < new_size / 4: + while new_size > STRDICT_INITSIZE and d.num_items < new_size / 4: new_size /= 2 d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size) d.num_pristine_entries = new_size - d.num_items Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Thu Jun 23 22:08:55 2005 @@ -78,7 +78,7 @@ return d[c2] char_by_hash = {} - base = 8 + base = rdict.STRDICT_INITSIZE for y in range(0, 256): y = chr(y) y_hash = lowlevelhash(y) % base @@ -115,7 +115,10 @@ c7 = chr(c7) ; d[c7] = 1; del d[c7] return d - res = interpret(func3, [ord(char_by_hash[i][0]) for i in range(8)]) + if rdict.STRDICT_INITSIZE != 8: + py.test.skip("make dict tests more indepdent from initsize") + res = interpret(func3, [ord(char_by_hash[i][0]) + for i in range(rdict.STRDICT_INITSIZE)]) count_frees = 0 for i in range(len(res.entries)): if not res.entries[i].key: @@ -125,8 +128,8 @@ def test_dict_resize(): def func(): d = {} - for i in range(8): + for i in range(rdict.STRDICT_INITSIZE): d[chr(ord('a') + i)] = i return d res = interpret(func, []) - assert len(res.entries) > 8 + assert len(res.entries) > rdict.STRDICT_INITSIZE From ac at codespeak.net Fri Jun 24 11:03:12 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 24 Jun 2005 11:03:12 +0200 (CEST) Subject: [pypy-svn] r13758 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624090312.673EF27B6A@code1.codespeak.net> Author: ac Date: Fri Jun 24 11:03:11 2005 New Revision: 13758 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: Add a test for shrinking of rdicts. Clear the value field when we delete the key. Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Fri Jun 24 11:03:11 2005 @@ -158,7 +158,9 @@ if not entry.key or entry.key == deleted_entry_marker: raise KeyError entry.key = deleted_entry_marker - # XXX: entry.value = ??? + valuetype = lltype.typeOf(entry).TO.value + if isinstance(valuetype, lltype.Ptr): + entry.value = lltype.nullptr(valuetype.TO) d.num_items -= 1 num_entries = len(d.entries) if num_entries > STRDICT_INITSIZE and d.num_items < num_entries / 4: Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Fri Jun 24 11:03:11 2005 @@ -126,10 +126,15 @@ assert count_frees >= 3 def test_dict_resize(): - def func(): + def func(want_empty): d = {} for i in range(rdict.STRDICT_INITSIZE): d[chr(ord('a') + i)] = i + if want_empty: + for i in range(rdict.STRDICT_INITSIZE): + del d[chr(ord('a') + i)] return d - res = interpret(func, []) + res = interpret(func, [0]) assert len(res.entries) > rdict.STRDICT_INITSIZE + res = interpret(func, [1]) + assert len(res.entries) == rdict.STRDICT_INITSIZE From hpk at codespeak.net Fri Jun 24 11:20:20 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 11:20:20 +0200 (CEST) Subject: [pypy-svn] r13759 - pypy/dist/pypy/rpython Message-ID: <20050624092020.B2EDF27B6A@code1.codespeak.net> Author: hpk Date: Fri Jun 24 11:20:19 2005 New Revision: 13759 Modified: pypy/dist/pypy/rpython/lltype.py Log: finally. change representation for Ptr's so that one can actually see some interesting information in the flow viewer. Ptrs are now representing by a c-ish '*' and we forget about specifiying 'Gc' because that is obvious by what it points to (GcStruct, GcArray). Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Fri Jun 24 11:20:19 2005 @@ -311,17 +311,8 @@ def _needsgc(self): return self.TO._gcstatus() - def _str_flags(self): - if self._needsgc(): - return 'gc' - else: - return '' - - def _str_flavor(self): - return 'ptr(%s)' % self._str_flags() - def __str__(self): - return '%s to %s' % (self._str_flavor(), self.TO) + return '* %s' % (self.TO, ) def _defl(self, parent=None, parentindex=None): return _ptr(self, None) @@ -558,7 +549,7 @@ return '<%s>' % (self,) def __str__(self): - return '%s to %s' % (self._TYPE._str_flavor(), self._obj) + return '* %s' % (self._obj, ) def __call__(self, *args): if isinstance(self._T, FuncType): From hpk at codespeak.net Fri Jun 24 11:23:41 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 11:23:41 +0200 (CEST) Subject: [pypy-svn] r13760 - pypy/extradoc/sprintinfo Message-ID: <20050624092341.9C2A227B70@code1.codespeak.net> Author: hpk Date: Fri Jun 24 11:23:39 2005 New Revision: 13760 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: update dict rpython implementation status Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 11:23:39 2005 @@ -16,7 +16,9 @@ - (medium) dicts with non-wrapped string keys to any object, and iterators over them - tasks: do it (iterators in a second step) + - basic getitem/setitem/delitem is done (ported Algos from CPython + actually!) + - remaining: dict iterators - (mostly easy) tuple to list task: the built-in list() should convert from homogenous tuples From arigo at codespeak.net Fri Jun 24 11:30:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 11:30:27 +0200 (CEST) Subject: [pypy-svn] r13761 - pypy/extradoc/sprintinfo Message-ID: <20050624093027.7D69927B80@code1.codespeak.net> Author: arigo Date: Fri Jun 24 11:30:27 2005 New Revision: 13761 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Done isinstance(). Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 11:30:27 2005 @@ -34,7 +34,7 @@ to be done: - list(list) - list(tuple) - - isinstance + - DONE isinstance - float(int), int(float), float(str) (likely delegate to backend) From mwh at codespeak.net Fri Jun 24 11:31:03 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 11:31:03 +0200 (CEST) Subject: [pypy-svn] r13762 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624093103.B66A327B83@code1.codespeak.net> Author: mwh Date: Fri Jun 24 11:31:02 2005 New Revision: 13762 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rclass.py Log: implement isinstance (easier than I expected!) (mwh, arigo) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Fri Jun 24 11:31:02 2005 @@ -8,6 +8,7 @@ from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr from pypy.rpython.rfloat import float_repr +from pypy.rpython import rclass class __extend__(annmodel.SomeBuiltin): @@ -98,6 +99,16 @@ assert hop.nb_args == 1 return hop.args_r[0].rtype_chr(hop) +def rtype_builtin_isinstance(hop): + instance_repr = rclass.getinstancerepr(hop.rtyper, None) + class_repr = rclass.get_type_repr(hop.rtyper) + + v_obj, v_cls = hop.inputargs(instance_repr, class_repr) + + v_objcls = hop.gendirectcall(rclass.ll_type, v_obj) + return hop.gendirectcall(rclass.ll_issubclass, v_objcls, v_cls) + + #def rtype_builtin_range(hop): see rrange.py def rtype_intmask(hop): Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Fri Jun 24 11:31:02 2005 @@ -75,6 +75,9 @@ def g(self): return 1 +class C(B): + pass + def test_simple_method_call(): def f(i): if i: @@ -86,3 +89,23 @@ assert res == 42 res = interpret(f, [False]) assert res == 1 + +def test_isinstance(): + def a(): + b = B() + return isinstance(b, A) + def b(): + b = B() + return isinstance(b, B) + def c(): + b = B() + return isinstance(b, C) + + res = interpret(a, []) + assert res is True + + res = interpret(b, []) + assert res is True + + res = interpret(c, []) + assert res is False From mwh at codespeak.net Fri Jun 24 11:33:52 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 11:33:52 +0200 (CEST) Subject: [pypy-svn] r13763 - pypy/extradoc/sprintinfo Message-ID: <20050624093352.574FA27B8B@code1.codespeak.net> Author: mwh Date: Fri Jun 24 11:33:51 2005 New Revision: 13763 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: move note. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 11:33:51 2005 @@ -30,11 +30,11 @@ Done removing zip from PyPy codebase DONE min + DONE isinstance to be done: - list(list) - list(tuple) - - DONE isinstance - float(int), int(float), float(str) (likely delegate to backend) From hpk at codespeak.net Fri Jun 24 11:47:05 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 11:47:05 +0200 (CEST) Subject: [pypy-svn] r13764 - pypy/extradoc/sprintinfo Message-ID: <20050624094705.4F9D027B8D@code1.codespeak.net> Author: hpk Date: Fri Jun 24 11:47:04 2005 New Revision: 13764 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: updated my information Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 24 11:47:04 2005 @@ -10,7 +10,7 @@ =================== ============== ===================== Armin Rigo 23rd- private Samuele Pedroni 23rd- private -Holger Krekel 23rd- ? +Holger Krekel 23rd- private Beatrice D?ring visiting private Anders Lehmann 22nd-26th SGS Michael Hudson 23rd- private @@ -29,7 +29,7 @@ Samuele Pedroni 1st-7th July private Carl Friedrich Bolz 1st-6th July private Eric van Riet Paap 1st-7th July SGS -Holger Krekel 1st-7th July ? +Holger Krekel 1st-7th July private Richard Emslie 1st-7th July ? Bert Freudenberg 1st-7th July ? Beatrice D?ring visiting private @@ -50,7 +50,7 @@ =================== ============== ===================== Armin Rigo 8th July private Samuele Pedroni 8th July private -Holger Krekel 8th July ? +Holger Krekel 8th July private Bea During 8th July private Jacob Hallen 8th July private Laura Creighton 8th July private @@ -58,4 +58,4 @@ Stephan Busemann 7+8th July Hotel Lilton Anders Chrigstr?m 8th July private Christian Tismer 8th July ? -=================== ============== ===================== \ No newline at end of file +=================== ============== ===================== From ac at codespeak.net Fri Jun 24 11:59:26 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 24 Jun 2005 11:59:26 +0200 (CEST) Subject: [pypy-svn] r13766 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624095926.05C9627B80@code1.codespeak.net> Author: ac Date: Fri Jun 24 11:59:25 2005 New Revision: 13766 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: Add iteration over rdicts. Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Fri Jun 24 11:59:25 2005 @@ -86,6 +86,9 @@ v_dict, = hop.inputargs(self) return hop.gendirectcall(ll_strdict_len, v_dict) + def make_iterator_repr(self): + return StrDictIteratorRepr(self) + class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): def rtype_getitem((r_dict, r_string), hop): @@ -241,3 +244,42 @@ v_result = hop.gendirectcall(ll_newstrdict, c1) return v_result +# ____________________________________________________________ +# +# Iteration. + +class StrDictIteratorRepr(rmodel.Repr): + + def __init__(self, r_dict): + self.r_dict = r_dict + self.lowleveltype = lltype.Ptr(lltype.GcStruct('strdictiter', + ('dict', r_dict.lowleveltype), + ('index', lltype.Signed))) + + def newiter(self, hop): + v_dict, = hop.inputargs(self.r_dict) + citerptr = hop.inputconst(lltype.Void, self.lowleveltype) + return hop.gendirectcall(ll_strdictiter, citerptr, v_dict) + + def rtype_next(self, hop): + v_iter, = hop.inputargs(self) + return hop.gendirectcall(ll_strdictnext, v_iter) + +def ll_strdictiter(ITERPTR, d): + iter = lltype.malloc(ITERPTR.TO) + iter.dict = d + iter.index = 0 + return iter + +def ll_strdictnext(iter): + entries = iter.dict.entries + index = iter.index + entries_len = len(entries) + while index < entries_len: + key = entries[index].key + index = index + 1 + if key and key != deleted_entry_marker: + iter.index = index + return key + iter.index = index + raise StopIteration Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Fri Jun 24 11:59:25 2005 @@ -138,3 +138,16 @@ assert len(res.entries) > rdict.STRDICT_INITSIZE res = interpret(func, [1]) assert len(res.entries) == rdict.STRDICT_INITSIZE + +def test_dict_iteration(): + def func(i, j): + d = {} + d['hello'] = i + d['world'] = j + k = 1 + for key in d: + k = k * d[key] + return k + res = interpret(func, [6, 7]) + assert res == 42 + From ale at codespeak.net Fri Jun 24 11:59:53 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 24 Jun 2005 11:59:53 +0200 (CEST) Subject: [pypy-svn] r13767 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624095953.E276427B83@code1.codespeak.net> Author: ale Date: Fri Jun 24 11:59:52 2005 New Revision: 13767 Added: pypy/dist/pypy/rpython/test/test_rbuiltin.py Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rtuple.py Log: Implement list builtin (ale, pedronis) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Fri Jun 24 11:59:52 2005 @@ -99,6 +99,9 @@ assert hop.nb_args == 1 return hop.args_r[0].rtype_chr(hop) +def rtype_builtin_list(hop): + return hop.args_r[0].rtype_bltn_list(hop) + def rtype_builtin_isinstance(hop): instance_repr = rclass.getinstancerepr(hop.rtyper, None) class_repr = rclass.get_type_repr(hop.rtyper) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Fri Jun 24 11:59:52 2005 @@ -86,6 +86,10 @@ raise TyperError, 'comparison not implemented for %r' % self return inputconst(Void, func) + def rtype_bltn_list(self,hop): + v_lst = hop.inputarg(self,0) + return hop.gendirectcall(ll_copy,v_lst) + def rtype_len(self, hop): v_lst, = hop.inputargs(self) return hop.gendirectcall(ll_len, v_lst) @@ -228,6 +232,17 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. +def ll_copy(l): + items = l.items + length = len(items) + new_lst = ll_newlist(typeOf(l), length) + i = 0 + new_items = new_lst.items + while i < length: + new_items[i] = items[i] + i += 1 + return new_lst + def ll_len(l): return len(l.items) Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Fri Jun 24 11:59:52 2005 @@ -19,6 +19,7 @@ class __extend__(annmodel.SomeTuple): def rtyper_makerepr(self, rtyper): return TupleRepr([rtyper.getrepr(s_item) for s_item in self.items]) + def rtyper_makekey(self): keys = [s_item.rtyper_makekey() for s_item in self.items] return tuple(keys) @@ -43,7 +44,23 @@ def rtype_len(self, hop): return hop.inputconst(Signed, len(self.items_r)) - + def rtype_bltn_list(self, hop): + from pypy.rpython import rlist + nitems = len(self.items_r) + vtup = hop.inputarg(self, 0) + c1 = inputconst(Void, hop.r_result.lowleveltype) + c2 = inputconst(Signed, nitems) + vlist = hop.gendirectcall(rlist.ll_newlist, c1, c2) + for index in range(nitems): + name = self.fieldnames[index] + ritem = self.items_r[index] + cname = hop.inputconst(Void, name) + vitem = hop.genop('getfield', [vtup, cname], resulttype = ritem) + vitem = hop.llops.convertvar(vitem, ritem, hop.r_result.item_repr) + cindex = inputconst(Signed, index) + hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem) + return vlist + class __extend__(pairtype(TupleRepr, IntegerRepr)): def rtype_getitem((r_tup, r_int), hop): @@ -113,3 +130,8 @@ llops.gencapicall('PyTuple_SetItem_WithIncref', [v_result, ci, v_converted]) return v_result + +def ll_newlist(LISTPTR, length): + l = malloc(LISTPTR.TO) + l.items = malloc(LISTPTR.TO.items.TO, length) + return l Added: pypy/dist/pypy/rpython/test/test_rbuiltin.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rbuiltin.py Fri Jun 24 11:59:52 2005 @@ -0,0 +1,21 @@ +from pypy.rpython.test.test_llinterp import interpret + +def test_rbuiltin_list(): + def f(): + l=list((1,2,3)) + return l == [1,2,3] + def g(): + l=list(('he','llo')) + return l == ['he','llo'] + def r(): + l = ['he','llo'] + l1=list(l) + return l == l1 and l is not l1 + result = interpret(f,[]) + assert result + + result = interpret(g,[]) + assert result + + result = interpret(r,[]) + assert result \ No newline at end of file From ac at codespeak.net Fri Jun 24 12:01:21 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 24 Jun 2005 12:01:21 +0200 (CEST) Subject: [pypy-svn] r13768 - pypy/extradoc/sprintinfo Message-ID: <20050624100121.7D47027B83@code1.codespeak.net> Author: ac Date: Fri Jun 24 12:01:21 2005 New Revision: 13768 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: String keyed rdicts are done. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 12:01:21 2005 @@ -14,7 +14,7 @@ tasks: 1. call to memoized functions, at first with a single PBC arg 2. find out if we really have visible dicts with PBC keys - - (medium) dicts with non-wrapped string keys to any object, and + - DONE (medium) dicts with non-wrapped string keys to any object, and iterators over them - basic getitem/setitem/delitem is done (ported Algos from CPython actually!) From ale at codespeak.net Fri Jun 24 12:02:02 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 24 Jun 2005 12:02:02 +0200 (CEST) Subject: [pypy-svn] r13769 - pypy/extradoc/sprintinfo Message-ID: <20050624100202.35ABF27B92@code1.codespeak.net> Author: ale Date: Fri Jun 24 12:02:01 2005 New Revision: 13769 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Implement list builtin (ale, pedronis) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 12:02:01 2005 @@ -20,7 +20,7 @@ actually!) - remaining: dict iterators - - (mostly easy) tuple to list + - Done (mostly easy) tuple to list task: the built-in list() should convert from homogenous tuples to lists @@ -33,8 +33,8 @@ DONE isinstance to be done: - - list(list) - - list(tuple) + - list(list) Done + - list(tuple) Done - float(int), int(float), float(str) (likely delegate to backend) From hpk at codespeak.net Fri Jun 24 12:16:32 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 12:16:32 +0200 (CEST) Subject: [pypy-svn] r13770 - pypy/extradoc/sprintinfo Message-ID: <20050624101632.BDCD127B8A@code1.codespeak.net> Author: hpk Date: Fri Jun 24 12:16:31 2005 New Revision: 13770 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: mark DONE items more clearly Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 12:16:31 2005 @@ -20,7 +20,7 @@ actually!) - remaining: dict iterators - - Done (mostly easy) tuple to list + - DONE (mostly easy) tuple to list task: the built-in list() should convert from homogenous tuples to lists @@ -28,13 +28,13 @@ task: write them into rpython/rbuiltin.py possibly remove support for some of them - Done removing zip from PyPy codebase + DONE removing zip from PyPy codebase DONE min DONE isinstance to be done: - - list(list) Done - - list(tuple) Done + - DONE list(list + - DONE list(tuple) - float(int), int(float), float(str) (likely delegate to backend) From mwh at codespeak.net Fri Jun 24 12:53:53 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 12:53:53 +0200 (CEST) Subject: [pypy-svn] r13771 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050624105353.CA4D127B70@code1.codespeak.net> Author: mwh Date: Fri Jun 24 12:53:51 2005 New Revision: 13771 Modified: pypy/dist/pypy/objspace/std/inttype.py pypy/dist/pypy/objspace/std/strutil.py pypy/dist/pypy/objspace/std/test/test_strutil.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: some grotty float parsing code, not much tested yet (armin has written tests), nor hooked up yet. also removed an unused space argument to string_to_int and some unused imports in unicodeobject.py Modified: pypy/dist/pypy/objspace/std/inttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/inttype.py (original) +++ pypy/dist/pypy/objspace/std/inttype.py Fri Jun 24 12:53:51 2005 @@ -22,7 +22,7 @@ value = w_value.intval elif space.is_true(space.isinstance(w_value, space.w_str)): try: - value = string_to_int(space, space.str_w(w_value)) + value = string_to_int(space.str_w(w_value)) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) @@ -32,7 +32,7 @@ from unicodeobject import unicode_to_decimal_w string = unicode_to_decimal_w(space, w_value) try: - value = string_to_int(space, string) + value = string_to_int(string) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) @@ -68,7 +68,7 @@ space.wrap("int() can't convert non-string " "with explicit base")) try: - value = string_to_int(space, s, base) + value = string_to_int(s, base) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Fri Jun 24 12:53:51 2005 @@ -86,7 +86,7 @@ else: return -1 -def string_to_int(space, s, base=10): +def string_to_int(s, base=10): """Utility to converts a string to an integer (or possibly a long). If base is 0, the proper base is guessed based on the leading characters of 's'. Raises ParseStringError in case of error. @@ -134,3 +134,88 @@ return w_result w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit))) +def break_up_float(s): + i = 0 + + sign = '' + before_point = '' + after_point = '' + exponent = '' + + if s[i] in '+-': + sign = s[i] + i += 1 + + while i < len(s) and s[i] in '0123456789': + before_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] == '.': + i += 1 + while i < len(s) and s[i] in '0123456789': + after_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] not in 'eE': + raise ParseStringError("invalid string literal for float()") + + i += 1 + if i == len(s): + raise ParseStringError("invalid string literal for float()") + + if s[i] in '-+': + exponent += s[i] + i += 1 + + if i == len(s): + raise ParseStringError("invalid string literal for float()") + + while i < len(s) and s[i] in '0123456789': + exponent += s[i] + i += 1 + + if i != len(s): + raise ParseStringError("invalid string literal for float()") + + return sign, before_point, after_point, exponent + + +def string_to_float(s): + s = strip_space(s) + + if not s: + raise ParseStringError("empty string for float()") + + sign, before_point, after_point, exponent = break_up_float(s) + + if not before_point and not after_point: + raise ParseStringError("invalid string literal for float()") + + r = 0.0 + i = len(before_point) - 1 + j = 0 + while i >= 0: + d = float(ord(before_point[i]) - ord('0')) + r += d * (10.0 ** j) + i -= 1 + j += 1 + + i = 0 + while i < len(after_point): + d = float(ord(after_point[i]) - ord('0')) + r += d * (10.0 ** (-i-1)) + + if exponent: + e = string_to_int(None, exponent) + r *= 10.0 ** e + + return r + + + Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Fri Jun 24 12:53:51 2005 @@ -1,6 +1,8 @@ import autopath from pypy.objspace.std.strutil import * +import py + objspacename = 'std' class TestStrUtil: @@ -24,7 +26,7 @@ (' -123456789 ', -123456789), ] for s, expected in cases: - assert string_to_int(space, s) == expected + assert string_to_int(s) == expected assert string_to_w_long(space, s).longval() == expected def test_string_to_int_base(self): @@ -54,12 +56,12 @@ ('0X', 16, 0), # " " ] for s, base, expected in cases: - assert string_to_int(space, s, base) == expected - assert string_to_int(space, '+'+s, base) == expected - assert string_to_int(space, '-'+s, base) == -expected - assert string_to_int(space, s+'\n', base) == expected - assert string_to_int(space, ' +'+s, base) == expected - assert string_to_int(space, '-'+s+' ', base) == -expected + assert string_to_int(s, base) == expected + assert string_to_int('+'+s, base) == expected + assert string_to_int('-'+s, base) == -expected + assert string_to_int(s+'\n', base) == expected + assert string_to_int(' +'+s, base) == expected + assert string_to_int('-'+s+' ', base) == -expected def test_string_to_int_error(self): space = self.space @@ -78,16 +80,16 @@ '@', ] for s in cases: - raises(ParseStringError, string_to_int, space, s) - raises(ParseStringError, string_to_int, space, ' '+s) - raises(ParseStringError, string_to_int, space, s+' ') - raises(ParseStringError, string_to_int, space, '+'+s) - raises(ParseStringError, string_to_int, space, '-'+s) + raises(ParseStringError, string_to_int, s) + raises(ParseStringError, string_to_int, ' '+s) + raises(ParseStringError, string_to_int, s+' ') + raises(ParseStringError, string_to_int, '+'+s) + raises(ParseStringError, string_to_int, '-'+s) def test_string_to_int_overflow(self): import sys space = self.space - raises(ParseStringOverflowError, string_to_int, space, + raises(ParseStringOverflowError, string_to_int, str(sys.maxint*17)) def test_string_to_int_base_error(self): @@ -107,11 +109,11 @@ ('12.3', 16), ] for s, base in cases: - raises(ParseStringError, string_to_int, space, s, base) - raises(ParseStringError, string_to_int, space, ' '+s, base) - raises(ParseStringError, string_to_int, space, s+' ', base) - raises(ParseStringError, string_to_int, space, '+'+s, base) - raises(ParseStringError, string_to_int, space, '-'+s, base) + raises(ParseStringError, string_to_int, s, base) + raises(ParseStringError, string_to_int, ' '+s, base) + raises(ParseStringError, string_to_int, s+' ', base) + raises(ParseStringError, string_to_int, '+'+s, base) + raises(ParseStringError, string_to_int, '-'+s, base) def test_string_to_w_long(self): space = self.space @@ -124,3 +126,23 @@ assert string_to_w_long(space, '123L', 22).longval() == 10648 + 968 + 66 + 21 assert string_to_w_long(space, '123L', 21).longval() == 441 + 42 + 3 assert string_to_w_long(space, '1891234174197319').longval() == 1891234174197319 + + +def test_break_up_float(): + assert break_up_float('1') == ('', '1', '', '') + assert break_up_float('+1') == ('+', '1', '', '') + assert break_up_float('-1') == ('-', '1', '', '') + + assert break_up_float('.5') == ('', '', '5', '') + + assert break_up_float('1.2e3') == ('', '1', '2', '3') + assert break_up_float('1.2e+3') == ('', '1', '2', '+3') + assert break_up_float('1.2e-3') == ('', '1', '2', '-3') + + # some that will get thrown out on return: + assert break_up_float('.') == ('', '', '', '') + assert break_up_float('+') == ('+', '', '', '') + assert break_up_float('-') == ('-', '', '', '') + assert break_up_float('e1') == ('', '', '', '1') + + py.test.raises(ParseStringError, break_up_float, 'e') Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Fri Jun 24 12:53:51 2005 @@ -4,7 +4,6 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.sliceobject import W_SliceObject from pypy.objspace.std import slicetype -from pypy.objspace.std.strutil import string_to_int, string_to_long, ParseStringError from pypy.rpython.rarithmetic import intmask from pypy.module.unicodedata import unicodedb From hpk at codespeak.net Fri Jun 24 13:05:11 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 13:05:11 +0200 (CEST) Subject: [pypy-svn] r13772 - pypy/dist/pypy/rpython Message-ID: <20050624110511.19FA827B6A@code1.codespeak.net> Author: hpk Date: Fri Jun 24 13:05:08 2005 New Revision: 13772 Modified: pypy/dist/pypy/rpython/lltype.py Log: shorten representation for functions from 'func' to 'fn' Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Fri Jun 24 13:05:08 2005 @@ -679,7 +679,7 @@ return '<%s>' % (self,) def __str__(self): - return "func %s" % self._name + return "fn %s" % self._name def __eq__(self, other): return (self.__class__ is other.__class__ and From arigo at codespeak.net Fri Jun 24 13:06:22 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 13:06:22 +0200 (CEST) Subject: [pypy-svn] r13773 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050624110622.0599D27B6A@code1.codespeak.net> Author: arigo Date: Fri Jun 24 13:06:19 2005 New Revision: 13773 Modified: pypy/dist/pypy/objspace/std/strutil.py pypy/dist/pypy/objspace/std/test/test_strutil.py Log: Trivial bug fixes in string_to_float(). Tests. Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Fri Jun 24 13:06:19 2005 @@ -187,7 +187,7 @@ def string_to_float(s): - s = strip_space(s) + s = strip_spaces(s) if not s: raise ParseStringError("empty string for float()") @@ -210,12 +210,13 @@ while i < len(after_point): d = float(ord(after_point[i]) - ord('0')) r += d * (10.0 ** (-i-1)) + i += 1 if exponent: - e = string_to_int(None, exponent) + e = string_to_int(exponent) r *= 10.0 ** e - return r - + if sign == '-': + r = -r - + return r Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Fri Jun 24 13:06:19 2005 @@ -1,4 +1,5 @@ import autopath +import py, random from pypy.objspace.std.strutil import * import py @@ -146,3 +147,44 @@ assert break_up_float('e1') == ('', '', '', '1') py.test.raises(ParseStringError, break_up_float, 'e') + + +def test_string_to_float(): + assert string_to_float('0') == 0.0 + assert string_to_float('1') == 1.0 + assert string_to_float('-1.5') == -1.5 + assert string_to_float('1.5E2') == 150.0 + assert string_to_float('2.5E-1') == 0.25 + + valid_parts = [['', ' ', ' \f\n\r\t\v'], + ['', '+', '-'], + ['00', '90', '.5', '2.4', '3.', '0.07', + '12.3489749871982471987198371293717398256187563298638726' + '2187362820947193247129871083561249818451804287437824015' + '013816418758104762348932657836583048761487632840726386'], + ['', 'e0', 'E+1', 'E-01', 'E42'], + ['', ' ', ' \f\n\r\t\v'], + ] + invalid_parts = [['#'], + ['++', '+-', '-+', '--'], + ['', '1.2.3', '.', '5..6'], + ['E+', 'E-', 'e', 'e++', 'E++2'], + ['#'], + ] + for part0 in valid_parts[0]: + for part1 in valid_parts[1]: + for part2 in valid_parts[2]: + for part3 in valid_parts[3]: + for part4 in valid_parts[4]: + s = part0+part1+part2+part3+part4 + assert (abs(string_to_float(s) - float(s)) <= + 1E-13 * abs(float(s))) + + for j in range(len(invalid_parts)): + for invalid in invalid_parts[j]: + for i in range(20): + parts = [random.choice(lst) for lst in valid_parts] + parts[j] = invalid + s = ''.join(parts) + print repr(s) + py.test.raises(ParseStringError, string_to_float, s) From arigo at codespeak.net Fri Jun 24 13:15:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 13:15:09 +0200 (CEST) Subject: [pypy-svn] r13775 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050624111509.EE2BB27B6A@code1.codespeak.net> Author: arigo Date: Fri Jun 24 13:15:07 2005 New Revision: 13775 Modified: pypy/dist/pypy/objspace/std/floattype.py pypy/dist/pypy/objspace/std/test/test_floatobject.py Log: Use string_to_float() from floattype.py. Some tests. Modified: pypy/dist/pypy/objspace/std/floattype.py ============================================================================== --- pypy/dist/pypy/objspace/std/floattype.py (original) +++ pypy/dist/pypy/objspace/std/floattype.py Fri Jun 24 13:15:07 2005 @@ -1,21 +1,22 @@ from pypy.objspace.std.stdtypedef import * from pypy.interpreter.error import OperationError -from pypy.objspace.std.strutil import ParseStringError +from pypy.objspace.std.strutil import string_to_float, ParseStringError def descr__new__(space, w_floattype, w_x=0.0): from pypy.objspace.std.floatobject import W_FloatObject w_value = w_x # 'x' is the keyword argument name in CPython if space.is_true(space.isinstance(w_value, space.w_str)): + strvalue = space.str_w(w_value) try: - value = float(space.str_w(w_value)) - except ValueError, e: + value = string_to_float(strvalue) + except ParseStringError, e: raise OperationError(space.w_ValueError, - space.wrap(str(e))) + space.wrap(e.msg)) elif space.is_true(space.isinstance(w_value, space.w_unicode)): + from unicodeobject import unicode_to_decimal_w + strvalue = unicode_to_decimal_w(space, w_value) try: - # XXX can produce unwrapped long - from unicodeobject import unicode_to_decimal_w - value = float(unicode_to_decimal_w(space, w_value)) + value = string_to_float(strvalue) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) Modified: pypy/dist/pypy/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_floatobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_floatobject.py Fri Jun 24 13:15:07 2005 @@ -56,9 +56,11 @@ def test_float_string(self): assert 42 == float("42") + assert 42.25 == float("42.25") def test_float_unicode(self): - assert 42.3 == float(unicode("42.3")) + # u00A0 and u2000 are some kind of spaces + assert 42.75 == float(unichr(0x00A0)+unicode("42.75")+unichr(0x2000)) def test_float_long(self): assert 42.0 == float(42L) From hpk at codespeak.net Fri Jun 24 13:15:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 13:15:43 +0200 (CEST) Subject: [pypy-svn] r13776 - pypy/extradoc/sprintinfo Message-ID: <20050624111543.CEBB027B6A@code1.codespeak.net> Author: hpk Date: Fri Jun 24 13:15:43 2005 New Revision: 13776 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: get rid of umlauts (sorry, but there are parsing problems and people editing the documents with different encodings can easily mess it up for the web page generation otherwise) Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Fri Jun 24 13:15:43 2005 @@ -11,10 +11,10 @@ Armin Rigo 23rd- private Samuele Pedroni 23rd- private Holger Krekel 23rd- private -Beatrice D?ring visiting private +Beatrice Duering visiting private Anders Lehmann 22nd-26th SGS Michael Hudson 23rd- private -Anders Chrigstr?m 23rd- private +Anders Chrigstroem 23rd- private Christian Tismer 23rd- ? =================== ============== ===================== @@ -32,12 +32,12 @@ Holger Krekel 1st-7th July private Richard Emslie 1st-7th July ? Bert Freudenberg 1st-7th July ? -Beatrice D?ring visiting private +Beatrice Duering visiting private Jacob Hallen ? private Laura Creighton ? private Adrien Di Mascio 1st-5th July Nice Hotel Ludovic Aubry 1st-5th July Nice Hotel -Anders Chrigstr?m 1st-7th July private +Anders Chrigstroem 1st-7th July private Christian Tismer 1st-7th July ? =================== ============== ===================== @@ -56,6 +56,6 @@ Laura Creighton 8th July private Lene Wagner 8th July ? Stephan Busemann 7+8th July Hotel Lilton -Anders Chrigstr?m 8th July private +Anders Chrigstroem 8th July private Christian Tismer 8th July ? =================== ============== ===================== From mwh at codespeak.net Fri Jun 24 13:16:29 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 13:16:29 +0200 (CEST) Subject: [pypy-svn] r13777 - pypy/extradoc/sprintinfo Message-ID: <20050624111629.093AC27B70@code1.codespeak.net> Author: mwh Date: Fri Jun 24 13:16:28 2005 New Revision: 13777 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: we don't need float(str) now. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 13:16:28 2005 @@ -35,7 +35,8 @@ to be done: - DONE list(list - DONE list(tuple) - - float(int), int(float), float(str) (likely delegate to backend) + - DONE float(str) (or rather, the need for it removed) + - float(int), int(float) (likely delegate to backend) - (mostly easy) a few more operations: issubtype, ...? From tismer at codespeak.net Fri Jun 24 13:16:53 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:16:53 +0200 (CEST) Subject: [pypy-svn] r13778 - pypy/dist/pypy/rpython Message-ID: <20050624111653.7B30C27B6A@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:16:52 2005 New Revision: 13778 Modified: pypy/dist/pypy/rpython/exceptiondata.py Log: removed the import aster-risk :-) Modified: pypy/dist/pypy/rpython/exceptiondata.py ============================================================================== --- pypy/dist/pypy/rpython/exceptiondata.py (original) +++ pypy/dist/pypy/rpython/exceptiondata.py Fri Jun 24 13:16:52 2005 @@ -1,7 +1,8 @@ from pypy.annotation import model as annmodel from pypy.rpython import rclass from pypy.rpython.annlowlevel import annotate_lowlevel_helper -from pypy.rpython.lltype import * +from pypy.rpython.lltype import Array, malloc, Ptr, PyObject, pyobjectptr +from pypy.rpython.lltype import FuncType, functionptr, Signed class ExceptionData: From tismer at codespeak.net Fri Jun 24 13:21:02 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:21:02 +0200 (CEST) Subject: [pypy-svn] r13779 - pypy/dist/pypy/rpython Message-ID: <20050624112102.9CF0027B8A@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:21:01 2005 New Revision: 13779 Modified: pypy/dist/pypy/rpython/llinterp.py Log: removed the import aster-risk :-) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 24 13:21:01 2005 @@ -1,10 +1,9 @@ -from pypy.rpython.lltype import * -from pypy.rpython.lltype import _ptr from pypy.translator.translator import Translator from pypy.tool.sourcetools import compile2 from pypy.objspace.flow.model import Constant, Variable, last_exception from pypy.rpython.rarithmetic import intmask, r_uint import py +from pypy.rpython.lltype import _ptr, Void, typeOf, malloc, cast_pointer, Array log = py.log.Producer('llinterp') From tismer at codespeak.net Fri Jun 24 13:27:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:27:20 +0200 (CEST) Subject: [pypy-svn] r13780 - pypy/dist/pypy/rpython Message-ID: <20050624112720.6358F27B8A@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:27:19 2005 New Revision: 13780 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/normalizecalls.py Log: even more less aster-risk Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 24 13:27:19 2005 @@ -3,7 +3,8 @@ from pypy.objspace.flow.model import Constant, Variable, last_exception from pypy.rpython.rarithmetic import intmask, r_uint import py -from pypy.rpython.lltype import _ptr, Void, typeOf, malloc, cast_pointer, Array +from pypy.rpython.lltype import _ptr, Ptr, Void, typeOf, malloc, cast_pointer +from pypy.rpython.lltype import Array log = py.log.Producer('llinterp') Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 24 13:27:19 2005 @@ -1,7 +1,7 @@ import types from pypy.objspace.flow.model import Variable, Constant, Block, Link from pypy.objspace.flow.model import SpaceOperation, checkgraph -from pypy.annotation.model import * +from pypy.annotation import model as annmodel from pypy.tool.sourcetools import has_varargs from pypy.rpython.rmodel import TyperError @@ -113,11 +113,11 @@ for graph, bindings in graph_bindings.items(): j = graph_argorders[graph][i] args_s.append(bindings[j]) - s_value = unionof(*args_s) + s_value = annmodel.unionof(*args_s) generalizedargs.append(s_value) result_s = [annotator.binding(graph.getreturnvar()) for graph in graph_bindings] - generalizedresult = unionof(*result_s) + generalizedresult = annmodel.unionof(*result_s) for func in functions: graph = annotator.translator.getflowgraph(func) From mwh at codespeak.net Fri Jun 24 13:28:50 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 13:28:50 +0200 (CEST) Subject: [pypy-svn] r13781 - pypy/dist/pypy/objspace/std Message-ID: <20050624112850.D30E427B8A@code1.codespeak.net> Author: mwh Date: Fri Jun 24 13:28:49 2005 New Revision: 13781 Modified: pypy/dist/pypy/objspace/std/strutil.py Log: appalling way of avoiding cpython overflow errors. Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Fri Jun 24 13:28:49 2005 @@ -213,8 +213,24 @@ i += 1 if exponent: - e = string_to_int(exponent) - r *= 10.0 ** e + try: + e = string_to_int(exponent) + except ParseStringOverflowError: + if exponent[0] == '-': + return 0.0 + else: + if sign == '-': + return -1e200 * 1e200 + else: + return 1e200 * 1e200 + if e > 0: + while e > 0: + r *= 10.0 + e -= 1 + else: + while e < 0: + r /= 10.0 + e += 1 if sign == '-': r = -r From arigo at codespeak.net Fri Jun 24 13:29:31 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 13:29:31 +0200 (CEST) Subject: [pypy-svn] r13782 - pypy/dist/pypy/objspace/std/test Message-ID: <20050624112931.DD37527B8A@code1.codespeak.net> Author: arigo Date: Fri Jun 24 13:29:29 2005 New Revision: 13782 Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py Log: Tests for previous commit. Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Fri Jun 24 13:29:29 2005 @@ -155,6 +155,10 @@ assert string_to_float('-1.5') == -1.5 assert string_to_float('1.5E2') == 150.0 assert string_to_float('2.5E-1') == 0.25 + assert string_to_float('1e1111111111111') == float('1e1111111111111') + assert string_to_float('1e-1111111111111') == float('1e-1111111111111') + assert string_to_float('-1e1111111111111') == float('-1e1111111111111') + assert string_to_float('-1e-1111111111111') == float('-1e-1111111111111') valid_parts = [['', ' ', ' \f\n\r\t\v'], ['', '+', '-'], From tismer at codespeak.net Fri Jun 24 13:33:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:33:39 +0200 (CEST) Subject: [pypy-svn] r13783 - pypy/dist/pypy/rpython Message-ID: <20050624113339.CA0EB27B61@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:33:38 2005 New Revision: 13783 Modified: pypy/dist/pypy/rpython/rclass.py Log: more less aster-risk Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 24 13:33:38 2005 @@ -2,8 +2,12 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.annotation.classdef import isclassdef -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, inputconst +from pypy.rpython.lltype import ForwardReference, GcForwardReference +from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc +from pypy.rpython.lltype import cast_pointer, castable +from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf +from pypy.rpython.lltype import Array, Char, Void # # There is one "vtable" per user class, with the following structure: From arigo at codespeak.net Fri Jun 24 13:33:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 13:33:46 +0200 (CEST) Subject: [pypy-svn] r13784 - in pypy/branch/pypy-translation-snapshot/objspace/std: . test Message-ID: <20050624113346.EF62927B85@code1.codespeak.net> Author: arigo Date: Fri Jun 24 13:33:46 2005 New Revision: 13784 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/floattype.py pypy/branch/pypy-translation-snapshot/objspace/std/inttype.py pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py pypy/branch/pypy-translation-snapshot/objspace/std/test/test_floatobject.py pypy/branch/pypy-translation-snapshot/objspace/std/test/test_strutil.py pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py Log: Port from the trunk of string_to_float(), revisions around 13771-13782. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/floattype.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/floattype.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/floattype.py Fri Jun 24 13:33:46 2005 @@ -1,21 +1,22 @@ from pypy.objspace.std.stdtypedef import * from pypy.interpreter.error import OperationError -from pypy.objspace.std.strutil import ParseStringError +from pypy.objspace.std.strutil import string_to_float, ParseStringError def descr__new__(space, w_floattype, w_x=0.0): from pypy.objspace.std.floatobject import W_FloatObject w_value = w_x # 'x' is the keyword argument name in CPython if space.is_true(space.isinstance(w_value, space.w_str)): + strvalue = space.str_w(w_value) try: - value = float(space.str_w(w_value)) - except ValueError, e: + value = string_to_float(strvalue) + except ParseStringError, e: raise OperationError(space.w_ValueError, - space.wrap(str(e))) + space.wrap(e.msg)) elif space.is_true(space.isinstance(w_value, space.w_unicode)): + from unicodeobject import unicode_to_decimal_w + strvalue = unicode_to_decimal_w(space, w_value) try: - # XXX can produce unwrapped long - from unicodeobject import unicode_to_decimal_w - value = float(unicode_to_decimal_w(space, w_value)) + value = string_to_float(strvalue) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/inttype.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/inttype.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/inttype.py Fri Jun 24 13:33:46 2005 @@ -22,7 +22,7 @@ value = w_value.intval elif space.is_true(space.isinstance(w_value, space.w_str)): try: - value = string_to_int(space, space.str_w(w_value)) + value = string_to_int(space.str_w(w_value)) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) @@ -32,7 +32,7 @@ from unicodeobject import unicode_to_decimal_w string = unicode_to_decimal_w(space, w_value) try: - value = string_to_int(space, string) + value = string_to_int(string) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) @@ -68,7 +68,7 @@ space.wrap("int() can't convert non-string " "with explicit base")) try: - value = string_to_int(space, s, base) + value = string_to_int(s, base) except ParseStringError, e: raise OperationError(space.w_ValueError, space.wrap(e.msg)) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/strutil.py Fri Jun 24 13:33:46 2005 @@ -86,7 +86,7 @@ else: return -1 -def string_to_int(space, s, base=10): +def string_to_int(s, base=10): """Utility to converts a string to an integer (or possibly a long). If base is 0, the proper base is guessed based on the leading characters of 's'. Raises ParseStringError in case of error. @@ -134,3 +134,105 @@ return w_result w_result = space.add(space.mul(w_result,w_base),space.newlong(r_uint(digit))) +def break_up_float(s): + i = 0 + + sign = '' + before_point = '' + after_point = '' + exponent = '' + + if s[i] in '+-': + sign = s[i] + i += 1 + + while i < len(s) and s[i] in '0123456789': + before_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] == '.': + i += 1 + while i < len(s) and s[i] in '0123456789': + after_point += s[i] + i += 1 + + if i == len(s): + return sign, before_point, after_point, exponent + + if s[i] not in 'eE': + raise ParseStringError("invalid string literal for float()") + + i += 1 + if i == len(s): + raise ParseStringError("invalid string literal for float()") + + if s[i] in '-+': + exponent += s[i] + i += 1 + + if i == len(s): + raise ParseStringError("invalid string literal for float()") + + while i < len(s) and s[i] in '0123456789': + exponent += s[i] + i += 1 + + if i != len(s): + raise ParseStringError("invalid string literal for float()") + + return sign, before_point, after_point, exponent + + +def string_to_float(s): + s = strip_spaces(s) + + if not s: + raise ParseStringError("empty string for float()") + + sign, before_point, after_point, exponent = break_up_float(s) + + if not before_point and not after_point: + raise ParseStringError("invalid string literal for float()") + + r = 0.0 + i = len(before_point) - 1 + j = 0 + while i >= 0: + d = float(ord(before_point[i]) - ord('0')) + r += d * (10.0 ** j) + i -= 1 + j += 1 + + i = 0 + while i < len(after_point): + d = float(ord(after_point[i]) - ord('0')) + r += d * (10.0 ** (-i-1)) + i += 1 + + if exponent: + try: + e = string_to_int(exponent) + except ParseStringOverflowError: + if exponent[0] == '-': + return 0.0 + else: + if sign == '-': + return -1e200 * 1e200 + else: + return 1e200 * 1e200 + if e > 0: + while e > 0: + r *= 10.0 + e -= 1 + else: + while e < 0: + r /= 10.0 + e += 1 + + if sign == '-': + r = -r + + return r Modified: pypy/branch/pypy-translation-snapshot/objspace/std/test/test_floatobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/test/test_floatobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/test/test_floatobject.py Fri Jun 24 13:33:46 2005 @@ -56,9 +56,11 @@ def test_float_string(self): assert 42 == float("42") + assert 42.25 == float("42.25") def test_float_unicode(self): - assert 42.3 == float(unicode("42.3")) + # u00A0 and u2000 are some kind of spaces + assert 42.75 == float(unichr(0x00A0)+unicode("42.75")+unichr(0x2000)) def test_float_long(self): assert 42.0 == float(42L) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/test/test_strutil.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/test/test_strutil.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/test/test_strutil.py Fri Jun 24 13:33:46 2005 @@ -1,6 +1,9 @@ import autopath +import py, random from pypy.objspace.std.strutil import * +import py + objspacename = 'std' class TestStrUtil: @@ -24,7 +27,7 @@ (' -123456789 ', -123456789), ] for s, expected in cases: - assert string_to_int(space, s) == expected + assert string_to_int(s) == expected assert string_to_w_long(space, s).longval() == expected def test_string_to_int_base(self): @@ -54,12 +57,12 @@ ('0X', 16, 0), # " " ] for s, base, expected in cases: - assert string_to_int(space, s, base) == expected - assert string_to_int(space, '+'+s, base) == expected - assert string_to_int(space, '-'+s, base) == -expected - assert string_to_int(space, s+'\n', base) == expected - assert string_to_int(space, ' +'+s, base) == expected - assert string_to_int(space, '-'+s+' ', base) == -expected + assert string_to_int(s, base) == expected + assert string_to_int('+'+s, base) == expected + assert string_to_int('-'+s, base) == -expected + assert string_to_int(s+'\n', base) == expected + assert string_to_int(' +'+s, base) == expected + assert string_to_int('-'+s+' ', base) == -expected def test_string_to_int_error(self): space = self.space @@ -78,16 +81,16 @@ '@', ] for s in cases: - raises(ParseStringError, string_to_int, space, s) - raises(ParseStringError, string_to_int, space, ' '+s) - raises(ParseStringError, string_to_int, space, s+' ') - raises(ParseStringError, string_to_int, space, '+'+s) - raises(ParseStringError, string_to_int, space, '-'+s) + raises(ParseStringError, string_to_int, s) + raises(ParseStringError, string_to_int, ' '+s) + raises(ParseStringError, string_to_int, s+' ') + raises(ParseStringError, string_to_int, '+'+s) + raises(ParseStringError, string_to_int, '-'+s) def test_string_to_int_overflow(self): import sys space = self.space - raises(ParseStringOverflowError, string_to_int, space, + raises(ParseStringOverflowError, string_to_int, str(sys.maxint*17)) def test_string_to_int_base_error(self): @@ -107,11 +110,11 @@ ('12.3', 16), ] for s, base in cases: - raises(ParseStringError, string_to_int, space, s, base) - raises(ParseStringError, string_to_int, space, ' '+s, base) - raises(ParseStringError, string_to_int, space, s+' ', base) - raises(ParseStringError, string_to_int, space, '+'+s, base) - raises(ParseStringError, string_to_int, space, '-'+s, base) + raises(ParseStringError, string_to_int, s, base) + raises(ParseStringError, string_to_int, ' '+s, base) + raises(ParseStringError, string_to_int, s+' ', base) + raises(ParseStringError, string_to_int, '+'+s, base) + raises(ParseStringError, string_to_int, '-'+s, base) def test_string_to_w_long(self): space = self.space @@ -124,3 +127,68 @@ assert string_to_w_long(space, '123L', 22).longval() == 10648 + 968 + 66 + 21 assert string_to_w_long(space, '123L', 21).longval() == 441 + 42 + 3 assert string_to_w_long(space, '1891234174197319').longval() == 1891234174197319 + + +def test_break_up_float(): + assert break_up_float('1') == ('', '1', '', '') + assert break_up_float('+1') == ('+', '1', '', '') + assert break_up_float('-1') == ('-', '1', '', '') + + assert break_up_float('.5') == ('', '', '5', '') + + assert break_up_float('1.2e3') == ('', '1', '2', '3') + assert break_up_float('1.2e+3') == ('', '1', '2', '+3') + assert break_up_float('1.2e-3') == ('', '1', '2', '-3') + + # some that will get thrown out on return: + assert break_up_float('.') == ('', '', '', '') + assert break_up_float('+') == ('+', '', '', '') + assert break_up_float('-') == ('-', '', '', '') + assert break_up_float('e1') == ('', '', '', '1') + + py.test.raises(ParseStringError, break_up_float, 'e') + + +def test_string_to_float(): + assert string_to_float('0') == 0.0 + assert string_to_float('1') == 1.0 + assert string_to_float('-1.5') == -1.5 + assert string_to_float('1.5E2') == 150.0 + assert string_to_float('2.5E-1') == 0.25 + assert string_to_float('1e1111111111111') == float('1e1111111111111') + assert string_to_float('1e-1111111111111') == float('1e-1111111111111') + assert string_to_float('-1e1111111111111') == float('-1e1111111111111') + assert string_to_float('-1e-1111111111111') == float('-1e-1111111111111') + + valid_parts = [['', ' ', ' \f\n\r\t\v'], + ['', '+', '-'], + ['00', '90', '.5', '2.4', '3.', '0.07', + '12.3489749871982471987198371293717398256187563298638726' + '2187362820947193247129871083561249818451804287437824015' + '013816418758104762348932657836583048761487632840726386'], + ['', 'e0', 'E+1', 'E-01', 'E42'], + ['', ' ', ' \f\n\r\t\v'], + ] + invalid_parts = [['#'], + ['++', '+-', '-+', '--'], + ['', '1.2.3', '.', '5..6'], + ['E+', 'E-', 'e', 'e++', 'E++2'], + ['#'], + ] + for part0 in valid_parts[0]: + for part1 in valid_parts[1]: + for part2 in valid_parts[2]: + for part3 in valid_parts[3]: + for part4 in valid_parts[4]: + s = part0+part1+part2+part3+part4 + assert (abs(string_to_float(s) - float(s)) <= + 1E-13 * abs(float(s))) + + for j in range(len(invalid_parts)): + for invalid in invalid_parts[j]: + for i in range(20): + parts = [random.choice(lst) for lst in valid_parts] + parts[j] = invalid + s = ''.join(parts) + print repr(s) + py.test.raises(ParseStringError, string_to_float, s) Modified: pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/unicodeobject.py Fri Jun 24 13:33:46 2005 @@ -4,7 +4,6 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.sliceobject import W_SliceObject from pypy.objspace.std import slicetype -from pypy.objspace.std.strutil import string_to_int, string_to_long, ParseStringError from pypy.rpython.rarithmetic import intmask from pypy.module.unicodedata import unicodedb From hpk at codespeak.net Fri Jun 24 13:36:23 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 13:36:23 +0200 (CEST) Subject: [pypy-svn] r13786 - pypy/extradoc/sprintinfo Message-ID: <20050624113623.E7F7D27B8A@code1.codespeak.net> Author: hpk Date: Fri Jun 24 13:36:23 2005 New Revision: 13786 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: fix ReST formatting (yes, every .txt document in extradoc needs to follow ReST format) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 13:36:23 2005 @@ -15,10 +15,9 @@ 2. find out if we really have visible dicts with PBC keys - DONE (medium) dicts with non-wrapped string keys to any object, and - iterators over them - - basic getitem/setitem/delitem is done (ported Algos from CPython - actually!) - - remaining: dict iterators + iterators over them + - basic getitem/setitem/delitem is done (ported Algos from CPython actually!) + - remaining: dict iterators - DONE (mostly easy) tuple to list task: the built-in list() should convert from homogenous tuples @@ -44,8 +43,9 @@ be supported - (probably easy): operations: str for ints, instances (only something - very simple for the latter). all other uses are cheating, as - are all uses of hex, oct, repr. + very simple for the latter). all other uses are cheating, as + are all uses of hex, oct, repr. + mostly DONE apart from instances which we're not sure we need anyway - DONE (easy) list methods reverse, pop, insert, index(!) @@ -65,9 +65,9 @@ - (medium) limited form of string formatting: 'constant template' only which should only generate a sequence of simple ll-function invocations like concatenation and str() on integers - task: 1. figure out what kind of formatting we use in PyPy - 2. implement them - mostly DONE apart from possibly '%s' % some random instance + task: 1. figure out what kind of formatting we use in PyPy + 2. implement them + mostly DONE apart from possibly '%s' % some random instance * lltype will also need to grow a new primitive type, UnicodeChar. From tismer at codespeak.net Fri Jun 24 13:42:02 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:42:02 +0200 (CEST) Subject: [pypy-svn] r13787 - pypy/dist/pypy/rpython Message-ID: <20050624114202.124D127B88@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:42:01 2005 New Revision: 13787 Modified: pypy/dist/pypy/rpython/rlist.py Log: and guess what: still more less aster-risk Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Fri Jun 24 13:42:01 2005 @@ -1,13 +1,15 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython import rrange from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr from pypy.rpython.rstr import string_repr, ll_streq from pypy.rpython.rclass import InstanceRepr +from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct +from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive +from pypy.rpython.lltype import Bool # ____________________________________________________________ # From mwh at codespeak.net Fri Jun 24 13:44:08 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 13:44:08 +0200 (CEST) Subject: [pypy-svn] r13788 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624114408.7F04527B88@code1.codespeak.net> Author: mwh Date: Fri Jun 24 13:44:07 2005 New Revision: 13788 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/test/test_rfloat.py Log: rtyper support for float(int) + tests Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 24 13:44:07 2005 @@ -1,7 +1,7 @@ from pypy.translator.translator import Translator from pypy.tool.sourcetools import compile2 from pypy.objspace.flow.model import Constant, Variable, last_exception -from pypy.rpython.rarithmetic import intmask, r_uint +from pypy.rpython.rarithmetic import intmask, r_uint, ovfcheck import py from pypy.rpython.lltype import _ptr, Ptr, Void, typeOf, malloc, cast_pointer from pypy.rpython.lltype import Array @@ -247,6 +247,10 @@ def op_bool_not(self, b): assert type(b) is bool return not b + + def op_cast_float_to_int(self, f): + assert type(f) is float + return ovfcheck(int(f)) def op_cast_char_to_int(self, b): assert type(b) is str and len(b) == 1 Modified: pypy/dist/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rfloat.py (original) +++ pypy/dist/pypy/rpython/test/test_rfloat.py Fri Jun 24 13:44:07 2005 @@ -2,6 +2,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet +from pypy.rpython.test.test_llinterp import make_interpreter class TestSnippet(object): @@ -36,3 +37,14 @@ # XXX TODO test if all binary operations are implemented for opname in annmodel.BINARY_OPERATIONS: print 'BINARY_OPERATIONS:', opname + +def test_int_conversion(): + def fn(f): + return int(f) + + ev_fun = make_interpreter(fn, [0.0]) + + assert ev_fun(1.0) == 1 + assert type(ev_fun(1.0)) is int + + assert ev_fun(2.34) == 2 From tismer at codespeak.net Fri Jun 24 13:44:12 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:44:12 +0200 (CEST) Subject: [pypy-svn] r13789 - pypy/dist/pypy/rpython Message-ID: <20050624114412.6E33827B93@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:44:11 2005 New Revision: 13789 Modified: pypy/dist/pypy/rpython/rrange.py Log: (import *) -- Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Fri Jun 24 13:44:11 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr -from pypy.rpython.lltype import * +from pypy.rpython.lltype import Ptr, GcStruct, Signed, malloc, Void # ____________________________________________________________ # From tismer at codespeak.net Fri Jun 24 13:45:56 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:45:56 +0200 (CEST) Subject: [pypy-svn] r13790 - pypy/dist/pypy/rpython Message-ID: <20050624114556.7E10127B88@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:45:55 2005 New Revision: 13790 Modified: pypy/dist/pypy/rpython/rslice.py Log: (import *) -- Modified: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/rslice.py (original) +++ pypy/dist/pypy/rpython/rslice.py Fri Jun 24 13:45:55 2005 @@ -1,9 +1,9 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr import sys +from pypy.rpython.lltype import GcStruct, Signed, Ptr # ____________________________________________________________ # From rxe at codespeak.net Fri Jun 24 13:46:07 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 24 Jun 2005 13:46:07 +0200 (CEST) Subject: [pypy-svn] r13791 - pypy/dist/pypy/rpython Message-ID: <20050624114607.661F027B8B@code1.codespeak.net> Author: rxe Date: Fri Jun 24 13:46:06 2005 New Revision: 13791 Modified: pypy/dist/pypy/rpython/rtyper.py Log: Minor typo. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Fri Jun 24 13:46:06 2005 @@ -5,7 +5,7 @@ to the care of the rtype_*() methods implemented in the other r* modules. For each high-level operation 'hop', the rtype_*() methods produce low-level operations that are collected in the 'llops' list defined here. When necessary, -convertions are inserted. +conversions are inserted. This logic borrows a bit from pypy.translator.annrpython, without the fixpoint computation part. From rxe at codespeak.net Fri Jun 24 13:48:10 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Fri, 24 Jun 2005 13:48:10 +0200 (CEST) Subject: [pypy-svn] r13792 - pypy/dist/pypy/rpython Message-ID: <20050624114810.B8CA027B88@code1.codespeak.net> Author: rxe Date: Fri Jun 24 13:48:09 2005 New Revision: 13792 Modified: pypy/dist/pypy/rpython/rtuple.py Log: Dead code? Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Fri Jun 24 13:48:09 2005 @@ -130,8 +130,3 @@ llops.gencapicall('PyTuple_SetItem_WithIncref', [v_result, ci, v_converted]) return v_result - -def ll_newlist(LISTPTR, length): - l = malloc(LISTPTR.TO) - l.items = malloc(LISTPTR.TO.items.TO, length) - return l From pedronis at codespeak.net Fri Jun 24 13:48:25 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 24 Jun 2005 13:48:25 +0200 (CEST) Subject: [pypy-svn] r13793 - in pypy/dist/pypy: annotation translator/goal Message-ID: <20050624114825.3682127B8A@code1.codespeak.net> Author: pedronis Date: Fri Jun 24 13:48:23 2005 New Revision: 13793 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/translator/goal/query.py Log: - stats for dict get/set/del -item - saner repr for big const SomeDicts Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Fri Jun 24 13:48:23 2005 @@ -374,13 +374,16 @@ class __extend__(pairtype(SomeDict, SomeObject)): def getitem((dic1, obj2)): + getbookkeeper().count("dict_getitem", dic1) return dic1.dictdef.read_value() def setitem((dic1, obj2), s_value): + getbookkeeper().count("dict_setitem", dic1) dic1.dictdef.generalize_key(obj2) dic1.dictdef.generalize_value(s_value) def delitem((dic1, obj1)): + getbookkeeper().count("dict_delitem", dic1) pass Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Jun 24 13:48:23 2005 @@ -145,6 +145,15 @@ return (str.const, tuple([self.typerepr(x) for x in args.items])) else: return (str.const, self.typerepr(args)) + + def consider_dict_getitem(self, dic): + return dic + + def consider_dict_setitem(self, dic): + return dic + + def consider_dict_delitem(self, dic): + return dic class Bookkeeper: Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Fri Jun 24 13:48:23 2005 @@ -260,6 +260,13 @@ def can_be_none(self): return False + def fmt_const(self, const): + if len(const) < 20: + return repr(const) + else: + return '{...%s...}'%(len(const),) + + class SomeIterator(SomeObject): "Stands for an iterator returning objects from a given container." knowntype = type(iter([])) # arbitrarily chose seqiter as the type Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Fri Jun 24 13:48:23 2005 @@ -411,6 +411,29 @@ if k.startswith('__builtin__'): statsfor(t, k) +def dicts(t): + ann = t.annotator + r = [] + + def sdicts(): + for so in ann.bindings.itervalues(): + if isinstance(so, annmodel.SomeDict): + yield so + for so in ann.bookkeeper.immutable_cache.itervalues(): + if isinstance(so, annmodel.SomeDict): + yield so + + for so in sdicts(): + sk, sv = so.dictdef.dictkey.s_value, so.dictdef.dictvalue.s_value + for x in r: + if x == (sk, sv): + break + else: + r.append((sk, sv)) + + for x in r: + print x + # debug helper def tryout(f, *args): try: From tismer at codespeak.net Fri Jun 24 13:52:40 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:52:40 +0200 (CEST) Subject: [pypy-svn] r13794 - pypy/dist/pypy/rpython Message-ID: <20050624115240.09E0127B61@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:52:39 2005 New Revision: 13794 Modified: pypy/dist/pypy/rpython/rslice.py pypy/dist/pypy/rpython/rstr.py Log: (import *) -- boring ++ Modified: pypy/dist/pypy/rpython/rslice.py ============================================================================== --- pypy/dist/pypy/rpython/rslice.py (original) +++ pypy/dist/pypy/rpython/rslice.py Fri Jun 24 13:52:39 2005 @@ -3,7 +3,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr import sys -from pypy.rpython.lltype import GcStruct, Signed, Ptr +from pypy.rpython.lltype import GcStruct, Signed, Ptr, Void,malloc # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Fri Jun 24 13:52:39 2005 @@ -1,7 +1,6 @@ from weakref import WeakValueDictionary from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst from pypy.rpython.rarithmetic import intmask @@ -10,6 +9,8 @@ from pypy.rpython import rint from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr +from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc +from pypy.rpython.lltype import Bool, Void, GcArray, nullptr # ____________________________________________________________ # From tismer at codespeak.net Fri Jun 24 13:54:48 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 13:54:48 +0200 (CEST) Subject: [pypy-svn] r13795 - pypy/dist/pypy/rpython Message-ID: <20050624115448.60F6E27B61@code1.codespeak.net> Author: tismer Date: Fri Jun 24 13:54:47 2005 New Revision: 13795 Modified: pypy/dist/pypy/rpython/rtuple.py Log: (import *) -- boring ++ Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Fri Jun 24 13:54:47 2005 @@ -1,9 +1,9 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import * from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr +from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed # ____________________________________________________________ # From arigo at codespeak.net Fri Jun 24 13:59:20 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 13:59:20 +0200 (CEST) Subject: [pypy-svn] r13796 - pypy/dist/pypy/rpython Message-ID: <20050624115920.D9A4727B61@code1.codespeak.net> Author: arigo Date: Fri Jun 24 13:59:18 2005 New Revision: 13796 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py Log: Fix yet another recursion trouble with setup(). Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 24 13:59:18 2005 @@ -7,7 +7,7 @@ from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc from pypy.rpython.lltype import cast_pointer, castable from pypy.rpython.lltype import RuntimeTypeInfo, getRuntimeTypeInfo, typeOf -from pypy.rpython.lltype import Array, Char, Void +from pypy.rpython.lltype import Array, Char, Void, attachRuntimeTypeInfo # # There is one "vtable" per user class, with the following structure: @@ -348,7 +348,10 @@ allinstancefields.update(fields) self.fields = fields self.allinstancefields = allinstancefields + attachRuntimeTypeInfo(self.object_type) self.initialized = True + + def setup_final_touch(self): self.rtyper.attachRuntimeTypeInfoFunc(self.object_type, ll_runtime_type_info, OBJECT) Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Fri Jun 24 13:59:18 2005 @@ -22,6 +22,11 @@ def setup(self): "For recursive data structure, which must be initialized in two steps." + def setup_final_touch(self): + """Same as setup(), called a bit later, for effects that are only + needed after the typer finished (as opposed to needed for other parts + of the typer itself).""" + def __getattr__(self, name): # Assume that when an attribute is missing, it's because setup() needs # to be called Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Fri Jun 24 13:59:18 2005 @@ -118,8 +118,13 @@ def call_all_setups(self): # make sure all reprs so far have had their setup() called + must_setup_more = [] while self.reprs_must_call_setup: - self.reprs_must_call_setup.pop().setup() + r = self.reprs_must_call_setup.pop() + r.setup() + must_setup_more.append(r) + for r in must_setup_more: + r.setup_final_touch() def setconcretetype(self, v): assert isinstance(v, Variable) @@ -359,7 +364,6 @@ def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None): self.call_all_setups() # compute ForwardReferences now - attachRuntimeTypeInfo(GCSTRUCT) if ARG_GCSTRUCT is None: ARG_GCSTRUCT = GCSTRUCT args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))] From hpk at codespeak.net Fri Jun 24 15:03:25 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 15:03:25 +0200 (CEST) Subject: [pypy-svn] r13797 - pypy/dist/pypy/rpython Message-ID: <20050624130325.999A027B60@code1.codespeak.net> Author: hpk Date: Fri Jun 24 15:03:24 2005 New Revision: 13797 Modified: pypy/dist/pypy/rpython/rdict.py Log: cosmetics Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Fri Jun 24 15:03:24 2005 @@ -12,7 +12,6 @@ # # struct dictentry { # struct STR *key; -# ### XXX? int state; # DICTVALUE value; # } # @@ -56,8 +55,9 @@ self.value_repr = self._value_repr_computer() if isinstance(self.STRDICT, lltype.GcForwardReference): self.DICTVALUE = self.value_repr.lowleveltype - self.DICTENTRY = lltype.Struct("dictentry", ("key", lltype.Ptr(STR)), - ('value', self.DICTVALUE)) + self.DICTENTRY = lltype.Struct("dictentry", + ("key", lltype.Ptr(STR)), + ('value', self.DICTVALUE)) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) self.STRDICT.become(lltype.GcStruct("dicttable", ("num_items", lltype.Signed), From hpk at codespeak.net Fri Jun 24 15:13:38 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 15:13:38 +0200 (CEST) Subject: [pypy-svn] r13798 - pypy/dist/pypy/rpython/test Message-ID: <20050624131338.EB24927B41@code1.codespeak.net> Author: hpk Date: Fri Jun 24 15:13:38 2005 New Revision: 13798 Modified: pypy/dist/pypy/rpython/test/test_rdict.py Log: added a test for dicts with a non-primitive value type Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Fri Jun 24 15:13:38 2005 @@ -150,4 +150,14 @@ return k res = interpret(func, [6, 7]) assert res == 42 + +def test_two_dicts_with_different_value_types(): + def func(i): + d1 = {} + d1['hello'] = i + 1 + d2 = {} + d2['world'] = d1 + return d2['world']['hello'] + res = interpret(func, [5]) + assert res == 6 From tismer at codespeak.net Fri Jun 24 15:22:14 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 15:22:14 +0200 (CEST) Subject: [pypy-svn] r13799 - pypy/dist/pypy/rpython Message-ID: <20050624132214.AD15127B41@code1.codespeak.net> Author: tismer Date: Fri Jun 24 15:22:13 2005 New Revision: 13799 Modified: pypy/dist/pypy/rpython/rtuple.py Log: missing import. I will stop doing this by hand... Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Fri Jun 24 15:22:13 2005 @@ -3,7 +3,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr -from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed +from pypy.rpython.lltype import Ptr, GcStruct, Void, Signed, malloc # ____________________________________________________________ # From arigo at codespeak.net Fri Jun 24 15:36:36 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 15:36:36 +0200 (CEST) Subject: [pypy-svn] r13800 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20050624133636.5AD1327B56@code1.codespeak.net> Author: arigo Date: Fri Jun 24 15:36:36 2005 New Revision: 13800 Modified: pypy/dist/pypy/objspace/std/strutil.py pypy/dist/pypy/objspace/std/test/test_strutil.py Log: Oups, a test that appears to hang (in fact it only runs for an incredibly long time)... Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Fri Jun 24 15:36:36 2005 @@ -217,20 +217,23 @@ e = string_to_int(exponent) except ParseStringOverflowError: if exponent[0] == '-': - return 0.0 + e = -400 else: - if sign == '-': - return -1e200 * 1e200 - else: - return 1e200 * 1e200 + e = 400 if e > 0: - while e > 0: - r *= 10.0 - e -= 1 + if e >= 400: + r = 1e200 * 1e200 + else: + while e > 0: + r *= 10.0 + e -= 1 else: - while e < 0: - r /= 10.0 - e += 1 + if e <= -400: + r = 0.0 + else: + while e < 0: + r /= 10.0 + e += 1 if sign == '-': r = -r Modified: pypy/dist/pypy/objspace/std/test/test_strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_strutil.py (original) +++ pypy/dist/pypy/objspace/std/test/test_strutil.py Fri Jun 24 15:36:36 2005 @@ -159,6 +159,10 @@ assert string_to_float('1e-1111111111111') == float('1e-1111111111111') assert string_to_float('-1e1111111111111') == float('-1e1111111111111') assert string_to_float('-1e-1111111111111') == float('-1e-1111111111111') + assert string_to_float('1e111111111111111111111') == float('1e111111111111111111111') + assert string_to_float('1e-111111111111111111111') == float('1e-111111111111111111111') + assert string_to_float('-1e111111111111111111111') == float('-1e111111111111111111111') + assert string_to_float('-1e-111111111111111111111') == float('-1e-111111111111111111111') valid_parts = [['', ' ', ' \f\n\r\t\v'], ['', '+', '-'], From mwh at codespeak.net Fri Jun 24 15:51:58 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 15:51:58 +0200 (CEST) Subject: [pypy-svn] r13802 - pypy/dist/pypy/objspace/std Message-ID: <20050624135158.EB51827B56@code1.codespeak.net> Author: mwh Date: Fri Jun 24 15:51:58 2005 New Revision: 13802 Modified: pypy/dist/pypy/objspace/std/strutil.py Log: Note a flaw. Modified: pypy/dist/pypy/objspace/std/strutil.py ============================================================================== --- pypy/dist/pypy/objspace/std/strutil.py (original) +++ pypy/dist/pypy/objspace/std/strutil.py Fri Jun 24 15:51:58 2005 @@ -213,6 +213,8 @@ i += 1 if exponent: + # XXX this fails for float('0.' + '0'*100 + '1e400') + # XXX later! try: e = string_to_int(exponent) except ParseStringOverflowError: From hpk at codespeak.net Fri Jun 24 16:03:36 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 16:03:36 +0200 (CEST) Subject: [pypy-svn] r13803 - pypy/extradoc/sprintinfo Message-ID: <20050624140336.CF34A27B5D@code1.codespeak.net> Author: hpk Date: Fri Jun 24 16:03:36 2005 New Revision: 13803 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: another planning session with DONE tasks removed and new tasks appearing Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 16:03:36 2005 @@ -4,77 +4,49 @@ Still missing are: -* GenC knows little about float operations. Need to complete - translator/c/float_include.h. - * Almost all the topics from the rtyper, from the previous status report: - - (hard) prebuilt constants -- PBCs -- and dicts with PBC keys + - (hard) (holger, armin) prebuilt constants -- PBCs -- and dicts with PBC keys tasks: 1. call to memoized functions, at first with a single PBC arg 2. find out if we really have visible dicts with PBC keys - - DONE (medium) dicts with non-wrapped string keys to any object, and - iterators over them - - basic getitem/setitem/delitem is done (ported Algos from CPython actually!) - - remaining: dict iterators - - - DONE (mostly easy) tuple to list - task: the built-in list() should convert from homogenous tuples - to lists - - - (varying) all built-in functions listed in annotation/builtin.py - task: write them into rpython/rbuiltin.py - possibly remove support for some of them - - DONE removing zip from PyPy codebase - DONE min - DONE isinstance - - to be done: - - DONE list(list - - DONE list(tuple) - - DONE float(str) (or rather, the need for it removed) - - float(int), int(float) (likely delegate to backend) - - - - (mostly easy) a few more operations: issubtype, ...? - task: go through them one by one and decide if they should - be supported + - (probably trivial) verify that we've done all the builtins we + need for translation. + + - (hard) a few more operations: issubtype, ...? + task: go through all space operations listed in baseobjspace.py + annotator/{unary.py,binary.py} + one by one and decide if they should be supported - - (probably easy): operations: str for ints, instances (only something + - (probably easy): operations: str for instances (only something very simple for the latter). all other uses are cheating, as - are all uses of hex, oct, repr. + are all uses of hex, oct, repr. Add some '%s' support of instances + as well. mostly DONE apart from instances which we're not sure we need anyway - - DONE (easy) list methods reverse, pop, insert, index(!) - task: do it. also support contains +* lltype will also need to grow a new primitive type, UnicodeChar. - - DONE (easy) tuple concatenation - task: do it +* (partially DONE) convert each file that does + 'from ... import *' to use explicit imports (e.g. + from pypy.rpython import lltype and then use lltype.*) - - DONE (easy) string slices - task: do it (see rlist) +* (samuele, michael) GenC knows little about float operations. Need to complete + translator/c/float_include.h. - - DONE (easy) equality and non-equality are generally missing - task: 1. missing for lists of primitives, and lists of strings - 2. annotator fix: unify lists when they are compared - 3. for instances, 'eq' is 'is' - - - (medium) limited form of string formatting: 'constant template' only - which should only generate a sequence of simple ll-function - invocations like concatenation and str() on integers - task: 1. figure out what kind of formatting we use in PyPy - 2. implement them - mostly DONE apart from possibly '%s' % some random instance +* progress on translation of example targets: + python demo/bpnn.py (samuele, michael) + python pypy/translator/goal/translate_pypy.py targetrichards.py -* lltype will also need to grow a new primitive type, UnicodeChar. +* (medium) write a tool that discovers which revision of the pypy tree + broke the high level annotator (in that it produced SomeObjects). + Consider distributing the actual annotation to multiple hosts. -* convert each file that does 'from ... import *' to use explicit - imports (e.g. from pypy.rpython import lltype and then use lltype.*) +* (medium) experiment in a branch with using Python 2.4 semantics + and the standard library (lib-python/2.4.1 ...) -* progress on translation of example targets: - python demo/bpnn.py - python pypy/translator/goal/translate_pypy.py targetrichards.py +* (medium) finish objspace/std/longobject.py. +* (hard) try out if genpickle.py can be used to save and load + the high level annotated flowgraphs of PyPy From tismer at codespeak.net Fri Jun 24 16:04:43 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 16:04:43 +0200 (CEST) Subject: [pypy-svn] r13804 - pypy/dist/pypy/rpython Message-ID: <20050624140443.9EAA927B5C@code1.codespeak.net> Author: tismer Date: Fri Jun 24 16:04:42 2005 New Revision: 13804 Modified: pypy/dist/pypy/rpython/rclass.py Log: missing import Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 24 16:04:42 2005 @@ -5,7 +5,7 @@ from pypy.rpython.rmodel import Repr, TyperError, inputconst from pypy.rpython.lltype import ForwardReference, GcForwardReference from pypy.rpython.lltype import Ptr, Struct, GcStruct, malloc -from pypy.rpython.lltype import cast_pointer, castable +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 tismer at codespeak.net Fri Jun 24 16:05:13 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 16:05:13 +0200 (CEST) Subject: [pypy-svn] r13805 - pypy/dist/pypy/translator/goal Message-ID: <20050624140513.D965727B5D@code1.codespeak.net> Author: tismer Date: Fri Jun 24 16:05:12 2005 New Revision: 13805 Modified: pypy/dist/pypy/translator/goal/targetrpystone.py Log: make the import work after reloading Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Fri Jun 24 16:05:12 2005 @@ -1,4 +1,4 @@ -import targetrpystonex +from pypy.translator.goal import targetrpystonex LOOPS = 2000000 From tismer at codespeak.net Fri Jun 24 16:05:50 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 16:05:50 +0200 (CEST) Subject: [pypy-svn] r13806 - pypy/dist/pypy/translator/goal Message-ID: <20050624140550.C231327B60@code1.codespeak.net> Author: tismer Date: Fri Jun 24 16:05:49 2005 New Revision: 13806 Removed: pypy/dist/pypy/translator/goal/targetrpystone2.py Log: this is no longer needed. Deleted: /pypy/dist/pypy/translator/goal/targetrpystone2.py ============================================================================== --- /pypy/dist/pypy/translator/goal/targetrpystone2.py Fri Jun 24 16:05:49 2005 +++ (empty file) @@ -1,15 +0,0 @@ -import targetrpystonex - - -LOOPS = 1000000000 #10**9 - -targetrpystonex.rpystone.setslow(False) - - -# __________ Entry point __________ -# _____ Define and setup target _____ -# _____ Run translated _____ - -(entry_point, - target, - run) = targetrpystonex.make_target_definition(LOOPS, "fast") From arigo at codespeak.net Fri Jun 24 16:05:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 16:05:53 +0200 (CEST) Subject: [pypy-svn] r13807 - pypy/dist/pypy/rpython Message-ID: <20050624140553.28B1F27B74@code1.codespeak.net> Author: arigo Date: Fri Jun 24 16:05:50 2005 New Revision: 13807 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py Log: Fix: make sure that we call setup() on all InstanceRepr, ClassRepr, PBCRepr. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 24 16:05:50 2005 @@ -64,6 +64,7 @@ else: result = ClassRepr(rtyper, classdef) rtyper.class_reprs[classdef] = result + rtyper.reprs_must_call_setup.append(result) return result def getinstancerepr(rtyper, classdef): @@ -76,6 +77,7 @@ else: result = InstanceRepr(rtyper,classdef) rtyper.instance_reprs[classdef] = result + rtyper.reprs_must_call_setup.append(result) return result class MissingRTypeAttribute(TyperError): Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jun 24 16:05:50 2005 @@ -83,6 +83,7 @@ except KeyError: result = MultipleFrozenPBCRepr(rtyper, access) rtyper.pbc_reprs[access] = result + rtyper.reprs_must_call_setup.append(result) return result From tismer at codespeak.net Fri Jun 24 16:07:11 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 16:07:11 +0200 (CEST) Subject: [pypy-svn] r13808 - in pypy/dist/pypy: objspace translator/goal Message-ID: <20050624140711.1CF7227B70@code1.codespeak.net> Author: tismer Date: Fri Jun 24 16:07:09 2005 New Revision: 13808 Removed: pypy/dist/pypy/objspace/dummy.py pypy/dist/pypy/translator/goal/targetpypy0.py Log: stuff no longer needed Deleted: /pypy/dist/pypy/objspace/dummy.py ============================================================================== --- /pypy/dist/pypy/objspace/dummy.py Fri Jun 24 16:07:09 2005 +++ (empty file) @@ -1,146 +0,0 @@ -from pypy.interpreter.baseobjspace import ObjSpace, W_Root, BaseWrappable -from pypy.interpreter.module import Module -from pypy.interpreter.error import OperationError - -from pypy.tool.cache import Cache - -class W_Obj(W_Root): - - def is_true(self): - return True - - def str_w(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - - def int_w(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - - def float_w(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - - def unwrap(self, space): - raise OperationError(space.w_TypeError,space.wrap("!")) - -class W_Str(W_Obj): - def __init__(self, s): - self.s = s - - def is_true(self): - return self.s != "" - - def str_w(self, space): - return self.s - - def unwrap(self, space): - return self.s - -class W_Int(W_Obj): - def __init__(self, i): - self.i = i - - def is_true(self): - return self.i != 0 - - def int_w(self, space): - return self.i - - def unwrap(self, space): - return self.i - -class W_None(W_Obj): - - def unwrap(self, space): - return None - -class W_Special(W_Obj): - def __init__(self, spec): - self.spec = spec - -class BuiltinModule(Module): - def __init__(self, space): - Module.__init__(self, space, space.wrap('__builtin__'), space.wrap({})) - - def pick_builtin(self, w_globals): - return self - -class DummyObjSpace(ObjSpace): - - def __init__(self): - """NOT_RPYTHON""" - self.builtin = BuiltinModule(self) - - self.sys = Module(self, self.wrap('sys'), self.wrap({})) - self.sys.recursionlimit = 1000 - - self.w_None = W_None() - self.w_NotImplemented = W_Special(NotImplemented) - self.w_Ellpisis = W_Special(Ellipsis) - self.w_False = self.wrap(0) - self.w_True = self.wrap(1) - self.w_tuple = W_Special(tuple) - self.w_type = W_Special(type) - self.w_str = W_Special(str) - - for en in ObjSpace.ExceptionTable: - setattr(self, 'w_'+en, self.wrap(en)) - - self._gatewaycache = Cache() - - for n, symbol, arity, ign in ObjSpace.MethodTable+[('newdict',"",1,[]), ('newlist',"",1,[]), - ('newtuple',"",1,[]), ('newslice',"",3,[]), ]: - source = ("""if 1: - def %s(self, %s): - return W_Root() -""" % (n, ', '.join(["w_a%d" % i for i in range(arity)]))) - #print source - exec source - - del n, symbol, arity, ign, i - - def wrap(self, obj): - if obj is None: - return self.w_None - if isinstance(obj, str): - return W_Str(obj) - if isinstance(obj, int): - return W_Int(obj) - return W_Root() - wrap._specialize_ = "argtypes" - - def call_args(self, w_obj, args): - return W_Root() - - def is_true(self, w_obj): - if isinstance(w_obj, W_Obj): - return w_obj.is_true() - return True - - def str_w(self, w_obj): - if not isinstance(w_obj, W_Obj): - w_obj = self.w_None - - return w_obj.str_w(self) - - def int_w(self, w_obj): - if not isinstance(w_obj, W_Obj): - w_obj = self.w_None - - return w_obj.int_w(self) - - def float_w(self, w_obj): - if not isinstance(w_obj, W_Obj): - w_obj = self.w_None - - return w_obj.float_w(self) - - def unwrap(self, w_obj): - if isinstance(w_obj, BaseWrappable): - return w_obj - return w_obj.unwrap() - - def _freeze_(self): - return True - -if __name__ == '__main__': - dummy_space = DummyObjSpace() - print dummy_space.eval("a+b",dummy_space.wrap({'a': 1,'b': 2}),dummy_space.wrap({})) Deleted: /pypy/dist/pypy/translator/goal/targetpypy0.py ============================================================================== --- /pypy/dist/pypy/translator/goal/targetpypy0.py Fri Jun 24 16:07:09 2005 +++ (empty file) @@ -1,33 +0,0 @@ -from pypy.objspace import dummy -from pypy.interpreter.pycode import PyCode - -# __________ Entry point __________ - -def entry_point(code, w_loc): - code2 = PyCode(space) - code2 = code2._from_code(code) - code2.exec_code(space, space.wrap({}), w_loc) - -# _____ Define and setup target _____ - -def target(): - global space - space = dummy.DummyObjSpace() - - from pypy.interpreter import pycode - - pycode.setup_frame_classes() - - from pypy.interpreter import pyopcode - - # cheat - space._gatewaycache.content[pyopcode.app] = space.newdict([]) - - return entry_point,[object, dummy.W_Obj] - -# _____ Run translated _____ - -def run(c_entry_point): - w_result = c_entry_point(compile("a+b","","eval"),dummy.W_Obj()) - print w_result - From ale at codespeak.net Fri Jun 24 16:07:15 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 24 Jun 2005 16:07:15 +0200 (CEST) Subject: [pypy-svn] r13809 - pypy/dist/pypy/lib Message-ID: <20050624140715.1D90E27B80@code1.codespeak.net> Author: ale Date: Fri Jun 24 16:07:14 2005 New Revision: 13809 Removed: pypy/dist/pypy/lib/inprogress__codecs.py pypy/dist/pypy/lib/unicodecodec.py Log: remove non used code Deleted: /pypy/dist/pypy/lib/inprogress__codecs.py ============================================================================== --- /pypy/dist/pypy/lib/inprogress__codecs.py Fri Jun 24 16:07:14 2005 +++ (empty file) @@ -1,407 +0,0 @@ -""" - - _codecs -- Provides access to the codec registry and the builtin - codecs. - - This module should never be imported directly. The standard library - module "codecs" wraps this builtin module for use within Python. - - The codec registry is accessible via: - - register(search_function) -> None - - lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer) - - The builtin Unicode codecs use the following interface: - - _encode(Unicode_object[,errors='strict']) -> - (string object, bytes consumed) - - _decode(char_buffer_obj[,errors='strict']) -> - (Unicode object, bytes consumed) - - _encode() interfaces also accept non-Unicode object as - input. The objects are then converted to Unicode using - PyUnicode_FromObject() prior to applying the conversion. - - These s are available: utf_8, unicode_escape, - raw_unicode_escape, unicode_internal, latin_1, ascii (7-bit), - mbcs (on win32). - - -Written by Marc-Andre Lemburg (mal at lemburg.com). - -Copyright (c) Corporation for National Research Initiatives. - -""" -from unicodecodec import * -#/* --- Registry ----------------------------------------------------------- */ -codec_search_path = [] -codec_search_cache = {} - -def codec_register( search_function ): - """register(search_function) - - Register a codec search function. Search functions are expected to take - one argument, the encoding name in all lower case letters, and return - a tuple of functions (encoder, decoder, stream_reader, stream_writer). - """ - - if callable(search_function): - codec_search_path.append(search_function) - -register = codec_register - -def codec_lookup(encoding): - """lookup(encoding) -> (encoder, decoder, stream_reader, stream_writer) - Looks up a codec tuple in the Python codec registry and returns - a tuple of functions. - """ - - result = codec_search_cache.get(encoding,None) - if not result: - if len(codec_search_path) == 0: - import encodings - if len(codec_search_path) == 0: - raise LookupError("no codec search functions registered: can't find encoding") - if not isinstance(encoding,str): - raise TypeError("Encoding must be a string") - for search in codec_search_path: - result=search(encoding) - if result : - if not( type(result) == tuple and len(result) == 4): - raise TypeError("codec search functions must return 4-tuples") - else: - codec_search_cache[encoding] = result - return result - if not result: - raise LookupError( "unknown encoding: %s" % encoding) - return result - - -lookup = codec_lookup - -def encode(v, encoding='defaultencoding',errors='strict'): - """encode(obj, [encoding[,errors]]) -> object - - Encodes obj using the codec registered for encoding. encoding defaults - to the default encoding. errors may be given to set a different error - handling scheme. Default is 'strict' meaning that encoding errors raise - a ValueError. Other possible values are 'ignore', 'replace' and - 'xmlcharrefreplace' as well as any other name registered with - codecs.register_error that can handle ValueErrors. - """ - if isinstance(encoding,str): - encoder = lookup(encoding)[0] - if encoder and isinstance(errors,str): - res = encoder(v,errors) - return res[0] - else: - raise TypeError("Errors must be a string") - else: - raise TypeError("Encoding must be a string") - -def decode(obj,encoding='defaultencoding',errors='strict'): - """decode(obj, [encoding[,errors]]) -> object - - Decodes obj using the codec registered for encoding. encoding defaults - to the default encoding. errors may be given to set a different error - handling scheme. Default is 'strict' meaning that encoding errors raise - a ValueError. Other possible values are 'ignore' and 'replace' - as well as any other name registerd with codecs.register_error that is - able to handle ValueErrors. - """ - if isinstance(encoding,str): - decoder = lookup(encoding)[1] - if decoder and isinstance(errors,str): - res = decoder(obj,errors) - if not isinstance(res,tuple) or len(res) != 2: - raise TypeError("encoder must return a tuple (object,integer)") - return res[0] - else: - raise TypeError("Errors must be a string") - else: - raise TypeError("Encoding must be a string") - -def latin_1_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeLatin1(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) -# XXX MBCS codec might involve ctypes ? -def mbcs_decode(): - """None - """ - pass - -def readbuffer_encode( obj,errors='strict'): - """None - """ - res = str(obj) - return res,len(res) - -def escape_encode( obj,errors='strict'): - """None - """ - s = repr(obj) - v = s[1:-1] - return v,len(v) - -def utf_8_decode( data,errors='strict',final=None): - """None - """ - res = PyUnicode_DecodeUTF8Stateful(data, len(data), errors, final) - res = u''.join(res) - return res,len(res) - -def raw_unicode_escape_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeRawUnicodeEscape(data, len(data), errors) - res = u''.join(res) - return res,len(res) - -def utf_7_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF7(data,len(data),errors) - res = u''.join(res) - return res,len(res) - -def unicode_escape_encode( obj,errors='strict'): - """None - """ - res = unicodeescape_string(obj,len(obj),0) - res = ''.join(res) - return res, len(res) - -def latin_1_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeLatin1(data,len(data),errors) - res = u''.join(res) - return res, len(res) - -def utf_16_decode( data,errors='strict',final=None): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors) - res = ''.join(res) - return res, len(res) - -def unicode_escape_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUnicodeEscape(data,len(data),errors) - res = ''.join(res) - return res, len(res) - - -def ascii_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeASCII(data,len(data),errors) - res = u''.join(res) - return res, len(res) - -def charmap_encode(obj,errors='strict',mapping='latin-1'): - """None - """ - res = PyUnicode_EncodeCharmap(obj,len(obj),mapping,errors) - res = ''.join(res) - return res, len(res) - -unicode_bytes = (len(hex(sys.maxunicode))-1)/2 - -def unicode_internal_encode( obj,errors='strict'): - """None - """ - if type(obj) == unicode: - p = [] - t = [ord(x) for x in obj] - for i in t: - for j in xrange(unicode_bytes): - p += chr(i%256) - i >>= 8 - res = ''.join(p) - return res, len(res) - else: - res = "You can do better than this" # XXX make this right - return res,len(res) - -def unicode_internal_decode( unistr,errors='strict'): - """None - """ - if type(unistr) == unicode: - return unistr,len(unistr) - else: - p=[] - i=0 - while i < len(unistr)-unicode_bytes+1: - t = 0 - for j in range(unicode_bytes): - t += ord(unistr[i+j])<<(j*8) - i += unicode_bytes - p += unichr(t) - res = u''.join(p) - return res, len(res) - -def utf_16_ex_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'native') - res = ''.join(res) - return res, len(res) -# XXX escape_decode Check if this is right -def escape_decode(data,errors='strict'): - """None - """ - return data,len(data) - -def charbuffer_encode( obj,errors='strict'): - """None - """ - res = str(obj) - res = ''.join(res) - return res, len(res) - -def charmap_decode( data,errors='strict',mapping=None): - """None - """ - res = PyUnicode_DecodeCharmap(data, len(data), mapping, errors) - res = ''.join(res) - return res, len(res) - - -def utf_7_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF7(obj,len(obj),0,0,errors) - res = ''.join(res) - return res, len(res) - -def mbcs_encode( obj,errors='strict'): - """None - """ - pass -## return (PyUnicode_EncodeMBCS( -## (obj), -## len(obj), -## errors), -## len(obj)) - - -def ascii_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeASCII(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) - -def utf_16_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF16(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) - -def raw_unicode_escape_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeRawUnicodeEscape(obj,len(obj)) - res = ''.join(res) - return res, len(res) - -def utf_8_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF8(obj,len(obj),errors) - res = ''.join(res) - return res, len(res) - -def utf_16_le_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF16(obj,len(obj),errors,'little') - res = ''.join(res) - return res, len(res) - -def utf_16_be_encode( obj,errors='strict'): - """None - """ - res = PyUnicode_EncodeUTF16(obj,len(obj),errors,'big') - res = ''.join(res) - return res, len(res) - -def utf_16_le_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'little') - res = ''.join(res) - return res, len(res) - -def utf_16_be_decode( data,errors='strict'): - """None - """ - res = PyUnicode_DecodeUTF16Stateful(data,len(data),errors,'big') - res = ''.join(res) - return res, len(res) - -def strict_errors(exc): - if isinstance(exc,Exception): - raise exc - else: - raise TypeError("codec must pass exception instance") - -def ignore_errors(exc): - if isinstance(exc,(UnicodeEncodeError,UnicodeDecodeError,UnicodeTranslateError)): - return u'',exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%exc) - -Py_UNICODE_REPLACEMENT_CHARACTER = u"\ufffd" - -def replace_errors(exc): - if isinstance(exc,UnicodeEncodeError): - return u'?'*(exc.end-exc.start),exc.end - elif isinstance(exc,(UnicodeTranslateError,UnicodeDecodeError)): - return Py_UNICODE_REPLACEMENT_CHARACTER*(exc.end-exc.start),exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%exc) - -def xmlcharrefreplace_errors(exc): - if isinstance(exc,UnicodeEncodeError): - res = [] - for ch in exc.object[exc.start:exc.end]: - res += '&#' - res += str(ord(ch)) - res += ';' - return u''.join(res),exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) - -def backslashreplace_errors(exc): - if isinstance(exc,UnicodeEncodeError): - p=[] - for c in exc.object[exc.start:exc.end]: - p.append('\\') - oc = ord(c) - if (oc >= 0x00010000): - p.append('U') - p.append("%.8x" % ord(c)) - elif (oc >= 0x100): - p.append('u') - p.append("%.4x" % ord(c)) - else: - p.append('x') - p.append("%.2x" % ord(c)) - return u''.join(p),exc.end - else: - raise TypeError("don't know how to handle %.400s in error callback"%type(exc)) - -register_error("strict",strict_errors) -register_error("ignore",ignore_errors) -register_error("replace",replace_errors) -register_error("xmlcharrefreplace",xmlcharrefreplace_errors) -register_error("backslashreplace",backslashreplace_errors) \ No newline at end of file Deleted: /pypy/dist/pypy/lib/unicodecodec.py ============================================================================== --- /pypy/dist/pypy/lib/unicodecodec.py Fri Jun 24 16:07:14 2005 +++ (empty file) @@ -1,1196 +0,0 @@ -import sys -""" Python implementation of CPythons builtin unicode codecs. - - Generally the functions in this module take a list of characters an returns - a list of characters. - - For use in the PyPy project""" - - -## indicate whether a UTF-7 character is special i.e. cannot be directly -## encoded: -## 0 - not special -## 1 - special -## 2 - whitespace (optional) -## 3 - RFC2152 Set O (optional) - -utf7_special = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, -] -unicode_latin1=[None]*256 - -codec_error_registry = {} -def lookup_error(errors): - """lookup_error(errors) -> handler - - Return the error handler for the specified error handling name - or raise a LookupError, if no handler exists under this name. - """ - - try: - err_handler = codec_error_registry[errors] - except KeyError: - raise LookupError("unknown error handler name %s"%errors) - return err_handler - -def register_error(errors, handler): - """register_error(errors, handler) - - Register the specified error handler under the name - errors. handler must be a callable object, that - will be called with an exception instance containing - information about the location of the encoding/decoding - error and must return a (replacement, new position) tuple. - """ - if callable(handler): - codec_error_registry[errors] = handler - else: - raise TypeError("handler must be callable") - -def SPECIAL(c, encodeO, encodeWS): - c = ord(c) - return (c>127 or utf7_special[c] == 1) or \ - (encodeWS and (utf7_special[(c)] == 2)) or \ - (encodeO and (utf7_special[(c)] == 3)) -def B64(n): - return ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f]) -def B64CHAR(c): - return (c.isalnum() or (c) == '+' or (c) == '/') -def UB64(c): - if (c) == '+' : - return 62 - elif (c) == '/': - return 63 - elif (c) >= 'a': - return ord(c) - 71 - elif (c) >= 'A': - return ord(c) - 65 - else: - return ord(c) + 4 - -def ENCODE( ch, bits) : - charvalue = 0 - out = [] -## for c in ch: -## charvalue <<= 16 -## charvalue += ord(c) - while (bits >= 6): - out += B64(ch >> (bits-6)) - bits -= 6 - return out,bits - - -def PyUnicode_DecodeUTF7(s, size, errors): - - starts = s - errmsg = "" - inShift = 0 - bitsleft = 0 - charsleft = 0 - surrogate = 0 - p = [] - errorHandler = None - exc = None - - if (size == 0): - return unicode('') - i = 0 - while i < size: - - ch = s[i] - if (inShift): - if ((ch == '-') or not B64CHAR(ch)): - inShift = 0 - i += 1 - - while (bitsleft >= 16): - outCh = ((charsleft) >> (bitsleft-16)) & 0xffff - bitsleft -= 16 - - if (surrogate): - ## We have already generated an error for the high surrogate - ## so let's not bother seeing if the low surrogate is correct or not - surrogate = 0 - elif (0xDC00 <= (outCh) and (outCh) <= 0xDFFF): - ## This is a surrogate pair. Unfortunately we can't represent - ## it in a 16-bit character - surrogate = 1 - msg = "code pairs are not supported" - out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i) - p += out - bitsleft = 0 - break - else: - p += unichr(outCh ) - #p += out - if (bitsleft >= 6): -## /* The shift sequence has a partial character in it. If -## bitsleft < 6 then we could just classify it as padding -## but that is not the case here */ - msg = "partial character in shift sequence" - out,x = unicode_call_errorhandler(errors,'utf-7',msg,s,i-1,i) - -## /* According to RFC2152 the remaining bits should be zero. We -## choose to signal an error/insert a replacement character -## here so indicate the potential of a misencoded character. */ - -## /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */ -## if (bitsleft and (charsleft << (sizeof(charsleft) * 8 - bitsleft))): -## raise UnicodeDecodeError, "non-zero padding bits in shift sequence" - if (ch == '-') : - if ((i < size) and (s[i] == '-')) : - p += '-' - inShift = 1 - - elif SPECIAL(ch,0,0) : - raise UnicodeDecodeError,"unexpected special character" - - else: - p += ch - else: - charsleft = (charsleft << 6) | UB64(ch) - bitsleft += 6 - i+=1 -## /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate); - elif ( ch == '+' ): - startinpos = i - i+=1 - if (i 0 - else: - out += chr(ord(ch)) - else: - if (not SPECIAL(ch, encodeSetO, encodeWhiteSpace)): - out += B64((charsleft) << (6-bitsleft)) - charsleft = 0 - bitsleft = 0 -## /* Characters not in the BASE64 set implicitly unshift the sequence -## so no '-' is required, except if the character is itself a '-' */ - if (B64CHAR(ch) or ch == '-'): - out += '-' - inShift = False - out += chr(ord(ch)) - else: - bitsleft += 16 - charsleft = (((charsleft) << 16) | ord(ch)) - p, bitsleft = ENCODE(charsleft, bitsleft) - out += p -## /* If the next character is special then we dont' need to terminate -## the shift sequence. If the next character is not a BASE64 character -## or '-' then the shift sequence will be terminated implicitly and we -## don't have to insert a '-'. */ - - if (bitsleft == 0): - if (i + 1 < size): - ch2 = s[i+1] - - if (SPECIAL(ch2, encodeSetO, encodeWhiteSpace)): - pass - elif (B64CHAR(ch2) or ch2 == '-'): - out += '-' - inShift = False - else: - inShift = False - else: - out += '-' - inShift = False - i+=1 - - if (bitsleft): - out += B64(charsleft << (6-bitsleft) ) - out += '-' - - return out - -unicode_empty=u'' - -##def PyUnicode_Decode(s,size,encoding,errors): -## -## if (encoding == None): -## encoding = PyUnicode_GetDefaultEncoding() -## -#### /* Shortcuts for common default encodings */ -## decoder = encodings.get(encoding,None) -## if decoder: -## return decoder(s,encoding,errors) -#### /* Decode via the codec registry */ -## buf = buffer(s) -## result = PyCodec_Decode(buf, encoding, errors) -## if (not isinstance(result,unicode)): -## raise UnicodeDecodeError, "decoder did not return an unicode object (type=%.400s)"%type(result) -## return result - -def unicodeescape_string(s, size, quotes): - - p = [] - if (quotes) : - p += 'u' - if (s.find('\'')!=-1 and s.find('"')==-1): - p += '"' - else: - p += '\'' - pos = 0 - while (pos < size): - ch = s[pos] - #/* Escape quotes */ - if (quotes and (ch == p[1] or ch == '\\')): - p += '\\' - p += ch - pos += 1 - continue - -#ifdef Py_UNICODE_WIDE - #/* Map 21-bit characters to '\U00xxxxxx' */ - elif (ord(ch) >= 0x10000): - p += '\\' - p += 'U' - p += '%08x'%ord(ch) - pos += 1 - continue -#endif - #/* Map UTF-16 surrogate pairs to Unicode \UXXXXXXXX escapes */ - elif (ord(ch) >= 0xD800 and ord(ch) < 0xDC00): - pos += 1 - ch2 = s[pos] - - if (ord(ch2) >= 0xDC00 and ord(ch2) <= 0xDFFF): - ucs = (((ord(ch) & 0x03FF) << 10) | (ord(ch2) & 0x03FF)) + 0x00010000 - p += '\\' - p += 'U' - p += '%08x'%ucs - pos += 1 - continue - - #/* Fall through: isolated surrogates are copied as-is */ - pos -= 1 - - #/* Map 16-bit characters to '\uxxxx' */ - if (ord(ch) >= 256): - p += '\\' - p += 'u' - p += '%04x'%ord(ch) - - #/* Map special whitespace to '\t', \n', '\r' */ - elif (ch == '\t'): - p += '\\' - p += 't' - - elif (ch == '\n'): - p += '\\' - p += 'n' - - elif (ch == '\r'): - p += '\\' - p += 'r' - - #/* Map non-printable US ASCII to '\xhh' */ - elif (ch < ' ' or ch >= 0x7F) : - p += '\\' - p += 'x' - p += '%02x'%ord(ch) - #/* Copy everything else as-is */ - else: - p += chr(ord(ch)) - pos += 1 - if (quotes): - p += p[1] - return p - -def PyUnicode_DecodeASCII(s, size, errors): - -# /* ASCII is equivalent to the first 128 ordinals in Unicode. */ - if (size == 1 and ord(s) < 128) : - return [unichr(ord(s))] - if (size == 0): - return [u''] #unicode('') - p = [] - pos = 0 - while pos < len(s): - c = s[pos] - if ord(c) < 128: - p += unichr(ord(c)) - pos += 1 - else: - - res = unicode_call_errorhandler( - errors, "ascii", "ordinal not in range(128)", - s, pos, pos+1) - p += [unichr(ord(x)) for x in res[0]] - pos = res[1] - return p - -def PyUnicode_EncodeASCII(p,size,errors): - - return unicode_encode_ucs1(p, size, errors, 128) - -def PyUnicode_AsASCIIString(unistr): - - if not type(unistr) == unicode: - raise TypeError - return PyUnicode_EncodeASCII(unicode(unistr), - len(unicode), - None) - -def PyUnicode_DecodeUTF16Stateful(s,size,errors,byteorder='native',consumed=None): - - bo = 0 #/* assume native ordering by default */ - errmsg = "" - - if sys.byteorder == 'little': - ihi = 1 - ilo = 0 - else: - ihi = 0 - ilo = 1 - - if (size == 0): - return [u''] - - #/* Unpack UTF-16 encoded data */ - -## /* Check for BOM marks (U+FEFF) in the input and adjust current -## byte order setting accordingly. In native mode, the leading BOM -## mark is skipped, in all other modes, it is copied to the output -## stream as-is (giving a ZWNBSP character). */ - q = 0 - p = [] - if byteorder == 'native': - if (size >= 2): - bom = (ord(s[ihi]) << 8) | ord(s[ilo]) -#ifdef BYTEORDER_IS_LITTLE_ENDIAN - if sys.byteorder == 'little': - if (bom == 0xFEFF): - q += 2 - bo = -1 - elif bom == 0xFFFE: - q += 2 - bo = 1 - else: - if bom == 0xFEFF: - q += 2 - bo = 1 - elif bom == 0xFFFE: - q += 2 - bo = -1 - elif byteorder == 'little': - bo = -1 - else: - bo = 1 - - if (bo == -1): - #/* force LE */ - ihi = 1 - ilo = 0 - - elif (bo == 1): - #/* force BE */ - ihi = 0 - ilo = 1 - - while (q < len(s)): - - #/* remaining bytes at the end? (size should be even) */ - if (len(s)-q<2): - if (consumed): - break - errmsg = "truncated data" - startinpos = q - endinpos = len(s) - unicode_call_errorhandler() -## /* The remaining input chars are ignored if the callback -## chooses to skip the input */ - - ch = (ord(s[q+ihi]) << 8) | ord(s[q+ilo]) - q += 2 - - if (ch < 0xD800 or ch > 0xDFFF): - p += unichr(ch) - continue - - #/* UTF-16 code pair: */ - if (q >= len(s)): - errmsg = "unexpected end of data" - startinpos = q-2 - endinpos = len(s) - unicode_call_errorhandler - - if (0xD800 <= ch and ch <= 0xDBFF): - ch2 = (ord(s[q+ihi]) << 8) | ord(s[q+ilo]) - q += 2 - if (0xDC00 <= ch2 and ch2 <= 0xDFFF): - #ifndef Py_UNICODE_WIDE - if sys.maxunicode < 65536: - p += unichr(ch) - p += unichr(ch2) - else: - p += unichr((((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000) - #endif - continue - - else: - errmsg = "illegal UTF-16 surrogate" - startinpos = q-4 - endinpos = startinpos+2 - unicode_call_errorhandler - - errmsg = "illegal encoding" - startinpos = q-2 - endinpos = startinpos+2 - unicode_call_errorhandler - - return p - -def PyUnicode_EncodeUTF16(s,size,errors,byteorder='little'): - -# /* Offsets from p for storing byte pairs in the right order. */ - - def STORECHAR(CH,byteorder): - hi = chr(((CH) >> 8) & 0xff) - lo = chr((CH) & 0xff) - if byteorder == 'little': - return [lo,hi] - else: - return [hi,lo] - - p = [] - bom = sys.byteorder - if (byteorder == 'native'): - - bom = sys.byteorder - p += STORECHAR(0xFEFF,bom) - - if (size == 0): - return "" - - if (byteorder == 'little' ): - bom = 'little' - elif (byteorder == 'big'): - bom = 'big' - - - for c in s: - ch = ord(c) - ch2 = 0 - if (ch >= 0x10000) : - ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF) - ch = 0xD800 | ((ch-0x10000) >> 10) - - p += STORECHAR(ch,bom) - if (ch2): - p +=STORECHAR(ch2,bom) - - return p - - -def PyUnicode_DecodeMBCS(s, size, errors): - pass - -def PyUnicode_EncodeMBCS(p, size, errors): - pass -#### /* If there are no characters, bail now! */ -## if (size==0) -## return "" -## from ctypes import * -## WideCharToMultiByte = windll.kernel32.WideCharToMultiByte -#### /* First get the size of the result */ -## mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, s, 0, None, None); -## if (mbcssize==0) -## raise UnicodeEncodeError, "Windows cannot decode the string %s" %p -### More error handling required (check windows errors and such) -## -### /* Do the conversion */ -#### s = ' '*mbcssize -#### if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)): -#### raise UnicodeEncodeError, "Windows cannot decode the string %s" %p -## return s -def unicode_call_errorhandler(errors, encoding, - reason, input, startinpos, endinpos,decode=True): - - errorHandler = lookup_error(errors) - if decode: - exceptionObject = UnicodeDecodeError(encoding, input, startinpos, endinpos, reason) - else: - exceptionObject = UnicodeEncodeError(encoding, input, startinpos, endinpos, reason) - res = errorHandler(exceptionObject) - if isinstance(res,tuple) and isinstance(res[0],unicode) and isinstance(res[1],int): - newpos = res[1] - if (newpos<0): - newpos = len(input)+newpos - if newpos<0 or newpos>len(input): - raise IndexError( "position %d from error handler out of bounds" % newpos) - return res[0],newpos - else: - raise TypeError("encoding error handler must return (unicode, int) tuple") - -def PyUnicode_DecodeUTF8(s, size, errors): - - return PyUnicode_DecodeUTF8Stateful(s, size, errors, None) - -## /* Map UTF-8 encoded prefix byte to sequence length. zero means -## illegal prefix. see RFC 2279 for details */ -utf8_code_length = [ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0 -] - -def PyUnicode_DecodeUTF8Stateful(s,size,errors,consumed): - - if (size == 0): - if (consumed): - consumed = 0 - return u'' - - p = [] - pos = 0 - while pos < size: - ch = s[pos] - if ord(ch) < 0x80: - p += ch - pos += 1 - continue - - n = utf8_code_length[ord(ch)] - startinpos = pos - if (startinpos + n > size): - if (consumed): - break - else: - errmsg = "unexpected end of data" - endinpos = size - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - if n == 0: - errmsg = "unexpected code byte" - endinpos = startinpos+1 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - elif n == 1: - errmsg = "internal error" - endinpos = startinpos+1 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - elif n == 2: - if ((ord(s[pos+1]) & 0xc0) != 0x80): - errmsg = "invalid data" - endinpos = startinpos+2 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - c = ((ord(s[pos]) & 0x1f) << 6) + (ord(s[pos+1]) & 0x3f) - if c<0x80: - errmsg = "illegal encoding" - endinpos = startinpos+2 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - p += unichr(c) - pos += n - #break - elif n == 3: - if ((ord(s[pos+1]) & 0xc0) != 0x80 or - (ord(s[pos+2]) & 0xc0) != 0x80): - errmsg = "invalid data" - endinpos = startinpos+3 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - c = ((ord(s[pos]) & 0x0f) << 12) + \ - ((ord(s[pos+1]) & 0x3f) << 6) +\ - (ord(s[pos+2]) & 0x3f) - -## /* Note: UTF-8 encodings of surrogates are considered -## legal UTF-8 sequences; -## -## XXX For wide builds (UCS-4) we should probably try -## to recombine the surrogates into a single code -## unit. -## */ - if c < 0x0800: - errmsg = "illegal encoding" - endinpos = startinpos+3 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - p += unichr(c) - pos += n - elif n == 4: -## case 4: - if ((ord(s[pos+1]) & 0xc0) != 0x80 or - (ord(s[pos+2]) & 0xc0) != 0x80 or - (ord(s[pos+3]) & 0xc0) != 0x80): - - errmsg = "invalid data" - startinpos = pos - endinpos = startinpos+4 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: - c = ((ord(s[pos+0]) & 0x7) << 18) + ((ord(s[pos+1]) & 0x3f) << 12) +\ - ((ord(s[pos+2]) & 0x3f) << 6) + (ord(s[pos+3]) & 0x3f) - #/* validate and convert to UTF-16 */ - if ((c < 0x10000) or (c > 0x10ffff)): - #/* minimum value allowed for 4 byte encoding */ - #/* maximum value allowed for UTF-16 */ - - errmsg = "illegal encoding" - startinpos = pos - endinpos = startinpos+4 - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - else: -#ifdef Py_UNICODE_WIDE - if c> 10)) - #/* low surrogate = bottom 10 bits added to DC00 */ - p += unichr(0xDC00 + (c & 0x03FF)) - pos += n - else: -## default: -## /* Other sizes are only needed for UCS-4 */ - errmsg = "unsupported Unicode code range" - startinpos = pos - endinpos = startinpos+n - res = unicode_call_errorhandler( - errors, "utf8", errmsg, - s, startinpos, endinpos) - p += res[0] - pos = res[1] - - #continue - - if (consumed): - consumed = pos - return p - -def PyUnicode_EncodeUTF8(s,size,errors): - - #assert(s != None) - assert(size >= 0) - p = [] - i = 0 - while i> 6))) - p += chr((0x80 | (ord(ch) & 0x3f))) - else: -## /* Encode UCS2 Unicode ordinals */ - if (ord(ch) < 0x10000): -## /* Special case: check for high surrogate */ - if (0xD800 <=ord(ch) and ord(ch) <= 0xDBFF and i != size) : - ch2 = s[i] -## /* Check for low surrogate and combine the two to -## form a UCS4 value */ - if (0xDC00 <= ord(ch2) and ord(ch2) <= 0xDFFF) : - ch3 = ((ord(ch) - 0xD800) << 10 | (ord(ch2) - 0xDC00)) + 0x10000 - i+=1 - p.extend(encodeUCS4(ch3)) - continue -## /* Fall through: handles isolated high surrogates */ - p += (chr((0xe0 | (ord(ch) >> 12)))) - p += (chr((0x80 | ((ord(ch) >> 6) & 0x3f)))) - p += (chr((0x80 | (ord(ch) & 0x3f)))) - continue - return p - -def encodeUCS4(ch): -## /* Encode UCS4 Unicode ordinals */ - p=[] - p += (chr((0xf0 | (ch >> 18)))) - p += (chr((0x80 | ((ch >> 12) & 0x3f)))) - p += (chr((0x80 | ((ch >> 6) & 0x3f)))) - p += (chr((0x80 | (ch & 0x3f)))) - return p - -#/* --- Latin-1 Codec ------------------------------------------------------ */ - -def PyUnicode_DecodeLatin1(s, size, errors): - #/* Latin-1 is equivalent to the first 256 ordinals in Unicode. */ -## if (size == 1): -## return [PyUnicode_FromUnicode(s, 1)] - pos = 0 - p = [] - while (pos < size): - p += unichr(ord(s[pos])) - pos += 1 - return p - -def unicode_encode_ucs1(p,size,errors,limit): - - if limit == 256: - reason = "ordinal not in range(256)" - encoding = "latin-1" - else: - reason = "ordinal not in range(128)" - encoding = "ascii" - - if (size == 0): - return [''] - res = [] - pos=0 - while pos < len(p): - #for ch in p: - ch = p[pos] - - if ord(ch) < limit: - res += chr(ord(ch)) - pos += 1 - else: - #/* startpos for collecting unencodable chars */ - collstart = pos - collend = pos+1 - while collend < len(p) and ord(p[collend]) >= limit: - collend += 1 - x = unicode_call_errorhandler(errors,encoding,reason,p,collstart,collend,False) - res += str(x[0]) - pos = x[1] - - return res - -def PyUnicode_EncodeLatin1(p,size,errors): - res=unicode_encode_ucs1(p, size, errors, 256) - return res - -hexdigits = [hex(i)[-1] for i in range(16)]+[hex(i)[-1].upper() for i in range(10,16)] -def hexescape(s,pos,digits,message,errors): - chr = 0 - p = [] - if (pos+digits>len(s)): - message = "end of string in escape sequence" - x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2,len(s)) - p += x[0] - pos = x[1] - else: - try: - chr = int(s[pos:pos+digits],16) - except ValueError: - endinpos = pos - while s[endinpos] in hexdigits: - endinpos +=1 - x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2, - endinpos+1) - p += x[0] - pos = x[1] - #/* when we get here, chr is a 32-bit unicode character */ - else: - if chr <= sys.maxunicode: - p += [unichr(chr)] - pos += digits - - elif (chr <= 0x10ffff): - chr -= 0x10000L - p += unichr(0xD800 + (chr >> 10)) - p += unichr(0xDC00 + (chr & 0x03FF)) - pos += digits - else: - message = "illegal Unicode character" - x = unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-2, - pos+1) - p += x[0] - pos = x[1] - res = p - return res,pos - -def PyUnicode_DecodeUnicodeEscape(s, size, errors): - - if (size == 0): - return u'' - - p = [] - pos = 0 - while (pos < size): -## /* Non-escape characters are interpreted as Unicode ordinals */ - if (s[pos] != '\\') : - p += s[pos] - pos += 1 - continue -## /* \ - Escapes */ - else: - pos +=1 - if pos>=len(s): - errmessage = "\\ at end of string" - unicode_call_errorhandler(errors,"unicodeescape",errmessage,s,pos-1,size) - ch = s[pos] - pos += 1 - ## /* \x escapes */ - #if ch == '\n': break; - if ch == '\\': p += '\\' - elif ch == '\'': p += '\'' - elif ch == '\"': p += '\"' - elif ch == 'b': p += '\b' - elif ch == 'f': p += '\014' #/* FF */ - elif ch == 't': p += '\t' - elif ch == 'n': p += '\n' - elif ch == 'r': - p += '\r' - - elif ch == 'v': p += '\013' #break; /* VT */ - elif ch == 'a': p += '\007' # break; /* BEL, not classic C */ - - ## /* \OOO (octal) escapes */ - elif ch in [ '0','1', '2', '3','4', '5', '6','7']: - x = ord(ch) - ord('0') - ch = s[pos] - if ('0' <= ch and ch <= '7'): - x = (x<<3) + ord(ch) - ord('0') - ch = s[pos+1] - if ('0' <= ch and ch <= '7'): - x = (x<<3) + ord(ch) - ord('0') - pos += 2 - - p += unichr(x) - ## /* hex escapes */ - ## /* \xXX */ - elif ch == 'x': - digits = 2 - message = "truncated \\xXX escape" - x = hexescape(s,pos,digits,message,errors) - p += x[0] - pos = x[1] - - # /* \uXXXX */ - elif ch == 'u': - digits = 4 - message = "truncated \\uXXXX escape" - x = hexescape(s,pos,digits,message,errors) - p += x[0] - pos = x[1] - - # /* \UXXXXXXXX */ - elif ch == 'U': - digits = 8 - message = "truncated \\UXXXXXXXX escape" - x = hexescape(s,pos,digits,message,errors) - p += x[0] - pos = x[1] -## /* \N{name} */ - elif ch == 'N': - message = "malformed \\N character escape" - #pos += 1 - try: - import unicodedata - except ImportError: - message = "\\N escapes not supported (can't load unicodedata module)" - unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,size) - if (s[pos] == '{'): - look = pos+1 - #/* look for the closing brace */ - while (s[look] != '}' and look < size): - look += 1 - if (look > pos+1 and look < size and s[look] == '}'): - #/* found a name. look it up in the unicode database */ - message = "unknown Unicode character name" - look += 1 - try: - chr = unicodedata.lookup(s[pos:look]) - #x = hexescape(chr,pos+1,8,message,errors) - except KeyError: - x=unicode_call_errorhandler(errors,"unicodeescape",message,s,pos-1,look) - else: - x = hexescape(s,pos+1,look-pos,message,errors) - p += x[0] - pos = x[1] - else: - if (pos > size): - message = "\\ at end of string" - handler = lookup_error(errors) - x = handler(UnicodeDecodeError("unicodeescape",s,pos, - size,message)) - p += x[0] - pos = x[1] - else: - p += '\\' - p += s[pos] - return p - -def PyUnicode_EncodeRawUnicodeEscape(s,size): - - if (size == 0): - return '' - - p = [] - for ch in s: -# /* Map 32-bit characters to '\Uxxxxxxxx' */ - if (ord(ch) >= 0x10000): - p += '\\' - p += 'U' - p += '%08x'%(ord(ch)) - elif (ord(ch) >= 256) : -# /* Map 16-bit characters to '\uxxxx' */ - p += '\\' - p += 'u' - p += '%04x'%(ord(ch)) -# /* Copy everything else as-is */ - else: - p += chr(ord(ch)) - - #p += '\0' - return p - -def charmapencode_output(c,mapping): - - - rep = mapping[c] - if isinstance(rep,(int,long)): - if rep<256: - return chr(rep) - else: - raise TypeError("character mapping must be in range(256)") - elif isinstance(rep,str): - return rep - elif rep == None: - raise KeyError("character maps to ") - else: - raise TypeError("character mapping must return integer, None or str") - -def PyUnicode_EncodeCharmap(p,size,mapping='latin-1',errors='strict'): - -## /* the following variable is used for caching string comparisons -## * -1=not initialized, 0=unknown, 1=strict, 2=replace, -## * 3=ignore, 4=xmlcharrefreplace */ - -# /* Default to Latin-1 */ - if mapping == 'latin-1': - return PyUnicode_EncodeLatin1(p, size, errors) - if (size == 0): - return '' - inpos = 0 - res = [] - while (inpos",p,inpos,inpos+1,False) - try: - res += [charmapencode_output(ord(y),mapping) for y in x[0]] - except KeyError: - raise UnicodeEncodeError("charmap",p,inpos,inpos+1, - "character maps to ") -## except TypeError,err: -## x = unicode_call_errorhandler(errors,"charmap", -## err,p,inpos,inpos+1,False) -## try: -## res += [charmapencode_output(ord(y),mapping) for y in x[0]] -## except KeyError: -## raise UnicodeEncodeError("charmap",p,inpos,inpos+1, -## "character maps to ") -## - #/* done with this character => adjust input position */ - inpos+=1 - return res - -def PyUnicode_DecodeCharmap(s, size, mapping, errors): - -## /* Default to Latin-1 */ - if (mapping == None): - return PyUnicode_DecodeLatin1(s, size, errors) - - if (size == 0): - return u'' - p = [] - inpos = 0 - while (inpos< len(s)): - - #/* Get mapping (char ordinal -> integer, Unicode char or None) */ - ch = s[inpos] - try: - x = mapping[ord(ch)] - if isinstance(x,int): - if x<65536: - p += unichr(x) - else: - raise TypeError("character mapping must be in range(65536)") - elif isinstance(x,unicode): - p += x - elif not x: - raise KeyError - else: - raise TypeError - except KeyError: - x = unicode_call_errorhandler(errors,"charmap", - "character maps to ",s,inpos,inpos+1) - p += x[0] -## except TypeError: -## x = unicode_call_errorhandler(errors,"charmap", -## "character mapping must return integer, None or unicode", -## s,inpos,inpos+1) -## p += x[0] - inpos +=1 - return p - -def PyUnicode_DecodeRawUnicodeEscape(s, size,errors): - - if (size == 0): - return u'' - pos = 0 - p = [] - while (pos < len(s)): - ch = s[pos] - #/* Non-escape characters are interpreted as Unicode ordinals */ - if (ch != '\\'): - p += unichr(ord(ch)) - pos += 1 - continue - startinpos = pos - #pos += 1 -## /* \u-escapes are only interpreted iff the number of leading -## backslashes is odd */ - bs = pos - while pos < size: - if (s[pos] != '\\'): - break - p += unichr(ord(s[pos])) - pos += 1 - - if (((pos - bs) & 1) == 0 or - pos >= size or - (s[pos] != 'u' and s[pos] != 'U')) : - p += s[pos] - pos += 1 - continue - - p.pop(-1) - if s[pos] == 'u': - count = 4 - else: - count = 8 - pos += 1 - - #/* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */ - - i = 0 - x = 0 - try: - x = int(s[pos:pos+count],16) - except ValueError: - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "truncated \\uXXXX", - s, size, pos, pos+count) - p += res[0] - pos = res[1] - else: - #ifndef Py_UNICODE_WIDE - if sys.maxunicode > 0xffff: - if (x > 0x10000): - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", - s, size, pos, pos+1) - pos = i = res[1] - p += res[0] - i += 1 - else: - if (x > 0x10000): - res = unicode_call_errorhandler( - errors, "rawunicodeescape", "\\Uxxxxxxxx out of range", - s, size, pos, pos+1) - pos = i = res[1] - p += res[0] - - #endif - else: - p += unichr(x) - pos += count - - return p \ No newline at end of file From hpk at codespeak.net Fri Jun 24 16:14:31 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 16:14:31 +0200 (CEST) Subject: [pypy-svn] r13810 - in pypy/dist/pypy: documentation documentation/tool documentation/website module module/_codecs module/recparser tool translator translator/llvm translator/llvm2 translator/pickle translator/pickle/attic translator/test Message-ID: <20050624141431.3B21E27B88@code1.codespeak.net> Author: hpk Date: Fri Jun 24 16:14:24 2005 New Revision: 13810 Modified: pypy/dist/pypy/documentation/contributor.txt (props changed) pypy/dist/pypy/documentation/faq.txt (props changed) pypy/dist/pypy/documentation/tool/makecontributor.py (props changed) pypy/dist/pypy/documentation/website/EP2005-announcement.txt (props changed) pypy/dist/pypy/module/README.txt (props changed) pypy/dist/pypy/module/_codecs/ (props changed) pypy/dist/pypy/module/recparser/tuplebuilder.py (props changed) pypy/dist/pypy/tool/import_graph.py (props changed) pypy/dist/pypy/tool/traceconfig.py (props changed) pypy/dist/pypy/translator/backendoptimization.py (props changed) pypy/dist/pypy/translator/llvm/pointerrepr.py (props changed) pypy/dist/pypy/translator/llvm/reprmap.py (props changed) pypy/dist/pypy/translator/llvm2/cfgtransform.py (props changed) pypy/dist/pypy/translator/llvm2/structnode.py (props changed) pypy/dist/pypy/translator/pickle/__init__.py (props changed) pypy/dist/pypy/translator/pickle/attic/ (props changed) pypy/dist/pypy/translator/test/test_backends.py (props changed) Log: fixeol From tismer at codespeak.net Fri Jun 24 16:17:07 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 16:17:07 +0200 (CEST) Subject: [pypy-svn] r13811 - pypy/dist/pypy/rpython/test Message-ID: <20050624141707.A9BEE27B88@code1.codespeak.net> Author: tismer Date: Fri Jun 24 16:17:06 2005 New Revision: 13811 Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py (contents, props changed) Log: fixeol 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 Fri Jun 24 16:17:06 2005 @@ -1,21 +1,21 @@ -from pypy.rpython.test.test_llinterp import interpret - -def test_rbuiltin_list(): - def f(): - l=list((1,2,3)) - return l == [1,2,3] - def g(): - l=list(('he','llo')) - return l == ['he','llo'] - def r(): - l = ['he','llo'] - l1=list(l) - return l == l1 and l is not l1 - result = interpret(f,[]) - assert result - - result = interpret(g,[]) - assert result - - result = interpret(r,[]) +from pypy.rpython.test.test_llinterp import interpret + +def test_rbuiltin_list(): + def f(): + l=list((1,2,3)) + return l == [1,2,3] + def g(): + l=list(('he','llo')) + return l == ['he','llo'] + def r(): + l = ['he','llo'] + l1=list(l) + return l == l1 and l is not l1 + result = interpret(f,[]) + assert result + + result = interpret(g,[]) + assert result + + result = interpret(r,[]) assert result \ No newline at end of file From tismer at codespeak.net Fri Jun 24 16:52:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 16:52:20 +0200 (CEST) Subject: [pypy-svn] r13812 - in pypy/dist/pypy/translator: goal test Message-ID: <20050624145220.8AC7727B4B@code1.codespeak.net> Author: tismer Date: Fri Jun 24 16:52:19 2005 New Revision: 13812 Modified: pypy/dist/pypy/translator/goal/targetrpystone.py pypy/dist/pypy/translator/test/rpystone.py Log: clean-up of rpystone2 crap which is no longer needed Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Fri Jun 24 16:52:19 2005 @@ -2,8 +2,6 @@ LOOPS = 2000000 -# targetrpystonex.rpystone.setslow(False) - # __________ Entry point __________ # _____ Define and setup target _____ Modified: pypy/dist/pypy/translator/test/rpystone.py ============================================================================== --- pypy/dist/pypy/translator/test/rpystone.py (original) +++ pypy/dist/pypy/translator/test/rpystone.py Fri Jun 24 16:52:19 2005 @@ -1,21 +1,5 @@ #! /usr/bin/env python -def setslow(X): - global XF1, XF2, XF3, XP1, XP2, XP3, XP4, XP5, XP6, XP7, XP8 - XF1 = True - XF2 = X - XF3 = True - XP1 = X - XP2 = X - XP3 = True - XP4 = X - XP5 = True - XP6 = True - XP7 = True - XP8 = X - -setslow(True) - """ "PYSTONE" Benchmark Program @@ -137,28 +121,28 @@ # XXX xrange support? i = 0 while i < loops: - if XP5:Proc5() - if XP4:Proc4() + Proc5() + Proc4() IntLoc1 = 2 IntLoc2 = 3 String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING" EnumLoc = Ident2 - if XF2:g.BoolGlob = not Func2(String1Loc, String2Loc) + g.BoolGlob = not Func2(String1Loc, String2Loc) while IntLoc1 < IntLoc2: IntLoc3 = 5 * IntLoc1 - IntLoc2 IntLoc3 = Proc7(IntLoc1, IntLoc2) IntLoc1 = IntLoc1 + 1 - if XP8:Proc8(g.Array1Glob, g.Array2Glob, IntLoc1, IntLoc3) - if XP1:g.PtrGlb = Proc1(g.PtrGlb) + Proc8(g.Array1Glob, g.Array2Glob, IntLoc1, IntLoc3) + g.PtrGlb = Proc1(g.PtrGlb) CharIndex = 'A' while CharIndex <= g.Char2Glob: - if XF1 and EnumLoc == Func1(CharIndex, 'C'): - if XP6:EnumLoc = Proc6(Ident1) + if EnumLoc == Func1(CharIndex, 'C'): + EnumLoc = Proc6(Ident1) CharIndex = chr(ord(CharIndex)+1) IntLoc3 = IntLoc2 * IntLoc1 IntLoc2 = IntLoc3 / IntLoc1 IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 - if XP2:IntLoc1 = Proc2(IntLoc1) + IntLoc1 = Proc2(IntLoc1) i += 1 benchtime = clock() - starttime - nulltime @@ -169,12 +153,12 @@ PtrParIn.IntComp = 5 NextRecord.IntComp = PtrParIn.IntComp NextRecord.PtrComp = PtrParIn.PtrComp - if XP3:NextRecord.PtrComp = Proc3(NextRecord.PtrComp) + NextRecord.PtrComp = Proc3(NextRecord.PtrComp) if NextRecord.Discr == Ident1: NextRecord.IntComp = 6 - if XP6:NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) + NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) NextRecord.PtrComp = g.PtrGlb.PtrComp - if XP7:NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) + NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) else: PtrParIn = NextRecord.copy() NextRecord.PtrComp = None @@ -199,7 +183,7 @@ PtrParOut = g.PtrGlb.PtrComp else: g.IntGlob = 100 - if XP7:g.PtrGlb.IntComp = Proc7(10, g.IntGlob) + g.PtrGlb.IntComp = Proc7(10, g.IntGlob) return PtrParOut def Proc4(): @@ -218,7 +202,7 @@ def Proc6(EnumParIn): EnumParOut = EnumParIn - if XF3 and not Func3(EnumParIn): + if not Func3(EnumParIn): EnumParOut = Ident4 if EnumParIn == Ident1: EnumParOut = Ident1 @@ -264,7 +248,7 @@ def Func2(StrParI1, StrParI2): IntLoc = 1 while IntLoc <= 1: - if XF1 and Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: + if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: CharLoc = 'A' IntLoc = IntLoc + 1 if CharLoc >= 'W' and CharLoc <= 'Z': From hpk at codespeak.net Fri Jun 24 16:54:41 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 16:54:41 +0200 (CEST) Subject: [pypy-svn] r13813 - in pypy/dist/pypy: interpreter objspace/std Message-ID: <20050624145441.1476F27B7A@code1.codespeak.net> Author: hpk Date: Fri Jun 24 16:54:39 2005 New Revision: 13813 Modified: pypy/dist/pypy/interpreter/pycode.py pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/objspace/std/objspace.py Log: (arigo, hpk) - remove usage of dictionaries with (bool,bool) keys and keys with integers 0,1,2,3 - remove some unused dictionaries (!) Modified: pypy/dist/pypy/interpreter/pycode.py ============================================================================== --- pypy/dist/pypy/interpreter/pycode.py (original) +++ pypy/dist/pypy/interpreter/pycode.py Fri Jun 24 16:54:39 2005 @@ -48,7 +48,7 @@ NESTED = 1 GENERATOR = 2 -frame_classes = {} +frame_classes = [] def setup_frame_classes(): "NOT_RPYTHON" @@ -66,6 +66,7 @@ dic[n] = func_with_new_name(x, x.__name__) return dic + frame_classes.extend([None]*4) frame_classes[0] = PyInterpFrame frame_classes[NESTED] = PyNestedScopeFrame frame_classes[GENERATOR] = type('PyGeneratorFrame', Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri Jun 24 16:54:39 2005 @@ -597,20 +597,23 @@ assert isinstance(b, KeyContainer) return CustomCompareSort.lt(self, a.w_key, b.w_key) -SortClass = { - (False, False): SimpleSort, - (True, False): CustomCompareSort, - (False, True) : CustomKeySort, - (True, True) : CustomKeyCompareSort, - } - def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse): has_cmp = not space.is_w(w_cmp, space.w_None) has_key = not space.is_w(w_keyfunc, space.w_None) has_reverse = space.is_true(w_reverse) # create and setup a TimSort instance - sorterclass = SortClass[has_cmp, has_key] + if has_cmp: + if has_key: + sorterclass = CustomKeyCompareSort + else: + sorterclass = CustomCompareSort + else: + if has_key: + sorterclass = CustomKeySort + else: + sorterclass = SimpleSort + sorter = sorterclass(w_list.ob_item, w_list.ob_size) sorter.space = space sorter.w_cmp = w_cmp Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Fri Jun 24 16:54:39 2005 @@ -136,7 +136,6 @@ specialnames = [operatorsymbol] self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__'] self.extras = extras - self.unbound_versions = {} # transform '+' => 'add' etc. for line in ObjSpace.MethodTable: realname, symbolname = line[:2] Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri Jun 24 16:54:39 2005 @@ -66,7 +66,6 @@ self.w_Ellipsis = self.wrap(Ellipsis(self)) # types - self.types_w = {} for typedef in self.model.pythontypes: w_type = self.gettypeobject(typedef) setattr(self, 'w_' + typedef.name, w_type) @@ -180,7 +179,7 @@ return ec def gettypeobject(self, typedef): - # types_w maps each StdTypeDef instance to its + # stdtypedef.TypeCache maps each StdTypeDef instance to its # unique-for-this-space W_TypeObject instance return self.fromcache(stdtypedef.TypeCache).getorbuild(typedef) From arigo at codespeak.net Fri Jun 24 16:55:55 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 16:55:55 +0200 (CEST) Subject: [pypy-svn] r13814 - in pypy/branch/pypy-translation-snapshot: interpreter objspace/std Message-ID: <20050624145555.8FFB727B7A@code1.codespeak.net> Author: arigo Date: Fri Jun 24 16:55:54 2005 New Revision: 13814 Modified: pypy/branch/pypy-translation-snapshot/interpreter/pycode.py pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py pypy/branch/pypy-translation-snapshot/objspace/std/model.py pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Log: Merge of rev 13813 into the pypy-translation-snapshot. Modified: pypy/branch/pypy-translation-snapshot/interpreter/pycode.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/pycode.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/pycode.py Fri Jun 24 16:55:54 2005 @@ -48,7 +48,7 @@ NESTED = 1 GENERATOR = 2 -frame_classes = {} +frame_classes = [] def setup_frame_classes(): "NOT_RPYTHON" @@ -66,6 +66,7 @@ dic[n] = func_with_new_name(x, x.__name__) return dic + frame_classes.extend([None]*4) frame_classes[0] = PyInterpFrame frame_classes[NESTED] = PyNestedScopeFrame frame_classes[GENERATOR] = type('PyGeneratorFrame', Modified: pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/listobject.py Fri Jun 24 16:55:54 2005 @@ -597,20 +597,23 @@ assert isinstance(b, KeyContainer) return CustomCompareSort.lt(self, a.w_key, b.w_key) -SortClass = { - (False, False): SimpleSort, - (True, False): CustomCompareSort, - (False, True) : CustomKeySort, - (True, True) : CustomKeyCompareSort, - } - def list_sort__List_ANY_ANY_ANY(space, w_list, w_cmp, w_keyfunc, w_reverse): has_cmp = not space.is_w(w_cmp, space.w_None) has_key = not space.is_w(w_keyfunc, space.w_None) has_reverse = space.is_true(w_reverse) # create and setup a TimSort instance - sorterclass = SortClass[has_cmp, has_key] + if has_cmp: + if has_key: + sorterclass = CustomKeyCompareSort + else: + sorterclass = CustomCompareSort + else: + if has_key: + sorterclass = CustomKeySort + else: + sorterclass = SimpleSort + sorter = sorterclass(w_list.ob_item, w_list.ob_size) sorter.space = space sorter.w_cmp = w_cmp Modified: pypy/branch/pypy-translation-snapshot/objspace/std/model.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/model.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/model.py Fri Jun 24 16:55:54 2005 @@ -136,7 +136,6 @@ specialnames = [operatorsymbol] self.specialnames = specialnames # e.g. ['__xxx__', '__rxxx__'] self.extras = extras - self.unbound_versions = {} # transform '+' => 'add' etc. for line in ObjSpace.MethodTable: realname, symbolname = line[:2] Modified: pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/objspace.py Fri Jun 24 16:55:54 2005 @@ -66,7 +66,6 @@ self.w_Ellipsis = self.wrap(Ellipsis(self)) # types - self.types_w = {} for typedef in self.model.pythontypes: w_type = self.gettypeobject(typedef) setattr(self, 'w_' + typedef.name, w_type) @@ -180,7 +179,7 @@ return ec def gettypeobject(self, typedef): - # types_w maps each StdTypeDef instance to its + # stdtypedef.TypeCache maps each StdTypeDef instance to its # unique-for-this-space W_TypeObject instance return self.fromcache(stdtypedef.TypeCache).getorbuild(typedef) From mwh at codespeak.net Fri Jun 24 17:08:01 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 17:08:01 +0200 (CEST) Subject: [pypy-svn] r13815 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624150801.53A2827B7A@code1.codespeak.net> Author: mwh Date: Fri Jun 24 17:07:59 2005 New Revision: 13815 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: simple str(instance) %-formatting to come. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri Jun 24 17:07:59 2005 @@ -491,6 +491,23 @@ vinst, vattr, vvalue = hop.inputargs(self, Void, r_value) self.setfield(vinst, attr, vvalue, hop.llops) + def rtype_str(self, hop): + v_arg = hop.inputarg(getinstancerepr(hop.rtyper, None), 0) + return hop.gendirectcall(ll_instance_str, v_arg) + + +def ll_instance_str(instance): + from pypy.rpython import rstr + nameLen = len(instance.typeptr.name) + nameString = malloc(rstr.STR, nameLen-1) + i = 0 + while i < nameLen - 1: + nameString.chars[i] = instance.typeptr.name[i] + i += 1 + return rstr.ll_strconcat(rstr.instance_str_prefix, + rstr.ll_strconcat(nameString, + rstr.instance_str_suffix)) + class __extend__(pairtype(InstanceRepr, InstanceRepr)): def convert_from_to((r_ins1, r_ins2), v, llops): Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Fri Jun 24 17:07:59 2005 @@ -549,3 +549,9 @@ raise StopIteration iter.index = index + 1 return chars[index] + +# these should be in rclass, but circular imports prevent (also it's +# not that insane that a string constant is built in this file). + +instance_str_prefix = string_repr.convert_const("<") +instance_str_suffix = string_repr.convert_const(" object>") Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Fri Jun 24 17:07:59 2005 @@ -245,3 +245,23 @@ return s1+s2 == s and s2+s1 == 'lohel' res = interpret(fn, ()) assert res + +def test_strformat_instance(): + class C: + pass + class D(C): + pass + def dummy(i): + if i: + x = C() + else: + x = D() + return str(x) + + ev_fun = make_interpreter(dummy, [0]) + + res = ev_fun(1) + assert ''.join(res.chars) == '' + + res = ev_fun(0) + assert ''.join(res.chars) == '' From tismer at codespeak.net Fri Jun 24 17:13:58 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 17:13:58 +0200 (CEST) Subject: [pypy-svn] r13816 - pypy/dist/pypy/translator/goal Message-ID: <20050624151358.0781B27B60@code1.codespeak.net> Author: tismer Date: Fri Jun 24 17:13:57 2005 New Revision: 13816 Modified: pypy/dist/pypy/translator/goal/targetrpystonex.py Log: clean-up of rpystone2 crap which is no longer needed Modified: pypy/dist/pypy/translator/goal/targetrpystonex.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystonex.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystonex.py Fri Jun 24 17:13:57 2005 @@ -15,7 +15,7 @@ for j in range(51): g.Array2Glob[i][j] = 0 g.PtrGlb = None - g.PtrGlbNext = None + g.PtrGlbNext = None return rpystone.pystones(loops), id(g) def target(): @@ -28,7 +28,7 @@ (version, LOOPS, benchtime) print "This machine benchmarks at %g translated rpystone/%s pystones/second" % (stones, version) res = c_entry_point(50000) - _, g_addr = res + _, g_addr = res print "CPython:" benchtime, stones = rpystone.pystones(50000) print "rpystone.pystones/%s time for %d passes = %g" % \ From tismer at codespeak.net Fri Jun 24 17:15:55 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 17:15:55 +0200 (CEST) Subject: [pypy-svn] r13817 - pypy/dist/pypy/translator/goal Message-ID: <20050624151555.A0E3B27B66@code1.codespeak.net> Author: tismer Date: Fri Jun 24 17:15:54 2005 New Revision: 13817 Modified: pypy/dist/pypy/translator/goal/targetrpystone.py pypy/dist/pypy/translator/goal/targetrpystonex.py Log: rest of clean-ups Modified: pypy/dist/pypy/translator/goal/targetrpystone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystone.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystone.py Fri Jun 24 17:15:54 2005 @@ -9,4 +9,4 @@ (entry_point, target, - run) = targetrpystonex.make_target_definition(LOOPS, "normal") + run) = targetrpystonex.make_target_definition(LOOPS) Modified: pypy/dist/pypy/translator/goal/targetrpystonex.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrpystonex.py (original) +++ pypy/dist/pypy/translator/goal/targetrpystonex.py Fri Jun 24 17:15:54 2005 @@ -2,7 +2,7 @@ from pypy.translator.c.symboltable import getsymboltable -def make_target_definition(LOOPS, version): +def make_target_definition(LOOPS): def entry_point(loops): g = rpystone.g g.IntGlob = 0 @@ -24,16 +24,16 @@ def run(c_entry_point): res = c_entry_point(LOOPS) (benchtime, stones), _ = res - print "translated rpystone.pystones/%s time for %d passes = %g" % \ - (version, LOOPS, benchtime) - print "This machine benchmarks at %g translated rpystone/%s pystones/second" % (stones, version) + print "translated rpystone.pystones time for %d passes = %g" % \ + (LOOPS, benchtime) + print "This machine benchmarks at %g translated rpystone pystones/second" % (stones,) res = c_entry_point(50000) _, g_addr = res print "CPython:" benchtime, stones = rpystone.pystones(50000) - print "rpystone.pystones/%s time for %d passes = %g" % \ - (version, 50000, benchtime) - print "This machine benchmarks at %g rpystone/%s pystones/second" % (stones, version) + print "rpystone.pystones time for %d passes = %g" % \ + (50000, benchtime) + print "This machine benchmarks at %g rpystone pystones/second" % (stones,) symtable = getsymboltable(c_entry_point.__module__) check_g_results(symtable, g_addr) From mwh at codespeak.net Fri Jun 24 17:18:58 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 17:18:58 +0200 (CEST) Subject: [pypy-svn] r13818 - in pypy/dist/pypy/rpython: . test Message-ID: <20050624151858.680D827B66@code1.codespeak.net> Author: mwh Date: Fri Jun 24 17:18:57 2005 New Revision: 13818 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: %-formatting for instances. Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Fri Jun 24 17:18:57 2005 @@ -11,6 +11,8 @@ from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc from pypy.rpython.lltype import Bool, Void, GcArray, nullptr +from pypy.rpython.rclass import InstanceRepr, ll_instance_str, getinstancerepr + # ____________________________________________________________ # @@ -221,9 +223,15 @@ if isinstance(thing, tuple): code = thing[0] vitem, r_arg = argsiter.next() - if code == 's': - assert isinstance(r_arg, StringRepr) - vchunk = hop.llops.convertvar(vitem, r_arg, string_repr) + if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)): + if isinstance(r_arg, StringRepr): + vchunk = hop.llops.convertvar(vitem, r_arg, string_repr) + elif isinstance(r_arg, InstanceRepr): + vinst = hop.llops.convertvar( + vitem, r_arg, getinstancerepr(hop.rtyper, None)) + vchunk = hop.gendirectcall(ll_instance_str, vinst) + else: + assert 0 elif code == 'd': assert isinstance(r_arg, IntegerRepr) vchunk = hop.gendirectcall(rint.ll_int2str, vitem) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Fri Jun 24 17:18:57 2005 @@ -265,3 +265,26 @@ res = ev_fun(0) assert ''.join(res.chars) == '' + +def test_percentformat_instance(): + class C: + pass + class D(C): + pass + + def dummy(i): + if i: + x = C() + y = D() + else: + x = D() + y = C() + return "what a nice %s, much nicer than %r"%(x, y) + + ev_fun = make_interpreter(dummy, [0]) + + res = ev_fun(1) + assert ''.join(res.chars) == 'what a nice , much nicer than ' + + res = ev_fun(0) + assert ''.join(res.chars) == 'what a nice , much nicer than ' From mwh at codespeak.net Fri Jun 24 17:19:45 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Fri, 24 Jun 2005 17:19:45 +0200 (CEST) Subject: [pypy-svn] r13819 - pypy/extradoc/sprintinfo Message-ID: <20050624151945.D166827B66@code1.codespeak.net> Author: mwh Date: Fri Jun 24 17:19:45 2005 New Revision: 13819 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: OK, that possibly pointless task is done. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Fri Jun 24 17:19:45 2005 @@ -19,13 +19,6 @@ annotator/{unary.py,binary.py} one by one and decide if they should be supported - - (probably easy): operations: str for instances (only something - very simple for the latter). all other uses are cheating, as - are all uses of hex, oct, repr. Add some '%s' support of instances - as well. - - mostly DONE apart from instances which we're not sure we need anyway - * lltype will also need to grow a new primitive type, UnicodeChar. * (partially DONE) convert each file that does From arigo at codespeak.net Fri Jun 24 17:23:27 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 24 Jun 2005 17:23:27 +0200 (CEST) Subject: [pypy-svn] r13820 - in pypy/dist/pypy: annotation rpython translator Message-ID: <20050624152327.0D77F27B66@code1.codespeak.net> Author: arigo Date: Fri Jun 24 17:23:24 2005 New Revision: 13820 Modified: pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/translator/annrpython.py Log: Moved BasicAnnotatorPolicy to annotation.policy. Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Fri Jun 24 17:23:24 2005 @@ -1,6 +1,15 @@ # base annotation policy for overrides and specialization from pypy.annotation.specialize import memo, ctr_location, default_specialize as default -from pypy.translator.annrpython import BasicAnnotatorPolicy + + +class BasicAnnotatorPolicy: + + def specialize(pol, bookkeeper, spaceop, func, args, mono): + return None, None + + def compute_at_fixpoint(pol, annotator): + annotator.bookkeeper.compute_at_fixpoint() + class AnnotatorPolicy(BasicAnnotatorPolicy): """ Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Fri Jun 24 17:23:24 2005 @@ -4,7 +4,7 @@ from pypy.annotation import model as annmodel from pypy.annotation.specialize import decide_callable -from pypy.translator.annrpython import BasicAnnotatorPolicy +from pypy.annotation.policy import BasicAnnotatorPolicy def not_const(s_obj): # xxx move it somewhere else if s_obj.is_constant(): Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Fri Jun 24 17:23:24 2005 @@ -15,14 +15,6 @@ class AnnotatorError(Exception): pass -class BasicAnnotatorPolicy: - - def specialize(pol, bookkeeper, spaceop, func, args, mono): - return None, None - - def compute_at_fixpoint(pol, annotator): - annotator.bookkeeper.compute_at_fixpoint() - class RPythonAnnotator: """Block annotator for RPython. @@ -55,7 +47,8 @@ self.frozen = False # user-supplied annotation logic for functions we don't want to flow into if policy is None: - self.policy = BasicAnnotatorPolicy() + from pypy.annotation.policy import AnnotatorPolicy + self.policy = AnnotatorPolicy() else: self.policy = policy From tismer at codespeak.net Fri Jun 24 17:42:00 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 17:42:00 +0200 (CEST) Subject: [pypy-svn] r13821 - pypy/dist/pypy/tool Message-ID: <20050624154200.C266427B51@code1.codespeak.net> Author: tismer Date: Fri Jun 24 17:41:59 2005 New Revision: 13821 Added: pypy/dist/pypy/tool/asterisk.py (contents, props changed) Log: started a toolfor half-automatic 'import *' removal Added: pypy/dist/pypy/tool/asterisk.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/tool/asterisk.py Fri Jun 24 17:41:59 2005 @@ -0,0 +1,67 @@ +# some analysis of global imports + +""" +The idea: +compile a module's source text and walk recursively +through the code objects. Find out which globals +are used. +Then examine each 'import *' by importing that module +and looking for those globals. +Replace the 'import *' by the list found. +""" + +import dis, cStringIO, sys + +def disasm(code): + hold = sys.stdout + try: + sys.stdout = cStringIO.StringIO() + dis.dis(code) + return sys.stdout.getvalue() + finally: + sys.stdout = hold + +def globalsof(code, globs=None): + names = code.co_names + vars = code.co_varnames + if globs is None: + globs = {} + for line in disasm(code).split('\n'): + words = line.split() + ofs = -1 + while words and words[0].isdigit(): + ofs = int(words.pop(0)) + if not words: + continue + op = words[0] + if op == 'LOAD_GLOBAL': + name = words[-1][1:-1] # omit () + refs = globs.setdefault(name, {}) + offsets = refs.setdefault(code, []) + offsets.append(ofs) + elif op == 'IMPORT_NAME': + impname = words[-1][1:-1] + elif op == 'IMPORT_STAR': + name = impname, '*' + del impname + refs = globs.setdefault(name, {}) + offsets = refs.setdefault(code, []) + offsets.append(ofs) + return globs + +def allglobalsof(code): + globs = {} + seen = {} + if type(code) is str: + fname = code + code = compile(file(fname).read(), fname, 'exec') + todo = [code] + while todo: + code = todo.pop(0) + globalsof(code, globs) + seen[code] = True + for const in code.co_consts: + if type(const) is type(code) and const not in seen: + todo.append(const) + return globs + From tismer at codespeak.net Fri Jun 24 17:52:29 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 17:52:29 +0200 (CEST) Subject: [pypy-svn] r13822 - pypy/dist/pypy/tool Message-ID: <20050624155229.15D5E27B51@code1.codespeak.net> Author: tismer Date: Fri Jun 24 17:52:28 2005 New Revision: 13822 Modified: pypy/dist/pypy/tool/asterisk.py Log: recording all offsets ofglobal access, and also all offsets of import * statements. next step is to try to do replacement. Modified: pypy/dist/pypy/tool/asterisk.py ============================================================================== --- pypy/dist/pypy/tool/asterisk.py (original) +++ pypy/dist/pypy/tool/asterisk.py Fri Jun 24 17:52:28 2005 @@ -42,10 +42,11 @@ elif op == 'IMPORT_NAME': impname = words[-1][1:-1] elif op == 'IMPORT_STAR': - name = impname, '*' + name = '*' + stars = globs.setdefault(name, {}) + mods = stars.setdefault(impname, {}) del impname - refs = globs.setdefault(name, {}) - offsets = refs.setdefault(code, []) + offsets = mods.setdefault(code, []) offsets.append(ofs) return globs From ale at codespeak.net Fri Jun 24 17:57:31 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 24 Jun 2005 17:57:31 +0200 (CEST) Subject: [pypy-svn] r13823 - pypy/dist/pypy/rpython Message-ID: <20050624155731.43A1A27B5C@code1.codespeak.net> Author: ale Date: Fri Jun 24 17:57:29 2005 New Revision: 13823 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rstr.py Log: lowlevel support for unicode chars ( arre, ale) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri Jun 24 17:57:29 2005 @@ -319,7 +319,18 @@ func = opimpls[%(opname)r] return func(x, y) """ % locals()).compile() + +def unichar_eq(x, y): + assert isinstance(x, unicode) and len(x) == 1 + assert isinstance(y, unicode) and len(y) == 1 + func = opimpls['eq'] + return func(x, y) +def unichar_ne(x, y): + assert isinstance(x, unicode) and len(x) == 1 + assert isinstance(y, unicode) and len(y) == 1 + func = opimpls['ne'] + return func(x, y) # by default we route all logging messages to nothingness # e.g. tests can then switch on logging to get more help Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Fri Jun 24 17:57:29 2005 @@ -297,6 +297,7 @@ Char = Primitive("Char", '\x00') Bool = Primitive("Bool", False) Void = Primitive("Void", None) +UniChar = Primitive("UniChar", u'\x00') class Ptr(LowLevelType): @@ -337,6 +338,9 @@ if isinstance(val, str): assert len(val) == 1 return Char + if isinstance(val, unicode): + assert len(val) == 1 + return UniChar if val is None: return Void # maybe return val._TYPE Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Fri Jun 24 17:57:29 2005 @@ -1,7 +1,7 @@ from pypy.annotation.pairtype import pair, pairtype, extendabletype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython.lltype import Void, Bool, Float, Signed, Char +from pypy.rpython.lltype import Void, Bool, Float, Signed, Char, UniChar from pypy.rpython.lltype import typeOf, LowLevelType, Ptr, PyObject from pypy.rpython.lltype import FuncType, functionptr @@ -173,6 +173,9 @@ class CharRepr(StringRepr): lowleveltype = Char +class UniCharRepr(Repr): + lowleveltype = UniChar + class VoidRepr(Repr): lowleveltype = Void impossible_repr = VoidRepr() Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Fri Jun 24 17:57:29 2005 @@ -2,7 +2,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr -from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst +from pypy.rpython.rmodel import StringRepr, CharRepr, inputconst, UniCharRepr from pypy.rpython.rarithmetic import intmask from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.rtuple import TupleRepr @@ -39,10 +39,16 @@ def rtyper_makekey(self): return None +class __extend__(annmodel.SomeUnicodeCodePoint): + def rtyper_makerepr(self, rtyper): + return unichar_repr + def rtyper_makekey(self): + return None CONST_STR_CACHE = WeakValueDictionary() string_repr = StringRepr() char_repr = CharRepr() +unichar_repr = UniCharRepr() class __extend__(StringRepr): @@ -297,6 +303,40 @@ vlist = hop.inputargs(char_repr, char_repr) return hop.genop('char_'+func, vlist, resulttype=Bool) +class __extend__(UniCharRepr): + + def convert_const(self, value): + if not isinstance(value, unicode) or len(value) != 1: + raise TyperError("not a unicode character: %r" % (value,)) + return value + +## def rtype_len(_, hop): +## return hop.inputconst(Signed, 1) +## +## def rtype_is_true(_, hop): +## assert not hop.args_s[0].can_be_None +## return hop.inputconst(Bool, True) + + def rtype_ord(_, hop): + vlist = hop.inputargs(unichar_repr) + return hop.genop('cast_unichar_to_int', vlist, resulttype=Signed) + + +class __extend__(pairtype(UniCharRepr, UniCharRepr)): + def rtype_eq(_, hop): return _rtype_unchr_compare_template(hop, 'eq') + def rtype_ne(_, hop): return _rtype_unchr_compare_template(hop, 'ne') +## def rtype_lt(_, hop): return _rtype_unchr_compare_template(hop, 'lt') +## def rtype_le(_, hop): return _rtype_unchr_compare_template(hop, 'le') +## def rtype_gt(_, hop): return _rtype_unchr_compare_template(hop, 'gt') +## def rtype_ge(_, hop): return _rtype_unchr_compare_template(hop, 'ge') + +#Helper functions for comparisons + +def _rtype_unchr_compare_template(hop, func): + vlist = hop.inputargs(unichar_repr, unichar_repr) + return hop.genop('unichar_'+func, vlist, resulttype=Bool) + + # # _________________________ Conversions _________________________ From ale at codespeak.net Fri Jun 24 18:25:43 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 24 Jun 2005 18:25:43 +0200 (CEST) Subject: [pypy-svn] r13824 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050624162543.E159527B51@code1.codespeak.net> Author: ale Date: Fri Jun 24 18:25:41 2005 New Revision: 13824 Added: pypy/dist/pypy/translator/c/unichar_include.h Modified: pypy/dist/pypy/translator/c/g_include.h pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/test/test_typed.py Log: Preliminary support for Unicode chars (arre,ale) Modified: pypy/dist/pypy/translator/c/g_include.h ============================================================================== --- pypy/dist/pypy/translator/c/g_include.h (original) +++ pypy/dist/pypy/translator/c/g_include.h Fri Jun 24 18:25:41 2005 @@ -17,6 +17,7 @@ #include "int_include.h" #include "char_include.h" +#include "unichar_include.h" #include "float_include.h" #include "ll_include.h" #include "pyobj_include.h" Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Fri Jun 24 18:25:41 2005 @@ -31,11 +31,17 @@ def name_void(value): return '/* nothing */' +def name_unichar(value): + assert type(value) is unicode and len(value) == 1 + return '%d' % ord(value) + + PrimitiveName = { Signed: name_signed, Unsigned: name_unsigned, Float: name_float, Char: name_char, + UniChar: name_unichar, Bool: name_bool, Void: name_void, } @@ -45,6 +51,7 @@ Unsigned: 'unsigned long @', Float: 'double @', Char: 'char @', + UniChar: 'pypy_unichar @', Bool: 'char @', Void: 'void @', } @@ -54,6 +61,7 @@ Unsigned: '((unsigned) -1)', Float: '-1.0', Char: '((char) -1)', + UniChar: '((pypy_unichar) -1)', Bool: '((char) -1)', Void: '/* error */', } Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Fri Jun 24 18:25:41 2005 @@ -169,6 +169,26 @@ for j in range(3): res = fn(i, j) assert res == fn(i, j) + + def xtest_unichr_eq(self): + l = list(u'Hello world') + def f(i=int,j=int): + return l[i] == l[j] + fn = self.getcompiled(f) #,view=True) + for i in range(len(l)): + for j in range(len(l)): + res = fn(i,j) + assert res == f(i,j) + + def xtest_unichr_ne(self): + l = list(u'Hello world') + def f(i=int,j=int): + return l[i] != l[j] + fn = self.getcompiled(f) #,view=True) + for i in range(len(l)): + for j in range(len(l)): + res = fn(i,j) + assert res == f(i,j) def test_slice_long(self): "the parent's test_slice_long() makes no sense here" Added: pypy/dist/pypy/translator/c/unichar_include.h ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/unichar_include.h Fri Jun 24 18:25:41 2005 @@ -0,0 +1,11 @@ +/************************************************************/ +/*** C header subsection: operations between chars ***/ + +/*** unary operations ***/ + +/*** binary operations ***/ + +typedef unsigned pypy_unichar; +#define OP_UNICHAR_EQ(x,y,r,err) r = ((x) == (y)); +#define OP_UNICHAR_NE(x,y,r,err) r = ((x) != (y)); + From ale at codespeak.net Fri Jun 24 18:28:53 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 24 Jun 2005 18:28:53 +0200 (CEST) Subject: [pypy-svn] r13825 - pypy/dist/pypy/annotation Message-ID: <20050624162853.355C327B51@code1.codespeak.net> Author: ale Date: Fri Jun 24 18:28:52 2005 New Revision: 13825 Modified: pypy/dist/pypy/annotation/model.py Log: Forgot to check in Unicode defs (arre,ale) Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Fri Jun 24 18:28:52 2005 @@ -402,6 +402,7 @@ (SomeInteger(nonneg=True, unsigned=True), lltype.Unsigned), (SomeFloat(), lltype.Float), (SomeChar(), lltype.Char), + (SomeUnicodeCodePoint(), lltype.UniChar), ] def annotation_to_lltype(s_val, info=None): From ac at codespeak.net Fri Jun 24 18:34:22 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 24 Jun 2005 18:34:22 +0200 (CEST) Subject: [pypy-svn] r13826 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050624163422.E373827B51@code1.codespeak.net> Author: ac Date: Fri Jun 24 18:34:22 2005 New Revision: 13826 Modified: pypy/dist/pypy/translator/c/primitive.py pypy/dist/pypy/translator/c/test/test_typed.py pypy/dist/pypy/translator/c/unichar_include.h Log: Initial (and crude) support for unicode characters in C. (arre, ale) Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Fri Jun 24 18:34:22 2005 @@ -51,7 +51,7 @@ Unsigned: 'unsigned long @', Float: 'double @', Char: 'char @', - UniChar: 'pypy_unichar @', + UniChar: 'unsigned @', Bool: 'char @', Void: 'void @', } @@ -61,7 +61,7 @@ Unsigned: '((unsigned) -1)', Float: '-1.0', Char: '((char) -1)', - UniChar: '((pypy_unichar) -1)', + UniChar: '((unsigned) -1)', Bool: '((char) -1)', Void: '/* error */', } Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Fri Jun 24 18:34:22 2005 @@ -170,7 +170,7 @@ res = fn(i, j) assert res == fn(i, j) - def xtest_unichr_eq(self): + def test_unichr_eq(self): l = list(u'Hello world') def f(i=int,j=int): return l[i] == l[j] @@ -180,7 +180,7 @@ res = fn(i,j) assert res == f(i,j) - def xtest_unichr_ne(self): + def test_unichr_ne(self): l = list(u'Hello world') def f(i=int,j=int): return l[i] != l[j] Modified: pypy/dist/pypy/translator/c/unichar_include.h ============================================================================== --- pypy/dist/pypy/translator/c/unichar_include.h (original) +++ pypy/dist/pypy/translator/c/unichar_include.h Fri Jun 24 18:34:22 2005 @@ -5,7 +5,7 @@ /*** binary operations ***/ -typedef unsigned pypy_unichar; +/* typedef unsigned pypy_unichar; */ #define OP_UNICHAR_EQ(x,y,r,err) r = ((x) == (y)); #define OP_UNICHAR_NE(x,y,r,err) r = ((x) != (y)); From tismer at codespeak.net Fri Jun 24 20:00:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 20:00:39 +0200 (CEST) Subject: [pypy-svn] r13827 - pypy/dist/pypy/tool Message-ID: <20050624180039.BD19B27B5C@code1.codespeak.net> Author: tismer Date: Fri Jun 24 20:00:38 2005 New Revision: 13827 Modified: pypy/dist/pypy/tool/asterisk.py Log: asterisk now finds nicely out, which globals are coming from which star import. We can produce code rewriting, now. Modified: pypy/dist/pypy/tool/asterisk.py ============================================================================== --- pypy/dist/pypy/tool/asterisk.py (original) +++ pypy/dist/pypy/tool/asterisk.py Fri Jun 24 20:00:38 2005 @@ -21,11 +21,13 @@ finally: sys.stdout = hold -def globalsof(code, globs=None): +def globalsof(code, globrefs=None, stars=None, globals=None): names = code.co_names vars = code.co_varnames - if globs is None: - globs = {} + if globrefs is None: globrefs = {} + if stars is None: stars = [] # do stars in order + if globals is None: globals = {} + in_seq = False for line in disasm(code).split('\n'): words = line.split() ofs = -1 @@ -36,22 +38,36 @@ op = words[0] if op == 'LOAD_GLOBAL': name = words[-1][1:-1] # omit () - refs = globs.setdefault(name, {}) + refs = globrefs.setdefault(name, {}) offsets = refs.setdefault(code, []) offsets.append(ofs) elif op == 'IMPORT_NAME': - impname = words[-1][1:-1] + in_seq = True + imp_module = words[-1][1:-1] + imp_what = None + elif op == 'IMPORT_FROM': + in_seq = True + imp_what = words[-1][1:-1] + elif op == 'STORE_NAME': + # we are not interested in local imports, which + # would generate a STORE_FAST + name = words[-1][1:-1] + if in_seq: + globals[name] = imp_what, imp_module + in_seq = False + else: + globals[name] = None, None elif op == 'IMPORT_STAR': - name = '*' - stars = globs.setdefault(name, {}) - mods = stars.setdefault(impname, {}) - del impname - offsets = mods.setdefault(code, []) - offsets.append(ofs) - return globs + stars.append( (imp_module, ofs) ) + in_seq = False + else: + in_seq = False + return globrefs, stars, globals def allglobalsof(code): - globs = {} + globrefs = {} + stars = [] + globals = {} seen = {} if type(code) is str: fname = code @@ -59,10 +75,45 @@ todo = [code] while todo: code = todo.pop(0) - globalsof(code, globs) + globalsof(code, globrefs, stars, globals) seen[code] = True for const in code.co_consts: if type(const) is type(code) and const not in seen: todo.append(const) - return globs + return globrefs, stars, globals + +class Analyser: + def __init__(self, fname): + self.fname = fname + self.globrefs, self.stars, self.globals = allglobalsof(fname) + self.starimports = [] + def get_unknown_globals(self): + from __builtin__ import __dict__ as bltin + ret = [name for name in self.globrefs.keys() + if name not in bltin and name not in self.globals] + return ret + + def get_from_star(self, modname): + dic = {} + exec "from %s import *" % modname in dic + return dic + + def resolve_star_imports(self): + implicit = {} + which = {} + for star, ofs in self.stars: + which[star] = [] + for key in self.get_from_star(star).keys(): + implicit[key] = star + # sort out in which star import we find what + # note that we walked star imports in order + # so we are sure to resolve ambiguities correctly + for name in self.get_unknown_globals(): + mod = implicit[name] + which[mod].append(name) + imps = [] + for star, ofs in self.stars: + imps.append( (ofs, star, which[star]) ) + self.starimports = imps + \ No newline at end of file From tismer at codespeak.net Fri Jun 24 20:56:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 20:56:26 +0200 (CEST) Subject: [pypy-svn] r13828 - pypy/dist/pypy/translator Message-ID: <20050624185626.E17FA27B51@code1.codespeak.net> Author: tismer Date: Fri Jun 24 20:56:25 2005 New Revision: 13828 Modified: pypy/dist/pypy/translator/ann_override.py Log: solved an import cycle,although I didn't find out what we changed to create this cycle. Modified: pypy/dist/pypy/translator/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/ann_override.py (original) +++ pypy/dist/pypy/translator/ann_override.py Fri Jun 24 20:56:25 2005 @@ -1,7 +1,9 @@ # overrides for annotation specific to PyPy codebase from pypy.annotation.policy import AnnotatorPolicy -from pypy.annotation.bookkeeper import getbookkeeper +# for some reason, model must be imported first, +# or we create a cycle. from pypy.annotation import model as annmodel +from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation import specialize class PyPyAnnotatorPolicy(AnnotatorPolicy): From tismer at codespeak.net Fri Jun 24 21:02:01 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Fri, 24 Jun 2005 21:02:01 +0200 (CEST) Subject: [pypy-svn] r13829 - pypy/dist/pypy/tool Message-ID: <20050624190201.6EDD027B56@code1.codespeak.net> Author: tismer Date: Fri Jun 24 21:02:00 2005 New Revision: 13829 Modified: pypy/dist/pypy/tool/asterisk.py Log: started to resolve line numbers. going home for today, my stomach hurts... Modified: pypy/dist/pypy/tool/asterisk.py ============================================================================== --- pypy/dist/pypy/tool/asterisk.py (original) +++ pypy/dist/pypy/tool/asterisk.py Fri Jun 24 21:02:00 2005 @@ -8,6 +8,8 @@ Then examine each 'import *' by importing that module and looking for those globals. Replace the 'import *' by the list found. +More advanced: If the new import has more than, say, 5 entries, +rewrite the import to use module.name throughout the source. """ import dis, cStringIO, sys @@ -20,7 +22,18 @@ return sys.stdout.getvalue() finally: sys.stdout = hold - + +def offset2lineno(c, stopat): + tab = c.co_lnotab + line = c.co_firstlineno + addr = 0 + for i in range(0, len(tab), 2): + addr = addr + ord(tab[i]) + if addr > stopat: + break + line = line + ord(tab[i+1]) + return line + def globalsof(code, globrefs=None, stars=None, globals=None): names = code.co_names vars = code.co_varnames @@ -106,9 +119,9 @@ which[star] = [] for key in self.get_from_star(star).keys(): implicit[key] = star - # sort out in which star import we find what - # note that we walked star imports in order - # so we are sure to resolve ambiguities correctly + # sort out in which star import we find what. + # note that we walked star imports in order, + # so we are sure to resolve ambiguities correctly. for name in self.get_unknown_globals(): mod = implicit[name] which[mod].append(name) From hpk at codespeak.net Fri Jun 24 21:13:39 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Fri, 24 Jun 2005 21:13:39 +0200 (CEST) Subject: [pypy-svn] r13830 - in pypy/dist/pypy: annotation rpython rpython/test translator Message-ID: <20050624191339.313B327B50@code1.codespeak.net> Author: hpk Date: Fri Jun 24 21:13:35 2005 New Revision: 13830 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/specialize.py pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/translator/transform.py Log: (arigo, hpk with special consulting by pedronis) - support for specialcase:memo functions (like the often used pypy.tool.cache.Cache.getorbuild function). Currently, only one PBC argument is allowed for such functions. Somewhat unfortunately, the support is spread across a number of files but it works and doesn't really involve a large number of lines. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri Jun 24 21:13:35 2005 @@ -24,6 +24,7 @@ self.objects = { obj: True } self.read_locations = {} self.attrs = {} + self.values = {} # used in the typer def update(self, other): self.objects.update(other.objects) @@ -193,6 +194,8 @@ self.pbc_call_sites = {} + self.memo_tables = [] + self.stats = Stats(self) # import ordering hack Modified: pypy/dist/pypy/annotation/specialize.py ============================================================================== --- pypy/dist/pypy/annotation/specialize.py (original) +++ pypy/dist/pypy/annotation/specialize.py Fri Jun 24 21:13:35 2005 @@ -126,6 +126,18 @@ # ____________________________________________________________________________ # specializations +class MemoTable: + def __init__(self, bookkeeper, func, s_result, arglist_s): + self.table = {} + self.arglist_s = arglist_s + self.s_result = s_result + for arglist in possible_arguments(arglist_s): + result = func(*arglist) + self.table[arglist] = result + bookkeeper.memo_tables.append(self) + def _freeze_(self): + return True + def memo(bookkeeper, mod, spaceop, func, args, mono): """NOT_RPYTHON""" assert mono, "not-static call to memoized %s" % func @@ -140,28 +152,32 @@ possible_results.append(bookkeeper.immutablevalue(result)) return unionof(*possible_results), args -def possible_arguments(args): +def possible_values_of(s): from pypy.annotation.model import SomeBool, SomePBC - # enumerate all tuples (x1,..xn) of concrete values that are contained - # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either - # a constant or SomePBC. - if not args: - yield () - return - s = args[0] if s.is_constant(): - possible_values = [s.const] + return [s.const] elif isinstance(s, SomePBC): for value in s.prebuiltinstances.values(): assert value is True, ("concrete call with a method bound " "on a non-constant instance") - possible_values = s.prebuiltinstances.keys() + return s.prebuiltinstances.keys() elif isinstance(s, SomeBool): - possible_values = [False, True] + return [False, True] else: - raise AssertionError, "concrete call with a non-constant arg %r" % (s,) - for tuple_tail in possible_arguments(args[1:]): - for value in possible_values: + raise ValueError, "memo call with a non-constant arg %r" % (s,) + +def possible_arguments(args): + # enumerate all tuples (x1,..xn) of concrete values that are contained + # in a tuple args=(s1,..sn) of SomeXxx. Requires that each s be either + # a constant or SomePBC. + return cartesian_product([possible_values_of(s) for s in args]) + +def cartesian_product(lstlst): + if not lstlst: + yield () + return + for tuple_tail in cartesian_product(lstlst[1:]): + for value in lstlst[0]: yield (value,) + tuple_tail #def argtypes(bookkeeper, spaceop, func, args, mono): Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri Jun 24 21:13:35 2005 @@ -165,9 +165,43 @@ annotator.setbinding(graph.getreturnvar(), generalizedresult) +def specialize_pbcs_by_memotables(annotator): + memo_tables = annotator.bookkeeper.memo_tables + access_sets = annotator.getpbcaccesssets() + for memo_table in memo_tables: + arglist_s = memo_table.arglist_s + assert len(arglist_s) == 1, "XXX implement >1 arguments" + arg1 = arglist_s[0] + assert isinstance(arg1, annmodel.SomePBC) + + if None in arg1.prebuiltinstances: + raise TyperError("unsupported: memo call with an argument that can be None") + pbcs = arg1.prebuiltinstances.keys() + _, _, access_set = access_sets.find(pbcs[0]) + + # enforce a structure where we can uniformly access + # our memofield later + for pbc in pbcs[1:]: + _, _, access_set = access_sets.union(pbcs[0], pbc) + + # we can have multiple memo_tables per PBC + i = 0 + while 1: + fieldname = "memofield_%d" % i + if fieldname in access_set.attrs: + i += 1 + continue + memo_table.fieldname = fieldname + break + access_set.attrs[fieldname] = memo_table.s_result + for pbc in pbcs: + value = memo_table.table[(pbc,)] + access_set.values[(pbc, fieldname)] = value + def perform_normalizations(annotator): annotator.frozen += 1 try: normalize_function_signatures(annotator) + specialize_pbcs_by_memotables(annotator) finally: annotator.frozen -= 1 Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri Jun 24 21:13:35 2005 @@ -5,7 +5,7 @@ from pypy.objspace.flow.model import Constant from pypy.rpython.lltype import typeOf, Void, ForwardReference, Struct, Bool from pypy.rpython.lltype import Ptr, malloc, nullptr -from pypy.rpython.rmodel import Repr, TyperError +from pypy.rpython.rmodel import Repr, TyperError, inputconst from pypy.rpython import rclass from pypy.rpython.rtyper import HighLevelOp @@ -166,7 +166,10 @@ result = malloc(self.pbc_type, immortal=True) self.pbc_cache[pbc] = result for attr, (mangled_name, r_value) in self.llfieldmap.items(): - thisattrvalue = getattr(pbc, attr) + try: + thisattrvalue = self.access_set.values[(pbc, attr)] + except KeyError: + thisattrvalue = getattr(pbc, attr) llvalue = r_value.convert_const(thisattrvalue) setattr(result, mangled_name, llvalue) return result @@ -174,10 +177,13 @@ def rtype_getattr(self, hop): attr = hop.args_s[1].const vpbc, vattr = hop.inputargs(self, Void) + return self.getfield(vpbc, attr, hop.llops) + + def getfield(self, vpbc, attr, llops): mangled_name, r_value = self.llfieldmap[attr] - cmangledname = hop.inputconst(Void, mangled_name) - return hop.genop('getfield', [vpbc, cmangledname], - resulttype = r_value) + cmangledname = inputconst(Void, mangled_name) + return llops.genop('getfield', [vpbc, cmangledname], + resulttype = r_value) # ____________________________________________________________ @@ -424,3 +430,15 @@ # now hop2 looks like simple_call(initfunc, instance, args...) hop2.dispatch() return v_instance + +# ____________________________________________________________ + +def rtype_call_memo(hop): + memo_table = hop.args_v[0].value + fieldname = memo_table.fieldname + assert hop.nb_args == 2, "XXX" + + r_pbc = hop.args_r[1] + assert isinstance(r_pbc, MultipleFrozenPBCRepr) + v_table, v_pbc = hop.inputargs(Void, r_pbc) + return r_pbc.getfield(v_pbc, fieldname, hop.llops) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Fri Jun 24 21:13:35 2005 @@ -352,6 +352,9 @@ def translate_op_newslice(self, hop): return rslice.rtype_newslice(hop) + def translate_op_call_memo(self, hop): + return rpbc.rtype_call_memo(hop) + def missing_operation(self, hop): raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname) Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Fri Jun 24 21:13:35 2005 @@ -31,6 +31,7 @@ t = Translator(func) t.annotate(argtypes) if viewbefore: + t.annotator.simplify() t.view() global typer # we need it for find_exception typer = RPythonTyper(t.annotator) @@ -40,8 +41,8 @@ return t, typer def interpret(func, values, view=False, viewbefore=False): - t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) for x in values], - viewbefore) + t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) + for x in values], viewbefore) if view: t.view() interp = LLInterpreter(t.flowgraphs, typer) @@ -49,8 +50,8 @@ return res def make_interpreter(func, example_values, view=False, viewbefore=False): - t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) for x in example_values], - viewbefore) + t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) + for x in example_values], viewbefore) if view: t.view() interp = LLInterpreter(t.flowgraphs, typer) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Fri Jun 24 21:13:35 2005 @@ -1,7 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, make_interpreter def test_easy_call(): @@ -143,3 +143,31 @@ assert res == 1+10+3 res = interpret(f3, []) assert res == 1+10+100 + +def test_call_memoized(): + fr1 = Freezing() + fr1.x = 0 + fr2 = Freezing() + fr2.x = 1 + def getorbuild(key): + a = 1 + if key is fr1: + result = eval("a+2") + else: + result = eval("a+6") + return result + getorbuild._annspecialcase_ = "specialize:memo" + + def f1(i): + if i > 0: + fr = fr1 + else: + fr = fr2 + # XXX this should work without fr.x + return getorbuild(fr) + fr.x + + ev_f1 = make_interpreter(f1, [0])#, viewbefore=True) + res = ev_f1(0) + assert res == 8 + res = ev_f1(1) + assert res == 3 Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Fri Jun 24 21:13:35 2005 @@ -13,6 +13,7 @@ from pypy.objspace.flow.model import last_exception from pypy.translator.annrpython import CannotSimplify from pypy.annotation import model as annmodel +from pypy.annotation.specialize import MemoTable def fully_annotated_blocks(self): """Ignore blocked blocks.""" @@ -152,10 +153,20 @@ if not specialcase: op.args[0] = Constant(specialized_callb.prebuiltinstances.keys()[0]) else: - if op.opname == 'simple_call': - op.opname = intern('simple_specialcase') + if op.opname != 'simple_call': + assert 0, "not supported: call_args to a specialized function" + callable = callb.prebuiltinstances.keys()[0] + tag = getattr(callable, '_annspecialcase_', None) + if tag == 'specialize:memo': + arglist_s = [self.binding(v) for v in op.args[1:]] + memo_table = MemoTable(self.bookkeeper, + callable, + self.binding(op.result), + arglist_s) + op.opname = intern('call_memo') + op.args[0] = Constant(memo_table) else: - op.opname = intern('specialcase_args') + op.opname = intern('call_specialcase') default_extra_passes = [ transform_specialization, From hpk at codespeak.net Sat Jun 25 10:21:14 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 10:21:14 +0200 (CEST) Subject: [pypy-svn] r13832 - pypy/extradoc/sprintinfo Message-ID: <20050625082114.54D5F27B51@code1.codespeak.net> Author: hpk Date: Sat Jun 25 10:21:13 2005 New Revision: 13832 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: memoized functions with a single PBC arg work Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 10:21:13 2005 @@ -8,8 +8,8 @@ status report: - (hard) (holger, armin) prebuilt constants -- PBCs -- and dicts with PBC keys - tasks: 1. call to memoized functions, at first with a single PBC arg - 2. find out if we really have visible dicts with PBC keys + DONE 1. call to memoized functions, at first with a single PBC arg + 2. find out if we really have visible dicts with PBC keys - (probably trivial) verify that we've done all the builtins we need for translation. From hpk at codespeak.net Sat Jun 25 10:30:36 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 10:30:36 +0200 (CEST) Subject: [pypy-svn] r13833 - pypy/dist/pypy/rpython/test Message-ID: <20050625083036.4826627B5D@code1.codespeak.net> Author: hpk Date: Sat Jun 25 10:30:35 2005 New Revision: 13833 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: XXX is actually resolved already (we generalize PBCs passed in to a specialize:memo'd function unconditionally, so we don't need no magic 'fr.x' accesses to trigger it) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sat Jun 25 10:30:35 2005 @@ -163,11 +163,10 @@ fr = fr1 else: fr = fr2 - # XXX this should work without fr.x - return getorbuild(fr) + fr.x + return getorbuild(fr) ev_f1 = make_interpreter(f1, [0])#, viewbefore=True) res = ev_f1(0) - assert res == 8 + assert res == 7 res = ev_f1(1) assert res == 3 From hpk at codespeak.net Sat Jun 25 10:49:01 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 10:49:01 +0200 (CEST) Subject: [pypy-svn] r13834 - pypy/dist/pypy/rpython/test Message-ID: <20050625084901.6211D27B51@code1.codespeak.net> Author: hpk Date: Sat Jun 25 10:49:00 2005 New Revision: 13834 Modified: pypy/dist/pypy/rpython/test/test_rpbc.py Log: add a more complex cache test using a standard Cache subclass (which also is somewhat instructive to look at in the flowviewer) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sat Jun 25 10:49:00 2005 @@ -144,11 +144,9 @@ res = interpret(f3, []) assert res == 1+10+100 -def test_call_memoized(): +def test_call_memoized_function(): fr1 = Freezing() - fr1.x = 0 fr2 = Freezing() - fr2.x = 1 def getorbuild(key): a = 1 if key is fr1: @@ -170,3 +168,48 @@ assert res == 7 res = ev_f1(1) assert res == 3 + +def test_call_memoized_cache(): + + # this test checks that we add a separate field + # per specialization and also it uses a subclass of + # the standard pypy.tool.cache.Cache + + from pypy.tool.cache import Cache + fr1 = Freezing() + fr2 = Freezing() + + class Cache1(Cache): + def _build(self, key): + "NOT_RPYTHON" + if key is fr1: + return fr2 + else: + return fr1 + + class Cache2(Cache): + def _build(self, key): + "NOT_RPYTHON" + a = 1 + if key is fr1: + result = eval("a+2") + else: + result = eval("a+6") + return result + + cache1 = Cache1() + cache2 = Cache2() + + def f1(i): + if i > 0: + fr = fr1 + else: + fr = fr2 + newfr = cache1.getorbuild(fr) + return cache2.getorbuild(newfr) + + ev_f1 = make_interpreter(f1, [0], view=0, viewbefore=0) + res = ev_f1(0) + assert res == 3 + res = ev_f1(1) + assert res == 7 From ale at codespeak.net Sat Jun 25 11:42:19 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 11:42:19 +0200 (CEST) Subject: [pypy-svn] r13836 - pypy/dist/pypy/rpython Message-ID: <20050625094219.EA86B27B51@code1.codespeak.net> Author: ale Date: Sat Jun 25 11:42:16 2005 New Revision: 13836 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rint.py Log: Added support for unichr builtin and ord for unichars Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat Jun 25 11:42:16 2005 @@ -256,6 +256,14 @@ assert type(b) is str and len(b) == 1 return ord(b) + def op_cast_unichar_to_int(self, b): + assert type(b) is unicode and len(b) == 1 + return ord(b) + + def op_cast_int_to_unichar(self, b): + assert type(b) is int + return unichr(b) + def op_cast_int_to_uint(self, b): assert type(b) is int return r_uint(b) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 25 11:42:16 2005 @@ -99,6 +99,10 @@ assert hop.nb_args == 1 return hop.args_r[0].rtype_chr(hop) +def rtype_builtin_unichr(hop): + assert hop.nb_args == 1 + return hop.args_r[0].rtype_unichr(hop) + def rtype_builtin_list(hop): return hop.args_r[0].rtype_bltn_list(hop) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Sat Jun 25 11:42:16 2005 @@ -2,7 +2,7 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.objspace import op_appendices from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Char, \ - GcArray, malloc, Array + UniChar, GcArray, malloc, Array from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, CharRepr, \ inputconst from pypy.rpython.robject import PyObjRepr, pyobj_repr @@ -206,6 +206,10 @@ vlist = hop.inputargs(Signed) return hop.genop('cast_int_to_char', vlist, resulttype=Char) + def rtype_unichr(_, hop): + vlist = hop.inputargs(Signed) + return hop.genop('cast_int_to_unichar', vlist, resulttype=UniChar) + def rtype_is_true(self, hop): if self.lowleveltype == Unsigned: vlist = hop.inputargs(Unsigned) From ale at codespeak.net Sat Jun 25 11:47:01 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 11:47:01 +0200 (CEST) Subject: [pypy-svn] r13837 - pypy/extradoc/sprintinfo Message-ID: <20050625094701.78FCE27B51@code1.codespeak.net> Author: ale Date: Sat Jun 25 11:47:00 2005 New Revision: 13837 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: UniChar support marked done (ale, arre) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 11:47:00 2005 @@ -19,7 +19,7 @@ annotator/{unary.py,binary.py} one by one and decide if they should be supported -* lltype will also need to grow a new primitive type, UnicodeChar. +* DONE (ale,arre) lltype will also need to grow a new primitive type, UnicodeChar. * (partially DONE) convert each file that does 'from ... import *' to use explicit imports (e.g. From ale at codespeak.net Sat Jun 25 12:00:07 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 12:00:07 +0200 (CEST) Subject: [pypy-svn] r13839 - pypy/extradoc/sprintinfo Message-ID: <20050625100007.17FDD27B85@code1.codespeak.net> Author: ale Date: Sat Jun 25 12:00:06 2005 New Revision: 13839 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Typo Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 12:00:06 2005 @@ -19,7 +19,7 @@ annotator/{unary.py,binary.py} one by one and decide if they should be supported -* DONE (ale,arre) lltype will also need to grow a new primitive type, UnicodeChar. +* DONE (ale, arre) lltype will also need to grow a new primitive type, UnicodeChar. * (partially DONE) convert each file that does 'from ... import *' to use explicit imports (e.g. From ac at codespeak.net Sat Jun 25 12:49:56 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 25 Jun 2005 12:49:56 +0200 (CEST) Subject: [pypy-svn] r13840 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050625104956.B630327B61@code1.codespeak.net> Author: ac Date: Sat Jun 25 12:49:56 2005 New Revision: 13840 Modified: pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/test/test_typed.py pypy/dist/pypy/translator/c/unichar_include.h (contents, props changed) Log: Add C support for ord on unicode characters and unichr. Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Sat Jun 25 12:49:56 2005 @@ -145,6 +145,9 @@ #define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); #define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ +#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (unsigned)(x); + /* bool operations */ #define OP_BOOL_NOT(x, r, err) r = !(x); Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sat Jun 25 12:49:56 2005 @@ -174,7 +174,7 @@ l = list(u'Hello world') def f(i=int,j=int): return l[i] == l[j] - fn = self.getcompiled(f) #,view=True) + fn = self.getcompiled(f) for i in range(len(l)): for j in range(len(l)): res = fn(i,j) @@ -184,12 +184,31 @@ l = list(u'Hello world') def f(i=int,j=int): return l[i] != l[j] - fn = self.getcompiled(f) #,view=True) + fn = self.getcompiled(f) for i in range(len(l)): for j in range(len(l)): res = fn(i,j) assert res == f(i,j) + def test_unichr_ord(self): + l = list(u'Hello world') + def f(i=int): + return ord(l[i]) + fn = self.getcompiled(f) + for i in range(len(l)): + res = fn(i) + assert res == f(i) + + def test_unichr_unichr(self): + l = list(u'Hello world') + def f(i=int, j=int): + return l[i] == unichr(j) + fn = self.getcompiled(f) + for i in range(len(l)): + for j in range(len(l)): + res = fn(i, ord(l[j])) + assert res == f(i, ord(l[j])) + def test_slice_long(self): "the parent's test_slice_long() makes no sense here" Modified: pypy/dist/pypy/translator/c/unichar_include.h ============================================================================== --- pypy/dist/pypy/translator/c/unichar_include.h (original) +++ pypy/dist/pypy/translator/c/unichar_include.h Sat Jun 25 12:49:56 2005 @@ -1,11 +1,11 @@ -/************************************************************/ -/*** C header subsection: operations between chars ***/ - -/*** unary operations ***/ - -/*** binary operations ***/ - -/* typedef unsigned pypy_unichar; */ -#define OP_UNICHAR_EQ(x,y,r,err) r = ((x) == (y)); -#define OP_UNICHAR_NE(x,y,r,err) r = ((x) != (y)); - +/************************************************************/ +/*** C header subsection: operations between chars ***/ + +/*** unary operations ***/ + +/*** binary operations ***/ + +/* typedef unsigned pypy_unichar; */ +#define OP_UNICHAR_EQ(x,y,r,err) r = ((x) == (y)); +#define OP_UNICHAR_NE(x,y,r,err) r = ((x) != (y)); + From arigo at codespeak.net Sat Jun 25 13:12:07 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 13:12:07 +0200 (CEST) Subject: [pypy-svn] r13841 - pypy/extradoc/sprintinfo Message-ID: <20050625111207.8623427B86@code1.codespeak.net> Author: arigo Date: Sat Jun 25 13:12:05 2005 New Revision: 13841 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Listing missing operations Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 13:12:05 2005 @@ -15,10 +15,79 @@ need for translation. - (hard) a few more operations: issubtype, ...? - task: go through all space operations listed in baseobjspace.py - annotator/{unary.py,binary.py} - one by one and decide if they should be supported - + found to be missing (ale, arigo): + + Builtins + -------- + + apply + callable + compile + hasattr + long + slice + tuple + unicode + zip + xrange + max + + math_floor + math_fmod + ovfcheck + ovfcheck_lshift + + sys.getrefcount + sys.getdefaultencoding + + time.time + + os.path.dirname + os.path.normpath + os.path.join + os.path.exists + os.path.isdir + + __import__ + + + Unary operations + ---------------- + + rclass: issubtype + + rdict: method_get + method_copy + method_update + method_keys + method_values + method_items + + fix the code not to use str.split() + + rpbc: is_true + + + Binary operations + ----------------- + + cmp ? + rint: divmod + coerce ?? + + rstr: mul, inplace_mul + + + Overridden functions in PyPy + ---------------------------- + + override:ignore + override:instantiate + override:wrap_exception_cls + override:fake_object + override:cpy_compile + + * DONE (ale, arre) lltype will also need to grow a new primitive type, UnicodeChar. * (partially DONE) convert each file that does From hpk at codespeak.net Sat Jun 25 13:15:38 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 13:15:38 +0200 (CEST) Subject: [pypy-svn] r13842 - pypy/dist/pypy/interpreter Message-ID: <20050625111538.A016127B88@code1.codespeak.net> Author: hpk Date: Sat Jun 25 13:15:36 2005 New Revision: 13842 Modified: pypy/dist/pypy/interpreter/typedef.py Log: (hpk, mwh) get rid of the only specialcase:memo occurence that used more than one PBC key Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Sat Jun 25 13:15:36 2005 @@ -24,16 +24,38 @@ # hint for the annotator: track individual constant instances of TypeDef return True -subclass_cache = {} -def get_unique_interplevel_subclass(cls, hasdict, wants_slots): - key = (cls, hasdict, wants_slots) - try: - return subclass_cache[key] - except KeyError: - subcls = _buildusercls(cls, hasdict, wants_slots) - subclass_cache[key] = subcls - return subcls -get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" + +# we cannot specialize:memo by more than one PBC key +# so we need to work a bit to allow that + +def get_unique_interplevel_subclass(cls, hasdict, wants_slots): + if hasdict: + if wants_slots: + return get_unique_interplevel_WithDictWithSlots(cls) + else: + return get_unique_interplevel_WithDictNoSlots(cls) + else: + if wants_slots: + return get_unique_interplevel_NoDictWithSlots(cls) + else: + return get_unique_interplevel_NoDictNoSlots(cls) + +for hasdict in False, True: + for wants_slots in False, True: + name = hasdict and "WithDict" or "NoDict" + name += wants_slots and "WithSlots" or "NoSlots" + funcname = "get_unique_interplevel_%s" % (name,) + exec compile2(""" + subclass_cache_%(name)s = {} + def %(funcname)s(cls): + try: + return subclass_cache_%(name)s[cls] + except KeyError: + subcls = _buildusercls(cls, %(hasdict)r, %(wants_slots)r) + subclass_cache_%(name)s[cls] = subcls + return subcls + %(funcname)s._annspecialcase_ = "specialize:memo" + """ % locals()) def _buildusercls(cls, hasdict, wants_slots): "NOT_RPYTHON: initialization-time only" From ac at codespeak.net Sat Jun 25 13:16:35 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 25 Jun 2005 13:16:35 +0200 (CEST) Subject: [pypy-svn] r13843 - pypy/dist/pypy/translator/c Message-ID: <20050625111635.15FD427B8E@code1.codespeak.net> Author: ac Date: Sat Jun 25 13:16:34 2005 New Revision: 13843 Modified: pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/primitive.py Log: Changed unicode characters to use CPython's Py_UCS4 instead of unsigned. Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Sat Jun 25 13:16:34 2005 @@ -146,7 +146,7 @@ #define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ #define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (long)(x); -#define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (unsigned)(x); +#define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (Py_UCS4)(x); /* bool operations */ Modified: pypy/dist/pypy/translator/c/primitive.py ============================================================================== --- pypy/dist/pypy/translator/c/primitive.py (original) +++ pypy/dist/pypy/translator/c/primitive.py Sat Jun 25 13:16:34 2005 @@ -51,7 +51,7 @@ Unsigned: 'unsigned long @', Float: 'double @', Char: 'char @', - UniChar: 'unsigned @', + UniChar: 'Py_UCS4 @', Bool: 'char @', Void: 'void @', } @@ -61,7 +61,7 @@ Unsigned: '((unsigned) -1)', Float: '-1.0', Char: '((char) -1)', - UniChar: '((unsigned) -1)', + UniChar: '((Py_UCS4) -1)', Bool: '((char) -1)', Void: '/* error */', } From hpk at codespeak.net Sat Jun 25 13:21:26 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 13:21:26 +0200 (CEST) Subject: [pypy-svn] r13844 - pypy/extradoc/sprintinfo Message-ID: <20050625112126.3191A27B92@code1.codespeak.net> Author: hpk Date: Sat Jun 25 13:21:25 2005 New Revision: 13844 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: specialecase:memo done for now (until someone objects) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 13:21:25 2005 @@ -4,12 +4,11 @@ Still missing are: -* Almost all the topics from the rtyper, from the previous - status report: +* currently remaining rtyper topics: - (hard) (holger, armin) prebuilt constants -- PBCs -- and dicts with PBC keys DONE 1. call to memoized functions, at first with a single PBC arg - 2. find out if we really have visible dicts with PBC keys + DONE 2. removed the only usage of specialize:memo with more than one PBC key - (probably trivial) verify that we've done all the builtins we need for translation. From ale at codespeak.net Sat Jun 25 13:30:19 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 13:30:19 +0200 (CEST) Subject: [pypy-svn] r13845 - pypy/extradoc/sprintinfo Message-ID: <20050625113019.9A4B227B7D@code1.codespeak.net> Author: ale Date: Sat Jun 25 13:30:18 2005 New Revision: 13845 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Marked the first half of the list of missing builtins Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 13:30:18 2005 @@ -19,35 +19,35 @@ Builtins -------- - apply - callable - compile - hasattr - long - slice - tuple - unicode - zip - xrange - max - - math_floor - math_fmod - ovfcheck - ovfcheck_lshift - - sys.getrefcount - sys.getdefaultencoding - - time.time - - os.path.dirname - os.path.normpath - os.path.join - os.path.exists - os.path.isdir + (discuss) apply + (remove) callable + (should be hidden by the specialcase)compile + (remove) hasattr + (is not there)long + (easy) slice + (easy) tuple + (easy) unicode + (removed) zip + (easy) xrange + (easy) max + + (easy) math_floor + (easy) math_fmod + (easy) ovfcheck + (easy) ovfcheck_lshift + + (strange)(delegating to backend?) sys.getrefcount + (medium) sys.getdefaultencoding + + (easy) time.time + + (delegating to backend) os.path.dirname + (delegating to backend) os.path.normpath + (delegating to backend) os.path.join + (delegating to backend) os.path.exists + (delegating to backend)os.path.isdir - __import__ + (should not be there) __import__ Unary operations From arigo at codespeak.net Sat Jun 25 14:17:44 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 14:17:44 +0200 (CEST) Subject: [pypy-svn] r13848 - in pypy/dist/pypy: annotation rpython translator Message-ID: <20050625121744.DFECB27B4D@code1.codespeak.net> Author: arigo Date: Sat Jun 25 14:17:41 2005 New Revision: 13848 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/translator/simplify.py Log: Progress in classifying the built-in functions we use in PyPy. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat Jun 25 14:17:41 2005 @@ -85,8 +85,8 @@ def builtin_unichr(s_int): return constpropagate(unichr, [s_int], SomeUnicodeCodePoint()) -def builtin_unicode(s_obj): - raise TypeError, "unicode() calls should not happen at interp-level" +##def builtin_unicode(s_obj): +## raise TypeError, "unicode() calls should not happen at interp-level" def our_issubclass(cls1, cls2): """ we're going to try to be less silly in the face of old-style classes""" @@ -148,8 +148,8 @@ r.const = hasattr(s_obj.const, s_attr.const) return r -def builtin_callable(s_obj): - return SomeBool() +##def builtin_callable(s_obj): +## return SomeBool() def builtin_tuple(s_iterable): if isinstance(s_iterable, SomeTuple): @@ -179,10 +179,10 @@ getbookkeeper().warning("ignoring apply%r" % (stuff,)) return SomeObject() -def builtin_compile(*stuff): - s = SomeObject() - s.knowntype = types.CodeType - return s +##def builtin_compile(*stuff): +## s = SomeObject() +## s.knowntype = types.CodeType +## return s def builtin_slice(*args): bk = getbookkeeper() Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Sat Jun 25 14:17:41 2005 @@ -81,7 +81,8 @@ res = TupleRepr(items_r) vlist = v_tuple + v_tuple1 return newtuple(hop.llops, res, vlist) - + rtype_inplace_add = rtype_add + # ____________________________________________________________ # Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Sat Jun 25 14:17:41 2005 @@ -341,6 +341,10 @@ iter get '''.split(): CanRemove[_op] = True del _op +CanRemoveBuiltins = { + isinstance: True, + hasattr: True, + } def transform_dead_op_vars_in_blocks(blocks): """Remove dead operations and variables that are passed over a link @@ -415,7 +419,7 @@ # ... if op.args and isinstance(op.args[0], Constant): func = op.args[0].value - if func is isinstance: + if func in CanRemoveBuiltins: del block.operations[i] # look for output variables never used From arigo at codespeak.net Sat Jun 25 14:18:13 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 14:18:13 +0200 (CEST) Subject: [pypy-svn] r13849 - pypy/extradoc/sprintinfo Message-ID: <20050625121813.E29EA27B4D@code1.codespeak.net> Author: arigo Date: Sat Jun 25 14:18:12 2005 New Revision: 13849 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Progress in classifying the builtins we use in PyPy. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 14:18:12 2005 @@ -19,15 +19,6 @@ Builtins -------- - (discuss) apply - (remove) callable - (should be hidden by the specialcase)compile - (remove) hasattr - (is not there)long - (easy) slice - (easy) tuple - (easy) unicode - (removed) zip (easy) xrange (easy) max @@ -47,20 +38,18 @@ (delegating to backend) os.path.exists (delegating to backend)os.path.isdir - (should not be there) __import__ - Unary operations ---------------- - rclass: issubtype + rclass: (easy) issubtype - rdict: method_get - method_copy - method_update - method_keys - method_values - method_items + rdict: (easy) method_get + (easy) method_copy + (easy) method_update + (easy) method_keys + (easy) method_values + (easy) method_items fix the code not to use str.split() From mwh at codespeak.net Sat Jun 25 14:28:54 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 14:28:54 +0200 (CEST) Subject: [pypy-svn] r13850 - pypy/dist/pypy/rpython Message-ID: <20050625122854.ED25427B4D@code1.codespeak.net> Author: mwh Date: Sat Jun 25 14:28:54 2005 New Revision: 13850 Modified: pypy/dist/pypy/rpython/rfloat.py Log: float % float in the rtyper (for demo/bpnn.py) Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sat Jun 25 14:28:54 2005 @@ -42,6 +42,11 @@ rtype_inplace_div = rtype_div + def rtype_mod(_, hop): + return _rtype_template(hop, 'mod') + + rtype_inplace_mod = rtype_mod + def rtype_pow(_, hop): s_float3 = hop.args_s[2] if s_float3.is_constant() and s_float3.const is None: From rxe at codespeak.net Sat Jun 25 14:46:14 2005 From: rxe at codespeak.net (rxe at codespeak.net) Date: Sat, 25 Jun 2005 14:46:14 +0200 (CEST) Subject: [pypy-svn] r13851 - pypy/extradoc/sprintinfo Message-ID: <20050625124614.497FF27B5E@code1.codespeak.net> Author: rxe Date: Sat Jun 25 14:46:13 2005 New Revision: 13851 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: Update my details. Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Sat Jun 25 14:46:13 2005 @@ -30,7 +30,7 @@ Carl Friedrich Bolz 1st-6th July private Eric van Riet Paap 1st-7th July SGS Holger Krekel 1st-7th July private -Richard Emslie 1st-7th July ? +Richard Emslie 1st-7th July private Bert Freudenberg 1st-7th July ? Beatrice Duering visiting private Jacob Hallen ? private From arigo at codespeak.net Sat Jun 25 15:28:42 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 15:28:42 +0200 (CEST) Subject: [pypy-svn] r13852 - pypy/extradoc/sprintinfo Message-ID: <20050625132842.D47E027B60@code1.codespeak.net> Author: arigo Date: Sat Jun 25 15:28:41 2005 New Revision: 13852 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Finished classifying the builtins and operations. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 15:28:41 2005 @@ -51,19 +51,16 @@ (easy) method_values (easy) method_items - fix the code not to use str.split() + (easy) rstr: str.split(single_constant_character) - rpbc: is_true + (easy) rpbc: is_true --> False for None + True for all other PBCs Binary operations ----------------- - cmp ? - rint: divmod - coerce ?? - - rstr: mul, inplace_mul + (easy) rstr: mul, inplace_mul (for CharRepr only!) Overridden functions in PyPy From arigo at codespeak.net Sat Jun 25 15:30:23 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 15:30:23 +0200 (CEST) Subject: [pypy-svn] r13853 - pypy/dist/pypy/annotation Message-ID: <20050625133023.A8EB527B5F@code1.codespeak.net> Author: arigo Date: Sat Jun 25 15:30:22 2005 New Revision: 13853 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/unaryop.py Log: Count some rare operations. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Sat Jun 25 15:30:22 2005 @@ -134,10 +134,10 @@ return SomeBool() def cmp((obj1, obj2)): + getbookkeeper().count("cmp", obj1, obj2) if obj1.is_constant() and obj2.is_constant(): return immutablevalue(cmp(obj1.const, obj2.const)) else: - getbookkeeper().count("non_int_comp", obj1, obj2) return SomeInteger() def is_((obj1, obj2)): @@ -183,9 +183,11 @@ return r def divmod((obj1, obj2)): + getbookkeeper().count("divmod", obj1, obj2) return SomeTuple([pair(obj1, obj2).div(), pair(obj1, obj2).mod()]) def coerce((obj1, obj2)): + getbookkeeper().count("coerce", obj1, obj2) return pair(obj1, obj2).union() # reasonable enough # cloning a function with identical code, for the can_only_throw attribute @@ -451,11 +453,13 @@ return SomeChar() def mul((str1, int2)): # xxx do we want to support this + getbookkeeper().count("str_mul", str1, int2) return SomeString() class __extend__(pairtype(SomeInteger, SomeString)): def mul((int1, str2)): # xxx do we want to support this + getbookkeeper().count("str_mul", str2, int1) return SomeString() class __extend__(pairtype(SomeInteger, SomeList)): Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jun 25 15:30:22 2005 @@ -317,6 +317,7 @@ return SomeInteger(nonneg=True) def method_split(str, patt): # XXX + getbookkeeper().count("str_split", str, patt) return getbookkeeper().newlist(SomeString()) @@ -435,6 +436,10 @@ def is_true(pbc): outcome = None for c in pbc.prebuiltinstances: + if c is not None and not bool(c): + getbookkeeper().warning("PBC %r has truth value False" % (c,)) + getbookkeeper().count("pbc_is_true", pbc) + for c in pbc.prebuiltinstances: if outcome is None: outcome = bool(c) else: From hpk at codespeak.net Sat Jun 25 16:40:43 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 16:40:43 +0200 (CEST) Subject: [pypy-svn] r13857 - pypy/extradoc/sprintinfo Message-ID: <20050625144043.4FB3B27B60@code1.codespeak.net> Author: hpk Date: Sat Jun 25 16:40:43 2005 New Revision: 13857 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: status update after another common planning session Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 16:40:43 2005 @@ -6,50 +6,40 @@ * currently remaining rtyper topics: - - (hard) (holger, armin) prebuilt constants -- PBCs -- and dicts with PBC keys - DONE 1. call to memoized functions, at first with a single PBC arg - DONE 2. removed the only usage of specialize:memo with more than one PBC key - - - (probably trivial) verify that we've done all the builtins we - need for translation. - - - (hard) a few more operations: issubtype, ...? - found to be missing (ale, arigo): + - found to be missing (ale, arigo):: Builtins -------- - (easy) xrange (easy) max - (easy) math_floor - (easy) math_fmod - (easy) ovfcheck - (easy) ovfcheck_lshift + (easy) math.floor + (easy) math.fmod (strange)(delegating to backend?) sys.getrefcount - (medium) sys.getdefaultencoding + (medium) applevel sys module should not refer to + interplevel sys.getdefaultencoding - (easy) time.time + (easy) time.time (see how time.clock is done) - (delegating to backend) os.path.dirname - (delegating to backend) os.path.normpath - (delegating to backend) os.path.join - (delegating to backend) os.path.exists - (delegating to backend)os.path.isdir + implement in RPython (and change importing.py accordingly) + os.path.dirname/normpath/join (including the closure of what they use) + (generate c_api calls) os.path.exists + (generate c_api calls) os.path.isdir Unary operations ---------------- rclass: (easy) issubtype - rdict: (easy) method_get + (arre, christian): + rdict: (easy) method_get (?) (easy) method_copy - (easy) method_update - (easy) method_keys - (easy) method_values - (easy) method_items + (easy) method_update (?) + (easy) method_keys (?) + (easy) method_values (?) + (easy) method_items (?) (easy) rstr: str.split(single_constant_character) @@ -66,24 +56,22 @@ Overridden functions in PyPy ---------------------------- - override:ignore - override:instantiate - override:wrap_exception_cls - override:fake_object - override:cpy_compile - - -* DONE (ale, arre) lltype will also need to grow a new primitive type, UnicodeChar. + (easy) override:ignore + (easy) override:instantiate + (hard, probably needs to be implemented at C/CPython level): + override:wrap_exception_cls + override:fake_object + override:cpy_compile * (partially DONE) convert each file that does 'from ... import *' to use explicit imports (e.g. from pypy.rpython import lltype and then use lltype.*) -* (samuele, michael) GenC knows little about float operations. Need to complete +* INPROGESS (holger, michael) GenC knows little about float operations. Need to complete translator/c/float_include.h. * progress on translation of example targets: - python demo/bpnn.py (samuele, michael) + python demo/bpnn.py python pypy/translator/goal/translate_pypy.py targetrichards.py * (medium) write a tool that discovers which revision of the pypy tree @@ -95,5 +83,6 @@ * (medium) finish objspace/std/longobject.py. -* (hard) try out if genpickle.py can be used to save and load - the high level annotated flowgraphs of PyPy +* (hard) find a way to generate c_api calls with automated + conversions from ll-strings to c-like strings + From ale at codespeak.net Sat Jun 25 16:54:03 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 16:54:03 +0200 (CEST) Subject: [pypy-svn] r13859 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625145403.446B827B49@code1.codespeak.net> Author: ale Date: Sat Jun 25 16:54:01 2005 New Revision: 13859 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rrange.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/rpython/test/test_rint.py pypy/dist/pypy/rpython/test/test_rrange.py Log: added low level xrange Startet on low level max moved min test from test_rint to test_rbuiltin Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 25 16:54:01 2005 @@ -3,7 +3,7 @@ from pypy.rpython import lltype from pypy.rpython import rarithmetic from pypy.rpython.rtyper import TyperError -from pypy.rpython.rrange import rtype_builtin_range +from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr @@ -118,6 +118,8 @@ #def rtype_builtin_range(hop): see rrange.py +#def rtype_builtin_xrange(hop): see rrange.py + def rtype_intmask(hop): vlist = hop.inputargs(lltype.Signed) return vlist[0] @@ -139,6 +141,18 @@ return i1 return i2 +def rtype_builtin_max(hop): + rint1, rint2 = hop.args_r + assert isinstance(rint1, IntegerRepr) + assert isinstance(rint2, IntegerRepr) + assert rint1.lowleveltype == rint2.lowleveltype + v1, v2 = hop.inputargs(rint1, rint2) + return hop.gendirectcall(ll_min, v1, v2) + +def ll_max(i1, i2): + if i1 > i2: + return i1 + return i2 # collect all functions import __builtin__ Modified: pypy/dist/pypy/rpython/rrange.py ============================================================================== --- pypy/dist/pypy/rpython/rrange.py (original) +++ pypy/dist/pypy/rpython/rrange.py Sat Jun 25 16:54:01 2005 @@ -92,6 +92,8 @@ "XXX not implemented") #return hop.gendirectcall(ll_range2list, vstart, vstop, vstep) +rtype_builtin_xrange = rtype_builtin_range + # ____________________________________________________________ # # Iteration. 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 Sat Jun 25 16:54:01 2005 @@ -1,4 +1,6 @@ -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.annotation.builtin import * +import py def test_rbuiltin_list(): def f(): @@ -18,4 +20,22 @@ assert result result = interpret(r,[]) - assert result \ No newline at end of file + assert result + +def test_int_min(): + def fn(i, j): + return min(i,j) + ev_fun = make_interpreter(fn, [0, 0]) + assert ev_fun(1, 2) == 1 + assert ev_fun(1, -1) == -1 + assert ev_fun(2, 2) == 2 + assert ev_fun(-1, -12) == -12 + +def test_int_min(): + def fn(i, j): + return min(i,j) + ev_fun = make_interpreter(fn, [0, 0]) + assert ev_fun(1, 2) == 1 + assert ev_fun(1, -1) == -1 + assert ev_fun(2, 2) == 2 + assert ev_fun(-1, -12) == -12 Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Sat Jun 25 16:54:01 2005 @@ -94,11 +94,3 @@ res = ev_fun(-1) assert res is False # -1 ==> 0xffffffff -def test_int_min(): - def fn(i, j): - return min(i,j) - ev_fun = make_interpreter(fn, [0, 0]) - assert ev_fun(1, 2) == 1 - assert ev_fun(1, -1) == -1 - assert ev_fun(2, 2) == 2 - assert ev_fun(-1, -12) == -12 Modified: pypy/dist/pypy/rpython/test/test_rrange.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rrange.py (original) +++ pypy/dist/pypy/rpython/test/test_rrange.py Sat Jun 25 16:54:01 2005 @@ -50,3 +50,12 @@ assert res == 14 res = interpret(dummyfn, [10, 17, -2]) assert res == 15 + +def test_range(): + def dummyfn(N): + total = 0 + for i in xrange(N): + total += i + return total + res = interpret(dummyfn, [10]) + assert res == 45 From hpk at codespeak.net Sat Jun 25 16:54:40 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 16:54:40 +0200 (CEST) Subject: [pypy-svn] r13860 - in pypy/dist/pypy: rpython translator/c translator/c/test Message-ID: <20050625145440.0152E27B49@code1.codespeak.net> Author: hpk Date: Sat Jun 25 16:54:39 2005 New Revision: 13860 Modified: pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/translator/c/float_include.h pypy/dist/pypy/translator/c/test/test_typed.py Log: (mwh, hpk) - implement remaining float operations for genc - simplified rfloat.py a bit around pow(3 args) Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sat Jun 25 16:54:39 2005 @@ -51,9 +51,9 @@ s_float3 = hop.args_s[2] if s_float3.is_constant() and s_float3.const is None: vlist = hop.inputargs(Float, Float, Void)[:2] + return hop.genop('float_pow', vlist, resulttype=Float) else: - vlist = hop.inputargs(Float, Float, Float) - return hop.genop('float_pow', vlist, resulttype=Float) + raise TyperError("cannot handle pow with three float arguments") def rtype_inplace_pow(_, hop): return _rtype_template(hop, 'pow') Modified: pypy/dist/pypy/translator/c/float_include.h ============================================================================== --- pypy/dist/pypy/translator/c/float_include.h (original) +++ pypy/dist/pypy/translator/c/float_include.h Sat Jun 25 16:54:39 2005 @@ -9,6 +9,7 @@ /*** unary operations ***/ #define OP_FLOAT_IS_TRUE(x,r,err) OP_FLOAT_NE(x,0.0,r,err) +#define OP_FLOAT_NEG(x,r,err) r = -x; /*** binary operations ***/ @@ -30,6 +31,9 @@ #define OP_FLOAT_MUL(x,y,r,err) r = x * y; #define OP_FLOAT_DIV(x,y,r,err) r = x / y; +#define OP_FLOAT_MOD(x,y,r,err) r = fmod(x, y); +#define OP_FLOAT_POW(x,y,r,err) r = pow(x, y); + /*** conversions ***/ #define OP_CAST_FLOAT_TO_INT(x,r,err) r = (long)(x); Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sat Jun 25 16:54:39 2005 @@ -241,3 +241,15 @@ assert fn(i) == (-(i), abs(i-1)) raises (OverflowError, fn, -sys.maxint-1) raises (OverflowError, fn, -sys.maxint) + + # floats + def test_float_operations(self): + def func(x=float, y=float): + z = x + y / 2.1 * x + z = z % 60.0 + z = pow(z, 2) + z = -z + return int(z) + + fn = self.getcompiled(func) + assert fn(5.0, 6.0) == func(5.0, 6.0) From hpk at codespeak.net Sat Jun 25 16:57:23 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 16:57:23 +0200 (CEST) Subject: [pypy-svn] r13861 - pypy/extradoc/sprintinfo Message-ID: <20050625145723.2CC4F27B57@code1.codespeak.net> Author: hpk Date: Sat Jun 25 16:57:22 2005 New Revision: 13861 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: float/genc complete, now on bpnn Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 16:57:22 2005 @@ -67,11 +67,10 @@ 'from ... import *' to use explicit imports (e.g. from pypy.rpython import lltype and then use lltype.*) -* INPROGESS (holger, michael) GenC knows little about float operations. Need to complete - translator/c/float_include.h. +* DONE (holger, michael) translator/c/float_include.h should be complete. * progress on translation of example targets: - python demo/bpnn.py + python demo/bpnn.py (holger, michael, samuele) python pypy/translator/goal/translate_pypy.py targetrichards.py * (medium) write a tool that discovers which revision of the pypy tree From ale at codespeak.net Sat Jun 25 16:58:44 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 16:58:44 +0200 (CEST) Subject: [pypy-svn] r13862 - pypy/extradoc/sprintinfo Message-ID: <20050625145844.442EA27B57@code1.codespeak.net> Author: ale Date: Sat Jun 25 16:58:43 2005 New Revision: 13862 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: builtin max done Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 16:58:43 2005 @@ -11,8 +11,6 @@ Builtins -------- - (easy) max - (easy) math.floor (easy) math.fmod From ale at codespeak.net Sat Jun 25 16:59:19 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 16:59:19 +0200 (CEST) Subject: [pypy-svn] r13863 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625145919.BA54027B5F@code1.codespeak.net> Author: ale Date: Sat Jun 25 16:59:18 2005 New Revision: 13863 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: builtin max done Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 25 16:59:18 2005 @@ -147,7 +147,7 @@ assert isinstance(rint2, IntegerRepr) assert rint1.lowleveltype == rint2.lowleveltype v1, v2 = hop.inputargs(rint1, rint2) - return hop.gendirectcall(ll_min, v1, v2) + return hop.gendirectcall(ll_max, v1, v2) def ll_max(i1, i2): if i1 > i2: 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 Sat Jun 25 16:59:18 2005 @@ -1,4 +1,5 @@ from pypy.rpython.test.test_llinterp import interpret, make_interpreter + from pypy.annotation.builtin import * import py @@ -31,11 +32,11 @@ assert ev_fun(2, 2) == 2 assert ev_fun(-1, -12) == -12 -def test_int_min(): +def test_int_max(): def fn(i, j): - return min(i,j) + return max(i,j) ev_fun = make_interpreter(fn, [0, 0]) - assert ev_fun(1, 2) == 1 - assert ev_fun(1, -1) == -1 + assert ev_fun(1, 2) == 2 + assert ev_fun(1, -1) == 1 assert ev_fun(2, 2) == 2 - assert ev_fun(-1, -12) == -12 + assert ev_fun(-1, -12) == -1 From hpk at codespeak.net Sat Jun 25 17:15:06 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 17:15:06 +0200 (CEST) Subject: [pypy-svn] r13865 - pypy/dist/pypy/tool Message-ID: <20050625151506.3578627B66@code1.codespeak.net> Author: hpk Date: Sat Jun 25 17:15:05 2005 New Revision: 13865 Modified: pypy/dist/pypy/tool/cache.py Log: fix comment (mwh, hpk) Modified: pypy/dist/pypy/tool/cache.py ============================================================================== --- pypy/dist/pypy/tool/cache.py (original) +++ pypy/dist/pypy/tool/cache.py Sat Jun 25 17:15:05 2005 @@ -13,7 +13,7 @@ # Cache class: # a cache meant to map a finite number of keys to values. # It is normally extended lazily, until it contains all possible -# keys. The _specialize_ attribute of the getorbuild() method +# keys. The _annspecialcase_ attribute of the getorbuild() method # forces the annotator to decode the argument's annotations, # which must be constants or SomePBCs, actually call the # method with all possible combinations, and gather the results. From tismer at codespeak.net Sat Jun 25 17:15:41 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 17:15:41 +0200 (CEST) Subject: [pypy-svn] r13866 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625151541.EEF2F27B66@code1.codespeak.net> Author: tismer Date: Sat Jun 25 17:15:40 2005 New Revision: 13866 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: StrDictRepr.get implemented & tested Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 17:15:40 2005 @@ -89,6 +89,20 @@ def make_iterator_repr(self): return StrDictIteratorRepr(self) + def rtype_method_get(self, hop): + v_dict, v_key, v_default = hop.inputargs(self, string_repr, + self.value_repr) + return hop.gendirectcall(ll_get, v_dict, v_key, v_default) + +""" + rdict: (easy) method_get (?) + (easy) method_copy + (easy) method_update (?) + (easy) method_keys (?) + (easy) method_values (?) + (easy) method_items (?) +""" + class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): def rtype_getitem((r_dict, r_string), hop): @@ -283,3 +297,15 @@ return key iter.index = index raise StopIteration + +# _____________________________________________________________ +# methods + +def ll_get(v_dict, v_key, v_default): + entry = ll_strdict_lookup(v_dict, v_key) + if entry.key and entry.key != deleted_entry_marker: + return entry.value + else: + return v_default + + Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Sat Jun 25 17:15:40 2005 @@ -160,4 +160,11 @@ return d2['world']['hello'] res = interpret(func, [5]) assert res == 6 - + +def test_dict_get(): + def func(): + # XXX shouldn't the get imply the type by its default? + dic = {'blah': 1} + return dic.get('hi', 42) * 10 + dic.get('blah', 2) + res = interpret(func, ()) + assert res == 421 From arigo at codespeak.net Sat Jun 25 17:33:06 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 17:33:06 +0200 (CEST) Subject: [pypy-svn] r13869 - in pypy/dist/pypy: annotation interpreter translator Message-ID: <20050625153306.5A21827B61@code1.codespeak.net> Author: arigo Date: Sat Jun 25 17:33:03 2005 New Revision: 13869 Modified: pypy/dist/pypy/annotation/policy.py pypy/dist/pypy/interpreter/pyopcode.py pypy/dist/pypy/translator/ann_override.py Log: Specialize print_item_to by argument type. Progress towards allowing print statements. Modified: pypy/dist/pypy/annotation/policy.py ============================================================================== --- pypy/dist/pypy/annotation/policy.py (original) +++ pypy/dist/pypy/annotation/policy.py Sat Jun 25 17:33:03 2005 @@ -1,5 +1,10 @@ # base annotation policy for overrides and specialization from pypy.annotation.specialize import memo, ctr_location, default_specialize as default +from pypy.annotation.specialize import argtype, argvalue +# for some reason, model must be imported first, +# or we create a cycle. +from pypy.annotation import model as annmodel +from pypy.annotation.bookkeeper import getbookkeeper class BasicAnnotatorPolicy: @@ -57,3 +62,11 @@ default_specialize = staticmethod(default) specialize__memo = staticmethod(memo) specialize__ctr_location = staticmethod(ctr_location) + specialize__arg0 = staticmethod(argvalue(0)) + specialize__argtype0 = staticmethod(argtype(0)) + specialize__arg1 = staticmethod(argvalue(1)) + specialize__argtype1 = staticmethod(argtype(1)) + + def override__ignore(pol, *args): + bk = getbookkeeper() + return bk.immutablevalue(None) Modified: pypy/dist/pypy/interpreter/pyopcode.py ============================================================================== --- pypy/dist/pypy/interpreter/pyopcode.py (original) +++ pypy/dist/pypy/interpreter/pyopcode.py Sat Jun 25 17:33:03 2005 @@ -777,6 +777,7 @@ return # XXX add unicode handling file_softspace(stream, True) + print_item_to._annspecialcase_ = "specialize:argtype0" def print_newline_to(stream): stream.write("\n") Modified: pypy/dist/pypy/translator/ann_override.py ============================================================================== --- pypy/dist/pypy/translator/ann_override.py (original) +++ pypy/dist/pypy/translator/ann_override.py Sat Jun 25 17:33:03 2005 @@ -8,10 +8,6 @@ class PyPyAnnotatorPolicy(AnnotatorPolicy): - def override__ignore(pol, *args): - bk = getbookkeeper() - return bk.immutablevalue(None) - def override__instantiate(pol, clspbc): assert isinstance(clspbc, annmodel.SomePBC) clsdef = None @@ -36,6 +32,3 @@ from pypy.interpreter import pycode clsdef = getbookkeeper().getclassdef(pycode.PyCode) return annmodel.SomeInstance(clsdef) - - specialize__arg1 = staticmethod(specialize.argvalue(1)) - specialize__argtype1 = staticmethod(specialize.argtype(1)) From arigo at codespeak.net Sat Jun 25 17:34:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 17:34:25 +0200 (CEST) Subject: [pypy-svn] r13870 - pypy/extradoc/sprintinfo Message-ID: <20050625153425.1F4DC27B4F@code1.codespeak.net> Author: arigo Date: Sat Jun 25 17:34:23 2005 New Revision: 13870 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Mention two forgotten tasks: - immutable prebuilt dicts with int keys. - the contains operation (for the 'in' operator). Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 17:34:23 2005 @@ -50,6 +50,17 @@ (easy) rstr: mul, inplace_mul (for CharRepr only!) + (easy) 'contains' applied on: + * dict of string keys + * constant tuple of ints + * constant tuple of strings + * constant tuple of unicode characters + * constant dict with int keys (which are pending now) + * constant string + * string + * list of instances + * list of strings + * list of unicode characters Overridden functions in PyPy ---------------------------- @@ -61,6 +72,8 @@ override:fake_object override:cpy_compile +* prebuilt immutable dictionaries with int keys + * (partially DONE) convert each file that does 'from ... import *' to use explicit imports (e.g. from pypy.rpython import lltype and then use lltype.*) From hpk at codespeak.net Sat Jun 25 17:57:39 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 17:57:39 +0200 (CEST) Subject: [pypy-svn] r13871 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625155739.CA32327B51@code1.codespeak.net> Author: hpk Date: Sat Jun 25 17:57:38 2005 New Revision: 13871 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: not really a fix, not really a test, just want to get things onto my machine. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 25 17:57:38 2005 @@ -217,6 +217,9 @@ hop2 = hop.copy() hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') + if isinstance(hop2.args_v[0], Constant): + hop2.args_v[0] = hop2.llops.genop('same_as', [hop2.args_v[0]], + resulttype=hop.args_r[0]) c = Constant(self.function) hop2.v_s_insertfirstarg(c, s_function) # insert 'function' # now hop2 looks like simple_call(function, self, args...) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sat Jun 25 17:57:38 2005 @@ -213,3 +213,13 @@ assert res == 3 res = ev_f1(1) assert res == 7 + +def dont_test_rpbc_bound_method_static_call(): + class R: + def meth(self): + return 0 + r = R() + def fn(): + return r.meth() + res = interpret(fn, []) + assert res == 0 From arigo at codespeak.net Sat Jun 25 18:07:49 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 18:07:49 +0200 (CEST) Subject: [pypy-svn] r13872 - pypy/dist/pypy/annotation Message-ID: <20050625160749.2400C27B5E@code1.codespeak.net> Author: arigo Date: Sat Jun 25 18:07:48 2005 New Revision: 13872 Modified: pypy/dist/pypy/annotation/builtin.py Log: os.path.dirname and os.path.join seem to be annotatable enough. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat Jun 25 18:07:48 2005 @@ -272,9 +272,9 @@ BUILTIN_ANALYZERS[unicodedata.decimal] = unicodedata_decimal # xxx # os.path stuff -BUILTIN_ANALYZERS[os.path.dirname] = pathpart +#BUILTIN_ANALYZERS[os.path.dirname] = pathpart BUILTIN_ANALYZERS[os.path.normpath] = pathpart -BUILTIN_ANALYZERS[os.path.join] = pathpart +#BUILTIN_ANALYZERS[os.path.join] = pathpart BUILTIN_ANALYZERS[os.path.exists] = test BUILTIN_ANALYZERS[os.path.isdir] = test From arigo at codespeak.net Sat Jun 25 18:09:53 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 18:09:53 +0200 (CEST) Subject: [pypy-svn] r13873 - in pypy/dist/pypy: objspace/std rpython Message-ID: <20050625160953.1374127B5E@code1.codespeak.net> Author: arigo Date: Sat Jun 25 18:09:50 2005 New Revision: 13873 Modified: pypy/dist/pypy/objspace/std/stringobject.py pypy/dist/pypy/rpython/rdict.py Log: - force all usages of str*int to be on a single-character string - check that we are not trying to build rpython dicts whose keys are string-or-None Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Sat Jun 25 18:09:50 2005 @@ -348,10 +348,10 @@ if len(fillchar) != 1: raise OperationError(space.w_TypeError, space.wrap("rjust() argument 2 must be a single character")) - d = u_arg - len(u_self) if d>0: + fillchar = fillchar[0] # annotator hint: it's a single character u_self = d * fillchar + u_self return space.wrap(u_self) @@ -368,6 +368,7 @@ d = u_arg - len(u_self) if d>0: + fillchar = fillchar[0] # annotator hint: it's a single character u_self += d * fillchar return space.wrap(u_self) @@ -585,6 +586,7 @@ d = u_arg - len(u_self) if d>0: offset = d//2 + fillchar = fillchar[0] # annotator hint: it's a single character u_centered = offset * fillchar + u_self + (d - offset) * fillchar else: u_centered = u_self Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 18:09:50 2005 @@ -27,6 +27,9 @@ def rtyper_makerepr(self, rtyper): s_key = self.dictdef.dictkey.s_value if isinstance(s_key, annmodel.SomeString): + if s_key.can_be_none(): + raise rmodel.TyperError("cannot make repr of dict with " + "string-or-None keys") dictvalue = self.dictdef.dictvalue return StrDictRepr(lambda: rtyper.getrepr(dictvalue.s_value), dictvalue) From arigo at codespeak.net Sat Jun 25 18:11:08 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 18:11:08 +0200 (CEST) Subject: [pypy-svn] r13874 - pypy/branch/pypy-translation-snapshot/objspace/std Message-ID: <20050625161108.DBDFC27B5E@code1.codespeak.net> Author: arigo Date: Sat Jun 25 18:11:08 2005 New Revision: 13874 Modified: pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py Log: Port to pypy-translation-snapshot of rev 13873. Modified: pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py (original) +++ pypy/branch/pypy-translation-snapshot/objspace/std/stringobject.py Sat Jun 25 18:11:08 2005 @@ -348,10 +348,10 @@ if len(fillchar) != 1: raise OperationError(space.w_TypeError, space.wrap("rjust() argument 2 must be a single character")) - d = u_arg - len(u_self) if d>0: + fillchar = fillchar[0] # annotator hint: it's a single character u_self = d * fillchar + u_self return space.wrap(u_self) @@ -368,6 +368,7 @@ d = u_arg - len(u_self) if d>0: + fillchar = fillchar[0] # annotator hint: it's a single character u_self += d * fillchar return space.wrap(u_self) @@ -585,6 +586,7 @@ d = u_arg - len(u_self) if d>0: offset = d//2 + fillchar = fillchar[0] # annotator hint: it's a single character u_centered = offset * fillchar + u_self + (d - offset) * fillchar else: u_centered = u_self From ale at codespeak.net Sat Jun 25 18:15:42 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 18:15:42 +0200 (CEST) Subject: [pypy-svn] r13877 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625161542.D916827B5E@code1.codespeak.net> Author: ale Date: Sat Jun 25 18:15:41 2005 New Revision: 13877 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: added support for math.floor and math.fmod Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat Jun 25 18:15:41 2005 @@ -5,6 +5,7 @@ import py from pypy.rpython.lltype import _ptr, Ptr, Void, typeOf, malloc, cast_pointer from pypy.rpython.lltype import Array +import math log = py.log.Producer('llinterp') @@ -272,6 +273,15 @@ assert type(b) is r_uint return intmask(b) + def op_float_floor(self, b): + assert type(b) is float + return math.floor(b) + + def op_float_fmod(self, b,c): + assert type(b) is float + assert type(c) is float + return math.fmod(b,c) + # __________________________________________________________ # primitive operations from pypy.objspace.flow.operation import FunctionByName Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 25 18:15:41 2005 @@ -7,7 +7,7 @@ from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr from pypy.rpython import rptr from pypy.rpython.robject import pyobj_repr -from pypy.rpython.rfloat import float_repr +from pypy.rpython.rfloat import float_repr, FloatRepr from pypy.rpython import rclass @@ -154,6 +154,18 @@ return i1 return i2 +def rtype_math_floor(hop): + vlist = hop.inputargs(lltype.Float) + return hop.genop('float_floor', vlist, resulttype=lltype.Float) + +def rtype_math_fmod(hop): + vlist = hop.inputargs(lltype.Float, lltype.Float) + return hop.genop('float_fmod', vlist, resulttype=lltype.Float) + +import math +##def ll_floor(f1): +## return float(int((f1) + # collect all functions import __builtin__ BUILTIN_TYPER = {} @@ -161,7 +173,8 @@ if name.startswith('rtype_builtin_'): original = getattr(__builtin__, name[14:]) BUILTIN_TYPER[original] = value - +BUILTIN_TYPER[math.floor] = rtype_math_floor +BUILTIN_TYPER[math.fmod] = rtype_math_fmod # annotation of low-level types def rtype_malloc(hop): 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 Sat Jun 25 18:15:41 2005 @@ -40,3 +40,27 @@ assert ev_fun(1, -1) == 1 assert ev_fun(2, 2) == 2 assert ev_fun(-1, -12) == -1 + +def test_builtin_math_floor(): + import math + def fn(f): + + return math.floor(f) + ev_fun = make_interpreter(fn, [0.0]) + import random + for i in range(20): + rv = 1000 * float(i-10) #random.random() + assert math.floor(rv) == ev_fun(rv) + +def test_builtin_math_fmod(): + import math + def fn(f,y): + + return math.fmod(f,y) + ev_fun = make_interpreter(fn, [0.0,0.0]) + for i in range(20): + for j in range(20): + rv = 1000 * float(i-10) + ry = 100 * float(i-10) +0.1 + assert math.fmod(rv,ry) == ev_fun(rv,ry) + \ No newline at end of file From arigo at codespeak.net Sat Jun 25 18:19:24 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 25 Jun 2005 18:19:24 +0200 (CEST) Subject: [pypy-svn] r13878 - pypy/dist/pypy/translator Message-ID: <20050625161924.8F7EE27B5E@code1.codespeak.net> Author: arigo Date: Sat Jun 25 18:19:22 2005 New Revision: 13878 Modified: pypy/dist/pypy/translator/simplify.py Log: Oups. 'func' may not be hashable if it's a bound method of a mutable object. Modified: pypy/dist/pypy/translator/simplify.py ============================================================================== --- pypy/dist/pypy/translator/simplify.py (original) +++ pypy/dist/pypy/translator/simplify.py Sat Jun 25 18:19:22 2005 @@ -419,8 +419,11 @@ # ... if op.args and isinstance(op.args[0], Constant): func = op.args[0].value - if func in CanRemoveBuiltins: - del block.operations[i] + try: + if func in CanRemoveBuiltins: + del block.operations[i] + except TypeError: # func is not hashable + pass # look for output variables never used # warning: this must be completely done *before* we attempt to From mwh at codespeak.net Sat Jun 25 18:23:25 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 18:23:25 +0200 (CEST) Subject: [pypy-svn] r13880 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625162325.D2A3427B66@code1.codespeak.net> Author: mwh Date: Sat Jun 25 18:23:24 2005 New Revision: 13880 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: enable test of calling a bound method attached to a constant. the reason the last checkin wasn't complete has to do with .setup() not being called on classes we only see as instances of constants. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sat Jun 25 18:23:24 2005 @@ -380,6 +380,7 @@ try: return self.prebuiltinstances[id(value)][1] except KeyError: + self.setup() result = malloc(self.object_type) self.prebuiltinstances[id(value)] = value, result self.initialize_prebuilt_instance(value, classdef, result) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sat Jun 25 18:23:24 2005 @@ -214,12 +214,13 @@ res = ev_f1(1) assert res == 7 -def dont_test_rpbc_bound_method_static_call(): +def test_rpbc_bound_method_static_call(): class R: def meth(self): return 0 r = R() + m = r.meth def fn(): - return r.meth() + return m() res = interpret(fn, []) assert res == 0 From ale at codespeak.net Sat Jun 25 18:33:55 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 18:33:55 +0200 (CEST) Subject: [pypy-svn] r13881 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625163355.1B2FC27B57@code1.codespeak.net> Author: ale Date: Sat Jun 25 18:33:53 2005 New Revision: 13881 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: added support for time.time Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 25 18:33:53 2005 @@ -222,6 +222,14 @@ return hop.llops.convertvar(v, pyobj_repr, float_repr) BUILTIN_TYPER[time.clock] = rtype_time_clock + + +def rtype_time_time(hop): + c = hop.inputconst(pyobj_repr, time.time) + v = hop.genop('simple_call', [c], resulttype = pyobj_repr) + return hop.llops.convertvar(v, pyobj_repr, float_repr) + +BUILTIN_TYPER[time.time] = rtype_time_time import math 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 Sat Jun 25 18:33:53 2005 @@ -63,4 +63,13 @@ rv = 1000 * float(i-10) ry = 100 * float(i-10) +0.1 assert math.fmod(rv,ry) == ev_fun(rv,ry) - \ No newline at end of file +import time +def test_time_time(): + def f(neg): + if neg: + return time.time() + else: + return time.clock() + ev_fn = make_interpreter(f,[True]) + assert isinstance(ev_fn(True),float) + assert isinstance(ev_fn(False),float) \ No newline at end of file From ale at codespeak.net Sat Jun 25 18:35:25 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 18:35:25 +0200 (CEST) Subject: [pypy-svn] r13882 - pypy/extradoc/sprintinfo Message-ID: <20050625163525.3FA1127B57@code1.codespeak.net> Author: ale Date: Sat Jun 25 18:35:24 2005 New Revision: 13882 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: added support for time.time Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 18:35:24 2005 @@ -11,9 +11,6 @@ Builtins -------- - (easy) math.floor - (easy) math.fmod - (strange)(delegating to backend?) sys.getrefcount (medium) applevel sys module should not refer to interplevel sys.getdefaultencoding From ale at codespeak.net Sat Jun 25 18:36:49 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 18:36:49 +0200 (CEST) Subject: [pypy-svn] r13883 - pypy/extradoc/sprintinfo Message-ID: <20050625163649.83A1B27B5E@code1.codespeak.net> Author: ale Date: Sat Jun 25 18:36:48 2005 New Revision: 13883 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: added support for time.time (Something went wrong with the previous checkin) Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 18:36:48 2005 @@ -15,8 +15,6 @@ (medium) applevel sys module should not refer to interplevel sys.getdefaultencoding - (easy) time.time (see how time.clock is done) - implement in RPython (and change importing.py accordingly) os.path.dirname/normpath/join (including the closure of what they use) From hpk at codespeak.net Sat Jun 25 18:38:50 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 18:38:50 +0200 (CEST) Subject: [pypy-svn] r13885 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050625163850.EE2B327B57@code1.codespeak.net> Author: hpk Date: Sat Jun 25 18:38:49 2005 New Revision: 13885 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: support chr.isspace() Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jun 25 18:38:49 2005 @@ -326,6 +326,9 @@ def len(chr): return immutablevalue(1) + def method_isspace(chr): + return SomeBool() + class __extend__(SomeUnicodeCodePoint): def ord(uchr): Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jun 25 18:38:49 2005 @@ -288,6 +288,9 @@ vlist = hop.inputargs(char_repr) return hop.genop('cast_char_to_int', vlist, resulttype=Signed) + def rtype_method_isspace(_, hop): + vlist = hop.inputargs(char_repr) + return hop.llops.gendirectcall(ll_char_isspace, vlist[0]) class __extend__(pairtype(CharRepr, CharRepr)): def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq') @@ -382,6 +385,12 @@ # Low-level methods. These can be run for testing, but are meant to # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. +# +def ll_char_isspace(ch): + # XXX: + #return ord(ch) in (9, 10, 11, 12, 13, 32) + c = ord(ch) + return 9 <= c <= 13 or c == 32 def ll_strlen(s): return len(s.chars) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sat Jun 25 18:38:49 2005 @@ -79,6 +79,15 @@ assert res.chars[0] == 'x' assert res.chars[1] == '.' +def test_char_isspace(): + def fn(s): + return s.isspace() + efn = make_interpreter(fn, ['x']) + res = efn('x') + assert res == False + res = efn(' ') + assert res == True + def test_char_compare(): res = interpret(lambda c1, c2: c1 == c2, ['a', 'b']) assert res is False From ale at codespeak.net Sat Jun 25 18:49:18 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 18:49:18 +0200 (CEST) Subject: [pypy-svn] r13888 - pypy/dist/pypy/rpython/test Message-ID: <20050625164918.74AE427B57@code1.codespeak.net> Author: ale Date: Sat Jun 25 18:49:17 2005 New Revision: 13888 Modified: pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: bogus test of time.time/clock 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 Sat Jun 25 18:49:17 2005 @@ -63,13 +63,15 @@ rv = 1000 * float(i-10) ry = 100 * float(i-10) +0.1 assert math.fmod(rv,ry) == ev_fun(rv,ry) -import time -def test_time_time(): - def f(neg): - if neg: - return time.time() - else: - return time.clock() - ev_fn = make_interpreter(f,[True]) - assert isinstance(ev_fn(True),float) - assert isinstance(ev_fn(False),float) \ No newline at end of file +##import time +##def test_time_time(): +## def f(neg): +## if neg: +## return time.time() +## else: +## return time.clock() +## ev_fn = make_interpreter(f,[True]) +## assert isinstance(ev_fn(True),float) +## assert isinstance(ev_fn(False),float) + + \ No newline at end of file From mwh at codespeak.net Sat Jun 25 19:05:33 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 19:05:33 +0200 (CEST) Subject: [pypy-svn] r13890 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625170533.5B2BF27B57@code1.codespeak.net> Author: mwh Date: Sat Jun 25 19:05:31 2005 New Revision: 13890 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Relax a test in RTyper.translate_hl_to_ll to being more realistic. Implement a convert_const for rpbc.MethodsPBCRepr. Test. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 25 19:05:31 2005 @@ -370,6 +370,11 @@ self.r_im_self = rclass.getinstancerepr(rtyper, self.classdef) self.lowleveltype = self.r_im_self.lowleveltype + def convert_const(self, method): + if getattr(method, 'im_func', None) is None: + raise TyperError("not a bound method: %r" % method) + return self.r_im_self.convert_const(method.im_self) + def rtype_simple_call(self, hop): r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sat Jun 25 19:05:31 2005 @@ -21,7 +21,7 @@ from pypy.rpython.lltype import Signed, Unsigned, Float, Char, Bool, Void from pypy.rpython.lltype import LowLevelType, Ptr, ContainerType from pypy.rpython.lltype import FuncType, functionptr, typeOf, RuntimeTypeInfo -from pypy.rpython.lltype import attachRuntimeTypeInfo +from pypy.rpython.lltype import attachRuntimeTypeInfo, Primitive from pypy.tool.sourcetools import func_with_new_name, valid_identifier from pypy.translator.unsimplify import insert_empty_block from pypy.rpython.rmodel import Repr, inputconst, TyperError, getfunctionptr @@ -265,16 +265,10 @@ # for simplicity of the translate_meth, resultvar is usually not # op.result here. We have to replace resultvar with op.result # in all generated operations. - if isinstance(resultvar, Constant): - if not hop.s_result.is_constant(): - raise TyperError("the annotator doesn't agree that '%s' " - "returns a constant" % op.opname) - # xxx allow not only primitive const to be returned, but we don't have - # general equality for non-primitive ll constant objects; - # works for strings tough - if resultvar.value != inputconst(hop.r_result, hop.s_result.const).value: - raise TyperError("constant mismatch: %r vs %r" % ( - resultvar.value, hop.s_result.const)) + if hop.s_result.is_constant(): + if isinstance(resultvar, Constant) and \ + isinstance(hop.r_result.lowleveltype, Primitive): + assert resultvar.value == hop.s_result.const resulttype = resultvar.concretetype op.result.concretetype = hop.r_result.lowleveltype if op.result.concretetype != resulttype: Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sat Jun 25 19:05:31 2005 @@ -224,3 +224,13 @@ return m() res = interpret(fn, []) assert res == 0 + +def test_constant_return_disagreement(): + class R: + def meth(self): + return 0 + r = R() + def fn(): + return r.meth() + res = interpret(fn, []) + assert res == 0 From hpk at codespeak.net Sat Jun 25 19:21:31 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 19:21:31 +0200 (CEST) Subject: [pypy-svn] r13892 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625172131.3D2B227B57@code1.codespeak.net> Author: hpk Date: Sat Jun 25 19:21:28 2005 New Revision: 13892 Modified: pypy/dist/pypy/rpython/rbool.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: (arigo, hpk) - new Repr.get_ll_eq_function which returns a lowlevel function suitable for checking equality for the given repr. None means that values/pointers can be =='ed - prepare rtuple's contains a bit Modified: pypy/dist/pypy/rpython/rbool.py ============================================================================== --- pypy/dist/pypy/rpython/rbool.py (original) +++ pypy/dist/pypy/rpython/rbool.py Sat Jun 25 19:21:28 2005 @@ -23,6 +23,9 @@ raise TyperError("not a bool: %r" % (value,)) return value + def get_ll_eq_function(self): + return None + def rtype_is_true(_, hop): vlist = hop.inputargs(Bool) return vlist[0] Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sat Jun 25 19:21:28 2005 @@ -386,6 +386,9 @@ self.initialize_prebuilt_instance(value, classdef, result) return result + def get_ll_eq_function(self): + return None + def initialize_prebuilt_instance(self, value, classdef, result): if self.classdef is not None: # recursively build the parent part of the instance Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sat Jun 25 19:21:28 2005 @@ -100,6 +100,9 @@ raise TyperError("not a float: %r" % (value,)) return float(value) + def get_ll_eq_function(self): + return None + def rtype_is_true(_, hop): vlist = hop.inputargs(Float) return hop.genop('float_is_true', vlist, resulttype=Bool) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Sat Jun 25 19:21:28 2005 @@ -198,6 +198,9 @@ return r_uint(value) raise NotImplementedError + def get_ll_eq_function(self): + return None + def rtype_float(_, hop): vlist = hop.inputargs(Float) return vlist[0] Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sat Jun 25 19:21:28 2005 @@ -78,15 +78,7 @@ return result def get_eqfunc(self): - if self.item_repr == string_repr: - func = ll_streq - elif isinstance(self.item_repr.lowleveltype, Primitive): - func = None - elif isinstance(self.item_repr, InstanceRepr): - func = None - else: - raise TyperError, 'comparison not implemented for %r' % self - return inputconst(Void, func) + return inputconst(Void, self.item_repr.get_ll_eq_function()) def rtype_bltn_list(self,hop): v_lst = hop.inputarg(self,0) Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sat Jun 25 19:21:28 2005 @@ -49,6 +49,9 @@ self, value)) return value + def get_ll_eq_function(self): + raise TyperError, 'no equality function for %r' % self + # default implementation of some operations def rtype_getattr(self, hop): @@ -223,3 +226,4 @@ lloutput = getconcretetype(graph.getreturnvar()) FT = FuncType(llinputs, lloutput) return functionptr(FT, func.func_name, graph = graph, _callable = func) + Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sat Jun 25 19:21:28 2005 @@ -70,6 +70,9 @@ CONST_STR_CACHE[value] = p return p + def get_ll_eq_function(self): + return ll_streq + def rtype_len(_, hop): v_str, = hop.inputargs(string_repr) return hop.gendirectcall(ll_strlen, v_str) @@ -277,6 +280,9 @@ raise TyperError("not a character: %r" % (value,)) return value + def get_ll_eq_function(self): + return None + def rtype_len(_, hop): return hop.inputconst(Signed, 1) @@ -313,6 +319,9 @@ raise TyperError("not a unicode character: %r" % (value,)) return value + def get_ll_eq_function(self): + return None + ## def rtype_len(_, hop): ## return hop.inputconst(Signed, 1) ## Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Sat Jun 25 19:21:28 2005 @@ -41,6 +41,9 @@ setattr(p, name, r.convert_const(obj)) return p + #def get_eqfunc(self): + # return inputconst(Void, self.item_repr.get_ll_eq_function()) + def rtype_len(self, hop): return hop.inputconst(Signed, len(self.items_r)) @@ -60,6 +63,10 @@ cindex = inputconst(Signed, index) hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem) return vlist + +#class __extend__(pairtype(TupleRepr, Repr)): +# def rtype_contains((r_tup, r_item), hop): +# XXX class __extend__(pairtype(TupleRepr, IntegerRepr)): Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Sat Jun 25 19:21:28 2005 @@ -5,6 +5,7 @@ from pypy.rpython.rint import signed_repr from pypy.rpython.rbool import bool_repr from pypy.rpython.test.test_llinterp import interpret, make_interpreter +import py def test_rtuple(): rtuple = TupleRepr([signed_repr, bool_repr]) @@ -69,3 +70,18 @@ fn = make_interpreter(f,[])#,view=True) res = fn() assert res == 123 + +def test_constant_tuple_contains(): + py.test.skip("tuple contains not implemented") + def f(i): + t1 = (1, 2, 3, 4) + return i in t1 + fn = make_interpreter(f, [3], view=False, viewbefore=False) + res = fn(3) + assert res is True + res = fn(0) + assert res is False + + + + From tismer at codespeak.net Sat Jun 25 19:39:38 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 19:39:38 +0200 (CEST) Subject: [pypy-svn] r13893 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050625173938.30F1427B57@code1.codespeak.net> Author: tismer Date: Sat Jun 25 19:39:36 2005 New Revision: 13893 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (arre + chris) implemented strdict's get(), keys(), values(), items() Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sat Jun 25 19:39:36 2005 @@ -272,14 +272,15 @@ return dct.dictdef.read_key() def method_get(dct, key, dfl): - return unionof(dct.dictdef.read_value(), dfl) + dct.dictdef.generalize_key(key) + dct.dictdef.generalize_value(dfl) + return dct.dictdef.read_value() def method_copy(dct): return dct def method_update(dct1, dct2): - dct1.dictdef.generalize_key(dct2.dictdef.read_key()) - dct1.dictdef.generalize_value(dct2.dictdef.read_value()) + dct1.dictdef.union(dct2.dictdef) def method_keys(dct): return getbookkeeper().newlist(dct.dictdef.read_key()) Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 19:39:36 2005 @@ -3,7 +3,8 @@ from pypy.objspace.flow.model import Constant from pypy.rpython import rmodel, lltype, rstr from pypy.rpython.rstr import STR, string_repr -from pypy.rpython.rarithmetic import r_uint +from pypy.rpython.rarithmetic import r_uint +from pypy.rpython import rlist # ____________________________________________________________ # @@ -97,19 +98,36 @@ self.value_repr) return hop.gendirectcall(ll_get, v_dict, v_key, v_default) -""" - rdict: (easy) method_get (?) - (easy) method_copy - (easy) method_update (?) - (easy) method_keys (?) - (easy) method_values (?) - (easy) method_items (?) -""" + def rtype_method_copy(self, hop): + v_dict, = hop.inputargs(self) + return hop.gendirectcall(ll_copy, v_dict) + + def rtype_method_update(self, hop): + v_dic1, v_dic2 = hop.inputargs(self, self) + return hop.gendirectcall(ll_update, v_dic1, v_dic2) + + def rtype_method_keys(self, hop): + v_dic, = hop.inputargs(self) + r_list = hop.r_result + c1 = hop.inputconst(lltype.Void, r_list.lowleveltype) + return hop.gendirectcall(ll_keys, v_dic, c1) + + def rtype_method_values(self, hop): + v_dic, = hop.inputargs(self) + r_list = hop.r_result + c1 = hop.inputconst(lltype.Void, r_list.lowleveltype) + return hop.gendirectcall(ll_values, v_dic, c1) + + def rtype_method_items(self, hop): + v_dic, = hop.inputargs(self) + r_list = hop.r_result + c1 = hop.inputconst(lltype.Void, r_list.lowleveltype) + return hop.gendirectcall(ll_items, v_dic, c1) class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): def rtype_getitem((r_dict, r_string), hop): - v_dict, v_key = hop.inputargs(r_dict, string_repr) + v_dict, v_key = hop.inputargs(r_dict, string_repr) return hop.gendirectcall(ll_strdict_getitem, v_dict, v_key) def rtype_delitem((r_dict, r_string), hop): @@ -311,4 +329,75 @@ else: return v_default +def ll_copy(v_dict): + DICTPTR = lltype.typeOf(v_dict) + d = lltype.malloc(DICTPTR.TO) + d.entries = lltype.malloc(DICTPTR.TO.entries.TO, len(v_dict.entries)) + d.num_items = v_dict.num_items + d.num_pristine_entries = v_dict.num_pristine_entries + i = 0 + dictlen = len(d.entries) + while i < dictlen: + d_entry = d.entries[i] + v_entry = v_dict.entries[i] + d_entry.key = v_entry.key + d_entry.value = v_entry.value + i += 1 + return d + +def ll_update(v_dic1, v_dic2): + d2len =len(v_dic2.entries) + entries = v_dic2.entries + i = 0 + while i < d2len: + entry = entries[i] + if entry.key and entry.key != deleted_entry_marker: + ll_strdict_setitem(v_dic1, entry.key, entry.value) + i += 1 + +def ll_keys(v_dic, LISTPTR): + res = rlist.ll_newlist(LISTPTR, v_dic.num_items) + dlen = len(v_dic.entries) + entries = v_dic.entries + i = 0 + p = 0 + while i < dlen: + key = entries[i].key + if key and key != deleted_entry_marker: + res.items[p] = key + p += 1 + i += 1 + return res +def ll_values(v_dic, LISTPTR): + res = rlist.ll_newlist(LISTPTR, v_dic.num_items) + dlen = len(v_dic.entries) + entries = v_dic.entries + i = 0 + p = 0 + while i < dlen: + key = entries[i].key + value = entries[i].value + if key and key != deleted_entry_marker: + res.items[p] = value + p += 1 + i += 1 + return res + +def ll_items(v_dic, LISTPTR): + res = rlist.ll_newlist(LISTPTR, v_dic.num_items) + dlen = len(v_dic.entries) + entries = v_dic.entries + i = 0 + p = 0 + while i < dlen: + key = entries[i].key + value = entries[i].value + if key and key != deleted_entry_marker: + r = lltype.malloc(LISTPTR.TO.items.TO.OF.TO) + r.item0 = key + r.item1 = value + res.items[p] = r + p += 1 + i += 1 + return res Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Sat Jun 25 19:39:36 2005 @@ -163,8 +163,78 @@ def test_dict_get(): def func(): - # XXX shouldn't the get imply the type by its default? - dic = {'blah': 1} - return dic.get('hi', 42) * 10 + dic.get('blah', 2) + dic = {} + x1 = dic.get('hi', 42) + dic['blah'] = 1 # XXX this triggers type determination + x2 = dic.get('blah', 2) + return x1 * 10 + x2 res = interpret(func, ()) assert res == 421 + +def test_dict_get_empty(): + def func(): + # this time without writing to the dict + dic = {} + x1 = dic.get('hi', 42) + x2 = dic.get('blah', 2) + return x1 * 10 + x2 + res = interpret(func, ()) + assert res == 422 + +def test_dict_copy(): + def func(): + # XXX this does not work if we use chars, only! + dic = {'ab':1, 'b':2} + d2 = dic.copy() + ok = 1 + for key in d2: + if dic[key] != d2[key]: + ok = 0 + ok &= len(dic) == len(d2) + d2['c'] = 3 + ok &= len(dic) == len(d2) - 1 + return ok + res = interpret(func, ()) + assert res == 1 + +def test_dict_update(): + def func(): + dic = {'ab':1000, 'b':200} + d2 = {'b':30, 'cb':4} + dic.update(d2) + ok = len(dic) == 3 + sum = ok + for key in dic: + sum += dic[key] + return sum + res = interpret(func, ()) + assert res == 1035 + +def test_dict_keys(): + def func(): + dic = {' 4':1000, ' 8':200} + keys = dic.keys() + return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys) + res = interpret(func, ()) + assert res == 14 + +def test_dict_values(): + def func(): + dic = {' 4':1000, ' 8':200} + values = dic.values() + return values[0] + values[1] + len(values) + res = interpret(func, ()) + assert res == 1202 + +def test_dict_items(): + def func(): + dic = {' 4':1000, ' 8':200} + items = dic.items() + res = len(items) + for key, value in items: + res += ord(key[1]) - ord('0') + value + return res + res = interpret(func, ()) + assert res == 1214 + + From tismer at codespeak.net Sat Jun 25 19:42:03 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 19:42:03 +0200 (CEST) Subject: [pypy-svn] r13894 - pypy/extradoc/sprintinfo Message-ID: <20050625174203.E8E0127B57@code1.codespeak.net> Author: tismer Date: Sat Jun 25 19:42:03 2005 New Revision: 13894 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: (arre + chris) implemented strdict's get(), copy(), update(), keys(), values(), items() Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 19:42:03 2005 @@ -27,13 +27,13 @@ rclass: (easy) issubtype (arre, christian): - rdict: (easy) method_get (?) - (easy) method_copy - (easy) method_update (?) - (easy) method_keys (?) - (easy) method_values (?) - (easy) method_items (?) - + rdict: (DONE) (easy) method_get (?) + (DONE) (easy) method_copy + (DONE) (easy) method_update (?) + (DONE) (easy) method_keys (?) + (DONE) (easy) method_values (?) + (DONE) (easy) method_items (?) + (easy) contains (easy) rstr: str.split(single_constant_character) (easy) rpbc: is_true --> False for None From mwh at codespeak.net Sat Jun 25 19:52:30 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 19:52:30 +0200 (CEST) Subject: [pypy-svn] r13895 - pypy/dist/pypy/rpython Message-ID: <20050625175230.F3C2227B57@code1.codespeak.net> Author: mwh Date: Sat Jun 25 19:52:29 2005 New Revision: 13895 Modified: pypy/dist/pypy/rpython/rbuiltin.py Log: prevent a list from ending up in a frozendict. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat Jun 25 19:52:29 2005 @@ -237,6 +237,6 @@ vlist = hop.inputargs(lltype.Float) # XXX need PyFPE_START_PROTECT/PyFPE_END_PROTECT/Py_SET_ERRNO_ON_MATH_ERROR return hop.llops.gencapicall('exp', vlist, resulttype=lltype.Float, - includes=["math.h"]) # XXX clean up needed + includes=("math.h",)) # XXX clean up needed BUILTIN_TYPER[math.exp] = rtype_math_exp From ac at codespeak.net Sat Jun 25 19:54:28 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sat, 25 Jun 2005 19:54:28 +0200 (CEST) Subject: [pypy-svn] r13896 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625175428.486B327B57@code1.codespeak.net> Author: ac Date: Sat Jun 25 19:54:28 2005 New Revision: 13896 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (arre + christian) Add contains to rdict. Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 19:54:28 2005 @@ -137,7 +137,11 @@ def rtype_setitem((r_dict, r_string), hop): v_dict, v_key, v_value = hop.inputargs(r_dict, string_repr, r_dict.value_repr) hop.gendirectcall(ll_strdict_setitem, v_dict, v_key, v_value) - + + def rtype_contains((r_dict, r_string), hop): + v_dict, v_key = hop.inputargs(r_dict, string_repr) + return hop.gendirectcall(ll_contains, v_dict, v_key) + class __extend__(pairtype(StrDictRepr, StrDictRepr)): def convert_from_to((r_dict1, r_dict2), v, llops): # check that we don't convert from StrDicts with @@ -401,3 +405,9 @@ p += 1 i += 1 return res + +def ll_contains(d, key): + entry = ll_strdict_lookup(d, key) + if entry.key and entry.key != deleted_entry_marker: + return True + return False Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Sat Jun 25 19:54:28 2005 @@ -237,4 +237,9 @@ res = interpret(func, ()) assert res == 1214 - +def test_dict_contains(): + def func(): + dic = {' 4':1000, ' 8':200} + return ' 4' in dic and ' 9' not in dic + res = interpret(func, ()) + assert res is True From tismer at codespeak.net Sat Jun 25 19:54:29 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 19:54:29 +0200 (CEST) Subject: [pypy-svn] r13897 - pypy/extradoc/sprintinfo Message-ID: <20050625175429.84ED827B57@code1.codespeak.net> Author: tismer Date: Sat Jun 25 19:54:28 2005 New Revision: 13897 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: (arre) stringdict.contains Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 19:54:28 2005 @@ -33,7 +33,7 @@ (DONE) (easy) method_keys (?) (DONE) (easy) method_values (?) (DONE) (easy) method_items (?) - (easy) contains + (DONE) (easy) contains (easy) rstr: str.split(single_constant_character) (easy) rpbc: is_true --> False for None From mwh at codespeak.net Sat Jun 25 20:02:57 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 20:02:57 +0200 (CEST) Subject: [pypy-svn] r13898 - pypy/dist/pypy/rpython Message-ID: <20050625180257.3F5B527B57@code1.codespeak.net> Author: mwh Date: Sat Jun 25 20:02:56 2005 New Revision: 13898 Modified: pypy/dist/pypy/rpython/rpbc.py Log: Support converting None to PyObject*. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 25 20:02:56 2005 @@ -8,7 +8,7 @@ from pypy.rpython.rmodel import Repr, TyperError, inputconst from pypy.rpython import rclass from pypy.rpython.rtyper import HighLevelOp - +from pypy.rpython import robject class __extend__(annmodel.SomePBC): def rtyper_makerepr(self, rtyper): @@ -121,6 +121,10 @@ def rtype_is_((rnone1, robj2), hop): return rtype_is_None(robj2, rnone1, hop, pos=1) +class __extend__(pairtype(NoneFrozenPBCRepr, robject.PyObjRepr)): + + def convert_from_to(_, v, llops): + return inputconst(robject.pyobj_repr, None) # ____________________________________________________________ From mwh at codespeak.net Sat Jun 25 20:03:50 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 20:03:50 +0200 (CEST) Subject: [pypy-svn] r13899 - pypy/dist/pypy/rpython Message-ID: <20050625180350.9D8E127B57@code1.codespeak.net> Author: mwh Date: Sat Jun 25 20:03:49 2005 New Revision: 13899 Modified: pypy/dist/pypy/rpython/rpbc.py Log: OK, that was an excessively complicated fix to the bound-method-of-Constant issue. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 25 20:03:49 2005 @@ -222,8 +222,7 @@ hop2.args_s[0] = self.s_im_self # make the 1st arg stand for 'im_self' hop2.args_r[0] = self.r_im_self # (same lowleveltype as 'self') if isinstance(hop2.args_v[0], Constant): - hop2.args_v[0] = hop2.llops.genop('same_as', [hop2.args_v[0]], - resulttype=hop.args_r[0]) + hop2.args_v[0] = hop.inputarg(self, 0) c = Constant(self.function) hop2.v_s_insertfirstarg(c, s_function) # insert 'function' # now hop2 looks like simple_call(function, self, args...) From tismer at codespeak.net Sat Jun 25 20:23:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 20:23:16 +0200 (CEST) Subject: [pypy-svn] r13900 - in pypy/dist/pypy: rpython rpython/test tool Message-ID: <20050625182316.5158427B57@code1.codespeak.net> Author: tismer Date: Sat Jun 25 20:23:14 2005 New Revision: 13900 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py pypy/dist/pypy/tool/asterisk.py Log: (arre, chris) refactored stringlist.keys()/values()/items() to use just a single implementation and specialization. Have a look, it is crazy! Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 20:23:14 2005 @@ -106,23 +106,21 @@ v_dic1, v_dic2 = hop.inputargs(self, self) return hop.gendirectcall(ll_update, v_dic1, v_dic2) - def rtype_method_keys(self, hop): + def _rtype_method_kvi(self, hop, spec): v_dic, = hop.inputargs(self) r_list = hop.r_result + v_func = hop.inputconst(lltype.Void, spec) c1 = hop.inputconst(lltype.Void, r_list.lowleveltype) - return hop.gendirectcall(ll_keys, v_dic, c1) + return hop.gendirectcall(ll_kvi, v_dic, c1, v_func) + + def rtype_method_keys(self, hop): + return self._rtype_method_kvi(hop, dum_keys) def rtype_method_values(self, hop): - v_dic, = hop.inputargs(self) - r_list = hop.r_result - c1 = hop.inputconst(lltype.Void, r_list.lowleveltype) - return hop.gendirectcall(ll_values, v_dic, c1) + return self._rtype_method_kvi(hop, dum_values) def rtype_method_items(self, hop): - v_dic, = hop.inputargs(self) - r_list = hop.r_result - c1 = hop.inputconst(lltype.Void, r_list.lowleveltype) - return hop.gendirectcall(ll_items, v_dic, c1) + return self._rtype_method_kvi(hop, dum_items) class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): @@ -359,50 +357,31 @@ ll_strdict_setitem(v_dic1, entry.key, entry.value) i += 1 -def ll_keys(v_dic, LISTPTR): - res = rlist.ll_newlist(LISTPTR, v_dic.num_items) - dlen = len(v_dic.entries) - entries = v_dic.entries - i = 0 - p = 0 - while i < dlen: - key = entries[i].key - if key and key != deleted_entry_marker: - res.items[p] = key - p += 1 - i += 1 - return res - -def ll_values(v_dic, LISTPTR): - res = rlist.ll_newlist(LISTPTR, v_dic.num_items) - dlen = len(v_dic.entries) - entries = v_dic.entries - i = 0 - p = 0 - while i < dlen: - key = entries[i].key - value = entries[i].value - if key and key != deleted_entry_marker: - res.items[p] = value - p += 1 - i += 1 - return res +def dum_keys(): pass +def dum_values(): pass +def dum_items():pass -def ll_items(v_dic, LISTPTR): +def ll_kvi(v_dic, LISTPTR, v_func): res = rlist.ll_newlist(LISTPTR, v_dic.num_items) dlen = len(v_dic.entries) entries = v_dic.entries + items = res.items i = 0 p = 0 while i < dlen: - key = entries[i].key - value = entries[i].value + entry = entries[i] + key = entry.key if key and key != deleted_entry_marker: + if v_func is dum_items: r = lltype.malloc(LISTPTR.TO.items.TO.OF.TO) r.item0 = key - r.item1 = value - res.items[p] = r - p += 1 + r.item1 = entry.value + items[p] = r + elif v_func is dum_keys: + items[p] = key + elif v_func is dum_values: + items[p] = entry.value + p += 1 i += 1 return res Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Sat Jun 25 20:23:14 2005 @@ -215,7 +215,7 @@ dic = {' 4':1000, ' 8':200} keys = dic.keys() return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys) - res = interpret(func, ()) + res = interpret(func, ())#, view=True) assert res == 14 def test_dict_values(): Modified: pypy/dist/pypy/tool/asterisk.py ============================================================================== --- pypy/dist/pypy/tool/asterisk.py (original) +++ pypy/dist/pypy/tool/asterisk.py Sat Jun 25 20:23:14 2005 @@ -23,16 +23,26 @@ finally: sys.stdout = hold -def offset2lineno(c, stopat): - tab = c.co_lnotab - line = c.co_firstlineno - addr = 0 - for i in range(0, len(tab), 2): - addr = addr + ord(tab[i]) - if addr > stopat: - break - line = line + ord(tab[i+1]) - return line +def opsequence(code): + for line in disasm(code).split('\n'): + pieces = line.split('(', 1) + if len(pieces) == 1: + start, arg = pieces[0], None + else: + start, arg = pieces + words = start.split() + while words and (words[0].isdigit() or words[0] == '>>'): + word = words.pop(0) + if word.isdigit(): + ofs = int(word) + if not words: + continue + op = words[0] + if arg: + arg = arg[:-1] # ) + if op.startswith('JUMP'): + arg = int(words[1]) + yield ofs, op, arg def globalsof(code, globrefs=None, stars=None, globals=None): names = code.co_names @@ -41,30 +51,23 @@ if stars is None: stars = [] # do stars in order if globals is None: globals = {} in_seq = False - for line in disasm(code).split('\n'): - words = line.split() - ofs = -1 - while words and words[0].isdigit(): - ofs = int(words.pop(0)) - if not words: - continue - op = words[0] + for ofs, op, arg in opsequence(code): if op == 'LOAD_GLOBAL': - name = words[-1][1:-1] # omit () + name = arg refs = globrefs.setdefault(name, {}) offsets = refs.setdefault(code, []) offsets.append(ofs) elif op == 'IMPORT_NAME': in_seq = True - imp_module = words[-1][1:-1] + imp_module = arg imp_what = None elif op == 'IMPORT_FROM': in_seq = True - imp_what = words[-1][1:-1] + imp_what = arg elif op == 'STORE_NAME': # we are not interested in local imports, which # would generate a STORE_FAST - name = words[-1][1:-1] + name = arg if in_seq: globals[name] = imp_what, imp_module in_seq = False @@ -77,29 +80,44 @@ in_seq = False return globrefs, stars, globals -def allglobalsof(code): - globrefs = {} - stars = [] - globals = {} - seen = {} - if type(code) is str: - fname = code - code = compile(file(fname).read(), fname, 'exec') - todo = [code] - while todo: - code = todo.pop(0) - globalsof(code, globrefs, stars, globals) - seen[code] = True - for const in code.co_consts: - if type(const) is type(code) and const not in seen: - todo.append(const) - return globrefs, stars, globals +def offsetmap(c): + # create a mapping from offsets to line numbers. + # we count lines from zero, here. + tab = c.co_lnotab + line = c.co_firstlineno - 1 + addr = 0 + res = { addr: line } + for i in range(0, len(tab), 2): + addr = addr + ord(tab[i]) + line = line + ord(tab[i+1]) + res[addr] = line + return res + class Analyser: def __init__(self, fname): self.fname = fname - self.globrefs, self.stars, self.globals = allglobalsof(fname) + self.source = file(fname).read() self.starimports = [] + self.codeobjects = {} + self.globrefs, self.stars, self.globals = self.analyse() + + def analyse(self): + globrefs = {} + stars = [] + globals = {} + seen = {} + code = compile(self.source, self.fname, 'exec') + todo = [code] + while todo: + code = todo.pop(0) + self.codeobjects[code] = offsetmap(code) + globalsof(code, globrefs, stars, globals) + seen[code] = True + for const in code.co_consts: + if type(const) is type(code) and const not in seen: + todo.append(const) + return globrefs, stars, globals def get_unknown_globals(self): from __builtin__ import __dict__ as bltin @@ -111,7 +129,7 @@ dic = {} exec "from %s import *" % modname in dic return dic - + def resolve_star_imports(self): implicit = {} which = {} @@ -129,4 +147,26 @@ for star, ofs in self.stars: imps.append( (ofs, star, which[star]) ) self.starimports = imps + + def find_statements(self): + # go through all code objects and collect + # line numbers. This gives us all statements. + lineset = {} + for co, ofs2line in self.codeobjects.items(): + for ofs, line in ofs2line.items(): + lineset[line] = True + linenos = lineset.keys() + if 0 not in linenos: + linenos.append(0) + linenos.sort() + self.linenos = linenos + # now create statement chunks + srclines = self.source.split('\n') + stmts = [] + start = 0 + for lno in linenos[1:] + [sys.maxint]: + stmt = '\n'.join(srclines[start:lno]) + stmts.append(stmt) + start = lno + self.statements = stmts \ No newline at end of file From mwh at codespeak.net Sat Jun 25 20:24:03 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 20:24:03 +0200 (CEST) Subject: [pypy-svn] r13901 - in pypy/dist/pypy/translator/c: . test Message-ID: <20050625182403.A69A927B57@code1.codespeak.net> Author: mwh Date: Sat Jun 25 20:24:02 2005 New Revision: 13901 Modified: pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_typed.py Log: tests that i tried and failed to check in a few minutes ago. test math.exp (which used gencapi with includes=something which was fairly broken) unbreak this. Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sat Jun 25 20:24:02 2005 @@ -400,15 +400,19 @@ if self.funcgen: argnames = self.funcgen.argnames() self.implementationtypename = db.gettype(T, argnames=argnames) - self.name = db.namespace.uniquename('g_' + self.basename()) - self.ptrname = self.name if hasattr(obj, 'includes'): self.includes = obj.includes + self.name = self.basename() + else: + self.name = db.namespace.uniquename('g_' + self.basename()) + self.ptrname = self.name def basename(self): return self.obj._name def enum_dependencies(self): + if self.funcgen is None: + return [] return self.funcgen.allconstantvalues() def forward_declaration(self): Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sat Jun 25 20:24:02 2005 @@ -253,3 +253,31 @@ fn = self.getcompiled(func) assert fn(5.0, 6.0) == func(5.0, 6.0) + + def test_rpbc_bound_method_static_call(self): + class R: + def meth(self): + return 0 + r = R() + m = r.meth + def fn(): + return m() + res = self.getcompiled(fn)() + assert res == 0 + + def test_constant_return_disagreement(self): + class R: + def meth(self): + return 0 + r = R() + def fn(): + return r.meth() + res = self.getcompiled(fn)() + assert res == 0 + + def test_math_exp(self): + from math import exp + def fn(f=float): + return exp(f) + f = self.getcompiled(fn) + assert f(1.0) == exp(1.0) From ale at codespeak.net Sat Jun 25 20:29:54 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 20:29:54 +0200 (CEST) Subject: [pypy-svn] r13902 - pypy/extradoc/sprintinfo Message-ID: <20050625182954.4A7DE27B5E@code1.codespeak.net> Author: ale Date: Sat Jun 25 20:29:51 2005 New Revision: 13902 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Done is_true for PBC's Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sat Jun 25 20:29:51 2005 @@ -36,9 +36,6 @@ (DONE) (easy) contains (easy) rstr: str.split(single_constant_character) - (easy) rpbc: is_true --> False for None - True for all other PBCs - Binary operations ----------------- From ale at codespeak.net Sat Jun 25 20:32:24 2005 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 25 Jun 2005 20:32:24 +0200 (CEST) Subject: [pypy-svn] r13903 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625183224.BAA9A27B57@code1.codespeak.net> Author: ale Date: Sat Jun 25 20:32:23 2005 New Revision: 13903 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rbuiltin.py Log: Done is_true for PBC's Fixed a bug in MultipleFrozenPBCRepr thanks to Armin Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 25 20:32:23 2005 @@ -60,8 +60,10 @@ lst = self.prebuiltinstances.items() lst.sort() return tuple(lst) - - + + def rtype_is_true(self,hop): + return Constant(True,Bool) + # ____________________________________________________________ @@ -100,7 +102,9 @@ # __ None ____________________________________________________ class NoneFrozenPBCRepr(SingleFrozenPBCRepr): - pass + + def rtype_is_true(self,hop): + return Constant(False,Bool) none_frozen_pbc_repr = NoneFrozenPBCRepr() @@ -161,8 +165,10 @@ def convert_const(self, pbc): if pbc is None: return nullptr(self.pbc_type) - if pbc not in self.access_set.objects: - raise TyperError("not found in PBC set: %r" % (pbc,)) + if isinstance(pbc, types.MethodType) and pbc.im_self is None: + value = pbc.im_func # unbound method -> bare function +## if pbc not in self.access_set.objects: +## raise TyperError("not found in PBC set: %r" % (pbc,)) try: return self.pbc_cache[pbc] except KeyError: 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 Sat Jun 25 20:32:23 2005 @@ -63,15 +63,22 @@ rv = 1000 * float(i-10) ry = 100 * float(i-10) +0.1 assert math.fmod(rv,ry) == ev_fun(rv,ry) -##import time -##def test_time_time(): -## def f(neg): -## if neg: -## return time.time() -## else: -## return time.clock() -## ev_fn = make_interpreter(f,[True]) -## assert isinstance(ev_fn(True),float) -## assert isinstance(ev_fn(False),float) - + +def test_pbc_isTrue(): + class C: + def f(self): + pass + + def g(obj): + return bool(obj) + def fn(neg): + c = C.f + return g(c) + ev_fun = make_interpreter(fn, [True]) + assert ev_fun(True) + def fn(neg): + c = None + return g(c) + ev_fun = make_interpreter(fn, [True]) + assert not ev_fun(True) \ No newline at end of file From mwh at codespeak.net Sat Jun 25 20:35:17 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 25 Jun 2005 20:35:17 +0200 (CEST) Subject: [pypy-svn] r13904 - pypy/dist/pypy/rpython Message-ID: <20050625183517.EBDEE27B57@code1.codespeak.net> Author: mwh Date: Sat Jun 25 20:35:17 2005 New Revision: 13904 Modified: pypy/dist/pypy/rpython/lltype.py Log: Catch a particular type of bug much earlier. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sat Jun 25 20:35:17 2005 @@ -744,6 +744,10 @@ def functionptr(TYPE, name, **attrs): if not isinstance(TYPE, FuncType): raise TypeError, "functionptr() for FuncTypes only" + try: + hash(tuple(attrs.items())) + except TypeError: + raise TypeError("'%r' must be hashable"%attrs) o = _func(TYPE, _name=name, **attrs) return _ptr(Ptr(TYPE), o) From tismer at codespeak.net Sat Jun 25 20:36:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 20:36:16 +0200 (CEST) Subject: [pypy-svn] r13905 - pypy/dist/pypy/rpython Message-ID: <20050625183616.A2FCA27B57@code1.codespeak.net> Author: tismer Date: Sat Jun 25 20:36:15 2005 New Revision: 13905 Modified: pypy/dist/pypy/rpython/rdict.py Log: commented the specialization trick Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 20:36:15 2005 @@ -361,6 +361,11 @@ def dum_values(): pass def dum_items():pass +# this is an implementation of keys(), values() and items() +# in a single function. +# note that by specialization on v_func, three different +# and very efficient functions are created. + def ll_kvi(v_dic, LISTPTR, v_func): res = rlist.ll_newlist(LISTPTR, v_dic.num_items) dlen = len(v_dic.entries) From tismer at codespeak.net Sat Jun 25 20:43:19 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 25 Jun 2005 20:43:19 +0200 (CEST) Subject: [pypy-svn] r13906 - pypy/dist/pypy/rpython Message-ID: <20050625184319.2F56A27B57@code1.codespeak.net> Author: tismer Date: Sat Jun 25 20:43:18 2005 New Revision: 13906 Modified: pypy/dist/pypy/rpython/rpbc.py Log: missing spaces. sorry for being penible, it is a personal thing :-) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sat Jun 25 20:43:18 2005 @@ -61,8 +61,8 @@ lst.sort() return tuple(lst) - def rtype_is_true(self,hop): - return Constant(True,Bool) + def rtype_is_true(self, hop): + return Constant(True, Bool) # ____________________________________________________________ @@ -103,8 +103,8 @@ # __ None ____________________________________________________ class NoneFrozenPBCRepr(SingleFrozenPBCRepr): - def rtype_is_true(self,hop): - return Constant(False,Bool) + def rtype_is_true(self, hop): + return Constant(False, Bool) none_frozen_pbc_repr = NoneFrozenPBCRepr() From hpk at codespeak.net Sat Jun 25 20:52:14 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sat, 25 Jun 2005 20:52:14 +0200 (CEST) Subject: [pypy-svn] r13907 - in pypy/dist/pypy/rpython: . test Message-ID: <20050625185214.785D927B57@code1.codespeak.net> Author: hpk Date: Sat Jun 25 20:52:11 2005 New Revision: 13907 Added: pypy/dist/pypy/rpython/rconstantdict.py - copied, changed from r13890, pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/test/test_rconstantdict.py (contents, props changed) Modified: pypy/dist/pypy/rpython/rdict.py Log: (hpk, arigo) - new: Constant Dictionaries with primitive types as keys (currently only ints and chars are supported and not really tested because people want to leave for dinner) Copied: pypy/dist/pypy/rpython/rconstantdict.py (from r13890, pypy/dist/pypy/rpython/rdict.py) ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sat Jun 25 20:52:11 2005 @@ -1,8 +1,7 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant -from pypy.rpython import rmodel, lltype, rstr -from pypy.rpython.rstr import STR, string_repr +from pypy.rpython import rmodel, lltype from pypy.rpython.rarithmetic import r_uint # ____________________________________________________________ @@ -11,133 +10,92 @@ # dictvalue type): # # struct dictentry { -# struct STR *key; +# DICTKEY key; # primitive +# bool valid; # to mark if the entry is filled # DICTVALUE value; # } # # struct dicttable { -# int num_items; -# int num_pristine_entries; # never used entries -# Array *entries; +# int num_items; +# Array entries; # } # -# -class __extend__(annmodel.SomeDict): - def rtyper_makerepr(self, rtyper): - s_key = self.dictdef.dictkey.s_value - if isinstance(s_key, annmodel.SomeString): - if s_key.can_be_none(): - raise rmodel.TyperError("cannot make repr of dict with " - "string-or-None keys") - dictvalue = self.dictdef.dictvalue - return StrDictRepr(lambda: rtyper.getrepr(dictvalue.s_value), - dictvalue) - else: - raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) - - def rtyper_makekey(self): - return (self.dictdef.dictkey, self.dictdef.dictvalue) - -class StrDictRepr(rmodel.Repr): - - def __init__(self, value_repr, dictvalue=None): - self.STRDICT = lltype.GcForwardReference() - self.lowleveltype = lltype.Ptr(self.STRDICT) - if not isinstance(value_repr, rmodel.Repr): # not computed yet, done by setup() - assert callable(value_repr) - self._value_repr_computer = value_repr - else: - self.value_repr = value_repr - self.dictvalue = dictvalue - #self.dict_cache = {} - # setup() needs to be called to finish this initialization +class ConstantDictRepr(rmodel.Repr): + + def __init__(self, key_repr, value_repr): + self.CONSTANTDICT = lltype.ForwardReference() + self.lowleveltype = lltype.Ptr(self.CONSTANTDICT) + self.key_repr = key_repr + self.value_repr = value_repr + self.dict_cache = {} def setup(self): - if 'value_repr' not in self.__dict__: - self.value_repr = self._value_repr_computer() - if isinstance(self.STRDICT, lltype.GcForwardReference): + if isinstance(self.CONSTANTDICT, lltype.ForwardReference): + self.DICTKEY = self.key_repr.lowleveltype self.DICTVALUE = self.value_repr.lowleveltype self.DICTENTRY = lltype.Struct("dictentry", - ("key", lltype.Ptr(STR)), + ("key", self.DICTKEY), + ("valid", lltype.Bool), ('value', self.DICTVALUE)) - self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) - self.STRDICT.become(lltype.GcStruct("dicttable", + self.DICTENTRYARRAY = lltype.Array(self.DICTENTRY) + self.CONSTANTDICT.become(lltype.Struct("dicttable", ("num_items", lltype.Signed), - ("num_pristine_entries", lltype.Signed), - ("entries", lltype.Ptr(self.DICTENTRYARRAY)))) + ("entries", self.DICTENTRYARRAY))) - #def convert_const(self, dictobj): - # dictobj = getattr(dictobj, '__self__', dictobj) # for bound list methods - # if not isinstance(dictobj, list): - # raise TyperError("expected a list: %r" % (dictobj,)) - # try: - # key = Constant(dictobj) - # return self.list_cache[key] - # except KeyError: - # self.setup() - # result = malloc(self.STRDICT, immortal=True) - # self.list_cache[key] = result - # result.items = malloc(self.STRDICT.items.TO, len(dictobj)) - # r_item = self.value_repr - # for i in range(len(dictobj)): - # x = dictobj[i] - # result.items[i] = r_item.convert_const(x) - # return result + def convert_const(self, dictobj): + dictobj = getattr(dictobj, '__self__', dictobj) # bound dict methods + if not isinstance(dictobj, dict): + raise TyperError("expected a dict: %r" % (dictobj,)) + try: + key = Constant(dictobj) + return self.dict_cache[key] + except KeyError: + self.setup() + dictlen = len(dictobj) + minentrylen = dictlen * 4 / 3 + entrylen = 1 + while entrylen < minentrylen: + entrylen *= 2 + result = lltype.malloc(self.CONSTANTDICT, entrylen, immortal=True) + self.dict_cache[key] = result + r_key = self.key_repr + r_value = self.value_repr + hashcompute = self.get_key_hash_function() + for dictkey, dictvalue in dictobj.items(): + llkey = r_key.convert_const(dictkey) + llvalue = r_value.convert_const(dictvalue) + ll_constantdict_setnewitem(result, llkey, llvalue, hashcompute) + return result + + def get_key_hash_function(self): + if isinstance(self.key_repr, rmodel.IntegerRepr): + return ll_hash_identity + elif isinstance(self.key_repr, rmodel.CharRepr): + return ll_hash_char + else: + raise TyperError("no easy hash function for %r" % (self.key_repr,)) def rtype_len(self, hop): v_dict, = hop.inputargs(self) - return hop.gendirectcall(ll_strdict_len, v_dict) + return hop.gendirectcall(ll_constantdict_len, v_dict) - def make_iterator_repr(self): - return StrDictIteratorRepr(self) + #def make_iterator_repr(self): + # return StrDictIteratorRepr(self) - def rtype_method_get(self, hop): - v_dict, v_key, v_default = hop.inputargs(self, string_repr, - self.value_repr) - return hop.gendirectcall(ll_get, v_dict, v_key, v_default) - -""" - rdict: (easy) method_get (?) - (easy) method_copy - (easy) method_update (?) - (easy) method_keys (?) - (easy) method_values (?) - (easy) method_items (?) -""" - -class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): - - def rtype_getitem((r_dict, r_string), hop): - v_dict, v_key = hop.inputargs(r_dict, string_repr) - return hop.gendirectcall(ll_strdict_getitem, v_dict, v_key) - - def rtype_delitem((r_dict, r_string), hop): - v_dict, v_key = hop.inputargs(r_dict, string_repr) - return hop.gendirectcall(ll_strdict_delitem, v_dict, v_key) - - def rtype_setitem((r_dict, r_string), hop): - v_dict, v_key, v_value = hop.inputargs(r_dict, string_repr, r_dict.value_repr) - hop.gendirectcall(ll_strdict_setitem, v_dict, v_key, v_value) - -class __extend__(pairtype(StrDictRepr, StrDictRepr)): - def convert_from_to((r_dict1, r_dict2), v, llops): - # check that we don't convert from StrDicts with - # different value types - if r_dict1.dictvalue is None or r_dict2.dictvalue is None: - return NotImplemented - if r_dict1.dictvalue is not r_dict2.dictvalue: - return NotImplemented - return v - - #def rtype_add((self, _), hop): - # v_lst1, v_lst2 = hop.inputargs(self, self) - # return hop.gendirectcall(ll_concat, v_lst1, v_lst2) -# -# def rtype_inplace_add((self, _), hop): -# v_lst1, v_lst2 = hop.inputargs(self, self) -# hop.gendirectcall(ll_extend, v_lst1, v_lst2) -# return v_lst1 + #def rtype_method_get(self, hop): + # v_dict, v_key, v_default = hop.inputargs(self, string_repr, + # self.value_repr) + # return hop.gendirectcall(ll_get, v_dict, v_key, v_default) + +class __extend__(pairtype(ConstantDictRepr, rmodel.Repr)): + + def rtype_getitem((r_dict, r_key), hop): + v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr) + hashcompute = r_dict.get_key_hash_function() + chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key, + chashcompute) # ____________________________________________________________ # @@ -145,170 +103,44 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. -deleted_entry_marker = lltype.malloc(STR, 0, immortal=True) - -def ll_strdict_len(d): +def ll_constantdict_len(d): return d.num_items -def ll_strdict_getitem(d, key): - entry = ll_strdict_lookup(d, key) - if entry.key and entry.key != deleted_entry_marker: +def ll_constantdict_getitem(d, key, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) + if entry.valid: return entry.value else: raise KeyError -def ll_strdict_setitem(d, key, value): - entry = ll_strdict_lookup(d, key) - if not entry.key: - entry.key = key - entry.value = value - d.num_items += 1 - d.num_pristine_entries -= 1 - if d.num_pristine_entries <= len(d.entries) / 3: - ll_strdict_resize(d) - elif entry.key == deleted_entry_marker: - entry.key = key - entry.value = value - d.num_items += 1 - else: - entry.value = value - -def ll_strdict_delitem(d, key): - entry = ll_strdict_lookup(d, key) - if not entry.key or entry.key == deleted_entry_marker: - raise KeyError - entry.key = deleted_entry_marker - valuetype = lltype.typeOf(entry).TO.value - if isinstance(valuetype, lltype.Ptr): - entry.value = lltype.nullptr(valuetype.TO) - d.num_items -= 1 - num_entries = len(d.entries) - if num_entries > STRDICT_INITSIZE and d.num_items < num_entries / 4: - ll_strdict_resize(d) - -def ll_strdict_resize(d): - old_entries = d.entries - old_size = len(old_entries) - # make a 'new_size' estimate and shrink it if there are many - # deleted entry markers - new_size = old_size * 2 - while new_size > STRDICT_INITSIZE and d.num_items < new_size / 4: - new_size /= 2 - d.entries = lltype.malloc(lltype.typeOf(old_entries).TO, new_size) - d.num_pristine_entries = new_size - d.num_items - i = 0 - while i < old_size: - entry = old_entries[i] - if entry.key and entry.key != deleted_entry_marker: - new_entry = ll_strdict_lookup(d, entry.key) - new_entry.key = entry.key - new_entry.value = entry.value - i += 1 +def ll_constantdict_setnewitem(d, key, value, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) + assert not entry.valid + entry.key = key + entry.valid = True + entry.value = value + d.num_items += 1 # the below is a port of CPython's dictobject.c's lookdict implementation PERTURB_SHIFT = 5 -def ll_strdict_lookup(d, key): - hash = rstr.ll_strhash(key) +def ll_constantdict_lookup(d, key, hashcompute): + hash = hashcompute(key) entries = d.entries mask = len(entries) - 1 - i = r_uint(hash & mask) - - # do the first try before any looping - entry = entries[i] - if not entry.key or entry.key == key: - return entry - if entry.key == deleted_entry_marker: - freeslot = entry - else: - if entry.key.hash == hash and rstr.ll_streq(entry.key, key): - return entry - freeslot = lltype.nullptr(lltype.typeOf(entry).TO) - - # In the loop, key == deleted_entry_marker is by far (factor of 100s) the - # least likely outcome, so test for that last. perturb = r_uint(hash) + i = r_uint(hash) while 1: - i = (i << 2) + i + perturb + 1 entry = entries[i & mask] - if not entry.key: - return freeslot or entry - if entry.key == key or (entry.key.hash == hash and - entry.key != deleted_entry_marker and - rstr.ll_streq(entry.key, key)): + if not entry.valid: + return entry + if entry.key == key: return entry - if entry.key == deleted_entry_marker and not freeslot: - freeslot = entry perturb >>= PERTURB_SHIFT + i = (i << 2) + i + perturb + 1 -# ____________________________________________________________ -# -# Irregular operations. -STRDICT_INITSIZE = 8 - -def ll_newstrdict(DICTPTR): - d = lltype.malloc(DICTPTR.TO) - d.entries = lltype.malloc(DICTPTR.TO.entries.TO, STRDICT_INITSIZE) - d.num_items = 0 # but still be explicit - d.num_pristine_entries = STRDICT_INITSIZE - return d - -def rtype_newdict(hop): - r_dict = hop.r_result - if not isinstance(r_dict, StrDictRepr): - raise rmodel.TyperError("cannot create non-StrDicts, got %r" %(r_dict,)) - c1 = hop.inputconst(lltype.Void, r_dict.lowleveltype) - v_result = hop.gendirectcall(ll_newstrdict, c1) - return v_result - -# ____________________________________________________________ -# -# Iteration. - -class StrDictIteratorRepr(rmodel.Repr): - - def __init__(self, r_dict): - self.r_dict = r_dict - self.lowleveltype = lltype.Ptr(lltype.GcStruct('strdictiter', - ('dict', r_dict.lowleveltype), - ('index', lltype.Signed))) - - def newiter(self, hop): - v_dict, = hop.inputargs(self.r_dict) - citerptr = hop.inputconst(lltype.Void, self.lowleveltype) - return hop.gendirectcall(ll_strdictiter, citerptr, v_dict) - - def rtype_next(self, hop): - v_iter, = hop.inputargs(self) - return hop.gendirectcall(ll_strdictnext, v_iter) - -def ll_strdictiter(ITERPTR, d): - iter = lltype.malloc(ITERPTR.TO) - iter.dict = d - iter.index = 0 - return iter - -def ll_strdictnext(iter): - entries = iter.dict.entries - index = iter.index - entries_len = len(entries) - while index < entries_len: - key = entries[index].key - index = index + 1 - if key and key != deleted_entry_marker: - iter.index = index - return key - iter.index = index - raise StopIteration - -# _____________________________________________________________ -# methods - -def ll_get(v_dict, v_key, v_default): - entry = ll_strdict_lookup(v_dict, v_key) - if entry.key and entry.key != deleted_entry_marker: - return entry.value - else: - return v_default - +def ll_hash_identity(x): + return x +def ll_hash_char(x): + return ord(x) Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sat Jun 25 20:52:11 2005 @@ -4,7 +4,7 @@ from pypy.rpython import rmodel, lltype, rstr from pypy.rpython.rstr import STR, string_repr from pypy.rpython.rarithmetic import r_uint -from pypy.rpython import rlist +from pypy.rpython import rlist, rconstantdict # ____________________________________________________________ # @@ -34,6 +34,12 @@ dictvalue = self.dictdef.dictvalue return StrDictRepr(lambda: rtyper.getrepr(dictvalue.s_value), dictvalue) + elif isinstance(s_key, (annmodel.SomeInteger, annmodel.SomeChar)): + dictkey = self.dictdef.dictkey + dictvalue = self.dictdef.dictvalue + return rconstantdict.ConstantDictRepr( + rtyper.getrepr(dictkey.s_value), + rtyper.getrepr(dictvalue.s_value)) else: raise rmodel.TyperError("cannot make repr of %r" %(self.dictdef,)) Added: pypy/dist/pypy/rpython/test/test_rconstantdict.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/test/test_rconstantdict.py Sat Jun 25 20:52:11 2005 @@ -0,0 +1,9 @@ +import py +from pypy.rpython.test.test_llinterp import make_interpreter, interpret + +def test_constant_int_dict(): + d = {1: 2, 2: 3, 3: 4} + def func(i): + return d[i] + res = interpret(func, [3]) + assert res == 4 From pedronis at codespeak.net Sun Jun 26 02:44:52 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Jun 2005 02:44:52 +0200 (CEST) Subject: [pypy-svn] r13909 - pypy/dist/pypy/translator Message-ID: <20050626004452.CC8D627B57@code1.codespeak.net> Author: pedronis Date: Sun Jun 26 02:44:52 2005 New Revision: 13909 Modified: pypy/dist/pypy/translator/transform.py Log: in transform_graph check the graphs only of the touched blocks Modified: pypy/dist/pypy/translator/transform.py ============================================================================== --- pypy/dist/pypy/translator/transform.py (original) +++ pypy/dist/pypy/translator/transform.py Sun Jun 26 02:44:52 2005 @@ -10,11 +10,18 @@ import types from pypy.objspace.flow.model import SpaceOperation from pypy.objspace.flow.model import Variable, Constant, Block, Link -from pypy.objspace.flow.model import last_exception +from pypy.objspace.flow.model import last_exception, checkgraph from pypy.translator.annrpython import CannotSimplify from pypy.annotation import model as annmodel from pypy.annotation.specialize import MemoTable + +def checkgraphs(self, blocks): + for block in blocks: + fn = self.annotated[block] + graph = self.translator.flowgraphs[fn] + checkgraph(graph) + def fully_annotated_blocks(self): """Ignore blocked blocks.""" for block, is_annotated in self.annotated.iteritems(): @@ -177,14 +184,14 @@ """Apply set of transformations available.""" # WARNING: this produces incorrect results if the graph has been # modified by t.simplify() after it had been annotated. - if ann.translator: - ann.translator.checkgraphs() if block_subset is None: block_subset = fully_annotated_blocks(ann) d = {} for block in block_subset: d[block] = True block_subset = d + if ann.translator: + checkgraphs(ann, block_subset) transform_dead_code(ann, block_subset) for pass_ in extra_passes: pass_(ann, block_subset) @@ -192,4 +199,5 @@ # chance to remove dependency on certain variables transform_dead_op_vars(ann, block_subset) if ann.translator: - ann.translator.checkgraphs() + checkgraphs(ann, block_subset) + From pedronis at codespeak.net Sun Jun 26 03:18:34 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Jun 2005 03:18:34 +0200 (CEST) Subject: [pypy-svn] r13910 - pypy/dist/pypy/objspace/flow Message-ID: <20050626011834.F206027B57@code1.codespeak.net> Author: pedronis Date: Sun Jun 26 03:18:32 2005 New Revision: 13910 Modified: pypy/dist/pypy/objspace/flow/model.py Log: leaner visit Modified: pypy/dist/pypy/objspace/flow/model.py ============================================================================== --- pypy/dist/pypy/objspace/flow/model.py (original) +++ pypy/dist/pypy/objspace/flow/model.py Sun Jun 26 03:18:32 2005 @@ -330,11 +330,6 @@ import inspect # for getmro class traverse: - edgedef = { - FunctionGraph : ('startblock',), - Block : ('exits',), - Link : ('target',), - } def __init__(self, visitor, functiongraph): """ send the visitor over all (reachable) nodes. @@ -342,6 +337,7 @@ or otherwise is callable itself. """ self.visitor = visitor + self.visitor_cache = {} self.seen = {} self.visit(functiongraph) @@ -351,26 +347,32 @@ # do the visit cls = node.__class__ - for subclass in inspect.getmro(cls): - consume = getattr(self.visitor, "visit_" + subclass.__name__, None) - if consume: - break - else: - consume = getattr(self.visitor, 'visit', self.visitor) + try: + consume = self.visitor_cache[cls] + except KeyError: + for subclass in inspect.getmro(cls): + consume = getattr(self.visitor, "visit_" + subclass.__name__, None) + if consume: + break + else: + consume = getattr(self.visitor, 'visit', self.visitor) + + assert callable(consume), "visitor not found for %r on %r" % (cls, self.visitor) + + self.visitor_cache[cls] = consume - assert callable(consume), "visitor not found for %r on %r" % (cls, self.visitor) self.seen[id(node)] = consume(node) # recurse - for dispclass, attrs in self.edgedef.items(): - for subclass in inspect.getmro(cls): - if subclass == dispclass: - for attr in attrs: - for obj in flattenobj(getattr(node, attr)): - self.visit(obj) - return - - raise ValueError, "could not dispatch %r" % cls + if isinstance(node, Block): + for obj in node.exits: + self.visit(obj) + elif isinstance(node, Link): + self.visit(node.target) + elif isinstance(node, FunctionGraph): + self.visit(node.startblock) + else: + raise ValueError, "could not dispatch %r" % cls def flatten(funcgraph): l = [] From mwh at codespeak.net Sun Jun 26 11:19:24 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 11:19:24 +0200 (CEST) Subject: [pypy-svn] r13916 - in pypy/dist/pypy: rpython translator/c/test Message-ID: <20050626091924.408F527B55@code1.codespeak.net> Author: mwh Date: Sun Jun 26 11:19:22 2005 New Revision: 13916 Modified: pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/translator/c/test/test_typed.py Log: small tweaks so codes that uses string formatting and converts ints to strings translates to code that actually compiles. with these changes, demo/bpnn.py on my machine compiles and runs (woohoo! -- although demo/bpnn.py on my machine is a bit hacked and in particular doesn't have any print statements in it any more). there is something "a bit odd" in the area of integer division, int_div operations get emitted sometimes, which there is no backend support for. I'll pester arigo & pedronis about this when they wake up :) Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Sun Jun 26 11:19:22 2005 @@ -303,7 +303,7 @@ else: while i: temp[len] = chr(i%10+ord('0')) - i /= 10 + i //= 10 len += 1 len += sign result = malloc(STR, len) @@ -336,7 +336,7 @@ else: while i: temp[len] = hex_chars[i%16] - i /= 16 + i //= 16 len += 1 len += sign if addPrefix: Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 11:19:22 2005 @@ -218,7 +218,7 @@ assert s_str.is_constant() s = s_str.const things = parse_fmt_string(s) - size = inputconst(Void, len(things)) + size = inputconst(Signed, len(things)) # could be unsigned? TEMP = GcArray(Ptr(STR)) cTEMP = inputconst(Void, TEMP) vtemp = hop.genop("malloc_varsize", [cTEMP, size], Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sun Jun 26 11:19:22 2005 @@ -281,3 +281,16 @@ return exp(f) f = self.getcompiled(fn) assert f(1.0) == exp(1.0) + + def test_stringformatting(self): + def fn(i=int): + return "you said %d, you did"%i + f = self.getcompiled(fn) + assert f(1) == fn(1) + + def test_str2int(self): + def fn(i=int): + return str(i) + f = self.getcompiled(fn) + assert f(1) == fn(1) + From hpk at codespeak.net Sun Jun 26 11:54:29 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 11:54:29 +0200 (CEST) Subject: [pypy-svn] r13919 - pypy/dist/pypy/rpython Message-ID: <20050626095429.2892527B61@code1.codespeak.net> Author: hpk Date: Sun Jun 26 11:54:28 2005 New Revision: 13919 Modified: pypy/dist/pypy/rpython/rconstantdict.py Log: docstring fix Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sun Jun 26 11:54:28 2005 @@ -7,7 +7,7 @@ # ____________________________________________________________ # # pseudo implementation of RPython dictionary (this is per -# dictvalue type): +# dictkey/dictvalue but dictkeys need to be primitive) # # struct dictentry { # DICTKEY key; # primitive From hpk at codespeak.net Sun Jun 26 12:06:02 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 12:06:02 +0200 (CEST) Subject: [pypy-svn] r13920 - pypy/dist/pypy/rpython/test Message-ID: <20050626100602.EB1A027B4E@code1.codespeak.net> Author: hpk Date: Sun Jun 26 12:06:00 2005 New Revision: 13920 Modified: pypy/dist/pypy/rpython/test/test_llinterp.py pypy/dist/pypy/rpython/test/test_rbuiltin.py pypy/dist/pypy/rpython/test/test_rconstantdict.py pypy/dist/pypy/rpython/test/test_rdict.py pypy/dist/pypy/rpython/test/test_rfloat.py pypy/dist/pypy/rpython/test/test_rint.py pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rpbc.py pypy/dist/pypy/rpython/test/test_rstr.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: remove redunancy regarding ll-interpreting instead of make_interpreter() one uses now interpret() which caches the last few translation/annotations/specializiations Now it's efficient to call interpret(func, [arg1,arg2,...]) repeatedly with different arguments. Modified: pypy/dist/pypy/rpython/test/test_llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_llinterp.py (original) +++ pypy/dist/pypy/rpython/test/test_llinterp.py Sun Jun 26 12:06:00 2005 @@ -27,38 +27,47 @@ if func(pyobjectptr(cls)).typeptr == klass: return cls +def timelog(prefix, call, *args): + #import time + #print prefix, "...", + #start = time.time() + res = call(*args) + #elapsed = time.time() - start + #print "%.2f secs" %(elapsed,) + return res + def gengraph(func, argtypes=[], viewbefore=False): t = Translator(func) - t.annotate(argtypes) + + timelog("annotating", t.annotate, argtypes) if viewbefore: t.annotator.simplify() t.view() global typer # we need it for find_exception typer = RPythonTyper(t.annotator) - typer.specialize() + timelog("rtyper-specializing", typer.specialize) #t.view() - t.checkgraphs() + timelog("checking graphs", t.checkgraphs) return t, typer +_lastinterpreted = [] +_tcache = {} def interpret(func, values, view=False, viewbefore=False): - t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) - for x in values], viewbefore) - if view: - t.view() - interp = LLInterpreter(t.flowgraphs, typer) - res = interp.eval_function(func, values) - return res - -def make_interpreter(func, example_values, view=False, viewbefore=False): - t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) - for x in example_values], viewbefore) + key = (func,) + tuple([typeOf(x) for x in values]) + try: + (t, interp) = _tcache[key] + except KeyError: + t, typer = gengraph(func, [lltype_to_annotation(typeOf(x)) + for x in values], viewbefore) + interp = LLInterpreter(t.flowgraphs, typer) + _tcache[key] = (t, interp) + # keep the cache small + _lastinterpreted.append(key) + if len(_lastinterpreted) >= 4: + del _tcache[_lastinterpreted.pop(0)] if view: t.view() - interp = LLInterpreter(t.flowgraphs, typer) - def evaluate(*values): - return interp.eval_function(func, values) - - return evaluate + return interp.eval_function(func, values) #__________________________________________________________________ # tests 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 Sun Jun 26 12:06:00 2005 @@ -1,4 +1,4 @@ -from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import interpret from pypy.annotation.builtin import * import py @@ -26,43 +26,40 @@ def test_int_min(): def fn(i, j): return min(i,j) - ev_fun = make_interpreter(fn, [0, 0]) - assert ev_fun(1, 2) == 1 - assert ev_fun(1, -1) == -1 - assert ev_fun(2, 2) == 2 - assert ev_fun(-1, -12) == -12 + ev_fun = interpret(fn, [0, 0]) + assert interpret(fn, (1, 2)) == 1 + assert interpret(fn, (1, -1)) == -1 + assert interpret(fn, (2, 2)) == 2 + assert interpret(fn, (-1, -12)) == -12 def test_int_max(): def fn(i, j): return max(i,j) - ev_fun = make_interpreter(fn, [0, 0]) - assert ev_fun(1, 2) == 2 - assert ev_fun(1, -1) == 1 - assert ev_fun(2, 2) == 2 - assert ev_fun(-1, -12) == -1 + assert interpret(fn, (1, 2)) == 2 + assert interpret(fn, (1, -1)) == 1 + assert interpret(fn, (2, 2)) == 2 + assert interpret(fn, (-1, -12)) == -1 def test_builtin_math_floor(): import math def fn(f): - return math.floor(f) - ev_fun = make_interpreter(fn, [0.0]) import random - for i in range(20): + for i in range(5): rv = 1000 * float(i-10) #random.random() - assert math.floor(rv) == ev_fun(rv) + res = interpret(fn, [rv]) + assert fn(rv) == res def test_builtin_math_fmod(): import math def fn(f,y): - return math.fmod(f,y) - ev_fun = make_interpreter(fn, [0.0,0.0]) - for i in range(20): - for j in range(20): + + for i in range(10): + for j in range(10): rv = 1000 * float(i-10) ry = 100 * float(i-10) +0.1 - assert math.fmod(rv,ry) == ev_fun(rv,ry) + assert fn(rv,ry) == interpret(fn, (rv, ry)) def test_pbc_isTrue(): class C: @@ -74,11 +71,9 @@ def fn(neg): c = C.f return g(c) - ev_fun = make_interpreter(fn, [True]) - assert ev_fun(True) + assert interpret(fn, [True]) def fn(neg): c = None return g(c) - ev_fun = make_interpreter(fn, [True]) - assert not ev_fun(True) - \ No newline at end of file + assert not interpret(fn, [True]) + Modified: pypy/dist/pypy/rpython/test/test_rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rconstantdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rconstantdict.py Sun Jun 26 12:06:00 2005 @@ -1,8 +1,8 @@ import py -from pypy.rpython.test.test_llinterp import make_interpreter, interpret +from pypy.rpython.test.test_llinterp import interpret def test_constant_int_dict(): - d = {1: 2, 2: 3, 3: 4} + d = {1: 2, 2: 3, 3: 4} def func(i): return d[i] res = interpret(func, [3]) Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Sun Jun 26 12:06:00 2005 @@ -4,6 +4,7 @@ from pypy.rpython import rstr, rdict import py +py.log.setconsumer("rtyper", py.log.STDOUT) def test_dict_creation(): def createdict(i): Modified: pypy/dist/pypy/rpython/test/test_rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rfloat.py (original) +++ pypy/dist/pypy/rpython/test/test_rfloat.py Sun Jun 26 12:06:00 2005 @@ -2,7 +2,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet -from pypy.rpython.test.test_llinterp import make_interpreter +from pypy.rpython.test.test_llinterp import interpret class TestSnippet(object): @@ -42,9 +42,8 @@ def fn(f): return int(f) - ev_fun = make_interpreter(fn, [0.0]) - - assert ev_fun(1.0) == 1 - assert type(ev_fun(1.0)) is int - - assert ev_fun(2.34) == 2 + res = interpret(fn, [1.0]) + assert res == 1 + assert type(res) is int + res = interpret(fn, [2.34]) + assert res == fn(2.34) Modified: pypy/dist/pypy/rpython/test/test_rint.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rint.py (original) +++ pypy/dist/pypy/rpython/test/test_rint.py Sun Jun 26 12:06:00 2005 @@ -2,7 +2,7 @@ from pypy.rpython.rtyper import RPythonTyper from pypy.annotation import model as annmodel from pypy.rpython.test import snippet -from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.rarithmetic import r_uint @@ -54,30 +54,26 @@ def dummy(i): return str(i) - ev_fun = make_interpreter(dummy, [0]) - - res = ev_fun(0) + res = interpret(dummy, [0]) assert ''.join(res.chars) == '0' - res = ev_fun(1034) + res = interpret(dummy, [1034]) assert ''.join(res.chars) == '1034' - res = ev_fun(-123) + res = interpret(dummy, [-123]) assert ''.join(res.chars) == '-123' def test_hex_of_int(): def dummy(i): return hex(i) - ev_fun = make_interpreter(dummy, [0]) - - res = ev_fun(0) + res = interpret(dummy, [0]) assert ''.join(res.chars) == '0x0' - res = ev_fun(1034) + res = interpret(dummy, [1034]) assert ''.join(res.chars) == '0x40a' - res = ev_fun(-123) + res = interpret(dummy, [-123]) assert ''.join(res.chars) == '-0x7b' def test_unsigned(): @@ -86,11 +82,9 @@ j = r_uint(12) return i < j - ev_fun = make_interpreter(dummy, [0]) - - res = ev_fun(0) + res = interpret(dummy,[0]) assert res is True - res = ev_fun(-1) + res = interpret(dummy, [-1]) assert res is False # -1 ==> 0xffffffff Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Sun Jun 26 12:06:00 2005 @@ -4,7 +4,7 @@ from pypy.rpython.rlist import * from pypy.rpython.rslice import ll_newslice from pypy.rpython.rint import signed_repr -from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.test.test_llinterp import find_exception @@ -230,11 +230,10 @@ s2 = [[1, 2, 3], [4, 5, 1], [1], [1, 2], [4, 5, 1, 6], [7, 1, 1, 8, 9, 10]] if neg: return s1[i] != s2[i] return s1[i] == s2[j] - ev_fn = make_interpreter(fn, [0, 0, False]) for i in range(2): for j in range(6): for case in False, True: - res = ev_fn(i, j, case) + res = interpret(fn, [i,j,case]) assert res is fn(i, j, case) def test_list_comparestr(): @@ -244,11 +243,10 @@ s2 = [["hello"], ["world"]] if neg: return s1[i] != s2[i] return s1[i] == s2[j] - ev_fn = make_interpreter(fn, [0, 0, False])#, view=True) for i in range(2): for j in range(2): for case in False, True: - res = ev_fn(i, j, case) + res = interpret(fn, [i,j,case]) assert res is fn(i, j, case) class Foo: pass @@ -264,11 +262,10 @@ s2 = s1[:] if neg: return s1[i] != s2[i] return s1[i] == s2[j] - ev_fn = make_interpreter(fn, [0, 0, False])#, view=True) for i in range(3): for j in range(3): for case in False, True: - res = ev_fn(i, j, case) + res = interpret(fn, [i, j, case]) assert res is fn(i, j, case) def test_list_contains(): @@ -281,10 +278,9 @@ args = lis + [bar2] if neg : return args[i] not in lis return args[i] in lis - ev_fn = make_interpreter(fn, [0, False]) for i in range(4): for case in False, True: - res = ev_fn(i, case) + res = interpret(fn, [i, case]) assert res is fn(i, case) def test_list_index(): @@ -296,10 +292,9 @@ lis = [foo1, foo2, bar1] args = lis + [bar2] return lis.index(args[i]) - ev_fn = make_interpreter(fn, [0]) for i in range(4): try: - res = ev_fn(i) + res = interpret(fn, [i]) except Exception, e: res = find_exception(e) try: Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sun Jun 26 12:06:00 2005 @@ -1,7 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import interpret def test_easy_call(): @@ -163,10 +163,9 @@ fr = fr2 return getorbuild(fr) - ev_f1 = make_interpreter(f1, [0])#, viewbefore=True) - res = ev_f1(0) + res = interpret(f1, [0]) assert res == 7 - res = ev_f1(1) + res = interpret(f1, [1]) assert res == 3 def test_call_memoized_cache(): @@ -208,10 +207,9 @@ newfr = cache1.getorbuild(fr) return cache2.getorbuild(newfr) - ev_f1 = make_interpreter(f1, [0], view=0, viewbefore=0) - res = ev_f1(0) + res = interpret(f1, [0], view=0, viewbefore=0) assert res == 3 - res = ev_f1(1) + res = interpret(f1, [1]) assert res == 7 def test_rpbc_bound_method_static_call(): Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 12:06:00 2005 @@ -2,16 +2,15 @@ from pypy.rpython.lltype import * from pypy.rpython.rstr import parse_fmt_string from pypy.rpython.rtyper import RPythonTyper -from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import interpret def test_simple(): def fn(i): s = 'hello' return s[i] - ev_fn = make_interpreter(fn, [0]) for i in range(5): - res = ev_fn(i) + res = interpret(fn, [i]) assert res == 'hello'[i] @@ -24,10 +23,9 @@ return bool(s) else: return False - ev_fn = make_interpreter(fn, [0, 0]) for i in [-2, -1, 0]: for j in range(2): - res = ev_fn(i, j) + res = interpret(fn, [i, j]) assert res is fn(i, j) def test_hash(): @@ -37,10 +35,9 @@ else: s = "xxx" return hash(s) - ev_fn = make_interpreter(fn, [0]) - res = ev_fn(0) + res = interpret(fn, [0]) assert res == -1 - res = ev_fn(1) + res = interpret(fn, [1]) assert typeOf(res) == Signed def test_concat(): @@ -48,10 +45,9 @@ s1 = ['', 'a', 'ab'] s2 = ['', 'x', 'xy'] return s1[i] + s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(3): for j in range(3): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert ''.join(res.chars) == fn(i, j) def test_iter(): @@ -66,9 +62,8 @@ return True return False - ev_fn = make_interpreter(fn, [0]) for i in range(3): - res = ev_fn(i) + res = interpret(fn, [i]) assert res is True def test_char_constant(): @@ -82,10 +77,9 @@ def test_char_isspace(): def fn(s): return s.isspace() - efn = make_interpreter(fn, ['x']) - res = efn('x') + res = interpret(fn, ['x']) assert res == False - res = efn(' ') + res = interpret(fn, [' ']) assert res == True def test_char_compare(): @@ -101,72 +95,64 @@ s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] == s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] != s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = ev_fn(i, j) + res = interpret(fn, [i, j]) assert res is fn(i, j) def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] < s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] <= s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] >= s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] return s1[i] > s2[j] - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(6): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) - def test_startswith(): def fn(i, j): s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] return s1[i].startswith(s2[j]) - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(9): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) def test_endswith(): @@ -174,10 +160,9 @@ s1 = ['one', 'two'] s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] return s1[i].endswith(s2[j]) - ev_fn = make_interpreter(fn, [0,0]) for i in range(2): for j in range(9): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert res is fn(i, j) def test_join(): @@ -188,10 +173,9 @@ s1 = [ '', ',', ' and '] s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']] return s1[i].join(s2[j]) - ev_fn = make_interpreter(fn, [0,0]) for i in range(3): for j in range(3): - res = ev_fn(i, j) + res = interpret(fn, [i,j]) assert ''.join(res.chars) == fn(i, j) def test_parse_fmt(): @@ -215,23 +199,18 @@ def percentX(i): return "bing %x bang" % (i,) - x_fn = make_interpreter(percentX, [0]) - - res = x_fn(23) + res = interpret(percentX, [23]) assert ''.join(res.chars) == 'bing 17 bang' - res = x_fn(-123) + res = interpret(percentX, [-123]) assert ''.join(res.chars) == 'bing -7b bang' def moreThanOne(s, d, x): return "string: %s decimal: %d hex: %x" % (s, d, x) - m_fn = make_interpreter(moreThanOne, ['a', 2, 3]) - args = 'a', 2, 3 - res = m_fn(*args) + res = interpret(moreThanOne, list(args)) assert ''.join(res.chars) == moreThanOne(*args) - def test_strformat_nontuple(): def percentD(i): @@ -267,12 +246,10 @@ x = D() return str(x) - ev_fun = make_interpreter(dummy, [0]) - - res = ev_fun(1) + res = interpret(dummy, [1]) assert ''.join(res.chars) == '' - res = ev_fun(0) + res = interpret(dummy, [0]) assert ''.join(res.chars) == '' def test_percentformat_instance(): @@ -290,10 +267,8 @@ y = C() return "what a nice %s, much nicer than %r"%(x, y) - ev_fun = make_interpreter(dummy, [0]) - - res = ev_fun(1) + res = interpret(dummy, [1]) assert ''.join(res.chars) == 'what a nice , much nicer than ' - res = ev_fun(0) + res = interpret(dummy, [0]) assert ''.join(res.chars) == 'what a nice , much nicer than ' Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Sun Jun 26 12:06:00 2005 @@ -4,7 +4,7 @@ from pypy.rpython.rtuple import * from pypy.rpython.rint import signed_repr from pypy.rpython.rbool import bool_repr -from pypy.rpython.test.test_llinterp import interpret, make_interpreter +from pypy.rpython.test.test_llinterp import interpret import py def test_rtuple(): @@ -57,8 +57,7 @@ tup1 = (3,) res = tup + tup1 + () return res[0]*100 + res[1]*10 + res[2] - fn = make_interpreter(f,[])#,view=True) - res = fn() + res = interpret(fn, []) assert res == 123 def test_tuple_concatenation_mix(): @@ -67,8 +66,7 @@ tup1 = ('3',) res = tup + tup1 return res[0]*100 + res[1]*10 + ord(res[2]) - ord('0') - fn = make_interpreter(f,[])#,view=True) - res = fn() + res = interpret(f, []) assert res == 123 def test_constant_tuple_contains(): @@ -76,12 +74,7 @@ def f(i): t1 = (1, 2, 3, 4) return i in t1 - fn = make_interpreter(f, [3], view=False, viewbefore=False) - res = fn(3) + res = interpret(f, [3], view=False, viewbefore=False) assert res is True - res = fn(0) + res = interpret(f, [0]) assert res is False - - - - From hpk at codespeak.net Sun Jun 26 12:11:11 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 12:11:11 +0200 (CEST) Subject: [pypy-svn] r13922 - pypy/dist/pypy/translator Message-ID: <20050626101111.AD27227B4E@code1.codespeak.net> Author: hpk Date: Sun Jun 26 12:11:10 2005 New Revision: 13922 Modified: pypy/dist/pypy/translator/annrpython.py Log: experimental (but seems to work) complain if the number of provided and expected args for a flowgraph differ Modified: pypy/dist/pypy/translator/annrpython.py ============================================================================== --- pypy/dist/pypy/translator/annrpython.py (original) +++ pypy/dist/pypy/translator/annrpython.py Sun Jun 26 12:11:10 2005 @@ -92,8 +92,9 @@ # make input arguments and set their type input_arg_types = list(input_arg_types) nbarg = len(flowgraph.getargs()) - while len(input_arg_types) < nbarg: - input_arg_types.append(object) + if len(input_arg_types) != nbarg: + raise TypeError("flowgraph %s expects %d args, got %d" %( + flowgraph.name, nbarg, len(input_arg_types))) inputcells = [] for t in input_arg_types: if not isinstance(t, annmodel.SomeObject): From arigo at codespeak.net Sun Jun 26 12:16:30 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 12:16:30 +0200 (CEST) Subject: [pypy-svn] r13923 - pypy/dist/pypy/rpython Message-ID: <20050626101630.B9BB127B5B@code1.codespeak.net> Author: arigo Date: Sun Jun 26 12:16:29 2005 New Revision: 13923 Modified: pypy/dist/pypy/rpython/lltype.py Log: Performance of rtyper. Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sun Jun 26 12:16:29 2005 @@ -1,4 +1,4 @@ -import weakref +import weakref, operator import py from pypy.rpython.rarithmetic import r_uint from pypy.tool.uid import Hashable @@ -22,6 +22,8 @@ del seeing[seeingkey] return safe +safe_equal = saferecursive(operator.eq, True) + class frozendict(dict): def __hash__(self): @@ -32,8 +34,8 @@ class LowLevelType(object): def __eq__(self, other): - return self.__class__ is other.__class__ and self.__dict__ == other.__dict__ - __eq__ = saferecursive(__eq__, True) + return self.__class__ is other.__class__ and ( + self is other or safe_equal(self.__dict__, other.__dict__)) def __ne__(self, other): return not (self == other) From hpk at codespeak.net Sun Jun 26 12:18:19 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 12:18:19 +0200 (CEST) Subject: [pypy-svn] r13924 - pypy/dist/pypy/rpython/test Message-ID: <20050626101819.3B54327B5B@code1.codespeak.net> Author: hpk Date: Sun Jun 26 12:18:18 2005 New Revision: 13924 Modified: pypy/dist/pypy/rpython/test/test_rtuple.py Log: fixifix Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Sun Jun 26 12:18:18 2005 @@ -57,7 +57,7 @@ tup1 = (3,) res = tup + tup1 + () return res[0]*100 + res[1]*10 + res[2] - res = interpret(fn, []) + res = interpret(f, []) assert res == 123 def test_tuple_concatenation_mix(): From arigo at codespeak.net Sun Jun 26 12:30:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 12:30:54 +0200 (CEST) Subject: [pypy-svn] r13925 - pypy/extradoc/sprintinfo Message-ID: <20050626103054.C82B227B5E@code1.codespeak.net> Author: arigo Date: Sun Jun 26 12:30:53 2005 New Revision: 13925 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Done by Christian some days ago. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sun Jun 26 12:30:53 2005 @@ -50,9 +50,6 @@ * constant dict with int keys (which are pending now) * constant string * string - * list of instances - * list of strings - * list of unicode characters Overridden functions in PyPy ---------------------------- From arigo at codespeak.net Sun Jun 26 12:35:30 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 12:35:30 +0200 (CEST) Subject: [pypy-svn] r13926 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626103530.DF16A27B5B@code1.codespeak.net> Author: arigo Date: Sun Jun 26 12:35:28 2005 New Revision: 13926 Modified: pypy/dist/pypy/rpython/rconstantdict.py pypy/dist/pypy/rpython/test/test_rconstantdict.py Log: 'contains' for constant dicts. Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sun Jun 26 12:35:28 2005 @@ -97,6 +97,13 @@ return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key, chashcompute) + def rtype_contains((r_dict, r_key), hop): + v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr) + hashcompute = r_dict.get_key_hash_function() + chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_contains, v_dict, v_key, + chashcompute) + # ____________________________________________________________ # # Low-level methods. These can be run for testing, but are meant to @@ -113,6 +120,10 @@ else: raise KeyError +def ll_constantdict_contains(d, key, hashcompute): + entry = ll_constantdict_lookup(d, key, hashcompute) + return entry.valid + def ll_constantdict_setnewitem(d, key, value, hashcompute): entry = ll_constantdict_lookup(d, key, hashcompute) assert not entry.valid Modified: pypy/dist/pypy/rpython/test/test_rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rconstantdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rconstantdict.py Sun Jun 26 12:35:28 2005 @@ -7,3 +7,12 @@ return d[i] res = interpret(func, [3]) assert res == 4 + +def test_constantdict_contains(): + d = {1: True, 4: True, 16: True} + def func(i): + return i in d + res = interpret(func, [15]) + assert res is False + res = interpret(func, [4]) + assert res is True From ac at codespeak.net Sun Jun 26 12:36:57 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 26 Jun 2005 12:36:57 +0200 (CEST) Subject: [pypy-svn] r13927 - pypy/dist/pypy/objspace/std/test Message-ID: <20050626103657.8212A27B5B@code1.codespeak.net> Author: ac Date: Sun Jun 26 12:36:57 2005 New Revision: 13927 Modified: pypy/dist/pypy/objspace/std/test/test_unicodestring.py Log: Make the test_float_from_unicode not rely on the accuracy of the string_to_float conversion. Modified: pypy/dist/pypy/objspace/std/test/test_unicodestring.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_unicodestring.py (original) +++ pypy/dist/pypy/objspace/std/test/test_unicodestring.py Sun Jun 26 12:36:57 2005 @@ -72,4 +72,4 @@ assert int(u'12345') == 12345 def test_float_from_unicode(self): - assert float(u'123.456e89') == 123.456e89 + assert float(u'123.456e89') == float('123.456e89') From arigo at codespeak.net Sun Jun 26 12:59:54 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 12:59:54 +0200 (CEST) Subject: [pypy-svn] r13929 - pypy/dist/pypy/rpython Message-ID: <20050626105954.BD25C27B5B@code1.codespeak.net> Author: arigo Date: Sun Jun 26 12:59:53 2005 New Revision: 13929 Modified: pypy/dist/pypy/rpython/rconstantdict.py Log: Commented out the hash computation functions now that we only use rconstantdict for integers. Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sun Jun 26 12:59:53 2005 @@ -61,20 +61,20 @@ self.dict_cache[key] = result r_key = self.key_repr r_value = self.value_repr - hashcompute = self.get_key_hash_function() + #hashcompute = self.get_key_hash_function() for dictkey, dictvalue in dictobj.items(): llkey = r_key.convert_const(dictkey) llvalue = r_value.convert_const(dictvalue) - ll_constantdict_setnewitem(result, llkey, llvalue, hashcompute) + ll_constantdict_setnewitem(result, llkey, llvalue)#,hashcompute) return result - def get_key_hash_function(self): - if isinstance(self.key_repr, rmodel.IntegerRepr): - return ll_hash_identity - elif isinstance(self.key_repr, rmodel.CharRepr): - return ll_hash_char - else: - raise TyperError("no easy hash function for %r" % (self.key_repr,)) +## def get_key_hash_function(self): +## if isinstance(self.key_repr, rmodel.IntegerRepr): +## return ll_hash_identity +## elif isinstance(self.key_repr, rmodel.CharRepr): +## return ll_hash_char +## else: +## raise TyperError("no easy hash function for %r" % (self.key_repr,)) def rtype_len(self, hop): v_dict, = hop.inputargs(self) @@ -92,17 +92,17 @@ def rtype_getitem((r_dict, r_key), hop): v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr) - hashcompute = r_dict.get_key_hash_function() - chashcompute = hop.inputconst(lltype.Void, hashcompute) - return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key, - chashcompute) + #hashcompute = r_dict.get_key_hash_function() + #chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_getitem, v_dict, v_key) + #chashcompute) def rtype_contains((r_dict, r_key), hop): v_dict, v_key = hop.inputargs(r_dict, r_dict.key_repr) - hashcompute = r_dict.get_key_hash_function() - chashcompute = hop.inputconst(lltype.Void, hashcompute) - return hop.gendirectcall(ll_constantdict_contains, v_dict, v_key, - chashcompute) + #hashcompute = r_dict.get_key_hash_function() + #chashcompute = hop.inputconst(lltype.Void, hashcompute) + return hop.gendirectcall(ll_constantdict_contains, v_dict, v_key) + #chashcompute) # ____________________________________________________________ # @@ -113,19 +113,19 @@ def ll_constantdict_len(d): return d.num_items -def ll_constantdict_getitem(d, key, hashcompute): - entry = ll_constantdict_lookup(d, key, hashcompute) +def ll_constantdict_getitem(d, key):#, hashcompute): + entry = ll_constantdict_lookup(d, key)#, hashcompute) if entry.valid: return entry.value else: raise KeyError -def ll_constantdict_contains(d, key, hashcompute): - entry = ll_constantdict_lookup(d, key, hashcompute) +def ll_constantdict_contains(d, key):#, hashcompute): + entry = ll_constantdict_lookup(d, key)#, hashcompute) return entry.valid -def ll_constantdict_setnewitem(d, key, value, hashcompute): - entry = ll_constantdict_lookup(d, key, hashcompute) +def ll_constantdict_setnewitem(d, key, value):#, hashcompute): + entry = ll_constantdict_lookup(d, key)#, hashcompute) assert not entry.valid entry.key = key entry.valid = True @@ -135,8 +135,8 @@ # the below is a port of CPython's dictobject.c's lookdict implementation PERTURB_SHIFT = 5 -def ll_constantdict_lookup(d, key, hashcompute): - hash = hashcompute(key) +def ll_constantdict_lookup(d, key):#, hashcompute): + hash = key #hashcompute(key) entries = d.entries mask = len(entries) - 1 perturb = r_uint(hash) @@ -150,8 +150,8 @@ perturb >>= PERTURB_SHIFT i = (i << 2) + i + perturb + 1 -def ll_hash_identity(x): - return x +##def ll_hash_identity(x): +## return x -def ll_hash_char(x): - return ord(x) +##def ll_hash_char(x): +## return ord(x) From hpk at codespeak.net Sun Jun 26 13:42:56 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 13:42:56 +0200 (CEST) Subject: [pypy-svn] r13934 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626114256.5781A27B4D@code1.codespeak.net> Author: hpk Date: Sun Jun 26 13:42:55 2005 New Revision: 13934 Modified: pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: (arigo, hpk) contains for constant tuples delegating to ConstantDict's Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Sun Jun 26 13:42:55 2005 @@ -64,10 +64,27 @@ hop.gendirectcall(rlist.ll_setitem_nonneg, vlist, cindex, vitem) return vlist -#class __extend__(pairtype(TupleRepr, Repr)): -# def rtype_contains((r_tup, r_item), hop): -# XXX - +class __extend__(pairtype(TupleRepr, Repr)): + def rtype_contains((r_tup, r_item), hop): + v_tup = hop.args_v[0] + if not isinstance(v_tup, Constant): + raise TyperError("contains() on non-const tuple") + t = v_tup.value + typ = type(t[0]) + for x in t[1:]: + if type(x) is not typ: + raise TyperError("contains() on mixed-type tuple " + "constant %r" % (v_tup,)) + d = {} + for x in t: + d[x] = None + hop2 = hop.copy() + _, _ = hop2.r_s_popfirstarg() + v_dict = Constant(d) + s_dict = hop.rtyper.annotator.bookkeeper.immutablevalue(d) + hop2.v_s_insertfirstarg(v_dict, s_dict) + return hop2.dispatch() + class __extend__(pairtype(TupleRepr, IntegerRepr)): def rtype_getitem((r_tup, r_int), hop): Modified: pypy/dist/pypy/rpython/test/test_rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rtuple.py (original) +++ pypy/dist/pypy/rpython/test/test_rtuple.py Sun Jun 26 13:42:55 2005 @@ -70,7 +70,6 @@ assert res == 123 def test_constant_tuple_contains(): - py.test.skip("tuple contains not implemented") def f(i): t1 = (1, 2, 3, 4) return i in t1 From mwh at codespeak.net Sun Jun 26 13:52:45 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 13:52:45 +0200 (CEST) Subject: [pypy-svn] r13936 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626115245.20E6D27B4D@code1.codespeak.net> Author: mwh Date: Sun Jun 26 13:52:42 2005 New Revision: 13936 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rint.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rlist.py Log: a rework of how rpython converts things to strings. also, add the ability to convert lists and strings(!) to strings. test (though only for lists...). Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sun Jun 26 13:52:42 2005 @@ -495,22 +495,19 @@ vinst, vattr, vvalue = hop.inputargs(self, Void, r_value) self.setfield(vinst, attr, vvalue, hop.llops) - def rtype_str(self, hop): - v_arg = hop.inputarg(getinstancerepr(hop.rtyper, None), 0) - return hop.gendirectcall(ll_instance_str, v_arg) - - -def ll_instance_str(instance): - from pypy.rpython import rstr - nameLen = len(instance.typeptr.name) - nameString = malloc(rstr.STR, nameLen-1) - i = 0 - while i < nameLen - 1: - nameString.chars[i] = instance.typeptr.name[i] - i += 1 - return rstr.ll_strconcat(rstr.instance_str_prefix, - rstr.ll_strconcat(nameString, - rstr.instance_str_suffix)) + def ll_str(i, r): + instance = cast_pointer(OBJECTPTR, i) + from pypy.rpython import rstr + nameLen = len(instance.typeptr.name) + nameString = malloc(rstr.STR, nameLen-1) + i = 0 + while i < nameLen - 1: + nameString.chars[i] = instance.typeptr.name[i] + i += 1 + return rstr.ll_strconcat(rstr.instance_str_prefix, + rstr.ll_strconcat(nameString, + rstr.instance_str_suffix)) + ll_str = staticmethod(ll_str) class __extend__(pairtype(InstanceRepr, InstanceRepr)): Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Sun Jun 26 13:52:42 2005 @@ -278,44 +278,43 @@ vlist = hop.inputargs(Float) return vlist[0] - def rtype_str(_, hop): - varg = hop.inputarg(hop.args_r[0], 0) - return hop.gendirectcall(ll_int2str, varg) + def ll_str(i, repr): + from pypy.rpython.rstr import STR + temp = malloc(CHAR_ARRAY, 20) + len = 0 + sign = 0 + if i < 0: + sign = 1 + i = -i + if i == 0: + len = 1 + temp[0] = '0' + else: + while i: + temp[len] = chr(i%10+ord('0')) + i //= 10 + len += 1 + len += sign + result = malloc(STR, len) + if sign: + result.chars[0] = '-' + j = 1 + else: + j = 0 + while j < len: + result.chars[j] = temp[len-j-1] + j += 1 + return result + ll_str = staticmethod(ll_str) def rtype_hex(_, hop): varg = hop.inputarg(hop.args_r[0], 0) true = inputconst(Bool, True) return hop.gendirectcall(ll_int2hex, varg, true) -CHAR_ARRAY = GcArray(Char) -def ll_int2str(i): - from pypy.rpython.rstr import STR - temp = malloc(CHAR_ARRAY, 20) - len = 0 - sign = 0 - if i < 0: - sign = 1 - i = -i - if i == 0: - len = 1 - temp[0] = '0' - else: - while i: - temp[len] = chr(i%10+ord('0')) - i //= 10 - len += 1 - len += sign - result = malloc(STR, len) - if sign: - result.chars[0] = '-' - j = 1 - else: - j = 0 - while j < len: - result.chars[j] = temp[len-j-1] - j += 1 - return result + +CHAR_ARRAY = GcArray(Char) hex_chars = malloc(Array(Char), 16, immortal=True) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Jun 26 13:52:42 2005 @@ -6,6 +6,7 @@ from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr from pypy.rpython.rstr import string_repr, ll_streq +from pypy.rpython import rstr from pypy.rpython.rclass import InstanceRepr from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive @@ -137,6 +138,24 @@ def make_iterator_repr(self): return ListIteratorRepr(self) + def ll_str(l, listrepr): + items = l.items + length = len(items) + item_repr = listrepr.item_repr + + temp = malloc(TEMP, length) + i = 0 + while i < length: + temp[i] = item_repr.ll_str(items[i], item_repr) + i += 1 + + return rstr.ll_strconcat( + rstr.list_str_open_bracket, + rstr.ll_strconcat(rstr.ll_join(rstr.list_str_sep, + temp), + rstr.list_str_close_bracket)) + ll_str = staticmethod(ll_str) + class __extend__(pairtype(ListRepr, Repr)): @@ -489,6 +508,10 @@ j += 1 raise ValueError # can't say 'list.index(x): x not in list' +TEMP = GcArray(Ptr(rstr.STR)) + + + # ____________________________________________________________ # # Irregular operations. Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sun Jun 26 13:52:42 2005 @@ -37,6 +37,9 @@ raise AttributeError("%s instance has no attribute %s" % ( self.__class__.__name__, name)) + def _freeze_(self): + return True + def convert_const(self, value): "Convert the given constant value to the low-level repr of 'self'." if self.lowleveltype != Void: @@ -69,6 +72,10 @@ else: raise TyperError("getattr() with a non-constant attribute name") + def rtype_str(self, hop): + vrepr = inputconst(Void, self) + return hop.gendirectcall(self.ll_str, hop.args_v[0], vrepr) + def rtype_nonzero(self, hop): return self.rtype_is_true(hop) # can call a subclass' rtype_is_true() Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 13:52:42 2005 @@ -10,8 +10,8 @@ from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr from pypy.rpython.lltype import GcStruct, Signed, Array, Char, Ptr, malloc -from pypy.rpython.lltype import Bool, Void, GcArray, nullptr -from pypy.rpython.rclass import InstanceRepr, ll_instance_str, getinstancerepr +from pypy.rpython.lltype import Bool, Void, GcArray, nullptr, typeOf +from pypy.rpython.rclass import InstanceRepr # ____________________________________________________________ @@ -116,6 +116,13 @@ v_items = hop.genop("getfield", [v_lst, cname], resulttype=Ptr(GcArray(Ptr(STR)))) return hop.gendirectcall(ll_join, v_str, v_items) + + def ll_str(s, r): + if typeOf(s) == Char: + return ll_chr2str(s) + else: + return s + ll_str = staticmethod(ll_str) def make_iterator_repr(self): return string_iterator_repr @@ -232,18 +239,12 @@ if isinstance(thing, tuple): code = thing[0] vitem, r_arg = argsiter.next() + rep = inputconst(Void, r_arg) if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)): - if isinstance(r_arg, StringRepr): - vchunk = hop.llops.convertvar(vitem, r_arg, string_repr) - elif isinstance(r_arg, InstanceRepr): - vinst = hop.llops.convertvar( - vitem, r_arg, getinstancerepr(hop.rtyper, None)) - vchunk = hop.gendirectcall(ll_instance_str, vinst) - else: - assert 0 + vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) elif code == 'd': assert isinstance(r_arg, IntegerRepr) - vchunk = hop.gendirectcall(rint.ll_int2str, vitem) + vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) elif code == 'x': assert isinstance(r_arg, IntegerRepr) vchunk = hop.gendirectcall(rint.ll_int2hex, vitem, @@ -621,3 +622,7 @@ instance_str_prefix = string_repr.convert_const("<") instance_str_suffix = string_repr.convert_const(" object>") + +list_str_open_bracket = string_repr.convert_const("[") +list_str_close_bracket = string_repr.convert_const("]") +list_str_sep = string_repr.convert_const(", ") Modified: pypy/dist/pypy/rpython/test/test_rlist.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rlist.py (original) +++ pypy/dist/pypy/rpython/test/test_rlist.py Sun Jun 26 13:52:42 2005 @@ -302,3 +302,16 @@ except Exception, e: res2 = e.__class__ assert res == res2 + +def test_list_str(): + def fn(): + return str([1,2,3]) + + res = interpret(fn, []) + assert ''.join(res.chars) == fn() + + def fn(): + return str([[1,2,3]]) + + res = interpret(fn, []) + assert ''.join(res.chars) == fn() From hpk at codespeak.net Sun Jun 26 14:11:35 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 14:11:35 +0200 (CEST) Subject: [pypy-svn] r13939 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626121135.A556A27B56@code1.codespeak.net> Author: hpk Date: Sun Jun 26 14:11:34 2005 New Revision: 13939 Modified: pypy/dist/pypy/rpython/rconstantdict.py pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/test/test_rdict.py Log: (hpk, arigo) convert_const() for StrDictRepr. Modified: pypy/dist/pypy/rpython/rconstantdict.py ============================================================================== --- pypy/dist/pypy/rpython/rconstantdict.py (original) +++ pypy/dist/pypy/rpython/rconstantdict.py Sun Jun 26 14:11:34 2005 @@ -44,7 +44,8 @@ ("entries", self.DICTENTRYARRAY))) def convert_const(self, dictobj): - dictobj = getattr(dictobj, '__self__', dictobj) # bound dict methods + # get object from bound dict methods + dictobj = getattr(dictobj, '__self__', dictobj) if not isinstance(dictobj, dict): raise TyperError("expected a dict: %r" % (dictobj,)) try: Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sun Jun 26 14:11:34 2005 @@ -57,7 +57,7 @@ else: self.value_repr = value_repr self.dictvalue = dictvalue - #self.dict_cache = {} + self.dict_cache = {} # setup() needs to be called to finish this initialization def setup(self): @@ -74,23 +74,25 @@ ("num_pristine_entries", lltype.Signed), ("entries", lltype.Ptr(self.DICTENTRYARRAY)))) - #def convert_const(self, dictobj): - # dictobj = getattr(dictobj, '__self__', dictobj) # for bound list methods - # if not isinstance(dictobj, list): - # raise TyperError("expected a list: %r" % (dictobj,)) - # try: - # key = Constant(dictobj) - # return self.list_cache[key] - # except KeyError: - # self.setup() - # result = malloc(self.STRDICT, immortal=True) - # self.list_cache[key] = result - # result.items = malloc(self.STRDICT.items.TO, len(dictobj)) - # r_item = self.value_repr - # for i in range(len(dictobj)): - # x = dictobj[i] - # result.items[i] = r_item.convert_const(x) - # return result + def convert_const(self, dictobj): + # get object from bound dict methods + dictobj = getattr(dictobj, '__self__', dictobj) + if not isinstance(dictobj, dict): + raise TyperError("expected a dict: %r" % (dictobj,)) + try: + key = Constant(dictobj) + return self.dict_cache[key] + except KeyError: + self.setup() + l_dict = ll_newstrdict(self.lowleveltype) + self.dict_cache[key] = l_dict + r_key = string_repr + r_value = self.value_repr + for dictkey, dictvalue in dictobj.items(): + llkey = r_key.convert_const(dictkey) + llvalue = r_value.convert_const(dictvalue) + ll_strdict_setitem(l_dict, llkey, llvalue) + return l_dict def rtype_len(self, hop): v_dict, = hop.inputargs(self) Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Jun 26 14:11:34 2005 @@ -61,7 +61,8 @@ self.LIST.become(GcStruct("list", ("items", Ptr(ITEMARRAY)))) def convert_const(self, listobj): - listobj = getattr(listobj, '__self__', listobj) # for bound list methods + # get object from bound list method + listobj = getattr(listobj, '__self__', listobj) if not isinstance(listobj, list): raise TyperError("expected a list: %r" % (listobj,)) try: Modified: pypy/dist/pypy/rpython/test/test_rdict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rdict.py (original) +++ pypy/dist/pypy/rpython/test/test_rdict.py Sun Jun 26 14:11:34 2005 @@ -244,3 +244,13 @@ return ' 4' in dic and ' 9' not in dic res = interpret(func, ()) assert res is True + +def test_dict_contains_with_constant_dict(): + dic = {'4':1000, ' 8':200} + def func(i): + return chr(i) in dic + res = interpret(func, [ord('4')]) + assert res is True + res = interpret(func, [1]) + assert res is False + From arigo at codespeak.net Sun Jun 26 14:22:05 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 14:22:05 +0200 (CEST) Subject: [pypy-svn] r13940 - pypy/extradoc/sprintinfo Message-ID: <20050626122205.86B8127B57@code1.codespeak.net> Author: arigo Date: Sun Jun 26 14:22:03 2005 New Revision: 13940 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: Some more things done. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sun Jun 26 14:22:03 2005 @@ -34,7 +34,7 @@ (DONE) (easy) method_values (?) (DONE) (easy) method_items (?) (DONE) (easy) contains - (easy) rstr: str.split(single_constant_character) + (DONE) (easy) rstr: str.split(single_constant_character) Binary operations @@ -43,11 +43,12 @@ (easy) rstr: mul, inplace_mul (for CharRepr only!) (easy) 'contains' applied on: - * dict of string keys - * constant tuple of ints - * constant tuple of strings + * (DONE) dict of string keys + * (DONE) constant tuple of ints + * (DONE) constant tuple of strings * constant tuple of unicode characters - * constant dict with int keys (which are pending now) + -- needs constant dict of unichr keys + * (DONE) constant dict with int keys * constant string * string @@ -61,7 +62,7 @@ override:fake_object override:cpy_compile -* prebuilt immutable dictionaries with int keys +* (DONE) prebuilt immutable dictionaries with int keys * (partially DONE) convert each file that does 'from ... import *' to use explicit imports (e.g. From ac at codespeak.net Sun Jun 26 14:38:23 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 26 Jun 2005 14:38:23 +0200 (CEST) Subject: [pypy-svn] r13942 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626123823.4E2ED27B56@code1.codespeak.net> Author: ac Date: Sun Jun 26 14:38:23 2005 New Revision: 13942 Modified: pypy/dist/pypy/rpython/rdict.py pypy/dist/pypy/rpython/rlist.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: Added rstr.split(). Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sun Jun 26 14:38:23 2005 @@ -2,7 +2,6 @@ from pypy.annotation import model as annmodel from pypy.objspace.flow.model import Constant from pypy.rpython import rmodel, lltype, rstr -from pypy.rpython.rstr import STR, string_repr from pypy.rpython.rarithmetic import r_uint from pypy.rpython import rlist, rconstantdict @@ -66,7 +65,7 @@ if isinstance(self.STRDICT, lltype.GcForwardReference): self.DICTVALUE = self.value_repr.lowleveltype self.DICTENTRY = lltype.Struct("dictentry", - ("key", lltype.Ptr(STR)), + ("key", lltype.Ptr(rstr.STR)), ('value', self.DICTVALUE)) self.DICTENTRYARRAY = lltype.GcArray(self.DICTENTRY) self.STRDICT.become(lltype.GcStruct("dicttable", @@ -86,7 +85,7 @@ self.setup() l_dict = ll_newstrdict(self.lowleveltype) self.dict_cache[key] = l_dict - r_key = string_repr + r_key = rstr.string_repr r_value = self.value_repr for dictkey, dictvalue in dictobj.items(): llkey = r_key.convert_const(dictkey) @@ -102,7 +101,7 @@ return StrDictIteratorRepr(self) def rtype_method_get(self, hop): - v_dict, v_key, v_default = hop.inputargs(self, string_repr, + v_dict, v_key, v_default = hop.inputargs(self, rstr.string_repr, self.value_repr) return hop.gendirectcall(ll_get, v_dict, v_key, v_default) @@ -133,19 +132,19 @@ class __extend__(pairtype(StrDictRepr, rmodel.StringRepr)): def rtype_getitem((r_dict, r_string), hop): - v_dict, v_key = hop.inputargs(r_dict, string_repr) + v_dict, v_key = hop.inputargs(r_dict, rstr.string_repr) return hop.gendirectcall(ll_strdict_getitem, v_dict, v_key) def rtype_delitem((r_dict, r_string), hop): - v_dict, v_key = hop.inputargs(r_dict, string_repr) + v_dict, v_key = hop.inputargs(r_dict, rstr.string_repr) return hop.gendirectcall(ll_strdict_delitem, v_dict, v_key) def rtype_setitem((r_dict, r_string), hop): - v_dict, v_key, v_value = hop.inputargs(r_dict, string_repr, r_dict.value_repr) + v_dict, v_key, v_value = hop.inputargs(r_dict, rstr.string_repr, r_dict.value_repr) hop.gendirectcall(ll_strdict_setitem, v_dict, v_key, v_value) def rtype_contains((r_dict, r_string), hop): - v_dict, v_key = hop.inputargs(r_dict, string_repr) + v_dict, v_key = hop.inputargs(r_dict, rstr.string_repr) return hop.gendirectcall(ll_contains, v_dict, v_key) class __extend__(pairtype(StrDictRepr, StrDictRepr)): @@ -173,7 +172,7 @@ # be direct_call'ed from rtyped flow graphs, which means that they will # get flowed and annotated, mostly with SomePtr. -deleted_entry_marker = lltype.malloc(STR, 0, immortal=True) +deleted_entry_marker = lltype.malloc(rstr.STR, 0, immortal=True) def ll_strdict_len(d): return d.num_items Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Sun Jun 26 14:38:23 2005 @@ -5,12 +5,11 @@ from pypy.rpython import rrange from pypy.rpython.rslice import SliceRepr from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr -from pypy.rpython.rstr import string_repr, ll_streq -from pypy.rpython import rstr from pypy.rpython.rclass import InstanceRepr from pypy.rpython.lltype import GcForwardReference, Ptr, GcArray, GcStruct from pypy.rpython.lltype import Void, Signed, malloc, typeOf, Primitive from pypy.rpython.lltype import Bool +from pypy.rpython import rstr # ____________________________________________________________ # Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 14:38:23 2005 @@ -117,6 +117,11 @@ resulttype=Ptr(GcArray(Ptr(STR)))) return hop.gendirectcall(ll_join, v_str, v_items) + def rtype_method_split(_, hop): + v_str, v_chr = hop.inputargs(string_repr, char_repr) + c = hop.inputconst(Void, hop.r_result.lowleveltype) + return hop.gendirectcall(ll_split_chr, c, v_str, v_chr) + def ll_str(s, r): if typeOf(s) == Char: return ll_chr2str(s) @@ -585,6 +590,41 @@ j += 1 return newstr +def ll_split_chr(LISTPTR, s, c): + chars = s.chars + strlen = len(chars) + count = 1 + i = 0 + while i < strlen: + if chars[i] == c: + count += 1 + i += 1 + res = malloc(LISTPTR.TO) + items = res.items = malloc(LISTPTR.TO.items.TO, count) + + i = 0 + j = 0 + resindex = 0 + while j < strlen: + if chars[j] == c: + item = items[resindex] = malloc(STR, j - i) + newchars = item.chars + k = i + while k < j: + newchars[k - i] = chars[k] + k += 1 + resindex += 1 + i = j + 1 + j += 1 + item = items[resindex] = malloc(STR, j - i) + newchars = item.chars + k = i + while k < j: + newchars[k - i] = chars[k] + k += 1 + resindex += 1 + + return res # ____________________________________________________________ # # Iteration. Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 14:38:23 2005 @@ -272,3 +272,16 @@ res = interpret(dummy, [0]) assert ''.join(res.chars) == 'what a nice , much nicer than ' + +def test_split(): + def fn(i): + s = ['', '0.1.2.4.8', '.1.2', '1.2.', '.1.2.4.'][i] + l = s.split('.') + sum = 0 + for num in l: + if len(num): + sum += ord(num) - ord('0') + return sum + len(l) * 100 + for i in range(5): + res = interpret(fn, [i]) + assert res == fn(i) From ac at codespeak.net Sun Jun 26 14:53:49 2005 From: ac at codespeak.net (ac at codespeak.net) Date: Sun, 26 Jun 2005 14:53:49 +0200 (CEST) Subject: [pypy-svn] r13943 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626125349.644BA27B56@code1.codespeak.net> Author: ac Date: Sun Jun 26 14:53:49 2005 New Revision: 13943 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: Implemented contains for rstr. Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 14:53:49 2005 @@ -199,6 +199,11 @@ def rtype_mod(_, hop): return do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) +class __extend__(pairtype(StringRepr, CharRepr)): + def rtype_contains(_, hop): + v_str, v_chr = hop.inputargs(string_repr, char_repr) + return hop.gendirectcall(ll_contains, v_str, v_chr) + def parse_fmt_string(fmt): # we support x, d, s, [r] @@ -625,6 +630,17 @@ resindex += 1 return res + +def ll_contains(s, c): + chars = s.chars + strlen = len(chars) + i = 0 + while i < strlen: + if chars[i] == c: + return True + i += 1 + return False + # ____________________________________________________________ # # Iteration. Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 14:53:49 2005 @@ -285,3 +285,12 @@ for i in range(5): res = interpret(fn, [i]) assert res == fn(i) + +def test_contains(): + def fn(i): + s = 'Hello world' + return chr(i) in s + for i in range(256): + res = interpret(fn, [i]) + assert res == fn(i) + From tismer at codespeak.net Sun Jun 26 14:54:20 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 14:54:20 +0200 (CEST) Subject: [pypy-svn] r13944 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626125420.54DEC27B57@code1.codespeak.net> Author: tismer Date: Sun Jun 26 14:54:19 2005 New Revision: 13944 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: implemented char_mul Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 14:54:19 2005 @@ -307,7 +307,13 @@ def rtype_method_isspace(_, hop): vlist = hop.inputargs(char_repr) - return hop.llops.gendirectcall(ll_char_isspace, vlist[0]) + return hop.gendirectcall(ll_char_isspace, vlist[0]) + +class __extend__(pairtype(CharRepr, IntegerRepr)): + + def rtype_mul(_, hop): + v_char, v_int = hop.inputargs(char_repr, Signed) + return hop.gendirectcall(ll_char_mul, v_char, v_int) class __extend__(pairtype(CharRepr, CharRepr)): def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq') @@ -412,6 +418,14 @@ c = ord(ch) return 9 <= c <= 13 or c == 32 +def ll_char_mul(ch, times): + newstr = malloc(STR, times) + j = 0 + while j < times: + newstr.chars[j] = ch + j += 1 + return newstr + def ll_strlen(s): return len(s.chars) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 14:54:19 2005 @@ -90,6 +90,16 @@ res = interpret(lambda c1, c2: c1 <= c2, ['z', 'a']) assert res is False +def test_char_mul(): + def fn(c, mul): + s = c * mul + res = 0 + for i in range(len(s)): + res = res*10 + ord(s[i]) - ord('0') + return res + res = interpret(fn, ['3', 5]) + assert res == 33333 + def test_str_compare(): def fn(i, j): s1 = ['one', 'two'] From hpk at codespeak.net Sun Jun 26 15:05:59 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 15:05:59 +0200 (CEST) Subject: [pypy-svn] r13945 - pypy/dist/pypy/translator/test Message-ID: <20050626130559.6DE8D27B56@code1.codespeak.net> Author: hpk Date: Sun Jun 26 15:05:58 2005 New Revision: 13945 Modified: pypy/dist/pypy/translator/test/test_annrpython.py Log: fix a few tests to use proper number of arguments (discovered by more strict arg-num checking) Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Sun Jun 26 15:05:58 2005 @@ -582,13 +582,13 @@ def test_flow_rev_numbers(self): a = self.RPythonAnnotator() - s = a.build_types(snippet.flow_rev_numbers, []) + s = a.build_types(snippet.flow_rev_numbers, [int]) assert s.knowntype == int assert not s.is_constant() # ! def test_methodcall_is_precise(self): a = self.RPythonAnnotator() - s = a.build_types(snippet.methodcall_is_precise, []) + s = a.build_types(snippet.methodcall_is_precise, [bool]) classes = a.bookkeeper.userclasses assert 'x' not in classes[snippet.CBase].attrs assert (classes[snippet.CSub1].attrs['x'].s_value == @@ -637,7 +637,7 @@ def assert_(x): assert x,"XXX" a = self.RPythonAnnotator() - s = a.build_types(assert_, []) + s = a.build_types(assert_, [int]) assert s.const is None def test_string_and_none(self): From mwh at codespeak.net Sun Jun 26 15:06:47 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 15:06:47 +0200 (CEST) Subject: [pypy-svn] r13946 - in pypy/dist/pypy: annotation rpython translator/c/test Message-ID: <20050626130647.4042F27B56@code1.codespeak.net> Author: mwh Date: Sun Jun 26 15:06:44 2005 New Revision: 13946 Modified: pypy/dist/pypy/annotation/model.py pypy/dist/pypy/rpython/lltype.py pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/translator/c/test/test_typed.py Log: c-ish cheating float str, fixes to annotation, lltype to allow calling external pointer in ll helpers. test. Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sun Jun 26 15:06:44 2005 @@ -429,7 +429,10 @@ def ll_to_annotation(v): if v is None: - raise ValueError, "cannot retrieve Void low-level type value" + # i think we can only get here in the case of void-returning + # functions + from bookkeeper import getbookkeeper + return getbookkeeper().immutablevalue(None) return lltype_to_annotation(lltype.typeOf(v)) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltype.py (original) +++ pypy/dist/pypy/rpython/lltype.py Sun Jun 26 15:06:44 2005 @@ -237,7 +237,7 @@ def _container_example(self): def ex(*args): - return self.RESULT._example() + return self.RESULT._defl() return _func(self, _callable=ex) class OpaqueType(ContainerType): Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sun Jun 26 15:06:44 2005 @@ -1,10 +1,12 @@ from pypy.annotation.pairtype import pairtype from pypy.annotation import model as annmodel -from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void +from pypy.rpython.lltype import Signed, Unsigned, Bool, Float, Void, Ptr from pypy.rpython.rmodel import Repr, TyperError, FloatRepr from pypy.rpython.rmodel import IntegerRepr, BoolRepr from pypy.rpython.robject import PyObjRepr, pyobj_repr - +from pypy.rpython.lltype import PyObject, Array, Char +from pypy.rpython.rstr import STR +from pypy.rpython.lltype import functionptr, FuncType, malloc debug = False @@ -121,6 +123,34 @@ rtype_float = rtype_pos + def ll_str(f, repr): + pyfloat = pyfloat_fromdouble_ptr(f) + pystring = pyobject_str_ptr(pyfloat) + stringsize = pystring_size_ptr(pystring) + + ret = malloc(STR, stringsize) + + tollchararray_ptr(pystring, ret.chars) + + return ret + + ll_str = staticmethod(ll_str) + +PyObjectPtr = Ptr(PyObject) + +pystring_size_ptr = functionptr(FuncType([PyObjectPtr], Signed), + "PyString_Size", + external="C") +pyfloat_fromdouble_ptr = functionptr(FuncType([Float], PyObjectPtr), + "PyFloat_FromDouble", + external="C") +pyobject_str_ptr = functionptr(FuncType([PyObjectPtr], PyObjectPtr), + "PyObject_Str", + external="C") +tollchararray_ptr = functionptr(FuncType([PyObjectPtr, Ptr(Array(Char))], Void), + "PyString_ToLLCharArray", + external="C") + # # _________________________ Conversions _________________________ Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Sun Jun 26 15:06:44 2005 @@ -293,4 +293,10 @@ return str(i) f = self.getcompiled(fn) assert f(1) == fn(1) + + def test_float2int(self): + def fn(i=float): + return str(i) + f = self.getcompiled(fn) + assert f(1.0) == fn(1.0) From tismer at codespeak.net Sun Jun 26 15:11:21 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 15:11:21 +0200 (CEST) Subject: [pypy-svn] r13947 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626131121.168D527B57@code1.codespeak.net> Author: tismer Date: Sun Jun 26 15:11:20 2005 New Revision: 13947 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: completed char mul, char inplace mul Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 15:11:20 2005 @@ -314,6 +314,7 @@ def rtype_mul(_, hop): v_char, v_int = hop.inputargs(char_repr, Signed) return hop.gendirectcall(ll_char_mul, v_char, v_int) + rtype_inplace_mul = rtype_mul class __extend__(pairtype(CharRepr, CharRepr)): def rtype_eq(_, hop): return _rtype_compare_template(hop, 'eq') Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 15:11:20 2005 @@ -96,9 +96,14 @@ res = 0 for i in range(len(s)): res = res*10 + ord(s[i]) - ord('0') + c2 = c + c2 *= mul + res = 10 * res + (c2 == s) return res res = interpret(fn, ['3', 5]) - assert res == 33333 + assert res == 333331 + res = interpret(fn, ['5', 3]) + assert res == 5551 def test_str_compare(): def fn(i, j): From tismer at codespeak.net Sun Jun 26 15:15:26 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 15:15:26 +0200 (CEST) Subject: [pypy-svn] r13949 - pypy/extradoc/sprintinfo Message-ID: <20050626131526.036EF27B57@code1.codespeak.net> Author: tismer Date: Sun Jun 26 15:15:26 2005 New Revision: 13949 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: char add/inplace add done Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sun Jun 26 15:15:26 2005 @@ -40,7 +40,7 @@ Binary operations ----------------- - (easy) rstr: mul, inplace_mul (for CharRepr only!) + (DONE) (easy) rstr: mul, inplace_mul (for CharRepr only!) (easy) 'contains' applied on: * (DONE) dict of string keys From hpk at codespeak.net Sun Jun 26 15:20:47 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 15:20:47 +0200 (CEST) Subject: [pypy-svn] r13951 - pypy/dist/pypy/translator/tool/pygame Message-ID: <20050626132047.98D0927B57@code1.codespeak.net> Author: hpk Date: Sun Jun 26 15:20:46 2005 New Revision: 13951 Modified: pypy/dist/pypy/translator/tool/pygame/graphclient.py Log: Using a CGI script on Codespeak to do the .dot -> .plain conversion. Codespeak has got a version of dot that includes odie's fix. Modified: pypy/dist/pypy/translator/tool/pygame/graphclient.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/graphclient.py (original) +++ pypy/dist/pypy/translator/tool/pygame/graphclient.py Sun Jun 26 15:20:46 2005 @@ -13,13 +13,42 @@ DOT_FILE = udir.join('graph.dot') PLAIN_FILE = udir.join('graph.plain') +import py +def dot2plain(dotfile, plainfile): + if 0: + cmdexec('dot -Tplain %s>%s' % (dotfile, plainfile)) + elif 0: + gw = py.execnet.SshGateway('codespeak.net') + channel = gw.remote_exec(""" + import py + content = channel.receive() + fn = py.path.local.make_numbered_dir('makegraph').join('graph.dot') + fn.write(content) + tfn = fn.new(ext='.plain') + py.process.cmdexec("dot -Tplain %s >%s" %(fn, tfn)) + channel.send(tfn.read()) + """) + channel.send(py.path.local(dotfile).read()) + plainfile = py.path.local(plainfile) + plainfile.write(channel.receive()) + else: + import urllib + content = py.path.local(dotfile).read() + request = urllib.urlencode({'dot': content}) + urllib.urlretrieve('http://codespeak.net/pypy/convertdot.cgi', + str(plainfile), + data=request) + plainfile = py.path.local(plainfile) + if not plainfile.check(file=1) or not plainfile.read().startswith('graph '): + print "NOTE: failed to use codespeak's convertdot.cgi, trying local 'dot'" + cmdexec('dot -Tplain %s>%s' % (dotfile, plainfile)) class ClientGraphLayout(GraphLayout): def __init__(self, connexion, key, dot, links, **ignored): # generate a temporary .dot file and call dot on it DOT_FILE.write(dot) - cmdexec('dot -Tplain %s>%s' % (str(DOT_FILE),str(PLAIN_FILE))) + dot2plain(DOT_FILE, PLAIN_FILE) GraphLayout.__init__(self, PLAIN_FILE) self.connexion = connexion self.key = key From arigo at codespeak.net Sun Jun 26 15:38:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 15:38:46 +0200 (CEST) Subject: [pypy-svn] r13953 - pypy/dist/pypy/translator/c Message-ID: <20050626133846.83E7227B56@code1.codespeak.net> Author: arigo Date: Sun Jun 26 15:38:44 2005 New Revision: 13953 Modified: pypy/dist/pypy/translator/c/int_include.h Log: More integer operations in the C back-end. Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Sun Jun 26 15:38:44 2005 @@ -135,6 +135,12 @@ if ((long)(y)) { OP_INT_MOD_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") +/* bit operations */ + +#define OP_INT_AND(x,y,r,err) r = (long)(x) & (long)(y); +#define OP_INT_OR( x,y,r,err) r = (long)(x) | (long)(y); +#define OP_INT_XOR(x,y,r,err) r = (long)(x) ^ (long)(y); + /*** conversions ***/ #define OP_CAST_BOOL_TO_INT(x,r,err) r = (long)(x); From tismer at codespeak.net Sun Jun 26 15:49:09 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 15:49:09 +0200 (CEST) Subject: [pypy-svn] r13954 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20050626134909.45E4E27B56@code1.codespeak.net> Author: tismer Date: Sun Jun 26 15:49:07 2005 New Revision: 13954 Modified: pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: string.replace(char, char) done Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sun Jun 26 15:49:07 2005 @@ -321,6 +321,9 @@ getbookkeeper().count("str_split", str, patt) return getbookkeeper().newlist(SomeString()) + def method_replace(str, s1, s2): + return SomeString() + class __extend__(SomeChar): Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 15:49:07 2005 @@ -121,7 +121,11 @@ v_str, v_chr = hop.inputargs(string_repr, char_repr) c = hop.inputconst(Void, hop.r_result.lowleveltype) return hop.gendirectcall(ll_split_chr, c, v_str, v_chr) - + + def rtype_method_replace(_, hop): + v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr) + return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2) + def ll_str(s, r): if typeOf(s) == Char: return ll_chr2str(s) @@ -434,7 +438,7 @@ return s.chars[i] def ll_stritem(s, i): - if i<0: + if i < 0: i += len(s.chars) return s.chars[i] @@ -646,6 +650,20 @@ return res +def ll_replace_chr_chr(s, c1, c2): + length = len(s.chars) + newstr = malloc(STR, length) + src = s.chars + dst = newstr.chars + j = 0 + while j < length: + c = src[j] + if c == c1: + c = c2 + dst[j] = c + j += 1 + return newstr + def ll_contains(s, c): chars = s.chars strlen = len(chars) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 15:49:07 2005 @@ -306,6 +306,20 @@ s = 'Hello world' return chr(i) in s for i in range(256): - res = interpret(fn, [i]) + res = interpret(fn, [i])#, view=i==42) assert res == fn(i) +def test_replace(): + def fn(c1, c2): + s = 'abbccc' + s = s.replace(c1, c2) + res = 0 + for c in s: + if c == c2: + res += 1 + return res + res = interpret(fn, ['a', 'c']) + assert res == 4 + res = interpret(fn, ['c', 'b']) + assert res == 5 + From tismer at codespeak.net Sun Jun 26 15:49:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 15:49:39 +0200 (CEST) Subject: [pypy-svn] r13955 - pypy/extradoc/sprintinfo Message-ID: <20050626134939.4B36727B56@code1.codespeak.net> Author: tismer Date: Sun Jun 26 15:49:38 2005 New Revision: 13955 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: string.replace(char, char) done Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sun Jun 26 15:49:38 2005 @@ -35,6 +35,7 @@ (DONE) (easy) method_items (?) (DONE) (easy) contains (DONE) (easy) rstr: str.split(single_constant_character) + (DONE) method_replace with char/char Binary operations @@ -49,8 +50,8 @@ * constant tuple of unicode characters -- needs constant dict of unichr keys * (DONE) constant dict with int keys - * constant string - * string + * (DONE via string) constant string + * (DONE) string Overridden functions in PyPy ---------------------------- From pedronis at codespeak.net Sun Jun 26 15:52:02 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 26 Jun 2005 15:52:02 +0200 (CEST) Subject: [pypy-svn] r13956 - pypy/dist/pypy/translator/test Message-ID: <20050626135202.1F09627B56@code1.codespeak.net> Author: pedronis Date: Sun Jun 26 15:52:01 2005 New Revision: 13956 Modified: pypy/dist/pypy/translator/test/test_cltrans.py Log: fix tests after args number check in annrpython change Modified: pypy/dist/pypy/translator/test/test_cltrans.py ============================================================================== --- pypy/dist/pypy/translator/test/test_cltrans.py (original) +++ pypy/dist/pypy/translator/test/test_cltrans.py Sun Jun 26 15:52:01 2005 @@ -43,7 +43,7 @@ py.test.skip("Common Lisp neither configured nor detected.") def test_if(self): - cl_if = make_cl_func(t.if_then_else) + cl_if = make_cl_func(t.if_then_else, [object, object, object]) assert cl_if(True, 50, 100) == 50 assert cl_if(False, 50, 100) == 100 assert cl_if(0, 50, 100) == 100 @@ -61,16 +61,16 @@ assert cl_perfect(28) == True def test_bool(self): - cl_bool = make_cl_func(t.my_bool) + cl_bool = make_cl_func(t.my_bool, [object]) assert cl_bool(0) == False assert cl_bool(42) == True assert cl_bool(True) == True def test_contains(self): - my_contains = make_cl_func(t.my_contains) + my_contains = make_cl_func(t.my_contains, [list, int]) assert my_contains([1, 2, 3], 1) assert not my_contains([1, 2, 3], 0) - is_one_or_two = make_cl_func(t.is_one_or_two) + is_one_or_two = make_cl_func(t.is_one_or_two, [int]) assert is_one_or_two(2) assert not is_one_or_two(3) @@ -88,9 +88,9 @@ assert f1(1) == 2 f2 = make_cl_func(t.while_func, [int]) assert f2(10) == 55 - f3 = make_cl_func(t.simple_id) + f3 = make_cl_func(t.simple_id, [int]) assert f3(9) == 9 - f4 = make_cl_func(t.branch_id) + f4 = make_cl_func(t.branch_id, [int, int, int]) assert f4(1, 2, 3) == 2 assert f4(0, 2, 3) == 3 f5 = make_cl_func(t.int_id, [int]) @@ -124,7 +124,7 @@ assert result.val == ( '#(#() #(0) #(1) #(0 1) #(2) #(0 2) #(1 2) #(0 1 2))') def test_yast(self): - cl_sum = make_cl_func(t.yast) # yet another sum test + cl_sum = make_cl_func(t.yast, [list]) # yet another sum test assert cl_sum(range(12)) == 66 From mwh at codespeak.net Sun Jun 26 15:59:39 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 15:59:39 +0200 (CEST) Subject: [pypy-svn] r13957 - pypy/dist/pypy/rpython Message-ID: <20050626135939.9E2BD27B56@code1.codespeak.net> Author: mwh Date: Sun Jun 26 15:59:38 2005 New Revision: 13957 Modified: pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rstr.py Log: simple %f string formatting. you want tests? hmm. Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Sun Jun 26 15:59:38 2005 @@ -7,6 +7,7 @@ from pypy.rpython.lltype import PyObject, Array, Char from pypy.rpython.rstr import STR from pypy.rpython.lltype import functionptr, FuncType, malloc +from pypy.rpython import rstr debug = False @@ -82,6 +83,9 @@ def rtype_ge(_, hop): return _rtype_compare_template(hop, 'ge') +class __extend__(pairtype(rstr.StringRepr, FloatRepr)): + def rtype_mod(_, hop): + return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])]) #Helpers FloatRepr,FloatRepr Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 15:59:38 2005 @@ -209,7 +209,7 @@ return hop.gendirectcall(ll_contains, v_str, v_chr) def parse_fmt_string(fmt): - # we support x, d, s, [r] + # we support x, d, s, f, [r] it = iter(fmt) r = [] @@ -224,7 +224,7 @@ if curstr: r.append(curstr) curstr = '' - assert f in 'xdsr' + assert f in 'xdsrf' r.append((f,)) else: @@ -259,6 +259,9 @@ elif code == 'd': assert isinstance(r_arg, IntegerRepr) vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) + elif code == 'f': + #assert isinstance(r_arg, FloatRepr) + vchunk = hop.gendirectcall(r_arg.ll_str, vitem, rep) elif code == 'x': assert isinstance(r_arg, IntegerRepr) vchunk = hop.gendirectcall(rint.ll_int2hex, vitem, From mwh at codespeak.net Sun Jun 26 16:00:39 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 16:00:39 +0200 (CEST) Subject: [pypy-svn] r13958 - pypy/dist/demo Message-ID: <20050626140039.949E827B56@code1.codespeak.net> Author: mwh Date: Sun Jun 26 16:00:38 2005 New Revision: 13958 Modified: pypy/dist/demo/bpnn.py Log: version of demo/bpnn.py that specializes and runs nicely. Modified: pypy/dist/demo/bpnn.py ============================================================================== --- pypy/dist/demo/bpnn.py (original) +++ pypy/dist/demo/bpnn.py Sun Jun 26 16:00:38 2005 @@ -21,6 +21,7 @@ import sys import math +import time # XXX the Translator needs the plain Python version of random.py: import autopath; from pypy.lib import random @@ -157,7 +158,7 @@ self.update(inputs) error = error + self.backPropagate(targets, N, M) if i % 100 == 0: - print 'error %-14f' % error + print 'error %f' % error def demo(): @@ -179,18 +180,26 @@ if __name__ == '__main__': - #demo() - print 'Loading...' from pypy.translator.translator import Translator t = Translator(demo) + print 'Annotating...' a = t.annotate([]) a.simplify() - #a.specialize() # enable this to see (some) lower-level Cish operations - print 'Displaying the call graph and the class hierarchy.' - t.viewcg() + + print 'Specializing...' + t.specialize() # enable this to see (some) lower-level Cish operations + print 'Compiling...' f = t.ccompile() + print 'Running...' + T = time.time() f() + print "that took", time.time() - T + + T = time.time() + demo() + print "compared to", time.time() - T + From arigo at codespeak.net Sun Jun 26 16:01:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 16:01:33 +0200 (CEST) Subject: [pypy-svn] r13959 - pypy/extradoc/sprintinfo Message-ID: <20050626140133.11B7A27B56@code1.codespeak.net> Author: arigo Date: Sun Jun 26 16:01:31 2005 New Revision: 13959 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: We miss unsigned int operations in the C back-end. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sun Jun 26 16:01:31 2005 @@ -71,6 +71,8 @@ * DONE (holger, michael) translator/c/float_include.h should be complete. +* translator/c/int_include.h needs unsigned arithmetic operations. + * progress on translation of example targets: python demo/bpnn.py (holger, michael, samuele) python pypy/translator/goal/translate_pypy.py targetrichards.py From arigo at codespeak.net Sun Jun 26 16:04:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 16:04:57 +0200 (CEST) Subject: [pypy-svn] r13960 - pypy/dist/pypy/rpython Message-ID: <20050626140457.3C08527B56@code1.codespeak.net> Author: arigo Date: Sun Jun 26 16:04:55 2005 New Revision: 13960 Modified: pypy/dist/pypy/rpython/rdict.py Log: This check can never match. Can't use ConstantDicts for Char keys. Modified: pypy/dist/pypy/rpython/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/rdict.py (original) +++ pypy/dist/pypy/rpython/rdict.py Sun Jun 26 16:04:55 2005 @@ -33,7 +33,7 @@ dictvalue = self.dictdef.dictvalue return StrDictRepr(lambda: rtyper.getrepr(dictvalue.s_value), dictvalue) - elif isinstance(s_key, (annmodel.SomeInteger, annmodel.SomeChar)): + elif isinstance(s_key, annmodel.SomeInteger): dictkey = self.dictdef.dictkey dictvalue = self.dictdef.dictvalue return rconstantdict.ConstantDictRepr( From tismer at codespeak.net Sun Jun 26 16:06:13 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 16:06:13 +0200 (CEST) Subject: [pypy-svn] r13961 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626140613.3FA9427B4E@code1.codespeak.net> Author: tismer Date: Sun Jun 26 16:06:12 2005 New Revision: 13961 Modified: pypy/dist/pypy/rpython/rstr.py pypy/dist/pypy/rpython/test/test_rstr.py Log: checking that replace really gets char args Modified: pypy/dist/pypy/rpython/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/rstr.py (original) +++ pypy/dist/pypy/rpython/rstr.py Sun Jun 26 16:06:12 2005 @@ -123,6 +123,8 @@ return hop.gendirectcall(ll_split_chr, c, v_str, v_chr) def rtype_method_replace(_, hop): + if not (hop.args_r[1] == char_repr and hop.args_r[2] == char_repr): + raise TyperError, 'replace only works for char args' v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr) return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2) Modified: pypy/dist/pypy/rpython/test/test_rstr.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rstr.py (original) +++ pypy/dist/pypy/rpython/test/test_rstr.py Sun Jun 26 16:06:12 2005 @@ -1,7 +1,7 @@ from pypy.translator.translator import Translator from pypy.rpython.lltype import * from pypy.rpython.rstr import parse_fmt_string -from pypy.rpython.rtyper import RPythonTyper +from pypy.rpython.rtyper import RPythonTyper, TyperError from pypy.rpython.test.test_llinterp import interpret @@ -322,4 +322,11 @@ assert res == 4 res = interpret(fn, ['c', 'b']) assert res == 5 - + def fn(): + s = 'abbccc' + s = s.replace('a', 'baz') + raises (TyperError, interpret, fn, ()) + def fn(): + s = 'abbccc' + s = s.replace('abb', 'c') + raises (TyperError, interpret, fn, ()) From mwh at codespeak.net Sun Jun 26 16:13:55 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 16:13:55 +0200 (CEST) Subject: [pypy-svn] r13962 - pypy/dist/demo Message-ID: <20050626141355.8980E27B4E@code1.codespeak.net> Author: mwh Date: Sun Jun 26 16:13:54 2005 New Revision: 13962 Modified: pypy/dist/demo/bpnn.py Log: a more useful version for benchmarking. Modified: pypy/dist/demo/bpnn.py ============================================================================== --- pypy/dist/demo/bpnn.py (original) +++ pypy/dist/demo/bpnn.py Sun Jun 26 16:13:54 2005 @@ -26,6 +26,7 @@ # XXX the Translator needs the plain Python version of random.py: import autopath; from pypy.lib import random +PRINT_IT = False random.seed(0) @@ -136,16 +137,18 @@ def test(self, patterns): for p in patterns: - print p[0], '->', self.update(p[0]) + if PRINT_IT: + print p[0], '->', self.update(p[0]) def weights(self): - print 'Input weights:' - for i in range(self.ni): - print self.wi[i] - print - print 'Output weights:' - for j in range(self.nh): - print self.wo[j] + if PRINT_IT: + print 'Input weights:' + for i in range(self.ni): + print self.wi[i] + print + print 'Output weights:' + for j in range(self.nh): + print self.wo[j] def train(self, patterns, iterations=2000, N=0.5, M=0.1): # N: learning rate @@ -157,7 +160,7 @@ targets = p[1] self.update(inputs) error = error + self.backPropagate(targets, N, M) - if i % 100 == 0: + if PRINT_IT and i % 100 == 0: print 'error %f' % error @@ -196,10 +199,15 @@ print 'Running...' T = time.time() - f() - print "that took", time.time() - T + for i in range(10): + f() + t1 = time.time() - T + print "that took", t1 T = time.time() - demo() - print "compared to", time.time() - T + for i in range(10): + demo() + t2 = time.time() - T + print "compared to", t2 + print "a speed-up of", t2/t1 From tismer at codespeak.net Sun Jun 26 16:20:07 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 16:20:07 +0200 (CEST) Subject: [pypy-svn] r13963 - pypy/dist/pypy/translator/c Message-ID: <20050626142007.2D6C927B4E@code1.codespeak.net> Author: tismer Date: Sun Jun 26 16:20:06 2005 New Revision: 13963 Modified: pypy/dist/pypy/translator/c/int_include.h Log: removed no-longer needed casts. reason: without the casts, most macros can be re-used to implement the r_uint operations. Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Sun Jun 26 16:20:06 2005 @@ -6,53 +6,53 @@ #define OP_INT_IS_TRUE(x,r,err) OP_INT_NE(x,0,r,err) -#define OP_INT_INVERT(x,r,err) r = ~((long)(x)); +#define OP_INT_INVERT(x,r,err) r = ~((x)); #define OP_INT_POS(x,r,err) r = x; -#define OP_INT_NEG(x,r,err) r = -((long)x); +#define OP_INT_NEG(x,r,err) r = -(x); #define OP_INT_NEG_OVF(x,r,err) \ OP_INT_NEG(x,r,err) \ - if ((long)(x) >= 0 || (long)(x) != -(long)(x)); \ + if ((x) >= 0 || (x) != -(x)); \ else FAIL_OVF(err, "integer negate") -#define OP_INT_ABS(x,r,err) r = (long)(x) >= 0 ? x : -((long)x); +#define OP_INT_ABS(x,r,err) r = (x) >= 0 ? x : -(x); #define OP_INT_ABS_OVF(x,r,err) \ OP_INT_ABS(x,r,err) \ - if ((long)(x) >= 0 || (long)(x) != -(long)(x)); \ + if ((x) >= 0 || (x) != -(x)); \ else FAIL_OVF(err, "integer absolute") /*** binary operations ***/ -#define OP_INT_EQ(x,y,r,err) r = ((long)(x) == (long)(y)); -#define OP_INT_NE(x,y,r,err) r = ((long)(x) != (long)(y)); -#define OP_INT_LE(x,y,r,err) r = ((long)(x) <= (long)(y)); -#define OP_INT_GT(x,y,r,err) r = ((long)(x) > (long)(y)); -#define OP_INT_LT(x,y,r,err) r = ((long)(x) < (long)(y)); -#define OP_INT_GE(x,y,r,err) r = ((long)(x) >= (long)(y)); +#define OP_INT_EQ(x,y,r,err) r = ((x) == (y)); +#define OP_INT_NE(x,y,r,err) r = ((x) != (y)); +#define OP_INT_LE(x,y,r,err) r = ((x) <= (y)); +#define OP_INT_GT(x,y,r,err) r = ((x) > (y)); +#define OP_INT_LT(x,y,r,err) r = ((x) < (y)); +#define OP_INT_GE(x,y,r,err) r = ((x) >= (y)); #define OP_INT_CMP(x,y,r,err) \ - r = (((long)(x) > (long)(y)) - ((long)(x) < (long)(y))) + r = (((x) > (y)) - ((x) < (y))) /* addition, subtraction */ -#define OP_INT_ADD(x,y,r,err) r = (long)(x) + (long)(y); +#define OP_INT_ADD(x,y,r,err) r = (x) + (y); #define OP_INT_ADD_OVF(x,y,r,err) \ OP_INT_ADD(x,y,r,err) \ - if ((r^((long)x)) >= 0 || (r^((long)y)) >= 0); \ + if ((r^(x)) >= 0 || (r^(y)) >= 0); \ else FAIL_OVF(err, "integer addition") -#define OP_INT_SUB(x,y,r,err) r = (long)(x) - (long)(y); +#define OP_INT_SUB(x,y,r,err) r = (x) - (y); #define OP_INT_SUB_OVF(x,y,r,err) \ OP_INT_SUB(x,y,r,err) \ - if ((r^(long)(x)) >= 0 || (r^~(long)(y)) >= 0); \ + if ((r^(x)) >= 0 || (r^~(y)) >= 0); \ else FAIL_OVF(err, "integer subtraction") -#define OP_INT_MUL(x,y,r,err) r = (long)(x) * (long)(y); +#define OP_INT_MUL(x,y,r,err) r = (x) * (y); #ifndef HAVE_LONG_LONG @@ -65,7 +65,7 @@ #define OP_INT_MUL_OVF(x,y,r,err) \ { \ PY_LONG_LONG lr = (PY_LONG_LONG)(x) * (PY_LONG_LONG)(y); \ - r = (long)lr; \ + r = lr; \ if ((PY_LONG_LONG)r == lr); \ else FAIL_OVF(err, "integer multiplication") \ } @@ -74,30 +74,30 @@ /* shifting */ #define OP_INT_RSHIFT(x,y,r,err) \ - if ((long)(y) < LONG_BIT) \ - r = Py_ARITHMETIC_RIGHT_SHIFT(long, (long)(x), (long)(y)); \ - else r = (long)(x) < 0 ? -1 : 0; + if ((y) < LONG_BIT) \ + r = Py_ARITHMETIC_RIGHT_SHIFT(long, (x), (y)); \ + else r = (x) < 0 ? -1 : 0; #define OP_INT_RSHIFT_VAL(x,y,r,err) \ - if ((long)(y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ + if ((y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ else FAIL_VAL(err, "negative shift count") #define OP_INT_LSHIFT(x,y,r,err) \ - if ((long)(y) < LONG_BIT) \ - r = (long)(x) << (long)(y); \ + if ((y) < LONG_BIT) \ + r = (x) << (y); \ else r = 0; #define OP_INT_LSHIFT_VAL(x,y,r,err) \ - if ((long)(y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ + if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ else FAIL_VAL(err, "negative shift count") #define OP_INT_LSHIFT_OVF(x,y,r,err) \ OP_INT_LSHIFT(x,y,r,err) \ - if ((long)(x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (long)(y))) \ + if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ + if ((y) >= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ else FAIL_VAL(err, "negative shift count") @@ -106,16 +106,16 @@ #define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); #define OP_INT_FLOORDIV_OVF(x,y,r,err) \ - if ((long)(y) == -1 && (long)(x) < 0 && ((unsigned long)(x) << 1) == 0) \ + if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ FAIL_OVF(err, "integer division") \ OP_INT_FLOORDIV(x,y,r,err) #define OP_INT_FLOORDIV_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_FLOORDIV(x,y,r,err) } \ + if ((y)) { OP_INT_FLOORDIV(x,y,r,err) } \ else FAIL_ZER(err, "integer division") #define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ + if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer division") /* modulus */ @@ -123,23 +123,23 @@ #define OP_INT_MOD(x,y,r,err) op_divmod_adj(x, y, &r); #define OP_INT_MOD_OVF(x,y,r,err) \ - if ((long)(y) == -1 && (long)(x) < 0 && ((unsigned long)(x) << 1) == 0) \ + if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ FAIL_OVF(err, "integer modulo") \ OP_INT_MOD(x,y,r,err); #define OP_INT_MOD_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_MOD(x,y,r,err) } \ + if ((y)) { OP_INT_MOD(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") #define OP_INT_MOD_OVF_ZER(x,y,r,err) \ - if ((long)(y)) { OP_INT_MOD_OVF(x,y,r,err) } \ + if ((y)) { OP_INT_MOD_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") /* bit operations */ -#define OP_INT_AND(x,y,r,err) r = (long)(x) & (long)(y); -#define OP_INT_OR( x,y,r,err) r = (long)(x) | (long)(y); -#define OP_INT_XOR(x,y,r,err) r = (long)(x) ^ (long)(y); +#define OP_INT_AND(x,y,r,err) r = (x) & (y); +#define OP_INT_OR( x,y,r,err) r = (x) | (y); +#define OP_INT_XOR(x,y,r,err) r = (x) ^ (y); /*** conversions ***/ @@ -151,7 +151,7 @@ #define OP_CAST_INT_TO_CHAR(x,r,err) r = (char)(x); #define OP_CAST_PTR_TO_INT(x,r,err) r = (long)(x); /* XXX */ -#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (long)(x); +#define OP_CAST_UNICHAR_TO_INT(x,r,err) r = (x); #define OP_CAST_INT_TO_UNICHAR(x,r,err) r = (Py_UCS4)(x); /* bool operations */ From tismer at codespeak.net Sun Jun 26 16:53:05 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 16:53:05 +0200 (CEST) Subject: [pypy-svn] r13967 - pypy/dist/pypy/translator/c Message-ID: <20050626145305.D2F0727B57@code1.codespeak.net> Author: tismer Date: Sun Jun 26 16:53:04 2005 New Revision: 13967 Added: pypy/dist/pypy/translator/c/mkuint.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/int_include.h Log: implemented all uint operations by the little mkuint.py script. no testing provided at all. If there are operations which need to be implemented differently, please implement them directly after the int implementation and re-run the script. Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Sun Jun 26 16:53:04 2005 @@ -18,11 +18,13 @@ else FAIL_OVF(err, "integer negate") #define OP_INT_ABS(x,r,err) r = (x) >= 0 ? x : -(x); +#define OP_UINT_ABS(x,r,err) r = (x); #define OP_INT_ABS_OVF(x,r,err) \ OP_INT_ABS(x,r,err) \ if ((x) >= 0 || (x) != -(x)); \ else FAIL_OVF(err, "integer absolute") +#define OP_UINT_ABS_OVF(x,r,err) r = (x); /*** binary operations ***/ @@ -113,7 +115,7 @@ #define OP_INT_FLOORDIV_ZER(x,y,r,err) \ if ((y)) { OP_INT_FLOORDIV(x,y,r,err) } \ else FAIL_ZER(err, "integer division") - + #define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \ if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer division") @@ -130,7 +132,7 @@ #define OP_INT_MOD_ZER(x,y,r,err) \ if ((y)) { OP_INT_MOD(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") - + #define OP_INT_MOD_OVF_ZER(x,y,r,err) \ if ((y)) { OP_INT_MOD_OVF(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") @@ -216,3 +218,44 @@ *p_rem = xmody; return xdivy; } +/* no editing below this point */ +/* following lines are generated by mkuint.py */ + +#define OP_UINT_IS_TRUE OP_INT_IS_TRUE +#define OP_UINT_INVERT OP_INT_INVERT +#define OP_UINT_POS OP_INT_POS +#define OP_UINT_NEG OP_INT_NEG +#define OP_UINT_NEG_OVF OP_INT_NEG_OVF +/* skipping OP_UINT_ABS */ +/* skipping OP_UINT_ABS_OVF */ +#define OP_UINT_EQ OP_INT_EQ +#define OP_UINT_NE OP_INT_NE +#define OP_UINT_LE OP_INT_LE +#define OP_UINT_GT OP_INT_GT +#define OP_UINT_LT OP_INT_LT +#define OP_UINT_GE OP_INT_GE +#define OP_UINT_CMP OP_INT_CMP +#define OP_UINT_ADD OP_INT_ADD +#define OP_UINT_ADD_OVF OP_INT_ADD_OVF +#define OP_UINT_SUB OP_INT_SUB +#define OP_UINT_SUB_OVF OP_INT_SUB_OVF +#define OP_UINT_MUL OP_INT_MUL +#define OP_UINT_MUL_OVF OP_INT_MUL_OVF +#define OP_UINT_MUL_OVF OP_INT_MUL_OVF +#define OP_UINT_RSHIFT OP_INT_RSHIFT +#define OP_UINT_RSHIFT_VAL OP_INT_RSHIFT_VAL +#define OP_UINT_LSHIFT OP_INT_LSHIFT +#define OP_UINT_LSHIFT_VAL OP_INT_LSHIFT_VAL +#define OP_UINT_LSHIFT_OVF OP_INT_LSHIFT_OVF +#define OP_UINT_LSHIFT_OVF_VAL OP_INT_LSHIFT_OVF_VAL +#define OP_UINT_FLOORDIV OP_INT_FLOORDIV +#define OP_UINT_FLOORDIV_OVF OP_INT_FLOORDIV_OVF +#define OP_UINT_FLOORDIV_ZER OP_INT_FLOORDIV_ZER +#define OP_UINT_FLOORDIV_OVF_ZER OP_INT_FLOORDIV_OVF_ZER +#define OP_UINT_MOD OP_INT_MOD +#define OP_UINT_MOD_OVF OP_INT_MOD_OVF +#define OP_UINT_MOD_ZER OP_INT_MOD_ZER +#define OP_UINT_MOD_OVF_ZER OP_INT_MOD_OVF_ZER +#define OP_UINT_AND OP_INT_AND +#define OP_UINT_OR OP_INT_OR +#define OP_UINT_XOR OP_INT_XOR Added: pypy/dist/pypy/translator/c/mkuint.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/mkuint.py Sun Jun 26 16:53:04 2005 @@ -0,0 +1,36 @@ +# auto-generating the unsigned part of int_include.h + +""" +usage: +run this script in int_include.h's folder. + +Rule: +all #define OP_INT_ macros are repeated for uint, +except: +if an int macro is immediately followed by an uint +version, this takes precedence. +""" + +fname = 'int_include.h' + +srclines = [] +lines = [] + +stopline = '/* no editing below this point */' + +for srcline in file(fname): + srcline = srcline.rstrip() + line = srcline.lstrip() + if line.startswith('#define OP_INT_'): + macroname = line.split('(')[0].split()[1] + newname = 'OP_UINT_' + macroname[7:] + lines.append('#define %s %s' % (newname, macroname)) + elif line.startswith('#define OP_UINT_'): + # comment the last one out + lines.append('/* skipping %s */' % lines.pop().split()[1]) + elif line == stopline: + break + srclines.append(srcline) + +print >> file(fname, 'w'), '\n'.join(srclines + [stopline, + '/* following lines are generated by mkuint.py */', ''] + lines) From hpk at codespeak.net Sun Jun 26 16:54:06 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 16:54:06 +0200 (CEST) Subject: [pypy-svn] r13968 - pypy/extradoc/sprintinfo Message-ID: <20050626145406.3CDD127B56@code1.codespeak.net> Author: hpk Date: Sun Jun 26 16:54:05 2005 New Revision: 13968 Added: pypy/extradoc/sprintinfo/post-ep2005-planning.txt - copied, changed from r13962, pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: a rough time and topic plan for the Post-EP 2005 sprint Copied: pypy/extradoc/sprintinfo/post-ep2005-planning.txt (from r13962, pypy/extradoc/sprintinfo/pre-ep2005-planning.txt) ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Sun Jun 26 16:54:05 2005 @@ -1,8 +1,53 @@ -Open areas in translation -------------------------------------- +PyPy EuroPython 2005 sprint planning (1st-7th July) +------------------------------------------------------- -Still missing are: +overall time planning:: + + 1st-3rd July (both including) we sprint at Chalmers from 10am-open + + 4th first half is "break" time, afternoon 3pm is meeting time at + LAURA's house (not chalmers anymore) on G?tabergsgatan 22. + + 5th-7th sprint continues from 10am-open at laura's house + +1st July start at 10am:: + - holger starts the session + + - introduction to PyPy + high level architecture (Armin or Holger?) + - introduction to Annotation + RTyping? (Samuele or Armin) + working on examples + - introduction to LLVM2 + status + Carl, holger + - introduction to GenC + status + Armin + +other suggested events:: + 3rd July 5pm: Bert talks about Squeak's VM architecture + +we decide about pairing at the venue (after everybody tells +what he/she is interested in). These are the people expected currently:: + + Armin Rigo + Samuele Pedroni + Niklaus Haldimann + Carl Friedrich Bolz + Eric van Riet Paap + Holger Krekel + Richard Emslie + Bert Freudenberg + Adrien Di Mascio + Ludovic Aubry + Anders Chrigstroem + Christian Tismer + Jacob Hallen + Laura Creighton + Beatrice Duering + + +Translation tasks +------------------ * currently remaining rtyper topics: @@ -14,10 +59,6 @@ (strange)(delegating to backend?) sys.getrefcount (medium) applevel sys module should not refer to interplevel sys.getdefaultencoding - - implement in RPython (and change importing.py accordingly) - os.path.dirname/normpath/join (including the closure of what they use) - (generate c_api calls) os.path.exists (generate c_api calls) os.path.isdir @@ -26,33 +67,6 @@ rclass: (easy) issubtype - (arre, christian): - rdict: (DONE) (easy) method_get (?) - (DONE) (easy) method_copy - (DONE) (easy) method_update (?) - (DONE) (easy) method_keys (?) - (DONE) (easy) method_values (?) - (DONE) (easy) method_items (?) - (DONE) (easy) contains - (DONE) (easy) rstr: str.split(single_constant_character) - (DONE) method_replace with char/char - - - Binary operations - ----------------- - - (DONE) (easy) rstr: mul, inplace_mul (for CharRepr only!) - - (easy) 'contains' applied on: - * (DONE) dict of string keys - * (DONE) constant tuple of ints - * (DONE) constant tuple of strings - * constant tuple of unicode characters - -- needs constant dict of unichr keys - * (DONE) constant dict with int keys - * (DONE via string) constant string - * (DONE) string - Overridden functions in PyPy ---------------------------- @@ -63,29 +77,63 @@ override:fake_object override:cpy_compile -* (DONE) prebuilt immutable dictionaries with int keys - * (partially DONE) convert each file that does 'from ... import *' to use explicit imports (e.g. from pypy.rpython import lltype and then use lltype.*) -* DONE (holger, michael) translator/c/float_include.h should be complete. - * translator/c/int_include.h needs unsigned arithmetic operations. * progress on translation of example targets: - python demo/bpnn.py (holger, michael, samuele) python pypy/translator/goal/translate_pypy.py targetrichards.py +Move to Python 2.4.1 +----------------------- + +experiment in a branch with using Python 2.4 semantics +and the standard library + +* use lib-python/2.4.1 instead of 2.3.4, review all modified + tests and library modules + +* semantic differences: comparison of recursive data structures, + more? + +* new required C-level modules: 'sets', 'collections' + +* run tests (including compatibility lib-python tests) + +Misc +-------- + * (medium) write a tool that discovers which revision of the pypy tree broke the high level annotator (in that it produced SomeObjects). Consider distributing the actual annotation to multiple hosts. -* (medium) experiment in a branch with using Python 2.4 semantics - and the standard library (lib-python/2.4.1 ...) - * (medium) finish objspace/std/longobject.py. * (hard) find a way to generate c_api calls with automated conversions from ll-strings to c-like strings +* fix Windows-related issues, '%'-formatting rounding errors, + add missing docstrings on app-level built-in types and functions, + etc. + +* GC discussion in the middle of the sprint (kickoff Carl Friedrich) + +Rewriting important C functionality in Python +-------------------------------------------------- + +* integrate the parser module, trying to make it RPython + conformant; + +* re module reimplementation kickoff + +* rewrite in Python a C module you are familiar with + (partial list of missing/incomplete modules: os, math, array, + regular expressions, binascii...) + +* implement Python 2.3's import hook extensions (zip-imports etc.) + +* weakrefs (but this requires discussion and planning on pypy-dev + before the sprint! feel free to start such a discussion, though.) + From tismer at codespeak.net Sun Jun 26 16:57:39 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 16:57:39 +0200 (CEST) Subject: [pypy-svn] r13970 - pypy/extradoc/sprintinfo Message-ID: <20050626145739.45BAA27B4E@code1.codespeak.net> Author: tismer Date: Sun Jun 26 16:57:37 2005 New Revision: 13970 Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Log: implemented all uint operations by the little mkuint.py script. no testing provided at all. If there are operations which need to be implemented differently, please implement them directly after the int implementation and re-run the script. Modified: pypy/extradoc/sprintinfo/pre-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/pre-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/pre-ep2005-planning.txt Sun Jun 26 16:57:37 2005 @@ -71,7 +71,7 @@ * DONE (holger, michael) translator/c/float_include.h should be complete. -* translator/c/int_include.h needs unsigned arithmetic operations. +DONE * translator/c/int_include.h needs unsigned arithmetic operations. * progress on translation of example targets: python demo/bpnn.py (holger, michael, samuele) From tismer at codespeak.net Sun Jun 26 17:05:10 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 17:05:10 +0200 (CEST) Subject: [pypy-svn] r13971 - pypy/extradoc/sprintinfo Message-ID: <20050626150510.EB81027B55@code1.codespeak.net> Author: tismer Date: Sun Jun 26 17:05:10 2005 New Revision: 13971 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: uint is done Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Sun Jun 26 17:05:10 2005 @@ -1,4 +1,4 @@ - +? PyPy EuroPython 2005 sprint planning (1st-7th July) ------------------------------------------------------- @@ -81,8 +81,6 @@ 'from ... import *' to use explicit imports (e.g. from pypy.rpython import lltype and then use lltype.*) -* translator/c/int_include.h needs unsigned arithmetic operations. - * progress on translation of example targets: python pypy/translator/goal/translate_pypy.py targetrichards.py From mwh at codespeak.net Sun Jun 26 17:15:02 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sun, 26 Jun 2005 17:15:02 +0200 (CEST) Subject: [pypy-svn] r13973 - pypy/extradoc/sprintinfo Message-ID: <20050626151502.7D2AF27B55@code1.codespeak.net> Author: mwh Date: Sun Jun 26 17:15:02 2005 New Revision: 13973 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: remove presumably accidental junk characters. Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Sun Jun 26 17:15:02 2005 @@ -1,4 +1,4 @@ -? + PyPy EuroPython 2005 sprint planning (1st-7th July) ------------------------------------------------------- From arigo at codespeak.net Sun Jun 26 17:54:25 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 17:54:25 +0200 (CEST) Subject: [pypy-svn] r13977 - pypy/dist/pypy/annotation Message-ID: <20050626155425.704D727B4D@code1.codespeak.net> Author: arigo Date: Sun Jun 26 17:54:22 2005 New Revision: 13977 Modified: pypy/dist/pypy/annotation/builtin.py Log: It seems that we can handle posixpath.normpath() and ntpath.normpath() in the annotator/rtyper in the normal way. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sun Jun 26 17:54:22 2005 @@ -273,7 +273,7 @@ # os.path stuff #BUILTIN_ANALYZERS[os.path.dirname] = pathpart -BUILTIN_ANALYZERS[os.path.normpath] = pathpart +#BUILTIN_ANALYZERS[os.path.normpath] = pathpart #BUILTIN_ANALYZERS[os.path.join] = pathpart BUILTIN_ANALYZERS[os.path.exists] = test BUILTIN_ANALYZERS[os.path.isdir] = test From tismer at codespeak.net Sun Jun 26 18:30:16 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 18:30:16 +0200 (CEST) Subject: [pypy-svn] r13979 - pypy/dist/pypy/annotation Message-ID: <20050626163016.71F4927B4D@code1.codespeak.net> Author: tismer Date: Sun Jun 26 18:30:15 2005 New Revision: 13979 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: small typo in bookkeeper Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Sun Jun 26 18:30:15 2005 @@ -143,9 +143,9 @@ else: s = "?!!!!!!" if isinstance(args, SomeTuple): - return (str.const, tuple([self.typerepr(x) for x in args.items])) + return (s, tuple([self.typerepr(x) for x in args.items])) else: - return (str.const, self.typerepr(args)) + return (s, self.typerepr(args)) def consider_dict_getitem(self, dic): return dic From tismer at codespeak.net Sun Jun 26 18:30:36 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 18:30:36 +0200 (CEST) Subject: [pypy-svn] r13980 - in pypy/dist/pypy/translator: goal pickle Message-ID: <20050626163036.6BA2327B56@code1.codespeak.net> Author: tismer Date: Sun Jun 26 18:30:34 2005 New Revision: 13980 Modified: pypy/dist/pypy/translator/goal/translate_pypy.py pypy/dist/pypy/translator/pickle/genpickle.py Log: added support for -inf Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Sun Jun 26 18:30:34 2005 @@ -242,7 +242,7 @@ targetspec = 'targetpypymain' huge = 100 load_file = None - save_file =None + save_file = None options = {'-text': False, '-no-c': False, Modified: pypy/dist/pypy/translator/pickle/genpickle.py ============================================================================== --- pypy/dist/pypy/translator/pickle/genpickle.py (original) +++ pypy/dist/pypy/translator/pickle/genpickle.py Sun Jun 26 18:30:34 2005 @@ -40,6 +40,8 @@ #XXX Hack: This float is supposed to overflow to inf OVERFLOWED_FLOAT = float("1e10000000000000000000000000000000") +#XXX Hack: and this one to underflow to -inf +OVERFLOWED_FLOATM = float("-1e10000000000000000000000000000000") class GenPickle: @@ -108,6 +110,8 @@ def save_float(self, fl): if fl == OVERFLOWED_FLOAT: return 'float("1e10000000000000000000000000000000")' + elif fl == OVERFLOWED_FLOATM: + return 'float("-1e10000000000000000000000000000000")' return repr(fl) def pickle(self, *args, **kwds): From hpk at codespeak.net Sun Jun 26 18:55:42 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 18:55:42 +0200 (CEST) Subject: [pypy-svn] r13982 - pypy/extradoc/talk Message-ID: <20050626165542.9700D27B4A@code1.codespeak.net> Author: hpk Date: Sun Jun 26 18:55:42 2005 New Revision: 13982 Added: pypy/extradoc/talk/pypy-ep2005-talk-prep.txt Log: draft EP 2005 talk preparation Added: pypy/extradoc/talk/pypy-ep2005-talk-prep.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/pypy-ep2005-talk-prep.txt Sun Jun 26 18:55:42 2005 @@ -0,0 +1,109 @@ + +http://www.python-in-business.org/ep2005/talk.chtml?talk=2238&track=687 +http://codespeak.net/~cfbolz/translation.pdf + + +PyPy as a Compiler +Carl Friedrich Bolz, Holger Krekel, Christian Tismer, Armin Rigo 60 minutes +A status report on PyPy, the Python interpreter implemented in Python. + +1) introduction to the PyPy release + Holger (10 minutes including thunk space example) + python implementation + +2) type inference and specialization + - flowgraph \ + - Annotation | + - RTyper | + 15 minutes | arigo + | +3) backends | + - genc 5 min / + - llvm 5 min \ + | cfbolz +4) show demo/bpnn.py example | + 5 minutes / + +5) Conclusions & roadmap 2005/2006 + 5 minutes + + the previous technqiues will be used internally to translate PyPy + to low level languages. In particular we aim for: + (the primary point is NOT to systematically translate your own programs!) + + - self-contained PyPy version before end 2005 + + - stackless and psyco/JIT-compilation in 2006! + + - tool for building custom PyPy versions by end 2006 + + + +The main part of the talk will be the second one, as it is where we are +putting the most efforts at the moment: "how to turn an interpreter into +a compiler". +We will dig into: + +- what kind of programs we can statically compile; +- the frontend infrastructure (control flow graph production, type + inference); +- the C back-end, and the role of the "typer" component bridging the gap +between high-level type annotations and the C data model; +- the LLVM back-end (targetting a virtual machine with a different model +and different trade-offs than plain C); +- how this relates to our rather different long-term goal of making a + really +fast PyPy interpreter. + + +The PyPy project (http://codespeak.net/pypy) aims at producing a simple +runtime system for the Python language, expressing the basic abstractions +within the Python language itself. Simplicity and Flexibilty are the foremost +goals. + +To reach our goal, we are currently working on a Python source analysis +and compilation toolchain -- based on PyPy as well -- and a minimal low-level +core that doesn't need CPython any more. The presentation will focus on +these tools, which are able to perform automatic static type inference +of "static enough" Python programs and then compile them to various lower-level +languages (currently, we have experimental back-ends for C, LLVM, Python, +Lisp, Pyrex and Java). This analysis works on fully standard Python sources +(bytecodes, actually), and the distinguishing feature of the techniques +we use -- "abstract interpretation" -- is to allow type inference to be +performed for any language for which we have an interpreter. Moreover, +it doesn't require explicit type annotations added by the user. + +To some extent, and although it is not our primary long-term goal, the +tools we have developped could be used generally to check or improve the +performance of any program. We will see in particular which "staticness" +restrictions must be met for these tools to work, and look under the hood: + + +* how we build control flow graphs; + +* how we perform type inference, and what "type inference" precisely +* means +in this context; + +* type inference is not the end of the story: good code must be +* generated +from the source and the inferred types. + +The presentation will focus on the latter point, explaining the two major +code generators we have at the moment: the C and LLVM back-ends. + +The techniques relate to Psyco's, the just-in-time specializer for CPython. +We will compare them, and also contrast the "internal" notion of type +used as an implementation detail (as in PyPy and Psyco) with the other +typical approach of explicit user-specified types. This point of view +puts our current efforts in the more general context of our long-term goals, +which are about dynamic optimizations rather than static compilation. + +Our approach is motivated by the desire of flexibility: it allows issues +that normally require early design decisions to be postponed, and addressed +later in possibly more than one way, without rewriting everything. Typical +example: adding Stackless-style continuations in CPython required a whole-scale +rewrite, but has only a "local" impact on PyPy. We will plead for a framework +based on interpreters as a way to gain the most flexibility from programming +languages -- and the best performances too, for very-high-level languages! + From arigo at codespeak.net Sun Jun 26 18:59:09 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 18:59:09 +0200 (CEST) Subject: [pypy-svn] r13983 - pypy/branch/pypy-translation-snapshot/interpreter Message-ID: <20050626165909.DD4FA27B4D@code1.codespeak.net> Author: arigo Date: Sun Jun 26 18:59:09 2005 New Revision: 13983 Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Log: Merge revision 13842 from the trunk. Modified: pypy/branch/pypy-translation-snapshot/interpreter/typedef.py ============================================================================== --- pypy/branch/pypy-translation-snapshot/interpreter/typedef.py (original) +++ pypy/branch/pypy-translation-snapshot/interpreter/typedef.py Sun Jun 26 18:59:09 2005 @@ -24,16 +24,38 @@ # hint for the annotator: track individual constant instances of TypeDef return True -subclass_cache = {} -def get_unique_interplevel_subclass(cls, hasdict, wants_slots): - key = (cls, hasdict, wants_slots) - try: - return subclass_cache[key] - except KeyError: - subcls = _buildusercls(cls, hasdict, wants_slots) - subclass_cache[key] = subcls - return subcls -get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" + +# we cannot specialize:memo by more than one PBC key +# so we need to work a bit to allow that + +def get_unique_interplevel_subclass(cls, hasdict, wants_slots): + if hasdict: + if wants_slots: + return get_unique_interplevel_WithDictWithSlots(cls) + else: + return get_unique_interplevel_WithDictNoSlots(cls) + else: + if wants_slots: + return get_unique_interplevel_NoDictWithSlots(cls) + else: + return get_unique_interplevel_NoDictNoSlots(cls) + +for hasdict in False, True: + for wants_slots in False, True: + name = hasdict and "WithDict" or "NoDict" + name += wants_slots and "WithSlots" or "NoSlots" + funcname = "get_unique_interplevel_%s" % (name,) + exec compile2(""" + subclass_cache_%(name)s = {} + def %(funcname)s(cls): + try: + return subclass_cache_%(name)s[cls] + except KeyError: + subcls = _buildusercls(cls, %(hasdict)r, %(wants_slots)r) + subclass_cache_%(name)s[cls] = subcls + return subcls + %(funcname)s._annspecialcase_ = "specialize:memo" + """ % locals()) def _buildusercls(cls, hasdict, wants_slots): "NOT_RPYTHON: initialization-time only" From tismer at codespeak.net Sun Jun 26 19:54:19 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sun, 26 Jun 2005 19:54:19 +0200 (CEST) Subject: [pypy-svn] r13987 - pypy/dist/pypy/translator/goal Message-ID: <20050626175419.39ECB27B49@code1.codespeak.net> Author: tismer Date: Sun Jun 26 19:54:18 2005 New Revision: 13987 Removed: pypy/dist/pypy/translator/goal/targetpypy1.py Log: dropped targetpypy1 Deleted: /pypy/dist/pypy/translator/goal/targetpypy1.py ============================================================================== --- /pypy/dist/pypy/translator/goal/targetpypy1.py Sun Jun 26 19:54:18 2005 +++ (empty file) @@ -1,75 +0,0 @@ -from pypy.objspace.std.objspace import StdObjSpace, W_Object -from pypy.objspace.std.intobject import W_IntObject -from pypy.objspace.std import stdtypedef - -# __________ Entry point __________ - -operations = "mul add sub div mod lshift rshift floordiv truediv ".split() - -def entry_point(): - w_a = W_IntObject(space, -7) - w_b = W_IntObject(space, 6) - results_w = [mmentrypoints[op](space, w_a, w_b) for op in operations] - return [space.unwrap(each) for each in resuls_w] - -# flatten the above code, to get a nicer look -def make_flat_code(): - g = globals() - # make globals constants from the operations - code = """def entry_point(): - import sys - w_a = W_IntObject(space, -7) - # -sys.maxint-1 crashes: genc problem with OP_SUB and int constant - # when implementing lshift_Long_Long and rshift__Long_Long - w_b = W_IntObject(space, 6) - results_w = [] - append = results_w.append -""" - for op in operations: - g["op_%s" % op] = mmentrypoints[op] - line = " append(op_%s(space, w_a, w_b))" % op - code += line + '\n' - code += " return [space.unwrap(each) for each in results_w]\n" - print code - exec code in g - -# _____ Define and setup target _____ -def target(): - global space, mmentrypoints - # disable translation of the whole of classobjinterp.py - StdObjSpace.setup_old_style_classes = lambda self: None - space = StdObjSpace() - # call cache filling code *not* needed here - - # ------------------------------------------------------------ - mmentrypoints = {} - for name in operations: - mm = getattr(space.MM, name) - exprargs, expr, miniglobals, fallback = ( - mm.install_not_sliced(space.model.typeorder, baked_perform_call=False)) - func = stdtypedef.make_perform_trampoline('__mm_'+name, - exprargs, expr, miniglobals, - mm) - mmentrypoints[name] = func - # ------------------------------------------------------------ - - # further call the entry_point once to trigger building remaining - # caches (as far as analyzing the entry_point is concerned) - make_flat_code() - entry_point() - - return entry_point, [] - -# _____ Run translated _____ - -def run(c_entry_point): - res = c_entry_point() - print res - import operator - assert res == [getattr(operator, name)(-7, 6) for name in operations] - -if __name__ == "__main__": - # just run it without translation - target() - run(entry_point) - \ No newline at end of file From hpk at codespeak.net Sun Jun 26 19:56:00 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 19:56:00 +0200 (CEST) Subject: [pypy-svn] r13988 - pypy/extradoc/talk Message-ID: <20050626175600.E8BD327B4A@code1.codespeak.net> Author: hpk Date: Sun Jun 26 19:56:00 2005 New Revision: 13988 Modified: pypy/extradoc/talk/pypy-ep2005-talk-prep.txt Log: format ReST correctly, delete some cruft Modified: pypy/extradoc/talk/pypy-ep2005-talk-prep.txt ============================================================================== --- pypy/extradoc/talk/pypy-ep2005-talk-prep.txt (original) +++ pypy/extradoc/talk/pypy-ep2005-talk-prep.txt Sun Jun 26 19:56:00 2005 @@ -9,9 +9,9 @@ 1) introduction to the PyPy release Holger (10 minutes including thunk space example) - python implementation + (python interpreter/objectspace/compliancy) -2) type inference and specialization +2) type inference and specialization:: - flowgraph \ - Annotation | - RTyper | @@ -38,72 +38,3 @@ - tool for building custom PyPy versions by end 2006 - -The main part of the talk will be the second one, as it is where we are -putting the most efforts at the moment: "how to turn an interpreter into -a compiler". -We will dig into: - -- what kind of programs we can statically compile; -- the frontend infrastructure (control flow graph production, type - inference); -- the C back-end, and the role of the "typer" component bridging the gap -between high-level type annotations and the C data model; -- the LLVM back-end (targetting a virtual machine with a different model -and different trade-offs than plain C); -- how this relates to our rather different long-term goal of making a - really -fast PyPy interpreter. - - -The PyPy project (http://codespeak.net/pypy) aims at producing a simple -runtime system for the Python language, expressing the basic abstractions -within the Python language itself. Simplicity and Flexibilty are the foremost -goals. - -To reach our goal, we are currently working on a Python source analysis -and compilation toolchain -- based on PyPy as well -- and a minimal low-level -core that doesn't need CPython any more. The presentation will focus on -these tools, which are able to perform automatic static type inference -of "static enough" Python programs and then compile them to various lower-level -languages (currently, we have experimental back-ends for C, LLVM, Python, -Lisp, Pyrex and Java). This analysis works on fully standard Python sources -(bytecodes, actually), and the distinguishing feature of the techniques -we use -- "abstract interpretation" -- is to allow type inference to be -performed for any language for which we have an interpreter. Moreover, -it doesn't require explicit type annotations added by the user. - -To some extent, and although it is not our primary long-term goal, the -tools we have developped could be used generally to check or improve the -performance of any program. We will see in particular which "staticness" -restrictions must be met for these tools to work, and look under the hood: - - -* how we build control flow graphs; - -* how we perform type inference, and what "type inference" precisely -* means -in this context; - -* type inference is not the end of the story: good code must be -* generated -from the source and the inferred types. - -The presentation will focus on the latter point, explaining the two major -code generators we have at the moment: the C and LLVM back-ends. - -The techniques relate to Psyco's, the just-in-time specializer for CPython. -We will compare them, and also contrast the "internal" notion of type -used as an implementation detail (as in PyPy and Psyco) with the other -typical approach of explicit user-specified types. This point of view -puts our current efforts in the more general context of our long-term goals, -which are about dynamic optimizations rather than static compilation. - -Our approach is motivated by the desire of flexibility: it allows issues -that normally require early design decisions to be postponed, and addressed -later in possibly more than one way, without rewriting everything. Typical -example: adding Stackless-style continuations in CPython required a whole-scale -rewrite, but has only a "local" impact on PyPy. We will plead for a framework -based on interpreters as a way to gain the most flexibility from programming -languages -- and the best performances too, for very-high-level languages! - From hpk at codespeak.net Sun Jun 26 19:57:57 2005 From: hpk at codespeak.net (hpk at codespeak.net) Date: Sun, 26 Jun 2005 19:57:57 +0200 (CEST) Subject: [pypy-svn] r13989 - pypy/extradoc/talk Message-ID: <20050626175757.CBB0B27B4A@code1.codespeak.net> Author: hpk Date: Sun Jun 26 19:57:57 2005 New Revision: 13989 Modified: pypy/extradoc/talk/pypy-ep2005-talk-prep.txt Log: assigned armin some more Modified: pypy/extradoc/talk/pypy-ep2005-talk-prep.txt ============================================================================== --- pypy/extradoc/talk/pypy-ep2005-talk-prep.txt (original) +++ pypy/extradoc/talk/pypy-ep2005-talk-prep.txt Sun Jun 26 19:57:57 2005 @@ -25,7 +25,7 @@ 5 minutes / 5) Conclusions & roadmap 2005/2006 - 5 minutes + 5 minutes (Armin) the previous technqiues will be used internally to translate PyPy to low level languages. In particular we aim for: @@ -37,4 +37,6 @@ - tool for building custom PyPy versions by end 2006 +6) questions and answers + (armin) From arigo at codespeak.net Sun Jun 26 20:52:57 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 26 Jun 2005 20:52:57 +0200 (CEST) Subject: [pypy-svn] r13990 - in pypy/dist/pypy/rpython: . test Message-ID: <20050626185257.2CDB927B4A@code1.codespeak.net> Author: arigo Date: Sun Jun 26 20:52:54 2005 New Revision: 13990 Modified: pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: is_true for SomePBCs that can contain None in their set. Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Sun Jun 26 20:52:54 2005 @@ -60,10 +60,7 @@ lst = self.prebuiltinstances.items() lst.sort() return tuple(lst) - - def rtype_is_true(self, hop): - return Constant(True, Bool) - + # ____________________________________________________________ @@ -184,6 +181,15 @@ setattr(result, mangled_name, llvalue) return result + def rtype_is_true(self, hop): + if hop.s_result.is_constant(): + assert hop.s_result.const is True # custom __nonzero__ on PBCs? + return hop.inputconst(Bool, hop.s_result.const) + else: + # None is a nullptr, which is false; everything else is true. + vlist = hop.inputargs(self) + return hop.genop('ptr_nonzero', vlist, resulttype=Bool) + def rtype_getattr(self, hop): attr = hop.args_s[1].const vpbc, vattr = hop.inputargs(self, Void) Modified: pypy/dist/pypy/rpython/test/test_rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rpbc.py (original) +++ pypy/dist/pypy/rpython/test/test_rpbc.py Sun Jun 26 20:52:54 2005 @@ -232,3 +232,24 @@ return r.meth() res = interpret(fn, []) assert res == 0 + +def test_None_is_false(): + def fn(i): + return bool([None, fn][i]) + res = interpret(fn, [1]) + assert res is True + res = interpret(fn, [0]) + assert res is False + +def INPROGRESS_test_classpbc_getattr(): + class A: + myvalue = 123 + class B(A): + myvalue = 456 + def f(i): + B() # force B and A to have a ClassDef + return [A,B][i].myvalue + res = interpret(f, [0], view=True) + assert res == 123 + res = interpret(f, [1]) + assert res == 456 From cfbolz at codespeak.net Tue Jun 28 13:36:00 2005 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 28 Jun 2005 13:36:00 +0200 (CEST) Subject: [pypy-svn] r13995 - in pypy/dist/pypy/translator/llvm2: . test Message-ID: <20050628113600.10EBA27B46@code1.codespeak.net> Author: cfbolz Date: Tue Jun 28 13:35:59 2005 New Revision: 13995 Modified: pypy/dist/pypy/translator/llvm2/database.py pypy/dist/pypy/translator/llvm2/funcnode.py pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Log: added mod Modified: pypy/dist/pypy/translator/llvm2/database.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/database.py (original) +++ pypy/dist/pypy/translator/llvm2/database.py Tue Jun 28 13:35:59 2005 @@ -92,3 +92,4 @@ self._tmpcount += 1 return "%tmp." + str(count) + \ No newline at end of file Modified: pypy/dist/pypy/translator/llvm2/funcnode.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/funcnode.py (original) +++ pypy/dist/pypy/translator/llvm2/funcnode.py Tue Jun 28 13:35:59 2005 @@ -140,6 +140,9 @@ def int_sub(self, op): self.binaryop('sub', op) + def int_mod(self, op): + self.binaryop('rem', op) + def int_eq(self, op): self.binaryop('seteq', op) @@ -165,7 +168,9 @@ fromvar = self.db.repr_arg(op.args[0]) fromtype = self.db.repr_arg_type(op.args[0]) self.codewriter.cast(targetvar, fromtype, fromvar, targettype) - + + int_is_true = cast_bool_to_int + def direct_call(self, op): assert len(op.args) >= 1 targetvar = self.db.repr_arg(op.result) Modified: pypy/dist/pypy/translator/llvm2/test/test_genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm2/test/test_genllvm.py (original) +++ pypy/dist/pypy/translator/llvm2/test/test_genllvm.py Tue Jun 28 13:35:59 2005 @@ -51,6 +51,7 @@ x += i != i x += i >= i x += i > i + x += x % i #x += i is not None #x += i is None return i + 1 * i // i - 1 From ericvrp at codespeak.net Wed Jun 29 13:09:46 2005 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 29 Jun 2005 13:09:46 +0200 (CEST) Subject: [pypy-svn] r14008 - pypy/extradoc/sprintinfo Message-ID: <20050629110946.9A23327B58@code1.codespeak.net> Author: ericvrp Date: Wed Jun 29 13:09:46 2005 New Revision: 14008 Modified: pypy/extradoc/sprintinfo/EP2005-people.txt Log: updating eric and Niklaus' schedules Modified: pypy/extradoc/sprintinfo/EP2005-people.txt ============================================================================== --- pypy/extradoc/sprintinfo/EP2005-people.txt (original) +++ pypy/extradoc/sprintinfo/EP2005-people.txt Wed Jun 29 13:09:46 2005 @@ -28,7 +28,8 @@ Armin Rigo 1st-7th July private Samuele Pedroni 1st-7th July private Carl Friedrich Bolz 1st-6th July private -Eric van Riet Paap 1st-7th July SGS +Niklaus Haldimann 1st-5th July SGS +Eric van Riet Paap 1st-8th July SGS Holger Krekel 1st-7th July private Richard Emslie 1st-7th July private Bert Freudenberg 1st-7th July ? From arigo at codespeak.net Wed Jun 29 19:52:02 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Jun 2005 19:52:02 +0200 (CEST) Subject: [pypy-svn] r14012 - pypy/dist/pypy/annotation Message-ID: <20050629175202.A598927B55@code1.codespeak.net> Author: arigo Date: Wed Jun 29 19:52:02 2005 New Revision: 14012 Modified: pypy/dist/pypy/annotation/builtin.py Log: Shouldn't see any ovfcheck() left in the code. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Wed Jun 29 19:52:02 2005 @@ -220,15 +220,15 @@ def rarith_intmask(s_obj): return SomeInteger() -def rarith_ovfcheck(s_obj): - if isinstance(s_obj, SomeInteger) and s_obj.unsigned: - getbookkeeper().warning("ovfcheck on unsigned") - return s_obj - -def rarith_ovfcheck_lshift(s_obj1, s_obj2): - if isinstance(s_obj1, SomeInteger) and s_obj1.unsigned: - getbookkeeper().warning("ovfcheck_lshift with unsigned") - return SomeInteger() +##def rarith_ovfcheck(s_obj): +## if isinstance(s_obj, SomeInteger) and s_obj.unsigned: +## getbookkeeper().warning("ovfcheck on unsigned") +## return s_obj + +##def rarith_ovfcheck_lshift(s_obj1, s_obj2): +## if isinstance(s_obj1, SomeInteger) and s_obj1.unsigned: +## getbookkeeper().warning("ovfcheck_lshift with unsigned") +## return SomeInteger() def unicodedata_decimal(s_uchr): raise TypeError, "unicodedate.decimal() calls should not happen at interp-level" @@ -254,8 +254,8 @@ BUILTIN_ANALYZERS[original] = value BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_uint] = restricted_uint -BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck -BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift +##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck] = rarith_ovfcheck +##BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.ovfcheck_lshift] = rarith_ovfcheck_lshift BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.intmask] = rarith_intmask BUILTIN_ANALYZERS[Exception.__init__.im_func] = exception_init From arigo at codespeak.net Wed Jun 29 20:35:16 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Jun 2005 20:35:16 +0200 (CEST) Subject: [pypy-svn] r14013 - in pypy/dist/pypy/translator/tool: . pygame Message-ID: <20050629183516.1387B27B54@code1.codespeak.net> Author: arigo Date: Wed Jun 29 20:35:14 2005 New Revision: 14013 Modified: pypy/dist/pypy/translator/tool/graphpage.py pypy/dist/pypy/translator/tool/pygame/drawgraph.py pypy/dist/pypy/translator/tool/pygame/graphclient.py Log: - Some crash-proofing of the pygame viewer. - Simplified a bit the displayed text for variables after typing (removed the annotation, showing only the low-level type). Modified: pypy/dist/pypy/translator/tool/graphpage.py ============================================================================== --- pypy/dist/pypy/translator/tool/graphpage.py (original) +++ pypy/dist/pypy/translator/tool/graphpage.py Wed Jun 29 20:35:14 2005 @@ -133,8 +133,9 @@ return for var in vars: if hasattr(var, 'concretetype'): - info = self.links.get(var.name, var.name) - info = '(%s) %s' % (var.concretetype, info) + #info = self.links.get(var.name, var.name) + #info = '(%s) %s' % (var.concretetype, info) + info = str(var.concretetype) self.links[var.name] = info for graph in graphs: traverse(visit, graph) Modified: pypy/dist/pypy/translator/tool/pygame/drawgraph.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/drawgraph.py (original) +++ pypy/dist/pypy/translator/tool/pygame/drawgraph.py Wed Jun 29 20:35:14 2005 @@ -230,7 +230,7 @@ def getfont(self, size): if size in self.FONTCACHE: return self.FONTCACHE[size] - elif size < 4: + elif size < 5: self.FONTCACHE[size] = None return None else: Modified: pypy/dist/pypy/translator/tool/pygame/graphclient.py ============================================================================== --- pypy/dist/pypy/translator/tool/pygame/graphclient.py (original) +++ pypy/dist/pypy/translator/tool/pygame/graphclient.py Wed Jun 29 20:35:14 2005 @@ -35,11 +35,17 @@ import urllib content = py.path.local(dotfile).read() request = urllib.urlencode({'dot': content}) - urllib.urlretrieve('http://codespeak.net/pypy/convertdot.cgi', - str(plainfile), - data=request) - plainfile = py.path.local(plainfile) - if not plainfile.check(file=1) or not plainfile.read().startswith('graph '): + try: + urllib.urlretrieve('http://codespeak.net/pypy/convertdot.cgi', + str(plainfile), + data=request) + except IOError: + success = False + else: + plainfile = py.path.local(plainfile) + success = (plainfile.check(file=1) and + plainfile.read().startswith('graph ')) + if not success: print "NOTE: failed to use codespeak's convertdot.cgi, trying local 'dot'" cmdexec('dot -Tplain %s>%s' % (dotfile, plainfile)) From arigo at codespeak.net Wed Jun 29 20:39:33 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Jun 2005 20:39:33 +0200 (CEST) Subject: [pypy-svn] r14014 - in pypy/dist/pypy: annotation rpython rpython/test translator/test Message-ID: <20050629183933.8C77A27B54@code1.codespeak.net> Author: arigo Date: Wed Jun 29 20:39:30 2005 New Revision: 14014 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py pypy/dist/pypy/translator/test/test_annrpython.py Log: - the annotator assigns a slightly more precise 'classdef' in SomePBCs representing methods: if the method comes from a parent class but is read through a getattr() from an instance of a subclass, the 'classdef' is the subclass now. This seems to be necessary for the rtyper. The PBC union of twice the same methods with different 'classdefs' just makes a PBC of the same method with the common 'classdef', without trying to be clever about moving the 'classdef' futher up to a class where the method is really defined. - annotator test for the above. - rtyper fix to handle this case (just removed a check). - rtyper test for the above. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Wed Jun 29 20:39:30 2005 @@ -507,11 +507,7 @@ classdef2 = classdef if classdef != d[x]: classdef = classdef.commonbase(d[x]) - for cand in classdef.getmro(): - if x in cand.cls.__dict__.values(): - classdef = cand - break - else: + if classdef is None: raise UnionError( "confused pbc union trying unwarranted" "moving up of method %s from pair %s %s" % Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Wed Jun 29 20:39:30 2005 @@ -336,7 +336,11 @@ continue # not matching d[func] = value if uplookup is not None: - d[upfunc] = uplookup + # when the method is found in a parent class, it get bound to the + # 'self' subclass. This allows the 'func: classdef' entry of the + # PBC dictionary to track more precisely with which 'self' the + # method is called. + d[upfunc] = self elif meth: self.check_missing_attribute_update(name) if d: Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 29 20:39:30 2005 @@ -160,10 +160,10 @@ count = 0 for x, classdef in s_value.prebuiltinstances.items(): if isclassdef(classdef): - if classdef.commonbase(self.classdef) != self.classdef: - raise TyperError("methods from PBC set %r don't belong " - "in %r" % (s_value.prebuiltinstances, - self.classdef.cls)) + #if classdef.commonbase(self.classdef) != self.classdef: + # raise TyperError("methods from PBC set %r don't belong " + # "in %r" % (s_value.prebuiltinstances, + # self.classdef.cls)) count += 1 classdef = True debound[x] = classdef Modified: pypy/dist/pypy/rpython/test/test_rclass.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_rclass.py (original) +++ pypy/dist/pypy/rpython/test/test_rclass.py Wed Jun 29 20:39:30 2005 @@ -109,3 +109,28 @@ res = interpret(c, []) assert res is False + +def test_method_used_in_subclasses_only(): + class A: + def meth(self): + return 123 + class B(A): + pass + def f(): + x = B() + return x.meth() + res = interpret(f, []) + assert res == 123 + +def test_method_both_A_and_B(): + class A: + def meth(self): + return 123 + class B(A): + pass + def f(): + a = A() + b = B() + return a.meth() + b.meth() + res = interpret(f, []) + assert res == 246 Modified: pypy/dist/pypy/translator/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/translator/test/test_annrpython.py (original) +++ pypy/dist/pypy/translator/test/test_annrpython.py Wed Jun 29 20:39:30 2005 @@ -1361,6 +1361,25 @@ assert isinstance(s2.dictdef.dictkey. s_value, annmodel.SomeInteger) assert isinstance(s2.dictdef.dictvalue.s_value, annmodel.SomeInteger) + def test_pbc_union(self): + class A: + def meth(self): + return 12 + class B(A): + pass + class C(B): + pass + def f(i): + if i: + f(0) + x = B() + else: + x = C() + return x.meth() + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s == a.bookkeeper.immutablevalue(12) + def g(n): return [0,1,2,n] From arigo at codespeak.net Wed Jun 29 21:09:58 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Jun 2005 21:09:58 +0200 (CEST) Subject: [pypy-svn] r14015 - pypy/dist/pypy/rpython Message-ID: <20050629190958.762E727B55@code1.codespeak.net> Author: arigo Date: Wed Jun 29 21:09:56 2005 New Revision: 14015 Modified: pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/rtyper.py Log: - Fix for already-checked-in failing test (oups) test_method_both_A_and_B. - Nicer error messages from low-level type mismatches in the rtyper. Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Wed Jun 29 21:09:56 2005 @@ -484,7 +484,8 @@ elif attr in self.rclass.allmethods: # special case for methods: represented as their 'self' only # (see MethodsPBCRepr) - return vinst + return hop.r_result.get_method_from_instance(self, vinst, + hop.llops) else: vcls = self.getfield(vinst, '__class__', hop.llops) return self.rclass.getclsfield(vcls, attr, hop.llops) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Wed Jun 29 21:09:56 2005 @@ -390,6 +390,11 @@ raise TyperError("not a bound method: %r" % method) return self.r_im_self.convert_const(method.im_self) + def get_method_from_instance(self, r_inst, v_inst, llops): + # The 'self' might have to be cast to a parent class + # (as shown for example in test_rclass/test_method_both_A_and_B) + return llops.convertvar(v_inst, r_inst, self.r_im_self) + def rtype_simple_call(self, hop): r_class = self.r_im_self.rclass mangled_name, r_func = r_class.clsfields[self.methodname] Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Wed Jun 29 21:09:56 2005 @@ -273,11 +273,11 @@ op.result.concretetype = hop.r_result.lowleveltype if op.result.concretetype != resulttype: raise TyperError("inconsistent type for the result of '%s':\n" - "annotator says %s,\n" - "whose lltype is %r\n" - "but rtype* says %r" % ( + "annotator says %s,\n" + "whose repr is %r\n" + "but rtype_%s returned %r" % ( op.opname, hop.s_result, - op.result.concretetype, resulttype)) + hop.r_result, op.opname, resulttype)) # figure out if the resultvar is a completely fresh Variable or not if (isinstance(resultvar, Variable) and resultvar not in self.annotator.bindings and @@ -473,7 +473,7 @@ self.rtyper = rtyper def convertvar(self, v, r_from, r_to): - assert isinstance(v, Variable) + assert isinstance(v, (Variable, Constant)) if r_from != r_to: v = pair(r_from, r_to).convert_from_to(v, self) if v is NotImplemented: From arigo at codespeak.net Wed Jun 29 21:17:47 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 29 Jun 2005 21:17:47 +0200 (CEST) Subject: [pypy-svn] r14016 - pypy/dist/pypy/rpython Message-ID: <20050629191747.15A1227B55@code1.codespeak.net> Author: arigo Date: Wed Jun 29 21:17:45 2005 New Revision: 14016 Modified: pypy/dist/pypy/rpython/rfloat.py pypy/dist/pypy/rpython/rint.py Log: Turn the 'div' operation into either 'int_floordiv' or 'float_truediv' depending on whether it's used on ints or floats. targetrichards now compiles and runs! It's even quite an acceptable performance -- 18x speed-up on my laptop :-) Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Wed Jun 29 21:17:45 2005 @@ -41,9 +41,12 @@ rtype_inplace_mul = rtype_mul def rtype_div(_, hop): - return _rtype_template(hop, 'div') + # turn 'div' on floats into 'truediv' + return _rtype_template(hop, 'truediv') - rtype_inplace_div = rtype_div + rtype_inplace_div = rtype_div + rtype_truediv = rtype_div + rtype_inplace_truediv = rtype_div def rtype_mod(_, hop): return _rtype_template(hop, 'mod') Modified: pypy/dist/pypy/rpython/rint.py ============================================================================== --- pypy/dist/pypy/rpython/rint.py (original) +++ pypy/dist/pypy/rpython/rint.py Wed Jun 29 21:17:45 2005 @@ -60,7 +60,8 @@ return _rtype_template(hop, 'mul_ovf') def rtype_div(_, hop): - return _rtype_template(hop, 'div', [ZeroDivisionError]) + # turn 'div' on integers into 'floordiv' + return _rtype_template(hop, 'floordiv', [ZeroDivisionError]) rtype_inplace_div = rtype_div def rtype_div_ovf(_, hop): From arigo at codespeak.net Thu Jun 30 00:23:52 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 30 Jun 2005 00:23:52 +0200 (CEST) Subject: [pypy-svn] r14017 - pypy/dist/pypy/translator/goal Message-ID: <20050629222352.5FE9527B57@code1.codespeak.net> Author: arigo Date: Thu Jun 30 00:23:50 2005 New Revision: 14017 Added: pypy/dist/pypy/translator/goal/unixcheckpoint.py (contents, props changed) Modified: pypy/dist/pypy/translator/goal/translate_pypy.py Log: This is a quick fork() hack that seems to provide a robust alternative to pickling on Unix systems. The process forks a copy of itself after annotation and runs the rtyper in the subprocess. When the subprocess terminates, the parent process prompts you again and let you fork another copy to re-run the rtyper. All modules not imported before the checkpoint can be modified between the runs (that's only the rtyper, essentially). Modified: pypy/dist/pypy/translator/goal/translate_pypy.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate_pypy.py (original) +++ pypy/dist/pypy/translator/goal/translate_pypy.py Thu Jun 30 00:23:50 2005 @@ -17,6 +17,7 @@ -no-t Don't type-specialize the graph operations with the C typer -no-o Don't do backend-oriented optimizations -no-c Don't generate the C code + -fork (UNIX) Create a restartable checkpoint after annotation -c Generate the C code, but don't compile it -o Generate and compile the C code, but don't run it -tcc Equivalent to the envvar PYPY_CC='tcc -shared -o "%s.so" "%s.c"' @@ -70,7 +71,6 @@ from pypy.annotation.model import SomeObject from pypy.tool.udir import udir from pypy.tool.ansi_print import ansi_print -from pypy.rpython.rtyper import RPythonTyper from pypy.translator.pickle.main import load, save # XXX this tries to make compiling faster @@ -104,6 +104,9 @@ if a and not options['-no-s']: print 'Simplifying...' a.simplify() + if a and options['-fork']: + from pypy.translator.goal import unixcheckpoint + unixcheckpoint.restartable_point() if a and not options['-no-t']: print 'Specializing...' t.specialize() @@ -257,6 +260,7 @@ '-no-d': False, '-load': False, '-save': False, + '-fork': False, } listen_port = None argiter = iter(sys.argv[1:]) Added: pypy/dist/pypy/translator/goal/unixcheckpoint.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/unixcheckpoint.py Thu Jun 30 00:23:50 2005 @@ -0,0 +1,51 @@ +import os + +def restartable_point(): + while True: + while True: + print '---> Checkpoint: run / quit / pdb ?' + try: + line = raw_input().strip().lower() + except KeyboardInterrupt: + print '(KeyboardInterrupt ignored)' + continue + if line == 'run': + break + if line == 'quit': + raise SystemExit + if line == 'pdb': + import pdb; pdb.set_trace() + + pid = os.fork() + if pid != 0: + # in parent + while True: + try: + pid, status = os.waitpid(pid, 0) + except KeyboardInterrupt: + continue + else: + break + print + print '_'*78 + print 'Child %d exited' % pid, + if os.WIFEXITED(status): + print '(exit code %d)' % os.WEXITSTATUS(status) + elif os.WIFSIGNALED(status): + print '(caught signal %d)' % os.WTERMSIG(status) + else: + print 'abnormally (status 0x%x)' % status + continue + + # in child + print '_'*78 + break + + +if __name__ == '__main__': + print 'doing stuff...' + print 'finished' + restartable_point() + print 'doing more stuff' + print 'press Enter to quit...' + raw_input() From pedronis at codespeak.net Thu Jun 30 03:11:41 2005 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 30 Jun 2005 03:11:41 +0200 (CEST) Subject: [pypy-svn] r14018 - in pypy/dist/pypy: rpython translator/c Message-ID: <20050630011141.E91D327B46@code1.codespeak.net> Author: pedronis Date: Thu Jun 30 03:11:39 2005 New Revision: 14018 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/translator/c/float_include.h Log: fix broken tests Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Thu Jun 30 03:11:39 2005 @@ -294,13 +294,13 @@ for typ in (float, int, r_uint): typname = typ.__name__ - optup = ('add', 'sub', 'mul', 'div', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq',) + optup = ('add', 'sub', 'mul', 'div', 'truediv', 'floordiv', 'mod', 'gt', 'lt', 'ge', 'ne', 'le', 'eq',) if typ is r_uint: opnameprefix = 'uint' else: opnameprefix = typname if typ in (int, r_uint): - optup += 'truediv', 'floordiv', 'and_', 'or_', 'lshift', 'rshift', 'xor' + optup += 'and_', 'or_', 'lshift', 'rshift', 'xor' for opname in optup: assert opname in opimpls if typ is int and opname not in ops_returning_a_bool: Modified: pypy/dist/pypy/translator/c/float_include.h ============================================================================== --- pypy/dist/pypy/translator/c/float_include.h (original) +++ pypy/dist/pypy/translator/c/float_include.h Thu Jun 30 03:11:39 2005 @@ -30,7 +30,7 @@ #define OP_FLOAT_SUB(x,y,r,err) r = x - y; #define OP_FLOAT_MUL(x,y,r,err) r = x * y; #define OP_FLOAT_DIV(x,y,r,err) r = x / y; - +#define OP_FLOAT_TRUEDIV(x,y,r,err) OP_FLOAT_DIV(x,y,r,err) #define OP_FLOAT_MOD(x,y,r,err) r = fmod(x, y); #define OP_FLOAT_POW(x,y,r,err) r = pow(x, y); From arigo at codespeak.net Thu Jun 30 12:49:43 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 30 Jun 2005 12:49:43 +0200 (CEST) Subject: [pypy-svn] r14020 - pypy/dist/pypy/translator/c Message-ID: <20050630104943.A1F3727B56@code1.codespeak.net> Author: arigo Date: Thu Jun 30 12:49:41 2005 New Revision: 14020 Modified: pypy/dist/pypy/translator/c/int_include.h pypy/dist/pypy/translator/c/mkuint.py Log: Reviewed the unsigned integer operations in the C translator. None of the overflow-checking operations seem to make much sense on unsigned integers. Neither does division/modulo. Removed the bound checks in OP_INT_LSHIFT and OP_INT_RSHIFT, assuming that the input code does the right thing (for example, objspace.std.intobject does). --This line, and those below, will be ignored-- M c/int_include.h M c/mkuint.py Modified: pypy/dist/pypy/translator/c/int_include.h ============================================================================== --- pypy/dist/pypy/translator/c/int_include.h (original) +++ pypy/dist/pypy/translator/c/int_include.h Thu Jun 30 12:49:41 2005 @@ -24,7 +24,6 @@ OP_INT_ABS(x,r,err) \ if ((x) >= 0 || (x) != -(x)); \ else FAIL_OVF(err, "integer absolute") -#define OP_UINT_ABS_OVF(x,r,err) r = (x); /*** binary operations ***/ @@ -75,37 +74,55 @@ /* shifting */ -#define OP_INT_RSHIFT(x,y,r,err) \ - if ((y) < LONG_BIT) \ - r = Py_ARITHMETIC_RIGHT_SHIFT(long, (x), (y)); \ - else r = (x) < 0 ? -1 : 0; - -#define OP_INT_RSHIFT_VAL(x,y,r,err) \ - if ((y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ - else FAIL_VAL(err, "negative shift count") - -#define OP_INT_LSHIFT(x,y,r,err) \ - if ((y) < LONG_BIT) \ - r = (x) << (y); \ - else r = 0; - -#define OP_INT_LSHIFT_VAL(x,y,r,err) \ - if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ - else FAIL_VAL(err, "negative shift count") +/* NB. shifting has same limitations as C: the shift count must be + >= 0 and < LONG_BITS. */ +#define OP_INT_RSHIFT(x,y,r,err) r = Py_ARITHMETIC_RIGHT_SHIFT(long, x, y); +#define OP_UINT_RSHIFT(x,y,r,err) r = (x) >> (y); + +#define OP_INT_LSHIFT(x,y,r,err) r = (x) << (y); +#define OP_UINT_LSHIFT(x,y,r,err) r = (x) << (y); #define OP_INT_LSHIFT_OVF(x,y,r,err) \ OP_INT_LSHIFT(x,y,r,err) \ if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ - else FAIL_VAL(err, "negative shift count") + +/* for reference, the safe value-checking version of the above macros + (not really used at the moment) */ + +/* #define OP_INT_RSHIFT(x,y,r,err) \ */ +/* if ((y) < LONG_BIT) \ */ +/* r = Py_ARITHMETIC_RIGHT_SHIFT(long, (x), (y)); \ */ +/* else r = (x) < 0 ? -1 : 0; */ + +/* #define OP_INT_RSHIFT_VAL(x,y,r,err) \ */ +/* if ((y) >= 0) { OP_INT_RSHIFT(x,y,r,err) } \ */ +/* else FAIL_VAL(err, "negative shift count") */ + +/* #define OP_INT_LSHIFT(x,y,r,err) \ */ +/* if ((y) < LONG_BIT) \ */ +/* r = (x) << (y); \ */ +/* else r = 0; */ + +/* #define OP_INT_LSHIFT_VAL(x,y,r,err) \ */ +/* if ((y) >= 0) { OP_INT_LSHIFT(x,y,r,err) } \ */ +/* else FAIL_VAL(err, "negative shift count") */ + +/* #define OP_INT_LSHIFT_OVF(x,y,r,err) \ */ +/* OP_INT_LSHIFT(x,y,r,err) \ */ +/* if ((x) != Py_ARITHMETIC_RIGHT_SHIFT(long, r, (y))) \ */ +/* FAIL_OVF(err, "x<= 0) { OP_INT_LSHIFT_OVF(x,y,r,err) } \ */ +/* else FAIL_VAL(err, "negative shift count") */ /* floor division */ -#define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); +#define OP_INT_FLOORDIV(x,y,r,err) r = op_divmod_adj(x, y, NULL); +#define OP_UINT_FLOORDIV(x,y,r,err) & Is_Unsigned_Division_Really_Useful; #define OP_INT_FLOORDIV_OVF(x,y,r,err) \ if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ @@ -115,6 +132,7 @@ #define OP_INT_FLOORDIV_ZER(x,y,r,err) \ if ((y)) { OP_INT_FLOORDIV(x,y,r,err) } \ else FAIL_ZER(err, "integer division") +#define OP_UINT_FLOORDIV_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; #define OP_INT_FLOORDIV_OVF_ZER(x,y,r,err) \ if ((y)) { OP_INT_FLOORDIV_OVF(x,y,r,err) } \ @@ -123,6 +141,7 @@ /* modulus */ #define OP_INT_MOD(x,y,r,err) op_divmod_adj(x, y, &r); +#define OP_UINT_MOD(x,y,r,err) & Is_Unsigned_Division_Really_Useful; #define OP_INT_MOD_OVF(x,y,r,err) \ if ((y) == -1 && (x) < 0 && ((unsigned long)(x) << 1) == 0) \ @@ -132,6 +151,7 @@ #define OP_INT_MOD_ZER(x,y,r,err) \ if ((y)) { OP_INT_MOD(x,y,r,err) } \ else FAIL_ZER(err, "integer modulo") +#define OP_UINT_MOD_ZER(x,y,r,err) & Is_Unsigned_Division_Really_Useful; #define OP_INT_MOD_OVF_ZER(x,y,r,err) \ if ((y)) { OP_INT_MOD_OVF(x,y,r,err) } \ @@ -225,9 +245,7 @@ #define OP_UINT_INVERT OP_INT_INVERT #define OP_UINT_POS OP_INT_POS #define OP_UINT_NEG OP_INT_NEG -#define OP_UINT_NEG_OVF OP_INT_NEG_OVF /* skipping OP_UINT_ABS */ -/* skipping OP_UINT_ABS_OVF */ #define OP_UINT_EQ OP_INT_EQ #define OP_UINT_NE OP_INT_NE #define OP_UINT_LE OP_INT_LE @@ -236,26 +254,14 @@ #define OP_UINT_GE OP_INT_GE #define OP_UINT_CMP OP_INT_CMP #define OP_UINT_ADD OP_INT_ADD -#define OP_UINT_ADD_OVF OP_INT_ADD_OVF #define OP_UINT_SUB OP_INT_SUB -#define OP_UINT_SUB_OVF OP_INT_SUB_OVF #define OP_UINT_MUL OP_INT_MUL -#define OP_UINT_MUL_OVF OP_INT_MUL_OVF -#define OP_UINT_MUL_OVF OP_INT_MUL_OVF -#define OP_UINT_RSHIFT OP_INT_RSHIFT -#define OP_UINT_RSHIFT_VAL OP_INT_RSHIFT_VAL -#define OP_UINT_LSHIFT OP_INT_LSHIFT -#define OP_UINT_LSHIFT_VAL OP_INT_LSHIFT_VAL -#define OP_UINT_LSHIFT_OVF OP_INT_LSHIFT_OVF -#define OP_UINT_LSHIFT_OVF_VAL OP_INT_LSHIFT_OVF_VAL -#define OP_UINT_FLOORDIV OP_INT_FLOORDIV -#define OP_UINT_FLOORDIV_OVF OP_INT_FLOORDIV_OVF -#define OP_UINT_FLOORDIV_ZER OP_INT_FLOORDIV_ZER -#define OP_UINT_FLOORDIV_OVF_ZER OP_INT_FLOORDIV_OVF_ZER -#define OP_UINT_MOD OP_INT_MOD -#define OP_UINT_MOD_OVF OP_INT_MOD_OVF -#define OP_UINT_MOD_ZER OP_INT_MOD_ZER -#define OP_UINT_MOD_OVF_ZER OP_INT_MOD_OVF_ZER +/* skipping OP_UINT_RSHIFT */ +/* skipping OP_UINT_LSHIFT */ +/* skipping OP_UINT_FLOORDIV */ +/* skipping OP_UINT_FLOORDIV_ZER */ +/* skipping OP_UINT_MOD */ +/* skipping OP_UINT_MOD_ZER */ #define OP_UINT_AND OP_INT_AND #define OP_UINT_OR OP_INT_OR #define OP_UINT_XOR OP_INT_XOR Modified: pypy/dist/pypy/translator/c/mkuint.py ============================================================================== --- pypy/dist/pypy/translator/c/mkuint.py (original) +++ pypy/dist/pypy/translator/c/mkuint.py Thu Jun 30 12:49:41 2005 @@ -21,7 +21,7 @@ for srcline in file(fname): srcline = srcline.rstrip() line = srcline.lstrip() - if line.startswith('#define OP_INT_'): + if line.startswith('#define OP_INT_') and line.find('_OVF') < 0: macroname = line.split('(')[0].split()[1] newname = 'OP_UINT_' + macroname[7:] lines.append('#define %s %s' % (newname, macroname)) From arigo at codespeak.net Thu Jun 30 12:59:46 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 30 Jun 2005 12:59:46 +0200 (CEST) Subject: [pypy-svn] r14021 - pypy/dist/pypy/translator/c/test Message-ID: <20050630105946.4A38E27B56@code1.codespeak.net> Author: arigo Date: Thu Jun 30 12:59:44 2005 New Revision: 14021 Modified: pypy/dist/pypy/translator/c/test/test_typed.py Log: For now, commented out the C tests about lshift_val and rshift_val. Modified: pypy/dist/pypy/translator/c/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_typed.py (original) +++ pypy/dist/pypy/translator/c/test/test_typed.py Thu Jun 30 12:59:44 2005 @@ -226,14 +226,14 @@ raises(OverflowError, fn, -1) raises(ZeroDivisionError, fn, 0) - def test_int_rshift_val(self): - fn = self.getcompiled(snippet.rshift_func) - raises(ValueError, fn, -1) - - def test_int_lshift_ovf_val(self): - fn = self.getcompiled(snippet.lshift_func) - raises(ValueError, fn, -1) - raises(OverflowError, fn, 1) +## def test_int_rshift_val(self): +## fn = self.getcompiled(snippet.rshift_func) +## raises(ValueError, fn, -1) + +## def test_int_lshift_ovf_val(self): +## fn = self.getcompiled(snippet.lshift_func) +## raises(ValueError, fn, -1) +## raises(OverflowError, fn, 1) def test_int_unary_ovf(self): fn = self.getcompiled(snippet.unary_func) From arigo at codespeak.net Thu Jun 30 13:05:34 2005 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 30 Jun 2005 13:05:34 +0200 (CEST) Subject: [pypy-svn] r14022 - pypy/extradoc/sprintinfo Message-ID: <20050630110534.4A36F27B46@code1.codespeak.net> Author: arigo Date: Thu Jun 30 13:05:32 2005 New Revision: 14022 Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt Log: - targetrichards.py compiles. - floats need clean-ups. Modified: pypy/extradoc/sprintinfo/post-ep2005-planning.txt ============================================================================== --- pypy/extradoc/sprintinfo/post-ep2005-planning.txt (original) +++ pypy/extradoc/sprintinfo/post-ep2005-planning.txt Thu Jun 30 13:05:32 2005 @@ -81,8 +81,11 @@ 'from ... import *' to use explicit imports (e.g. from pypy.rpython import lltype and then use lltype.*) -* progress on translation of example targets: - python pypy/translator/goal/translate_pypy.py targetrichards.py +* fix floats:: + - translator/c/float_include.h should catch floating-point signals + with a technique similar to CPython's. + - objspace/std/floatobject.py needs some clean-ups: + look for XXX, for %reimplement% and for all try:except: blocks. Move to Python 2.4.1 ----------------------- From tismer at codespeak.net Thu Jun 30 14:30:28 2005 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 30 Jun 2005 14:30:28 +0200 (CEST) Subject: [pypy-svn] r14023 - pypy/dist/pypy/translator/goal Message-ID: <20050630123028.2089B27B56@code1.codespeak.net> Author: tismer Date: Thu Jun 30 14:30:27 2005 New Revision: 14023 Modified: pypy/dist/pypy/translator/goal/targetrichards.py Log: use absolute imports, always Modified: pypy/dist/pypy/translator/goal/targetrichards.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrichards.py (original) +++ pypy/dist/pypy/translator/goal/targetrichards.py Thu Jun 30 14:30:27 2005 @@ -1,4 +1,4 @@ -import richards +from pypy.translator.goal import richards entry_point = richards.entry_point From mwh at codespeak.net Thu Jun 30 14:45:18 2005 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 30 Jun 2005 14:45:18 +0200 (CEST) Subject: [pypy-svn] r14024 - pypy/dist/pypy/objspace/std Message-ID: <20050630124518.AA57727B59@code1.codespeak.net> Author: mwh Date: Thu Jun 30 14:45:17 2005 New Revision: 14024 Modified: pypy/dist/pypy/objspace/std/floatobject.py Log: tyop Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Thu Jun 30 14:45:17 2005 @@ -241,7 +241,7 @@ def nonzero__Float(space, w_float): return space.newbool(w_float.floatval != 0.0) -######## coersion must be done later +######## coercion must be done later later = """ def float_coerce(space, w_float): if w_float.__class__ == W_FloatObject: